Commit 45a04f5f authored by argon.sun's avatar argon.sun

network

parent e8d9922f
#ifndef MATCH_DUEL_H
#define MATCH_DUEL_H
#include "config.h"
namespace ygo {
class MatchDuel: public DuelMode {
};
}
#endif //MATCH_DUEL_H
......@@ -3248,7 +3248,8 @@ bool Game::AnalyzeReplay(void* pd, char* engbuf) {
break;
}
case MSG_SHUFFLE_HAND: {
player = mainGame->LocalPlayer(NetManager::ReadInt8(pbuf));
int oplayer = NetManager::ReadInt8(pbuf);
player = mainGame->LocalPlayer(oplayer);
mainGame->WaitFrameSignal(5);
for (auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) {
(*cit)->dPos = irr::core::vector3df((3.9f - (*cit)->curPos.X) / 5, 0, 0);
......@@ -3258,7 +3259,7 @@ bool Game::AnalyzeReplay(void* pd, char* engbuf) {
(*cit)->aniFrame = 5;
}
mainGame->WaitFrameSignal(10);
mainGame->ReplayRefreshHand(player);
mainGame->ReplayRefreshHand(oplayer);
for (auto cit = mainGame->dField.hand[player].begin(); cit != mainGame->dField.hand[player].end(); ++cit) {
(*cit)->is_hovered = false;
mainGame->dField.MoveCard(*cit, 5);
......
#include "netserver.h"
#include "single_duel.h"
#include "match_duel.h"
namespace ygo {
std::unordered_map<bufferevent*, DuelPlayer> NetServer::users;
event_base* NetServer::net_evbase = 0;
DuelMode* NetServer::duel_mode = 0;
char NetServer::net_buffer_read[0x2000];
char NetServer::net_buffer_write[0x2000];
bool NetServer::StartServer(unsigned short port) {
if(net_evbase)
return false;
net_evbase = event_base_new();
if(!net_evbase)
return false;
#ifdef _WIN32
evthread_use_windows_threads();
#else
evthread_use_pthreads();
#endif
sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(port);
evconnlistener* listener = evconnlistener_new_bind(net_evbase, ServerAccept, NULL,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (sockaddr*)&sin, sizeof(sin));
if(!listener)
return false;
evconnlistener_set_error_cb(listener, ServerAcceptError);
Thread::NewThread(ServerThread, net_evbase);
return true;
}
void NetServer::StopServer() {
if(!net_evbase)
return;
event_base_loopexit(net_evbase, NULL);
}
void NetServer::ServerAccept(evconnlistener* listener, evutil_socket_t fd, sockaddr* address, int socklen, void* ctx) {
bufferevent* bev = bufferevent_socket_new(net_evbase, fd, BEV_OPT_CLOSE_ON_FREE);
DuelPlayer dp;
dp.output = bufferevent_get_output(bev);
users[bev] = dp;
bufferevent_setcb(bev, ServerEchoRead, NULL, ServerEchoEvent, NULL);
bufferevent_enable(bev, EV_READ | EV_WRITE);
}
void NetServer::ServerAcceptError(evconnlistener* listener, void* ctx) {
event_base_loopexit(net_evbase, NULL);
}
void NetServer::ServerEchoRead(bufferevent *bev, void *ctx) {
evbuffer* input = bufferevent_get_input(bev);
size_t len = evbuffer_get_length(input);
unsigned short packet_len = 0;
while(true) {
if(len < 2)
return;
evbuffer_copyout(input, &packet_len, 2);
if(len < packet_len + 2)
return;
evbuffer_remove(input, net_buffer_read, packet_len + 2);
if(len)
HandleCTOSPacket(users[bev], &net_buffer_read[2], len);
}
}
void NetServer::ServerEchoEvent(bufferevent* bev, short events, void* ctx) {
if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
bufferevent_free(bev);
users.erase(bev);
}
}
int NetServer::ServerThread(void* param) {
event_base_dispatch(net_evbase);
event_base_free(net_evbase);
net_evbase = 0;
return 0;
}
void NetServer::HandleCTOSPacket(DuelPlayer& dp, char* data, unsigned int len) {
char* pdata = data;
unsigned char pktType = NetManager::ReadUInt8(pdata);
if(dp.state && dp.state != pktType)
return;
switch(pktType) {
case CTOS_RESPONSE:
break;
case CTOS_CHANGEDECK:
break;
case CTOS_PLAYER_INFO: {
CTOS_PlayerInfo* pkt = (CTOS_PlayerInfo*)pdata;
for(int i = 0; i < 20; ++i)
dp.name[i] = pkt->name[i];
break;
}
case CTOS_CREATE_GAME: {
if(dp.game || len < sizeof(CTOS_CreateGame))
return;
CTOS_CreateGame* pkt = (CTOS_CreateGame*)pdata;
if(pkt->info.mode == MODE_SINGLE) {
dp.game = new SingleDuel;
} else {
dp.game = new MatchDuel;
}
dp.game->host_info = pkt->info;
duel_mode = dp.game;
break;
}
case CTOS_JOIN_GAME: {
if(dp.game)
return;
if(!duel_mode)
return;
if(!duel_mode->players[0])
duel_mode->players[0] = &dp;
else if(!duel_mode->players[1])
duel_mode->players[1] = &dp;
else duel_mode->observers.insert(&dp);
break;
}
case CTOS_EXIT_GAME:
break;
case CTOS_HS_COMMAND:
break;
}
}
}
......@@ -3,6 +3,13 @@
#include "config.h"
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/thread.h>
#include "network.h"
#include <array>
#include <set>
#include <unordered_map>
#define NETPLAYER_TYPE_PLAYER1 0
......@@ -18,50 +25,62 @@ namespace ygo {
class DuelMode;
struct DuelPlayer {
unsigned short name[20];
DuelMode* game;
unsigned char type;
unsigned char state;
unsigned char pos;
unsigned int uid;
evbuffer* output;
DuelPlayer() {
uid = 0;
pos = 0;
game = 0;
type = 0;
state = 0;
output = 0;
}
};
class DuelMode {
private:
std::array<DuelPlayer*, 6> players;
std::vector<DuelPlayer*> observers;
bool ready[6];
unsigned int host_uid;
unsigned long pduel;
public:
DuelMode() {
for(int i = 0; i < 6; ++i){
players[i] = 0;
ready[i] = false;
}
for(int i = 0; i < 8; ++i)
observers[i] = 0;
host_uid = 0;
host_player = 0;
pduel = 0;
}
void Start();
void Process();
void End();
public:
DuelPlayer* players[6];
bool ready[6];
std::set<DuelPlayer*> observers;
DuelPlayer* host_player;
HostInfo host_info;
unsigned long pduel;
};
class NetServer {
private:
static std::unordered_map<int, DuelPlayer> users;
static bool server_started;
static unsigned int uid;
static std::unordered_map<bufferevent*, DuelPlayer> users;
static event_base* net_evbase;
static DuelMode* duel_mode;
static char net_buffer_read[0x2000];
static char net_buffer_write[0x2000];
public:
static bool StartServer(unsigned short port);
static void StopServer();
static void ServerAccept(evconnlistener* listener, evutil_socket_t fd, sockaddr* address, int socklen, void* ctx);
static void ServerAcceptError(evconnlistener *listener, void* ctx);
static void ServerEchoRead(bufferevent* bev, void* ctx);
static void ServerEchoEvent(bufferevent* bev, short events, void* ctx);
static int ServerThread(void* param);
static void HandleCTOSPacket(DuelPlayer& dp, char* data, unsigned int len);
};
}
......
......@@ -8,17 +8,6 @@ const unsigned short PROTO_VERSION = 0x1020;
bool NetManager::CreateHost(int ipindex) {
wchar_t* pstr;
int wp;
hInfo.identifier = NETWORK_SERVER_ID;
hInfo.version = PROTO_VERSION;
for(wp = 0, pstr = (wchar_t*)mainGame->ebServerName->getText(); wp < 19 && pstr[wp]; ++wp)
hInfo.name[wp] = pstr[wp];
hInfo.port = serv_port;
hInfo.name[wp] = 0;
hInfo.no_check_deck = mainGame->chkNoCheckDeck->isChecked();
hInfo.no_shuffle_deck = mainGame->chkNoShuffleDeck->isChecked();
hInfo.start_lp = _wtoi(mainGame->ebStartLP->getText());
hInfo.start_hand = _wtoi(mainGame->ebStartHand->getText());
hInfo.draw_count = _wtoi(mainGame->ebDrawCount->getText());
sBHost = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sBHost == INVALID_SOCKET)
return false;
......@@ -196,15 +185,6 @@ int NetManager::BroadcastClient(void* np) {
net->hosts.clear();
SOCKADDR_IN sockFrom;
int sz = sizeof(SOCKADDR_IN);
while(result != 0 && result != SOCKET_ERROR) {
int recvLen = recvfrom(net->sBClient, (char*)&net->hInfo, sizeof(HostInfo), 0, (sockaddr*)&sockFrom, &sz);
if(recvLen == sizeof(HostInfo) && net->hInfo.identifier == NETWORK_SERVER_ID
&& net->hInfo.version == PROTO_VERSION && addrset.find(sockFrom.sin_addr.s_addr) == addrset.end()) {
net->hInfo.address = sockFrom.sin_addr.s_addr;
net->hosts.push_back(net->hInfo);
}
result = select(0, &fds, 0, 0, &tv);
}
if(mainGame->is_closing)
return 0;
wchar_t tbuf[256];
......
......@@ -9,11 +9,7 @@
namespace ygo {
struct HostInfo {
unsigned short identifier;
unsigned short version;
unsigned int address;
unsigned short port;
char name[32];
unsigned short name[20];
unsigned char rule;
unsigned char mode;
unsigned int lflist;
......@@ -24,10 +20,45 @@ struct HostInfo {
unsigned char draw_count;
};
struct HostPacket {
unsigned short identifier;
unsigned short version;
unsigned int address;
unsigned short port;
HostInfo host;
};
struct HostRequest {
unsigned short identifier;
};
struct CTOS_Response {
};
struct CTOS_ChangeDeck {
};
struct CTOS_PlayerInfo {
unsigned short name[20];
};
struct CTOS_CreateGame {
HostInfo info;
};
struct CTOS_JoinGame {
unsigned int gameid;
};
struct CTOS_ExitGame {
};
struct CTOS_HS_Command {
unsigned char cmd;
};
struct STOC_CreateGame {
unsigned int gameid;
};
struct STOC_JoinGame {
};
struct STOC_ExitGame {
};
class NetManager {
public:
unsigned int local_addr[8];
......@@ -100,4 +131,26 @@ extern const unsigned short PROTO_VERSION;
#define NETWORK_SERVER_ID 0x7428
#define NETWORK_CLIENT_ID 0xdef6
#define CTOS_RESPONSE 0x1
#define CTOS_CHANGEDECK 0x2
#define CTOS_PLAYER_INFO 0x10
#define CTOS_CREATE_GAME 0x11
#define CTOS_JOIN_GAME 0x12
#define CTOS_EXIT_GAME 0x13
#define CTOS_HS_COMMAND 0x14
#define HS_COMMAND_TODUELIST 0x1
#define HS_COMMAND_TOOBSERVER 0x2
#define HS_COMMAND_READY 0x3
#define HS_COMMAND_KICK1 0x4
#define HS_COMMAND_KICK2 0x5
#define HS_COMMAND_START 0x6
#define STOC_CREATE_GAME 0x11
#define STOC_JION_GAME 0x12
#define STOC_EXIT_GAME 0x13
#define STOC_
#define MODE_SINGLE 0x1
#define MODE_MATCH 0x2
#endif //NETWORK_H
......@@ -6,7 +6,7 @@ project "gframe"
files { "**.cpp", "**.cc", "**.c", "**.h" }
excludes "lzma/**"
includedirs { "../ocgcore" }
links { "ocgcore", "clzma", "irrlicht", "freetype", "sqlite3", "lua" }
links { "ocgcore", "clzma", "irrlicht", "freetype", "sqlite3", "lua" , "event"}
configuration "windows"
links { "opengl32", "wsock32", "winmm", "gdi32", "kernel32", "user32" }
......
......@@ -5,7 +5,7 @@
namespace ygo {
class SingleDuel {
class SingleDuel: public DuelMode {
};
......
......@@ -29,7 +29,7 @@ end
function c39648965.piercecon(e,tp,eg,ep,ev,re,r,rp)
local a=Duel.GetAttacker()
local d=Duel.GetAttackTarget()
return d and a:IsControler(tp) and d:IsDefence() and a:IsSetCard(0x13)
return d and a:IsControler(tp) and a~=e:GetHandler() and d:IsDefence() and a:IsSetCard(0x13)
end
function c39648965.piercetg(e,tp,eg,ep,ev,re,r,rp,chk)
if chk==0 then return true end
......
......@@ -31,7 +31,7 @@ function c69448290.spop(e,tp,eg,ep,ev,re,r,rp)
e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetCode(EFFECT_CANNOT_ATTACK)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE)
e1:SetReset(RESET_EVENT+0x1fe0000)
e1:SetReset(RESET_EVENT+0x1fe0000+RESET_PHASE+PHASE_END)
c:RegisterEffect(e1)
end
end
......@@ -151,6 +151,7 @@ function Auxiliary.SynOperation2(f1,f2)
if tuner then
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SMATERIAL)
g=Duel.SelectMatchingCard(tp,Auxiliary.SynFilter2,tp,LOCATION_MZONE,LOCATION_MZONE,1,1,tuner,c,lv-tuner:GetLevel(),f2)
g:AddCard(tuner)
else
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_SMATERIAL)
g=Duel.SelectMatchingCard(tp,Auxiliary.SynFilter1,tp,LOCATION_MZONE,LOCATION_MZONE,1,1,nil,c,lv,f1,f2)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment