Commit 3516ba98 authored by edo9300's avatar edo9300

Merge remote-tracking branch 'refs/remotes/origin/new-replay-system'

parents 80ffa24b 38ff205e
......@@ -53,7 +53,8 @@ ClientCard::ClientCard() {
void ClientCard::SetCode(int code) {
if((location == LOCATION_HAND) && (this->code != (unsigned int)code)) {
this->code = code;
mainGame->dField.MoveCard(this, 5);
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->dField.MoveCard(this, 5);
} else
this->code = code;
}
......@@ -66,7 +67,8 @@ void ClientCard::UpdateInfo(char* buf) {
pdata = BufferIO::ReadInt32(buf);
if((location == LOCATION_HAND) && ((unsigned int)pdata != code)) {
code = pdata;
mainGame->dField.MoveCard(this, 5);
if(!mainGame->dInfo.isReplay || !mainGame->dInfo.isReplaySkiping)
mainGame->dField.MoveCard(this, 5);
} else
code = pdata;
}
......
This diff is collapsed.
......@@ -13,6 +13,7 @@
#include "data_manager.h"
#include "deck_manager.h"
#include "../ocgcore/mtrandom.h"
#include "replay.h"
namespace ygo {
......@@ -45,6 +46,9 @@ public:
static void ClientEvent(bufferevent *bev, short events, void *ctx);
static int ClientThread(void* param);
static void HandleSTOCPacketLan(char* data, unsigned int len);
static std::vector<ReplayPacket> replay_stream;
static Replay last_replay;
static bool old_replay;
static int ClientAnalyze(char* msg, unsigned int len);
static void SetResponseI(int respI);
static void SetResponseB(void* respB, unsigned char len);
......
......@@ -95,13 +95,13 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
case BUTTON_REPLAY_SAVE: {
if(mainGame->ebRSName->getText()[0] == 0)
break;
mainGame->actionParam = 1;
mainGame->saveReplay = 1;
mainGame->HideElement(mainGame->wReplaySave);
mainGame->replaySignal.Set();
break;
}
case BUTTON_REPLAY_CANCEL: {
mainGame->actionParam = 0;
mainGame->saveReplay = 0;
mainGame->HideElement(mainGame->wReplaySave);
mainGame->replaySignal.Set();
break;
......
......@@ -617,6 +617,7 @@ bool Game::Initialize() {
btnReplayCancel = env->addButton(rect<s32>(460, 385, 570, 410), wReplay, BUTTON_CANCEL_REPLAY, dataManager.GetSysString(1347));
env->addStaticText(dataManager.GetSysString(1349), rect<s32>(360, 30, 570, 50), false, true, wReplay);
stReplayInfo = env->addStaticText(L"", rect<s32>(360, 60, 570, 350), false, true, wReplay);
chkYrp = env->addCheckBox(false, recti(360, 250, 560, 270), wReplay, -1, dataManager.GetSysString(1999));
env->addStaticText(dataManager.GetSysString(1353), rect<s32>(360, 275, 570, 295), false, true, wReplay);
ebRepStartTurn = env->addEditBox(L"", rect<s32>(360, 300, 460, 320), true, wReplay, -1);
ebRepStartTurn->setTextAlignment(irr::gui::EGUIA_CENTER, irr::gui::EGUIA_CENTER);
......@@ -1228,7 +1229,7 @@ bool Game::PlayChant(unsigned int code) {
return false;
}
void Game::PlaySoundEffect(char* sound) {
if(chkEnableSound->isChecked()) {
if(chkEnableSound->isChecked() && (!dInfo.isReplay || !dInfo.isReplaySkiping)) {
engineSound->play2D(sound);
engineSound->setSoundVolume(gameConf.volume);
}
......@@ -1563,8 +1564,46 @@ int Game::GetMasterRule(uint32 param, uint32 forbiddentypes, int* truerule) {
}
}
}
void Game::OnResize()
{
void Game::SetPhaseButtons() {
// reset master rule 4 phase button position
wPhase->setRelativePosition(Resize(480, 310, 855, 330));
if (dInfo.extraval & 0x1) {
if (dInfo.duel_field >= 4) {
wPhase->setRelativePosition(Resize(480, 290, 855, 350));
btnShuffle->setRelativePosition(Resize(0, 40, 50, 60));
btnDP->setRelativePosition(Resize(0, 40, 50, 60));
btnSP->setRelativePosition(Resize(0, 40, 50, 60));
btnM1->setRelativePosition(Resize(160, 20, 210, 40));
btnBP->setRelativePosition(Resize(160, 20, 210, 40));
btnM2->setRelativePosition(Resize(160, 20, 210, 40));
btnEP->setRelativePosition(Resize(310, 0, 360, 20));
} else {
btnShuffle->setRelativePosition(Resize(65, 0, 115, 20));
btnDP->setRelativePosition(Resize(65, 0, 115, 20));
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
btnEP->setRelativePosition(Resize(260, 0, 310, 20));
}
} else {
btnDP->setRelativePosition(Resize(0, 0, 50, 20));
if (dInfo.duel_field >= 4) {
btnSP->setRelativePosition(Resize(0, 0, 50, 20));
btnM1->setRelativePosition(Resize(160, 0, 210, 20));
btnBP->setRelativePosition(Resize(160, 0, 210, 20));
btnM2->setRelativePosition(Resize(160, 0, 210, 20));
} else {
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
}
btnEP->setRelativePosition(Resize(320, 0, 370, 20));
btnShuffle->setRelativePosition(Resize(0, 0, 50, 20));
}
}
void Game::OnResize() {
wMainMenu->setRelativePosition(ResizeWin(370, 200, 650, 415));
wDeckEdit->setRelativePosition(Resize(309, 8, 605, 130));
cbDBLFList->setRelativePosition(Resize(80, 5, 220, 30));
......@@ -1662,42 +1701,7 @@ void Game::OnResize()
btnReplaySwap->setRelativePosition(Resize(5, 30, 85, 50));
btnReplayExit->setRelativePosition(Resize(5, 105, 85, 125));
wPhase->setRelativePosition(Resize(480, 310, 855, 330));
if(dInfo.extraval & 0x1) {
if(dInfo.duel_field >= 4) {
wPhase->setRelativePosition(Resize(480, 290, 855, 350));
btnShuffle->setRelativePosition(Resize(0, 40, 50, 60));
btnDP->setRelativePosition(Resize(0, 40, 50, 60));
btnSP->setRelativePosition(Resize(0, 40, 50, 60));
btnM1->setRelativePosition(Resize(160, 20, 210, 40));
btnBP->setRelativePosition(Resize(160, 20, 210, 40));
btnM2->setRelativePosition(Resize(160, 20, 210, 40));
btnEP->setRelativePosition(Resize(310, 0, 360, 20));
} else {
btnShuffle->setRelativePosition(Resize(65, 0, 115, 20));
btnDP->setRelativePosition(Resize(65, 0, 115, 20));
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
btnEP->setRelativePosition(Resize(260, 0, 310, 20));
}
} else {
btnDP->setRelativePosition(Resize(0, 0, 50, 20));
if(dInfo.duel_field >= 4) {
btnSP->setRelativePosition(Resize(0, 0, 50, 20));
btnM1->setRelativePosition(Resize(160, 0, 210, 20));
btnBP->setRelativePosition(Resize(160, 0, 210, 20));
btnM2->setRelativePosition(Resize(160, 0, 210, 20));
} else {
btnSP->setRelativePosition(Resize(65, 0, 115, 20));
btnM1->setRelativePosition(Resize(130, 0, 180, 20));
btnBP->setRelativePosition(Resize(195, 0, 245, 20));
btnM2->setRelativePosition(Resize(260, 0, 310, 20));
}
btnEP->setRelativePosition(Resize(320, 0, 370, 20));
btnShuffle->setRelativePosition(Resize(0, 0, 50, 20));
}
SetPhaseButtons();
btnSpectatorSwap->setRelativePosition(Resize(205, 100, 295, 135));
btnChainAlways->setRelativePosition(Resize(205, 140, 295, 175));
btnChainIgnore->setRelativePosition(Resize(205, 100, 295, 135));
......
......@@ -48,6 +48,7 @@ struct Config {
struct DuelInfo {
bool isStarted;
bool isReplay;
bool isOldReplay;
bool isReplaySkiping;
bool isFirst;
bool isTag;
......@@ -134,6 +135,7 @@ public:
const wchar_t* LocalName(int local_player);
void UpdateDuelParam();
int GetMasterRule(uint32 param, uint32 forbidden, int* truerule = 0);
void SetPhaseButtons();
bool HasFocus(EGUI_ELEMENT_TYPE type) const {
irr::gui::IGUIElement* focus = env->getFocus();
......@@ -170,7 +172,7 @@ public:
unsigned short linePattern;
int waitFrame;
int signalFrame;
int actionParam;
int saveReplay;
const wchar_t* showingtext;
int showcard;
int showcardcode;
......@@ -309,6 +311,7 @@ public:
irr::gui::IGUIWindow* wReplay;
irr::gui::IGUIListBox* lstReplayList;
irr::gui::IGUIStaticText* stReplayInfo;
irr::gui::IGUICheckBox* chkYrp;
irr::gui::IGUIButton* btnLoadReplay;
irr::gui::IGUIButton* btnReplayCancel;
irr::gui::IGUIEditBox* ebRepStartTurn;
......
......@@ -274,6 +274,8 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
if(!ReplayMode::cur_replay.OpenReplay(mainGame->lstReplayList->getListItem(mainGame->lstReplayList->getSelected())))
break;
}
if(mainGame->chkYrp->isChecked() && !ReplayMode::cur_replay.LoadYrp())
break;
mainGame->imgCard->setImage(imageManager.tCover[0]);
mainGame->wCardImg->setVisible(true);
mainGame->wInfos->setVisible(true);
......@@ -393,6 +395,11 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
repinfo.append(infobuf);
mainGame->ebRepStartTurn->setText(L"1");
mainGame->SetStaticText(mainGame->stReplayInfo, 180, mainGame->guiFont, (wchar_t*)repinfo.c_str());
if(ReplayMode::cur_replay.pheader.id == 0x31707279) {
mainGame->chkYrp->setChecked(false);
mainGame->chkYrp->setEnabled(false);
} else
mainGame->chkYrp->setEnabled(true);
break;
}
}
......
......@@ -215,6 +215,9 @@ public:
#define STOC_HS_PLAYER_CHANGE 0x21
#define STOC_HS_WATCH_CHANGE 0x22
#define STOC_NEW_REPLAY 0x30
#define PLAYERCHANGE_OBSERVE 0x8
#define PLAYERCHANGE_READY 0x9
#define PLAYERCHANGE_NOTREADY 0xa
......
This diff is collapsed.
#include "replay.h"
#include "../ocgcore/ocgapi.h"
#include "../ocgcore/card.h"
#include "../ocgcore/field.h"
#include <algorithm>
#include "lzma/LzmaLib.h"
namespace ygo {
ReplayPacket::ReplayPacket(char * buf, int len) {
message = BufferIO::ReadInt8(buf);
length = len;
memcpy(data, buf, length);
}
ReplayPacket::ReplayPacket(int msg, char * buf, int len) {
message = msg;
length = len;
memcpy(data, buf, length);
}
void ReplayPacket::Set(int msg, char * buf, int len) {
message = msg;
length = len;
memcpy(data, buf, length);
}
Replay::Replay() {
is_recording = false;
is_replaying = false;
......@@ -16,25 +33,42 @@ Replay::~Replay() {
delete[] replay_data;
delete[] comp_data;
}
void Replay::BeginRecord() {
void Replay::BeginRecord(bool write) {
#ifdef _WIN32
if(is_recording)
if(is_recording && is_writing)
CloseHandle(recording_fp);
recording_fp = CreateFileW(L"./replay/_LastReplay.yrp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
if(recording_fp == INVALID_HANDLE_VALUE)
return;
is_writing = write;
if(is_writing) {
recording_fp = CreateFileW(L"./replay/_LastReplay.yrpX", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
if(recording_fp == INVALID_HANDLE_VALUE)
return;
}
#else
if(is_recording)
if(is_recording && is_writing)
fclose(fp);
fp = fopen("./replay/_LastReplay.yrp", "wb");
if(!fp)
return;
is_writing = write;
if(is_writing) {
fp = fopen("./replay/_LastReplay.yrpX", "wb");
if(!fp)
return;
}
#endif
pdata = replay_data;
is_recording = true;
}
void Replay::WritePacket(ReplayPacket p) {
WriteInt8(p.message, false);
WriteInt32(p.length, false);
WriteData((char*)p.data, p.length);
}
void Replay::WriteStream(std::vector<ReplayPacket> stream) {
if(stream.size())
for(auto it = stream.begin(); it != stream.end(); it++)
WritePacket((*it));
}
void Replay::WriteHeader(ReplayHeader& header) {
pheader = header;
if(!is_writing) return;
#ifdef _WIN32
DWORD size;
WriteFile(recording_fp, &header, sizeof(header), &size, NULL);
......@@ -48,6 +82,7 @@ void Replay::WriteData(const void* data, unsigned int length, bool flush) {
return;
memcpy(pdata, data, length);
pdata += length;
if(!is_writing) return;
#ifdef _WIN32
DWORD size;
WriteFile(recording_fp, data, length, &size, NULL);
......@@ -62,6 +97,7 @@ void Replay::WriteInt32(int data, bool flush) {
return;
*((int*)(pdata)) = data;
pdata += 4;
if(!is_writing) return;
#ifdef _WIN32
DWORD size;
WriteFile(recording_fp, &data, sizeof(int), &size, NULL);
......@@ -76,6 +112,7 @@ void Replay::WriteInt16(short data, bool flush) {
return;
*((short*)(pdata)) = data;
pdata += 2;
if(!is_writing) return;
#ifdef _WIN32
DWORD size;
WriteFile(recording_fp, &data, sizeof(short), &size, NULL);
......@@ -90,6 +127,7 @@ void Replay::WriteInt8(char data, bool flush) {
return;
*pdata = data;
pdata++;
if(!is_writing) return;
#ifdef _WIN32
DWORD size;
WriteFile(recording_fp, &data, sizeof(char), &size, NULL);
......@@ -102,14 +140,16 @@ void Replay::WriteInt8(char data, bool flush) {
void Replay::Flush() {
if(!is_recording)
return;
if(!is_writing) return;
#ifdef _WIN32
#else
fflush(fp);
#endif
}
void Replay::EndRecord() {
void Replay::EndRecord(size_t size) {
if(!is_recording)
return;
if(is_writing)
#ifdef _WIN32
CloseHandle(recording_fp);
#else
......@@ -118,13 +158,13 @@ void Replay::EndRecord() {
pheader.datasize = pdata - replay_data;
pheader.flag |= REPLAY_COMPRESSED;
size_t propsize = 5;
comp_size = 0x1000;
comp_size = size;
LzmaCompress(comp_data, &comp_size, replay_data, pdata - replay_data, pheader.props, &propsize, 5, 1 << 24, 3, 0, 2, 32, 1);
is_recording = false;
}
void Replay::SaveReplay(const wchar_t* name) {
wchar_t fname[256];
myswprintf(fname, L"./replay/%ls.yrp", name);
myswprintf(fname, L"./replay/%ls.yrpX", name);
#ifdef WIN32
fp = _wfopen(fname, L"wb");
#else
......@@ -161,7 +201,7 @@ bool Replay::OpenReplay(const wchar_t* name) {
return false;
fread(&pheader, sizeof(pheader), 1, fp);
if(pheader.flag & REPLAY_COMPRESSED) {
comp_size = fread(comp_data, 1, 0x1000, fp);
comp_size = fread(comp_data, 1, 0x20000, fp);
fclose(fp);
replay_size = pheader.datasize;
if(LzmaUncompress(replay_data, &replay_size, comp_data, &comp_size, pheader.props, 5) != SZ_OK)
......@@ -190,7 +230,23 @@ bool Replay::CheckReplay(const wchar_t* name) {
ReplayHeader rheader;
fread(&rheader, sizeof(ReplayHeader), 1, rfp);
fclose(rfp);
return rheader.id == 0x31707279 && rheader.version >= 0x12d0;
return (rheader.id == 0x31707279 || rheader.id == 0x58707279) && rheader.version >= 0x12d0;
}
bool Replay::ReadNextPacket(ReplayPacket* packet) {
if (pdata - replay_data >= (int)replay_size)
return false;
packet->message = *pdata++;
packet->length = ReadInt32();
ReadData((char*)&packet->data, packet->length);
return true;
}
bool Replay::ReadStream(std::vector<ReplayPacket>* stream) {
stream->clear();
ReplayPacket p;
while (ReadNextPacket(&p)) {
stream->push_back(p);
}
return !!stream->size();
}
bool Replay::ReadNextResponse(unsigned char resp[64]) {
if(pdata - replay_data >= (int)replay_size)
......@@ -238,4 +294,31 @@ void Replay::Rewind() {
pdata = replay_data;
}
bool Replay::LoadYrp() {
if (pheader.flag & REPLAY_NEWREPLAY) {
pdata += (4 + ((pheader.flag & REPLAY_TAG) ? 160 : 80));
ReplayPacket p;
while (ReadNextPacket(&p))
if (p.message == OLD_REPLAY_MODE) {
char* prep = (char*)p.data;
memcpy(&pheader, prep, sizeof(ReplayHeader));
prep += sizeof(ReplayHeader);
if(pheader.flag & REPLAY_COMPRESSED) {
comp_size = (size_t)(p.length - sizeof(ReplayHeader));
replay_size = pheader.datasize;
if (LzmaUncompress(replay_data, &replay_size, (unsigned char*)prep, &comp_size, pheader.props, 5) != SZ_OK)
return false;
} else {
comp_size = fread(replay_data, 1, 0x20000, fp);
fclose(fp);
replay_size = comp_size;
}
pdata = replay_data;
is_replaying = true;
return true;
}
}
return !(pheader.flag & REPLAY_NEWREPLAY);
}
}
......@@ -11,6 +11,7 @@ namespace ygo {
#define REPLAY_DECODED 0x4
#define REPLAY_SINGLE_MODE 0x8
#define REPLAY_LUA64 0x10
#define REPLAY_NEWREPLAY 0x20
struct ReplayHeader {
unsigned int id;
......@@ -22,29 +23,44 @@ struct ReplayHeader {
unsigned char props[8];
};
class ReplayPacket {
public:
int message;
int length;
unsigned char data[0x2000];
ReplayPacket() {}
ReplayPacket(char * buf, int len);
ReplayPacket(int msg, char * buf, int len);
void Set(int msg, char * buf, int len);
};
class Replay {
public:
Replay();
~Replay();
void BeginRecord();
void BeginRecord(bool write = true);
void WriteStream(std::vector<ReplayPacket> stream);
void WritePacket(ReplayPacket p);
void WriteHeader(ReplayHeader& header);
void WriteData(const void* data, unsigned int length, bool flush = true);
void WriteInt32(int data, bool flush = true);
void WriteInt16(short data, bool flush = true);
void WriteInt8(char data, bool flush = true);
void Flush();
void EndRecord();
void EndRecord(size_t size = 0x20000);
void SaveReplay(const wchar_t* name);
bool OpenReplay(const wchar_t* name);
static bool CheckReplay(const wchar_t* name);
bool ReadNextPacket(ReplayPacket* packet);
bool ReadStream(std::vector<ReplayPacket>* stream);
bool ReadNextResponse(unsigned char resp[64]);
void ReadName(wchar_t* data);
void ReadHeader(ReplayHeader& header);
void ReadData(void* data, unsigned int length);
int ReadInt32();
short ReadInt16();
char ReadInt8();
void Rewind();
bool LoadYrp();
FILE* fp;
ReplayHeader pheader;
......@@ -57,6 +73,7 @@ public:
size_t replay_size;
size_t comp_size;
bool is_recording;
bool is_writing;
bool is_replaying;
};
......
This diff is collapsed.
......@@ -12,12 +12,14 @@ namespace ygo {
class ReplayMode {
private:
static long pduel;
static bool yrp;
static bool is_continuing;
static bool is_closing;
static bool is_pausing;
static bool is_paused;
static bool is_swaping;
static bool is_swapping;
static bool is_restarting;
static bool undo;
static bool exit_pending;
static int skip_turn;
static int current_step;
......@@ -25,6 +27,7 @@ private:
public:
static Replay cur_replay;
static std::vector<ReplayPacket> ReplayMode::current_stream;
public:
static bool StartReplay(int skipturn);
......@@ -33,12 +36,14 @@ public:
static void Pause(bool is_pause, bool is_step);
static bool ReadReplayResponse();
static int ReplayThread(void* param);
static int OldReplayThread(void* param);
static bool StartDuel();
static void EndDuel();
static void Restart(bool refresh);
static void Undo();
static bool ReplayAnalyze(ReplayPacket p);
static bool ReplayAnalyze(char* msg, unsigned int len);
static void ReplayRefresh(int flag = 0xf81fff);
static void ReplayRefreshHand(int player, int flag = 0x781fff);
static void ReplayRefreshGrave(int player, int flag = 0x181fff);
......
This diff is collapsed.
......@@ -40,6 +40,9 @@ public:
static int MessageHandler(long fduel, int type);
static void SingleTimer(evutil_socket_t fd, short events, void* arg);
void PseudoRefreshDeck(int player, int flag = 0x181fff);
static std::vector<ReplayPacket> replay_stream;
protected:
DuelPlayer* players[2];
......@@ -51,6 +54,7 @@ protected:
unsigned char last_response;
std::set<DuelPlayer*> observers;
Replay last_replay;
Replay new_replay;
bool match_mode;
int match_kill;
bool game_started;
......
This diff is collapsed.
......@@ -18,11 +18,8 @@ public:
static int SinglePlayThread(void* param);
static bool SinglePlayAnalyze(char* msg, unsigned int len);
static void SinglePlayRefresh(int player, int location, int flag = 0xf81fff);
static void SinglePlayRefresh(int flag = 0xf81fff);
static void SinglePlayRefreshHand(int player, int flag = 0x781fff);
static void SinglePlayRefreshGrave(int player, int flag = 0x181fff);
static void SinglePlayRefreshDeck(int player, int flag = 0x181fff);
static void SinglePlayRefreshExtra(int player, int flag = 0x181fff);
static void SinglePlayRefreshSingle(int player, int location, int sequence, int flag = 0xf81fff);
static void SinglePlayReload();
......@@ -31,6 +28,8 @@ public:
protected:
static Replay last_replay;
static Replay new_replay;
static std::vector<ReplayPacket> replay_stream;
};
}
......
......@@ -9,6 +9,8 @@
namespace ygo {
std::vector<ReplayPacket> TagDuel::replay_stream;
TagDuel::TagDuel() {
game_started = false;
for(int i = 0; i < 4; ++i) {
......@@ -355,13 +357,23 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
rh.flag = REPLAY_TAG + REPLAY_LUA64;
time_t seed = time(0);
rh.seed = seed;
last_replay.BeginRecord();
last_replay.BeginRecord(false);
last_replay.WriteHeader(rh);
rnd.reset(seed);
last_replay.WriteData(players[0]->name, 40, false);
last_replay.WriteData(players[1]->name, 40, false);
last_replay.WriteData(players[2]->name, 40, false);
last_replay.WriteData(players[3]->name, 40, false);
//records the replay with the new system
new_replay.BeginRecord();
rh.id = 0x58707279;
rh.flag |= REPLAY_NEWREPLAY;
new_replay.WriteHeader(rh);
new_replay.WriteData(players[0]->name, 40, false);
new_replay.WriteData(players[1]->name, 40, false);
new_replay.WriteData(players[2]->name, 40, false);
new_replay.WriteData(players[3]->name, 40);
replay_stream.clear();
if(!host_info.no_shuffle_deck) {
for(size_t i = pdeck[0].main.size() - 1; i > 0; --i) {
int swap = rnd.real() * (i + 1);
......@@ -395,6 +407,7 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
if(host_info.speed)
opt |= SPEED_DUEL;
opt |= DUEL_TAG_MODE;
new_replay.WriteInt32((mainGame->GetMasterRule(opt, 0)) | (opt & SPEED_DUEL) << 8);
last_replay.WriteInt32(host_info.start_lp, false);
last_replay.WriteInt32(host_info.start_hand, false);
last_replay.WriteInt32(host_info.draw_count, false);
......@@ -519,8 +532,14 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
else startbuf[1] = 0x11;
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 18);
startbuf[1] = 0;
ReplayPacket p((char*)startbuf, 17);
replay_stream.push_back(p);
PseudoRefreshDeck(0);
PseudoRefreshDeck(1);
RefreshExtra(0);
RefreshExtra(1);
new_replay.WriteStream(replay_stream);
start_duel(pduel, opt);
Process();
}
......@@ -558,12 +577,19 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
char* offset, *pbufw, *pbuf = msgbuffer;
int player, count, type;
while (pbuf - msgbuffer < (int)len) {
replay_stream.clear();
bool record = true;
ReplayPacket p;
offset = pbuf;
unsigned char engType = BufferIO::ReadUInt8(pbuf);
p.message = engType;
p.length = len - 1;
memcpy(p.data, pbuf, p.length);
switch (engType) {
case MSG_RETRY: {
WaitforResponse(last_response);
NetServer::SendBufferToPlayer(cur_player[last_response], STOC_GAME_MSG, offset, pbuf - offset);
replay_stream.push_back(p);
return 1;
}
case MSG_HINT: {
......@@ -577,6 +603,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
case 5:
case 10: {
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
record = false;
break;
}
case 4:
......@@ -603,6 +630,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
replay_stream.push_back(p);
EndDuel();
return 2;
}
......@@ -817,6 +845,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(player);
break;
}
case MSG_SHUFFLE_HAND: {
......@@ -875,6 +904,8 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(0);
PseudoRefreshDeck(1);
break;
}
case MSG_DECK_TOP: {
......@@ -1499,6 +1530,7 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[p], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
PseudoRefreshDeck(player);
RefreshExtra(player);
RefreshMzone(0, 0x81fff, 0);
RefreshMzone(1, 0x81fff, 0);
......@@ -1513,6 +1545,12 @@ int TagDuel::Analyze(char* msgbuffer, unsigned int len) {
break;
}
}
//setting the length again in case of multiple messages in a row,
//when the packet will be written in the replay, the extra data registered previously will be discarded
p.length = (pbuf - offset) - 1;
if (record)
replay_stream.insert(replay_stream.begin(), p);
new_replay.WriteStream(replay_stream);
}
return 0;
}
......@@ -1535,11 +1573,29 @@ void TagDuel::GetResponse(DuelPlayer* dp, void* pdata, unsigned int len) {
void TagDuel::EndDuel() {
if(!pduel)
return;
last_replay.EndRecord();
last_replay.EndRecord(0x1000);
char replaybuf[0x2000], *pbuf = replaybuf;
memcpy(pbuf, &last_replay.pheader, sizeof(ReplayHeader));
pbuf += sizeof(ReplayHeader);
memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
replay_stream.push_back(ReplayPacket(OLD_REPLAY_MODE, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size));
//in case of remaining packets, e.g. MSG_WIN
new_replay.WriteStream(replay_stream);
new_replay.EndRecord();
char nreplaybuf[0x2000], *npbuf = nreplaybuf;
memcpy(npbuf, &new_replay.pheader, sizeof(ReplayHeader));
npbuf += sizeof(ReplayHeader);
memcpy(npbuf, new_replay.comp_data, new_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_NEW_REPLAY, nreplaybuf, sizeof(ReplayHeader) + new_replay.comp_size);
NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]);
NetServer::ReSendToPlayer(players[3]);
for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]);
......@@ -1586,6 +1642,8 @@ void TagDuel::RefreshMzone(int player, int flag, int use_cache) {
int len = query_field_card(pduel, player, LOCATION_MZONE, flag, (unsigned char*)qbuf, use_cache);
int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
NetServer::ReSendToPlayer(players[pid + 1]);
int qlen = 0;
while(qlen < len) {
......@@ -1612,6 +1670,8 @@ void TagDuel::RefreshSzone(int player, int flag, int use_cache) {
int len = query_field_card(pduel, player, LOCATION_SZONE, flag, (unsigned char*)qbuf, use_cache);
int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
NetServer::ReSendToPlayer(players[pid + 1]);
int qlen = 0;
while(qlen < len) {
......@@ -1637,6 +1697,8 @@ void TagDuel::RefreshHand(int player, int flag, int use_cache) {
BufferIO::WriteInt8(qbuf, LOCATION_HAND);
int len = query_field_card(pduel, player, LOCATION_HAND, flag | QUERY_IS_PUBLIC, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
int qlen = 0;
while(qlen < len) {
int slen = BufferIO::ReadInt32(qbuf);
......@@ -1670,6 +1732,8 @@ void TagDuel::RefreshGrave(int player, int flag, int use_cache) {
NetServer::ReSendToPlayer(players[3]);
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
}
void TagDuel::RefreshExtra(int player, int flag, int use_cache) {
char query_buffer[0x2000];
......@@ -1679,6 +1743,8 @@ void TagDuel::RefreshExtra(int player, int flag, int use_cache) {
BufferIO::WriteInt8(qbuf, LOCATION_EXTRA);
int len = query_field_card(pduel, player, LOCATION_EXTRA, flag, (unsigned char*)qbuf, use_cache);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer, len + 3);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
}
void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
char query_buffer[0x2000];
......@@ -1688,6 +1754,8 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
BufferIO::WriteInt8(qbuf, location);
BufferIO::WriteInt8(qbuf, sequence);
int len = query_card(pduel, player, location, sequence, flag, (unsigned char*)qbuf, 0);
ReplayPacket p((char*)query_buffer, len + 3);
replay_stream.push_back(p);
if(location & LOCATION_ONFIELD) {
int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4);
......@@ -1714,6 +1782,16 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
}
}
}
void TagDuel::PseudoRefreshDeck(int player, int flag) {
char query_buffer[0x2000];
char* qbuf = query_buffer;
BufferIO::WriteInt8(qbuf, MSG_UPDATE_DATA);
BufferIO::WriteInt8(qbuf, player);
BufferIO::WriteInt8(qbuf, LOCATION_DECK);
int len = query_field_card(pduel, player, LOCATION_DECK, flag, (unsigned char*)qbuf, 0);
ReplayPacket p((char*)query_buffer, len + 2);
replay_stream.push_back(p);
}
int TagDuel::MessageHandler(long fduel, int type) {
if(!enable_log)
return 0;
......@@ -1735,6 +1813,8 @@ void TagDuel::TagTimer(evutil_socket_t fd, short events, void* arg) {
NetServer::ReSendToPlayer(sd->players[1]);
NetServer::ReSendToPlayer(sd->players[2]);
NetServer::ReSendToPlayer(sd->players[3]);
ReplayPacket p((char*)wbuf, 3);
sd->replay_stream.push_back(p);
sd->EndDuel();
sd->DuelEndProc();
event_del(sd->etimer);
......
......@@ -40,6 +40,9 @@ public:
static int MessageHandler(long fduel, int type);
static void TagTimer(evutil_socket_t fd, short events, void* arg);
void PseudoRefreshDeck(int player, int flag = 0x181fff);
static std::vector<ReplayPacket> replay_stream;
protected:
DuelPlayer* players[4];
......@@ -52,6 +55,7 @@ protected:
unsigned char hand_result[2];
unsigned char last_response;
Replay last_replay;
Replay new_replay;
bool game_started;
unsigned char turn_count;
unsigned short time_limit[2];
......
Subproject commit cbcff83c4001fb4208a530f580ad7ce0ac1fdfb2
Subproject commit 2a37a9fad5e84d06998e16eb530c0c2acdbb4e81
#The first line is used for comment
#line doesn't start with '!' is also neglected
#called by DataManager::GetSysString(), DataManager::GetDesc()
#system
!system 1 Normal Summon
!system 2 Special Summon
......@@ -375,6 +375,7 @@
!system 1353 Start at turn
!system 1354 Hide Set Names 
!system 1355 Hide Chain Buttons
!system 1356 Old Replay Mode
!system 1360 Previous
!system 1370 Level
!system 1371 Attack
......
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