Commit bcfd1afc authored by argon.sun's avatar argon.sun

recon

parent bfda4280
#ifndef BUFFERIO_H
#define BUFFERIO_H
class BufferIO {
public:
inline static int ReadInt32(char*& p) {
int ret = *(int*)p;
p += 4;
return ret;
}
inline static short ReadInt16(char*& p) {
short ret = *(short*)p;
p += 2;
return ret;
}
inline static char ReadInt8(char*& p) {
char ret = *(char*)p;
p++;
return ret;
}
inline static unsigned char ReadUInt8(char*& p) {
unsigned char ret = *(unsigned char*)p;
p++;
return ret;
}
inline static void WriteInt32(char*& p, int val) {
(*(int*)p) = val;
p += 4;
}
inline static void WriteInt16(char*& p, short val) {
(*(short*)p) = val;
p += 2;
}
inline static void WriteInt8(char*& p, char val) {
*p = val;
p++;
}
};
#endif //BUFFERIO_H
......@@ -41,42 +41,42 @@ void ClientCard::SetCode(int code) {
this->code = code;
}
void ClientCard::UpdateInfo(char* buf) {
int flag = NetManager::ReadInt32(buf);
int flag = BufferIO::ReadInt32(buf);
if(flag == 0)
return;
int pdata;
if(flag & QUERY_CODE) {
pdata = NetManager::ReadInt32(buf);
pdata = BufferIO::ReadInt32(buf);
if(location == LOCATION_HAND && controler == 1 && pdata != code)
mainGame->dField.MoveCard(this, 5);
code = pdata;
}
if(flag & QUERY_POSITION)
pdata = NetManager::ReadInt32(buf);
pdata = BufferIO::ReadInt32(buf);
if(flag & QUERY_ALIAS)
alias = NetManager::ReadInt32(buf);
alias = BufferIO::ReadInt32(buf);
if(flag & QUERY_TYPE)
type = NetManager::ReadInt32(buf);
type = BufferIO::ReadInt32(buf);
if(flag & QUERY_LEVEL) {
pdata = NetManager::ReadInt32(buf);
pdata = BufferIO::ReadInt32(buf);
if(pdata && level != pdata) {
level = pdata;
myswprintf(lvstring, L"L%d", level);
}
}
if(flag & QUERY_RANK) {
pdata = NetManager::ReadInt32(buf);
pdata = BufferIO::ReadInt32(buf);
if(pdata && rank != pdata) {
rank = pdata;
myswprintf(lvstring, L"R%d", rank);
}
}
if(flag & QUERY_ATTRIBUTE)
attribute = NetManager::ReadInt32(buf);
attribute = BufferIO::ReadInt32(buf);
if(flag & QUERY_RACE)
race = NetManager::ReadInt32(buf);
race = BufferIO::ReadInt32(buf);
if(flag & QUERY_ATTACK) {
attack = NetManager::ReadInt32(buf);
attack = BufferIO::ReadInt32(buf);
if(attack < 0) {
atkstring[0] = '?';
atkstring[1] = 0;
......@@ -84,7 +84,7 @@ void ClientCard::UpdateInfo(char* buf) {
myswprintf(atkstring, L"%d", attack);
}
if(flag & QUERY_DEFENCE) {
defence = NetManager::ReadInt32(buf);
defence = BufferIO::ReadInt32(buf);
if(defence < 0) {
defstring[0] = '?';
defstring[1] = 0;
......@@ -92,15 +92,15 @@ void ClientCard::UpdateInfo(char* buf) {
myswprintf(defstring, L"%d", defence);
}
if(flag & QUERY_BASE_ATTACK)
base_attack = NetManager::ReadInt32(buf);
base_attack = BufferIO::ReadInt32(buf);
if(flag & QUERY_BASE_DEFENCE)
base_defence = NetManager::ReadInt32(buf);
base_defence = BufferIO::ReadInt32(buf);
if(flag & QUERY_REASON)
reason = NetManager::ReadInt32(buf);
reason = BufferIO::ReadInt32(buf);
if(flag & QUERY_IS_DISABLED)
is_disabled = NetManager::ReadInt32(buf);
is_disabled = BufferIO::ReadInt32(buf);
if(flag & QUERY_IS_PUBLIC)
is_public = NetManager::ReadInt32(buf);
is_public = BufferIO::ReadInt32(buf);
}
void ClientCard::ClearTarget() {
for(auto cit = cardTarget.begin(); cit != cardTarget.end(); ++cit)
......
......@@ -269,7 +269,7 @@ void ClientField::UpdateFieldCard(int controler, int location, char* data) {
return;
int len;
for(cit = lst->begin(); cit != lst->end(); ++cit) {
len = NetManager::ReadInt32(data);
len = BufferIO::ReadInt32(data);
if(len > 8)
(*cit)->UpdateInfo(data);
data += len - 4;
......
......@@ -14,7 +14,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "mytimer.h"
#include "bufferio.h"
#include "mymutex.h"
#include "mysignal.h"
#include "mythread.h"
......
#include "duelclient.h"
#include "game.h"
namespace ygo {
unsigned DuelClient::connect_state = 0;
int DuelClient::responseI;
unsigned char DuelClient::responseB[64];
bool DuelClient::is_responseB;
unsigned char DuelClient::response_len;
bool DuelClient::StartClient(unsigned int ip, unsigned short port) {
if(connect_state)
return false;
event_base* evbase;
bufferevent* bev;
sockaddr_in sin;
evbase = event_base_new();
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(ip);
sin.sin_port = htons(port);
bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, ClientRead, NULL, ClientEvent, NULL);
if (bufferevent_socket_connect(bev, (sockaddr*)&sin, sizeof(sin)) < 0) {
bufferevent_free(bev);
return false;
}
connect_state = 1;
Thread::NewThread(ClientThread, evbase);
return true;
}
void DuelClient::ClientRead(bufferevent* bev, void* ctx) {
}
void DuelClient::ClientEvent(bufferevent *bev, short events, void *ptr) {
if (events & BEV_EVENT_CONNECTED) {
connect_state = 2;
} else if (events & BEV_EVENT_ERROR) {
}
}
int DuelClient::ClientThread(void* param) {
event_base* evbase = (event_base*)param;
event_base_dispatch(evbase);
event_base_loopexit(evbase, NULL);
connect_state = 0;
}
void DuelClient::HandleSTOCPacket(char* data, unsigned int len) {
}
void DuelClient::SetResponseI(int respI) {
responseI = respI;
is_responseB = false;
}
void DuelClient::SetResponseB(unsigned char* respB, unsigned char len) {
memcpy(responseB, respB, len);
is_responseB = true;
response_len = len;
}
}
#ifndef DUELCLIENT_H
#define DUELCLIENT_H
#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 "data_manager.h"
#include "deck_manager.h"
namespace ygo {
class DuelClient {
private:
static unsigned int connect_state;
static int responseI;
static unsigned char responseB[64];
static bool is_responseB;
static unsigned char response_len;
public:
static bool StartClient(unsigned int ip, unsigned short port);
static void ClientRead(bufferevent* bev, void* ctx);
static void ClientEvent(bufferevent *bev, short events, void *ptr);
static int ClientThread(void* param);
static void HandleSTOCPacket(char* data, unsigned int len);
static void SetResponseI(int respI);
static void SetResponseB(unsigned char* respB, unsigned char len);
};
}
#endif //DUELCLIENT_H
This diff is collapsed.
......@@ -5,6 +5,7 @@
#ifndef WIN32
#include <sys/types.h>
#include <dirent.h>
#include "replay.h"
#endif
namespace ygo {
......@@ -36,9 +37,8 @@ bool Game::Initialize() {
always_chain = false;
ignore_chain = false;
is_building = false;
exit_window = 0;
memset(&dInfo, 0, sizeof(DuelInfo));
netManager.GetLocalAddress();
netManager.send_buffer_ptr = &netManager.send_buf[2];
deckManager.LoadLFList();
driver = device->getVideoDriver();
driver->setTextureCreationFlag(irr::video::ETCF_CREATE_MIP_MAPS, false);
......@@ -412,10 +412,7 @@ bool Game::Initialize() {
return true;
}
void Game::MainLoop() {
int fps = 0;
wchar_t cap[256];
gTimer.Reset();
float st, ed;
is_closing = false;
camera = smgr->addCameraSceneNode(0);
irr::core::matrix4 mProjection;
......@@ -427,11 +424,14 @@ void Game::MainLoop() {
light->getLightData().AmbientColor = SColorf(1.0f, 1.0f, 1.0f);
light->getLightData().DiffuseColor = SColorf(0.0f, 0.0f, 0.0f);
float atkframe = 0.1f;
irr::ITimer* timer = device->getTimer();
timer->setTime(0);
int fps = 0;
unsigned int last_time = 0, cur_time = 0;
while(device->run()) {
linePattern = (linePattern << 1) | (linePattern >> 15);
atkframe += 0.1f;
atkdy = (float)sin(atkframe);
st = gTimer.GetElapsedTime();
driver->beginScene(true, true, SColor(0, 0, 0, 0));
if(imageManager.tBackGround)
driver->draw2DImage(imageManager.tBackGround, recti(0, 0, 1024, 640), recti(0, 0, imageManager.tBackGround->getSize().Width, imageManager.tBackGround->getSize().Height));
......@@ -454,6 +454,11 @@ void Game::MainLoop() {
if(!signalFrame)
frameSignal.Set();
}
if(exit_window && !fadingFrame) {
irr::SEvent sevt;
sevt.EventType = irr::EET_USER_EVENT;
sevt.UserEvent.UserData1 = UEVENT_TOWINDOW;
}
if(waitFrame >= 0) {
waitFrame++;
if(waitFrame % 90 == 0) {
......@@ -466,24 +471,22 @@ void Game::MainLoop() {
}
driver->endScene();
fps++;
ed = gTimer.GetElapsedTime();
if(ed - st < 16900) {
gTimer.Wait(16900 + st - ed);
}
if(ed >= 1000000.0f) {
cur_time = timer->getTime();
if(cur_time < fps * 17 - 20)
#ifdef _WIN32
Sleep(20);
#else
usleep(20000000);
#endif
if(cur_time >= 1000) {
myswprintf(cap, L"FPS: %d", fps);
device->setWindowCaption(cap);
fps = 0;
gTimer.Reset();
cur_time -= 1000;
timer->setTime(0);
}
}
is_closing = true;
shutdown(netManager.sBHost, SD_BOTH);
closesocket(netManager.sBHost);
shutdown(netManager.sListen, SD_BOTH);
closesocket(netManager.sListen);
shutdown(netManager.sRemote, SD_BOTH);
closesocket(netManager.sRemote);
SaveConfig();
device->drop();
}
......
......@@ -9,7 +9,6 @@
#include "client_field.h"
#include "deck_con.h"
#include "menu_handler.h"
#include "network.h"
#include "deck_manager.h"
#include "replay.h"
#include <string>
......@@ -38,10 +37,7 @@ struct DuelInfo {
bool is_first_turn;
bool is_local_host;
bool is_responsed;
long pDuel;
int resPlayer;
int responseI;
char responseB[64];
int lp[2];
int engFlag;
int engLen;
......@@ -91,12 +87,7 @@ public:
int LocalPlayer(int player);
const wchar_t* LocalName(int local_player);
bool SendByte(int player, char val);
bool SendGameMessage(int player, char* buf, int len);
bool WaitforResponse(int player);
void SetResponseI();
void SetResponseB(int len);
bool RefreshMzone(int player, int flag = 0x181fff, int use_cache = 1);
/* bool RefreshMzone(int player, int flag = 0x181fff, int use_cache = 1);
bool RefreshSzone(int player, int flag = 0x181fff, int use_cache = 1);
bool RefreshHand(int player, int flag = 0x181fff, int use_cache = 1);
bool RefreshGrave(int player, int flag = 0x181fff, int use_cache = 1);
......@@ -116,7 +107,7 @@ public:
static int GameThread(void*);
static bool SolveMessage(void*, char*, int);
static int ReplayThread(void* pd);
static bool AnalyzeReplay(void*, char*);
static bool AnalyzeReplay(void*, char*);*/
//
char msgBuffer[0x1000];
......@@ -125,7 +116,6 @@ public:
bool is_closing;
bool is_refreshing;
mtrandom rnd;
Timer gTimer;
Mutex gMutex;
Mutex gBuffer;
Signal frameSignal;
......@@ -133,7 +123,6 @@ public:
Signal localResponse;
Signal localAction;
Config gameConf;
NetManager netManager;
DataManager dataManager;
ImageManager imageManager;
DeckManager deckManager;
......@@ -160,6 +149,7 @@ public:
int showcardp;
int is_attacking;
int attack_sv;
irr::gui::IGUIElement* exit_window;
irr::core::vector3df atk_r;
irr::core::vector3df atk_t;
float atkdy;
......@@ -368,6 +358,9 @@ extern Game* mainGame;
}
#define UEVENT_EXIT 0x1
#define UEVENT_TOWINDOW 0x2
#define COMMAND_ACTIVATE 0x0001
#define COMMAND_SUMMON 0x0002
#define COMMAND_SPSUMMON 0x0004
......
......@@ -7,7 +7,6 @@ int main() {
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
WSAStartup(wVersionRequested, &wsaData);
timeBeginPeriod(1);
#else
#endif //_WIN32
ygo::Game _game;
......@@ -16,7 +15,6 @@ int main() {
return 0;
ygo::mainGame->MainLoop();
#ifdef _WIN32
timeEndPeriod(1);
WSACleanup();
#else
#endif //_WIN32
......
......@@ -17,67 +17,7 @@ int Game::LocalPlayer(int player) {
const wchar_t* Game::LocalName(int local_player) {
return local_player == 0 ? dInfo.hostname : dInfo.clientname;
}
bool Game::SendByte(int player, char val) {
netManager.send_buf[2] = val;
return SendGameMessage(player, netManager.send_buffer_ptr, 1);
}
bool Game::SendGameMessage(int player, char* buf, int len) {
*(short*)(buf - 2) = len;
if(dInfo.is_host_player[player]) {
gBuffer.Lock();
memcpy(&msgBuffer[dInfo.msgLen], buf - 2, len + 2);
dInfo.msgLen += len + 2;
localMessage.Set();
gBuffer.Unlock();
return true;
} else {
return netManager.SendtoRemote(buf - 2, len + 2);
}
}
bool Game::WaitforResponse(int player) {
if(!SendByte(1 - player, MSG_WAITING))
return false;
dInfo.resPlayer = player;
if(dInfo.is_host_player[player]) {
localResponse.Wait();
return true;
} else {
return netManager.WaitClientResponse();
}
}
void Game::SetResponseI() {
if(dInfo.is_responsed)
return;
dInfo.is_responsed = true;
if(dInfo.is_local_host) {
set_responsei(dInfo.pDuel, dInfo.responseI);
lastReplay.WriteInt8(1, false);
lastReplay.WriteInt32(dInfo.responseI);
} else {
char* pbuf = netManager.send_buf;
NetManager::WriteInt8(pbuf, 1);
NetManager::WriteInt32(pbuf, dInfo.responseI);
netManager.SendtoRemote(netManager.send_buf, 5);
}
}
void Game::SetResponseB(int len) {
if(dInfo.is_responsed)
return;
dInfo.is_responsed = true;
if(dInfo.is_local_host) {
set_responseb(dInfo.pDuel, (byte*)dInfo.responseB);
lastReplay.WriteInt8(2, false);
lastReplay.WriteInt8(len, false);
lastReplay.WriteData(dInfo.responseB, len);
} else {
char* pbuf = netManager.send_buf;
NetManager::WriteInt8(pbuf, 2);
NetManager::WriteInt8(pbuf, len);
for(int i = 0; i < len; ++i)
pbuf[i] = dInfo.responseB[i];
netManager.SendtoRemote(netManager.send_buf, 2 + len);
}
}
/*
bool Game::RefreshMzone(int player, int flag, int use_cache) {
int len = query_field_card(dInfo.pDuel, player, LOCATION_MZONE, flag, (unsigned char*)queryBuffer, use_cache);
char* pbuf = netManager.send_buffer_ptr;
......@@ -3564,5 +3504,5 @@ bool Game::AnalyzeReplay(void* pd, char* engbuf) {
}
return true;
}
*/
}
#ifndef TIMER_H
#define TIMER_H
#ifdef _WIN32
#include <windows.h>
class Timer {
public:
Timer() {
hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
}
~Timer() {
CloseHandle(hTimer);
}
void Reset() {
QueryPerformanceCounter(&startTime);
}
float GetElapsedTime() {
LARGE_INTEGER endTime;
LARGE_INTEGER timerFreq;
QueryPerformanceFrequency(&timerFreq);
QueryPerformanceCounter(&endTime);
return (endTime.QuadPart - startTime.QuadPart) * 1000000.0f / timerFreq.QuadPart;
}
void Wait(long long us) {
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = us * -10LL;
SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0);
WaitForSingleObject(hTimer, INFINITE);
}
private:
LARGE_INTEGER startTime;
HANDLE hTimer;
};
#else // _WIN32
#include <sys/time.h>
#include <unistd.h>
class Timer {
public:
Timer() {
}
~Timer() {
}
void Reset() {
gettimeofday(&startTime, 0);
}
float GetElapsedTime() {
timeval endTime;
gettimeofday(&endTime, 0);
return (endTime.tv_sec - startTime.tv_sec) * 1000000.0f + endTime.tv_usec - startTime.tv_usec;
}
void Wait(long long us) {
usleep(us);
}
private:
timeval startTime;
};
#endif // _WIN32
#endif // TIMER_H
......@@ -5,9 +5,11 @@
namespace ygo {
std::unordered_map<bufferevent*, DuelPlayer> NetServer::users;
event_base* NetServer::net_evbase = 0;
evconnlistener* NetServer::listener = 0;
DuelMode* NetServer::duel_mode = 0;
char NetServer::net_buffer_read[0x2000];
char NetServer::net_buffer_write[0x2000];
char NetServer::net_server_read[0x2000];
char NetServer::net_server_write[0x2000];
unsigned short NetServer::last_sent = 0;
bool NetServer::StartServer(unsigned short port) {
if(net_evbase)
......@@ -25,8 +27,8 @@ bool NetServer::StartServer(unsigned short port) {
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));
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);
......@@ -41,6 +43,7 @@ void NetServer::StopServer() {
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.name[0] = 0;
dp.output = bufferevent_get_output(bev);
users[bev] = dp;
bufferevent_setcb(bev, ServerEchoRead, NULL, ServerEchoEvent, NULL);
......@@ -59,9 +62,10 @@ void NetServer::ServerEchoRead(bufferevent *bev, void *ctx) {
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);
evbuffer_remove(input, net_server_read, packet_len + 2);
if(packet_len)
HandleCTOSPacket(&users[bev], &net_server_read[2], packet_len);
len -= packet_len + 2;
}
}
void NetServer::ServerEchoEvent(bufferevent* bev, short events, void* ctx) {
......@@ -76,10 +80,10 @@ int NetServer::ServerThread(void* param) {
net_evbase = 0;
return 0;
}
void NetServer::HandleCTOSPacket(DuelPlayer& dp, char* data, unsigned int len) {
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)
unsigned char pktType = BufferIO::ReadUInt8(pdata);
if(dp->state == 0xff || (dp->state && dp->state != pktType))
return;
switch(pktType) {
case CTOS_RESPONSE:
......@@ -89,32 +93,91 @@ void NetServer::HandleCTOSPacket(DuelPlayer& dp, char* data, unsigned int len) {
case CTOS_PLAYER_INFO: {
CTOS_PlayerInfo* pkt = (CTOS_PlayerInfo*)pdata;
for(int i = 0; i < 20; ++i)
dp.name[i] = pkt->name[i];
dp->name[i] = pkt->name[i];
break;
}
case CTOS_CREATE_GAME: {
if(dp.game || len < sizeof(CTOS_CreateGame))
if(dp->game || duel_mode || len < sizeof(CTOS_CreateGame))
return;
CTOS_CreateGame* pkt = (CTOS_CreateGame*)pdata;
if(pkt->info.mode == MODE_SINGLE) {
dp.game = new SingleDuel;
duel_mode = new SingleDuel;
} else {
dp.game = new MatchDuel;
duel_mode = new MatchDuel;
}
dp.game->host_info = pkt->info;
duel_mode = dp.game;
break;
duel_mode->host_info = pkt->info;
}
case CTOS_JOIN_GAME: {
if(dp.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);
dp->game = duel_mode;
if(!duel_mode->players[0] && !duel_mode->players[1] && duel_mode->observers.size() == 0)
duel_mode->host_player = dp;
STOC_JoinGame scjg;
scjg.info = duel_mode->host_info;
scjg.type = (duel_mode->host_player == dp) ? 0x10 : 0;
if(!duel_mode->players[0] || !duel_mode->players[1]) {
STOC_HS_PlayerEnter scpe;
for(int i = 0; i < 20; ++i)
scpe.name[i] = dp->name[1];
if(duel_mode->players[0])
NetServer::SendPacketToPlayer(duel_mode->players[0], STOC_HS_PLAYER_ENTER, scpe);
if(duel_mode->players[1])
NetServer::SendPacketToPlayer(duel_mode->players[1], STOC_HS_PLAYER_ENTER, scpe);
for(auto pit = duel_mode->observers.begin(); pit != duel_mode->observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe);
if(!duel_mode->players[0]) {
duel_mode->players[0] = dp;
dp->type = NETPLAYER_TYPE_PLAYER1;
scjg.type |= NETPLAYER_TYPE_PLAYER1;
} else {
duel_mode->players[1] = dp;
dp->type = NETPLAYER_TYPE_PLAYER2;
scjg.type |= NETPLAYER_TYPE_PLAYER2;
}
} else {
duel_mode->observers.insert(dp);
dp->type = NETPLAYER_TYPE_OBSERVER;
scjg.type |= NETPLAYER_TYPE_OBSERVER;
STOC_HS_ReadyChange scrc;
scrc.ready = duel_mode->observers.size();
if(duel_mode->players[0])
NetServer::SendPacketToPlayer(duel_mode->players[0], STOC_HS_READY_CHANGE, scrc);
if(duel_mode->players[1])
NetServer::SendPacketToPlayer(duel_mode->players[1], STOC_HS_READY_CHANGE, scrc);
for(auto pit = duel_mode->observers.begin(); pit != duel_mode->observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_READY_CHANGE, scrc);
}
NetServer::SendPacketToPlayer(dp, STOC_JOIN_GAME, scjg);
if(duel_mode->players[0]) {
STOC_HS_PlayerEnter scpe;
for(int i = 0; i < 20; ++i)
scpe.name[i] = duel_mode->players[0]->name[1];
NetServer::SendPacketToPlayer(dp, STOC_HS_PLAYER_ENTER, scpe);
if(duel_mode->ready[0]) {
STOC_HS_PlayerChange scpc;
scpc.status = PLAYERCHANGE_READY;
NetServer::SendPacketToPlayer(dp, STOC_HS_PLAYER_CHANGE, scpc);
}
}
if(duel_mode->players[1]) {
STOC_HS_PlayerEnter scpe;
for(int i = 0; i < 20; ++i)
scpe.name[i] = duel_mode->players[1]->name[1];
NetServer::SendPacketToPlayer(dp, STOC_HS_PLAYER_ENTER, scpe);
if(duel_mode->ready[1]) {
STOC_HS_PlayerChange scpc;
scpc.status = 0x10 | PLAYERCHANGE_READY;
NetServer::SendPacketToPlayer(dp, STOC_HS_PLAYER_CHANGE, scpc);
}
}
if(duel_mode->observers.size()) {
STOC_HS_ReadyChange scrc;
scrc.ready = duel_mode->observers.size();
NetServer::SendPacketToPlayer(dp, STOC_HS_READY_CHANGE, scrc);
}
break;
}
case CTOS_EXIT_GAME:
......@@ -129,9 +192,11 @@ void NetServer::HandleCTOSPacket(DuelPlayer& dp, char* data, unsigned int len) {
break;
case CTOS_HS_KICK2:
break;
case CTOS_HS_START:
case CTOS_HS_START: {
evconnlistener_disable(listener);
break;
}
}
}
}
......@@ -2,41 +2,31 @@
#define NETSERVER_H
#include "config.h"
#include "network.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 "data_manager.h"
#include "deck_manager.h"
#include <array>
#include <set>
#include <unordered_map>
#define NETPLAYER_TYPE_PLAYER1 0
#define NETPLAYER_TYPE_PLAYER2 1
#define NETPLAYER_TYPE_PLAYER3 2
#define NETPLAYER_TYPE_PLAYER4 3
#define NETPLAYER_TYPE_PLAYER5 4
#define NETPLAYER_TYPE_PLAYER6 5
#define NETPLAYER_TYPE_OBSERVER 7
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;
......@@ -47,7 +37,7 @@ struct DuelPlayer {
class DuelMode {
public:
DuelMode() {
for(int i = 0; i < 6; ++i){
for(int i = 0; i < 6; ++i) {
players[i] = 0;
ready[i] = false;
}
......@@ -57,7 +47,7 @@ public:
void Start();
void Process();
void End();
public:
DuelPlayer* players[6];
bool ready[6];
......@@ -72,9 +62,11 @@ class NetServer {
private:
static std::unordered_map<bufferevent*, DuelPlayer> users;
static event_base* net_evbase;
static evconnlistener* listener;
static DuelMode* duel_mode;
static char net_buffer_read[0x2000];
static char net_buffer_write[0x2000];
static char net_server_read[0x2000];
static char net_server_write[0x2000];
static unsigned short last_sent;
public:
static bool StartServer(unsigned short port);
static void StopServer();
......@@ -83,9 +75,37 @@ public:
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);
static void HandleCTOSPacket(DuelPlayer* dp, char* data, unsigned int len);
template<typename ST>
static void SendPacketToPlayer(DuelPlayer* dp, unsigned char proto, ST& st) {
char* p = net_server_write;
BufferIO::WriteInt16(p, 1 + sizeof(ST));
BufferIO::WriteInt8(p, proto);
memcpy(p, &st, sizeof(ST));
last_sent = sizeof(ST) + 3;
evbuffer_add(dp->output, net_server_write, last_sent);
}
static void SendBufferToPlayer(DuelPlayer* dp, unsigned char proto, void* buffer, size_t len) {
char* p = net_server_write;
BufferIO::WriteInt16(p, 1 + len);
BufferIO::WriteInt8(p, proto);
memcpy(p, buffer, len);
last_sent = len + 3;
evbuffer_add(dp->output, net_server_write, last_sent);
}
static void ReSendToPlayer(DuelPlayer* dp) {
evbuffer_add(dp->output, net_server_write, last_sent);
}
};
}
#define NETPLAYER_TYPE_PLAYER1 0
#define NETPLAYER_TYPE_PLAYER2 1
#define NETPLAYER_TYPE_PLAYER3 2
#define NETPLAYER_TYPE_PLAYER4 3
#define NETPLAYER_TYPE_PLAYER5 4
#define NETPLAYER_TYPE_PLAYER6 5
#define NETPLAYER_TYPE_OBSERVER 7
#endif //NETSERVER_H
......@@ -4,135 +4,7 @@
namespace ygo {
const unsigned short PROTO_VERSION = 0x1020;
bool NetManager::CreateHost(int ipindex) {
wchar_t* pstr;
int wp;
sBHost = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sBHost == INVALID_SOCKET)
return false;
BOOL opt = TRUE;
setsockopt(sBHost, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(BOOL));
SOCKADDR_IN local;
if(ipindex == -1)
local.sin_addr.s_addr = htonl(INADDR_ANY);
else
local.sin_addr.s_addr = local_addr[ipindex];
local.sin_family = AF_INET;
local.sin_port = htons(7913);
if(::bind(sBHost, (sockaddr*)&local, sizeof(sockaddr)) == SOCKET_ERROR) {
closesocket(sBHost);
return false;
}
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sListen == INVALID_SOCKET) {
closesocket(sBHost);
return false;
}
local.sin_port = htons(serv_port);
if(::bind(sListen, (sockaddr*)&local, sizeof(sockaddr)) == SOCKET_ERROR) {
closesocket(sBHost);
closesocket(sListen);
return false;
}
is_creating_host = true;
Thread::NewThread(BroadcastServer, this);
Thread::NewThread(ListenThread, this);
return true;
}
bool NetManager::CancelHost() {
if(!is_creating_host)
return false;
closesocket(sBHost);
closesocket(sListen);
is_creating_host = false;
}
bool NetManager::RefreshHost(int ipindex) {
sBClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sBClient == INVALID_SOCKET)
return false;
BOOL opt = TRUE;
setsockopt(sBClient, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(BOOL));
SOCKADDR_IN local;
if(ipindex == -1)
local.sin_addr.s_addr = htonl(INADDR_ANY);
else
local.sin_addr.s_addr = local_addr[ipindex];
local.sin_family = AF_INET;
local.sin_port = htons(7912);
hReq.identifier = NETWORK_CLIENT_ID;
if(::bind(sBClient, (sockaddr*)&local, sizeof(sockaddr)) == SOCKET_ERROR) {
closesocket(sBClient);
return false;
}
Thread::NewThread(BroadcastClient, this);
return true;
}
bool NetManager::JoinHost() {
sRemote = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sRemote == INVALID_SOCKET) {
closesocket(sRemote);
return false;
}
char ip[20];
int i = 0;
wchar_t* pstr = (wchar_t *)mainGame->ebJoinIP->getText();
while(*pstr && i < 16) {
ip[i++] = *pstr;
*pstr++;
}
ip[i] = 0;
remote_addr = inet_addr(ip);
remote_port = _wtoi(mainGame->ebJoinPort->getText());
Thread::NewThread(JoinThread, (void*)this);
return true;
}
bool NetManager::SendtoRemote(char* buf, int len) {
int result = send(sRemote, buf, len, 0);
if( result == SOCKET_ERROR)
return false;
return true;
}
bool NetManager::WaitClientResponse() {
bool retry = false;
do {
int result = recv(sRemote, recv_buf, 2048, 0);
if(result == 0) {
if(!mainGame->is_closing) {
mainGame->gMutex.Lock();
mainGame->stACMessage->setText(L"与对方的连接中断");
mainGame->dInfo.netError = true;
mainGame->gMutex.Unlock();
}
return false;
}
if(result == SOCKET_ERROR) {
if(!mainGame->is_closing) {
mainGame->gMutex.Lock();
mainGame->stACMessage->setText(L"网络连接发生错误");
mainGame->dInfo.netError = true;
mainGame->gMutex.Unlock();
return false;
}
}
char* pbuf = recv_buf;
int type = NetManager::ReadInt8(pbuf);
mainGame->dInfo.is_responsed = false;
if(type == 1) {
mainGame->dInfo.responseI = NetManager::ReadInt32(pbuf);
mainGame->SetResponseI();
} else if(type == 2) {
int len = NetManager::ReadInt8(pbuf);
for(int i = 0; i < len; ++i)
mainGame->dInfo.responseB[i] = NetManager::ReadInt8(pbuf);
mainGame->SetResponseB(len);
} else {
mainGame->SendByte(mainGame->dInfo.resPlayer, 1);
retry = true;
}
} while(retry);
return true;
}
/*
int NetManager::GetLocalAddress() {
char hname[256];
gethostname(hname, 256);
......@@ -201,165 +73,5 @@ int NetManager::BroadcastClient(void* np) {
closesocket(net->sBClient);
return 0;
}
int NetManager::ListenThread(void* np) {
NetManager* net = (NetManager*)np;
if(listen(net->sListen, SOMAXCONN) == SOCKET_ERROR) {
closesocket(net->sListen);
return 0;
}
int recvlen, index;
char* pbuf, *psbuf;
net->sRemote = accept(net->sListen, 0, 0);
while(net->sRemote != SOCKET_ERROR) {
recvlen = recv(net->sRemote, net->recv_buf, 4096, 0);
if(recvlen == SOCKET_ERROR) {
closesocket(net->sRemote);
net->sRemote = accept(net->sListen, 0, 0);
continue;
}
//check deck
pbuf = net->recv_buf;
int ver = ReadInt16(pbuf);
if(ver != PROTO_VERSION) {
psbuf = net->send_buf;
WriteInt8(psbuf, 0x1);
WriteInt16(psbuf, PROTO_VERSION);
send(net->sRemote, net->send_buf, 3, 0);
closesocket(net->sRemote);
net->sRemote = accept(net->sListen, 0, 0);
continue;
}
int mode = ReadInt16(pbuf);
if(mode == 1 && (net->hInfo.no_check_deck || net->hInfo.no_shuffle_deck || net->hInfo.start_lp != 8000 || net->hInfo.start_hand != 5 || net->hInfo.draw_count != 1 )) {
psbuf = net->send_buf;
WriteInt8(psbuf, 0x4);
send(net->sRemote, net->send_buf, 1, 0);
closesocket(net->sRemote);
net->sRemote = accept(net->sListen, 0, 0);
continue;
}
wchar_t cn = ReadInt16(pbuf);
int off = 0;
while(cn != 0 && off < 19) {
mainGame->dInfo.pass[off++] = cn;
cn = ReadInt16(pbuf);
}
mainGame->dInfo.pass[off] = 0;
if(wcscmp(mainGame->dInfo.pass, mainGame->ebServerPass->getText())) {
psbuf = net->send_buf;
WriteInt8(psbuf, 0x3);
send(net->sRemote, net->send_buf, 1, 0);
closesocket(net->sRemote);
net->sRemote = accept(net->sListen, 0, 0);
continue;
}
cn = ReadInt16(pbuf);
off = 0;
while(cn != 0 && off < 19) {
mainGame->dInfo.clientname[off++] = cn;
cn = ReadInt16(pbuf);
}
mainGame->dInfo.clientname[off] = 0;
int maincount = ReadInt16(pbuf);
int sidecount = ReadInt16(pbuf);
mainGame->deckManager.LoadDeck(mainGame->deckManager.deckclient, (int*)pbuf, maincount, sidecount);
psbuf = net->send_buf;
WriteInt8(psbuf, 0);
int li = 0;
// while(ln[li] && li < 19) {
// mainGame->dInfo.hostname[li] = ln[li];
// WriteInt16(psbuf, ln[li++]);
// }
mainGame->dInfo.hostname[li] = 0;
WriteInt16(psbuf, 0);
send(net->sRemote, net->send_buf, 3 + li * 2, 0);
mainGame->gMutex.Lock();
mainGame->imgCard->setImage(mainGame->imageManager.tCover);
mainGame->wCardImg->setVisible(true);
mainGame->wInfos->setVisible(true);
mainGame->stName->setText(L"");
mainGame->stInfo->setText(L"");
mainGame->stDataInfo->setText(L"");
mainGame->stText->setText(L"");
mainGame->dInfo.engLen = 0;
mainGame->dInfo.msgLen = 0;
mainGame->dField.Clear();
mainGame->gMutex.Unlock();
mainGame->WaitFrameSignal(10);
closesocket(net->sBHost);
net->is_creating_host = false;
Thread::NewThread(Game::EngineThread, &mainGame->dInfo);
Thread::NewThread(Game::GameThread, &mainGame->dInfo);
break;
}
return 0;
}
int NetManager::JoinThread(void* adr) {
SOCKADDR_IN server;
NetManager* pnet = (NetManager*)adr;
server.sin_addr.s_addr = pnet->remote_addr;
server.sin_family = AF_INET;
server.sin_port = htons(pnet->remote_port);
if(connect(pnet->sRemote, (sockaddr*)&server, sizeof(sockaddr)) == SOCKET_ERROR) {
closesocket(pnet->sRemote);
if(!mainGame->is_closing) {
// mainGame->stModeStatus->setText(L"无法连接至主机");
}
return 0;
}
char* pbuf = pnet->send_buf;
NetManager::WriteInt16(pbuf, PROTO_VERSION);
NetManager::WriteInt16(pbuf, 1);
const wchar_t* pname = mainGame->ebJoinPass->getText();
int i = 0;
while(pname[i] != 0 && i < 19)
NetManager::WriteInt16(pbuf, pname[i++]);
NetManager::WriteInt16(pbuf, 0);
i = 0;
// pname = mainGame->ebUsername->getText();
while(pname[i] != 0 && i < 19) {
mainGame->dInfo.hostname[i] = pname[i];
NetManager::WriteInt16(pbuf, pname[i++]);
}
NetManager::WriteInt16(pbuf, 0);
mainGame->dInfo.hostname[i] = 0;
NetManager::WriteInt16(pbuf, mainGame->deckManager.deckhost.main.size() + mainGame->deckManager.deckhost.extra.size());
NetManager::WriteInt16(pbuf, mainGame->deckManager.deckhost.side.size());
for(int i = 0; i < mainGame->deckManager.deckhost.main.size(); ++i)
NetManager::WriteInt32(pbuf, mainGame->deckManager.deckhost.main[i]->first);
for(int i = 0; i < mainGame->deckManager.deckhost.extra.size(); ++i)
NetManager::WriteInt32(pbuf, mainGame->deckManager.deckhost.extra[i]->first);
for(int i = 0; i < mainGame->deckManager.deckhost.side.size(); ++i)
NetManager::WriteInt32(pbuf, mainGame->deckManager.deckhost.side[i]->first);
pnet->SendtoRemote(pnet->send_buf, pbuf - pnet->send_buf);
int result = recv(pnet->sRemote, pnet->recv_buf, 4096, 0);
if(result == SOCKET_ERROR || pnet->recv_buf[0] != 0) {
closesocket(pnet->sRemote);
}
wchar_t* pn = (wchar_t*)&pnet->recv_buf[1];
int pi = 0;
while(pn[pi] && pi < 19) {
mainGame->dInfo.clientname[pi] = pn[pi];
pi++;
}
mainGame->dInfo.clientname[pi] = 0;
mainGame->gMutex.Lock();
mainGame->imgCard->setImage(mainGame->imageManager.tCover);
mainGame->wCardImg->setVisible(true);
mainGame->wInfos->setVisible(true);
mainGame->stName->setText(L"");
mainGame->stInfo->setText(L"");
mainGame->stDataInfo->setText(L"");
mainGame->stText->setText(L"");
// mainGame->stModeStatus->setText(L"");
mainGame->dInfo.engLen = 0;
mainGame->dInfo.msgLen = 0;
mainGame->dInfo.is_local_host = false;
mainGame->dField.Clear();
mainGame->gMutex.Unlock();
mainGame->WaitFrameSignal(10);
Thread::NewThread(Game::RecvThread, &mainGame->dInfo);
Thread::NewThread(Game::GameThread, &mainGame->dInfo);
}
*/
}
......@@ -2,7 +2,6 @@
#define NETWORK_H
#include "config.h"
#include <event2/event.h>
#include <set>
#include <vector>
......@@ -51,7 +50,7 @@ struct STOC_CreateGame {
};
struct STOC_JoinGame {
HostInfo info;
bool is_host;
unsigned char type;
};
struct STOC_ExitGame {
};
......@@ -68,72 +67,6 @@ struct STOC_HS_WatchChange {
unsigned short watch_count;
};
class NetManager {
public:
unsigned int local_addr[8];
unsigned short serv_port;
unsigned int remote_addr;
unsigned short remote_port;
bool is_creating_host;
SOCKET sBHost;
SOCKET sBClient;
SOCKET sListen;
SOCKET sRemote;
HostInfo hInfo;
HostRequest hReq;
std::vector<HostInfo> hosts;
char* send_buffer_ptr;
char send_buf[4096];
char recv_buf[4096];
bool CreateHost(int ipindex);
bool CancelHost();
bool RefreshHost(int ipindex);
bool JoinHost();
bool SendtoRemote(char* buf, int len);
bool WaitClientResponse();
inline static int ReadInt32(char*& p) {
int ret = *(int*)p;
p += 4;
return ret;
}
inline static short ReadInt16(char*& p) {
short ret = *(short*)p;
p += 2;
return ret;
}
inline static char ReadInt8(char*& p) {
char ret = *(char*)p;
p++;
return ret;
}
inline static unsigned char ReadUInt8(char*& p) {
unsigned char ret = *(unsigned char*)p;
p++;
return ret;
}
inline static void WriteInt32(char*& p, int val) {
(*(int*)p) = val;
p += 4;
}
inline static void WriteInt16(char*& p, short val) {
(*(short*)p) = val;
p += 2;
}
inline static void WriteInt8(char*& p, char val) {
*p = val;
p++;
}
int GetLocalAddress();
static int BroadcastServer(void*);
static int BroadcastClient(void*);
static int ListenThread(void*);
static int JoinThread(void*);
};
extern const unsigned short PROTO_VERSION;
}
......@@ -162,6 +95,11 @@ extern const unsigned short PROTO_VERSION;
#define STOC_HS_READY_CHANGE 0x22
#define STOC_HS_WATCH_CHANGE 0x23
#define PLAYERCHANGE_READY 0x1
#define PLAYERCHANGE_NOTREADY 0x2
#define PLAYERCHANGE_LEAVE 0x3
#define PLAYERCHANGE_OBSERVE 0x4
#define MODE_SINGLE 0x1
#define MODE_MATCH 0x2
#endif //NETWORK_H
#include "game.h"
#include "replay.h"
#include "../ocgcore/ocgapi.h"
#include "../ocgcore/card.h"
......@@ -146,19 +145,17 @@ bool Replay::CheckReplay(const wchar_t* name) {
fclose(fp);
return pheader.id == 0x31707279 && pheader.version >= 0x1008;
}
bool Replay::ReadNextResponse() {
bool Replay::ReadNextResponse(unsigned char resp[64]) {
char resType = *pdata++;
if(pdata - replay_data >= replay_size)
return false;
if(resType == 1) {
mainGame->dInfo.responseI = *((int*)pdata);
*((int*)resp) = *((int*)pdata);
pdata += 4;
set_responsei(mainGame->dInfo.pDuel, mainGame->dInfo.responseI);
} else if(resType = 2) {
int len = *pdata++;
for(int i = 0; i < len; ++i)
mainGame->dInfo.responseB[i] = *pdata++;
set_responseb(mainGame->dInfo.pDuel, (byte*)mainGame->dInfo.responseB);
resp[i] = *pdata++;
} else
return false;
return true;
......
......@@ -33,7 +33,7 @@ public:
void SaveReplay(const wchar_t* name);
bool OpenReplay(const wchar_t* name);
bool CheckReplay(const wchar_t* name);
bool ReadNextResponse();
bool ReadNextResponse(unsigned char resp[64]);
void ReadHeader(ReplayHeader& header);
void ReadData(void* data, unsigned int length);
int ReadInt32();
......
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