1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Merge pull request #1521 from vcmi/android-remove-server-main

Rework netpacks
This commit is contained in:
Andrii Danylchenko 2023-02-13 22:10:33 +02:00 committed by GitHub
commit 4f4f2db9c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 3058 additions and 1588 deletions

View File

@ -212,6 +212,8 @@ set(client_HEADERS
CVideoHandler.h
Client.h
ClientCommandManager.h
ClientNetPackVisitors.h
LobbyClientNetPackVisitors.h
resource.h
)

View File

@ -37,7 +37,7 @@
#include "../lib/CConfigHandler.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/CThreadHelper.h"
#include "../lib/NetPacks.h"
#include "../lib/NetPackVisitor.h"
#include "../lib/StartInfo.h"
#include "../lib/VCMIDirs.h"
#include "../lib/mapping/CCampaignHandler.h"
@ -53,6 +53,7 @@
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include "../lib/serializer/Cast.h"
#include "LobbyClientNetPackVisitors.h"
#include <vcmi/events/EventBus.h>
@ -86,15 +87,21 @@ public:
bool applyOnLobbyHandler(CServerHandler * handler, void * pack) const override
{
T * ptr = static_cast<T *>(pack);
ApplyOnLobbyHandlerNetPackVisitor visitor(*handler);
logNetwork->trace("\tImmediately apply on lobby: %s", typeList.getTypeInfo(ptr)->name());
return ptr->applyOnLobbyHandler(handler);
ptr->visit(visitor);
return visitor.getResult();
}
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler, void * pack) const override
{
T * ptr = static_cast<T *>(pack);
ApplyOnLobbyScreenNetPackVisitor visitor(*handler, lobby);
logNetwork->trace("\tApply on lobby from queue: %s", typeList.getTypeInfo(ptr)->name());
ptr->applyOnLobbyScreen(lobby, handler);
ptr->visit(visitor);
}
};
@ -575,7 +582,7 @@ void CServerHandler::sendStartGame(bool allowOnlyAI) const
c->disableStackSendingByID();
}
void CServerHandler::startGameplay(CGameState * gameState)
void CServerHandler::startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState)
{
if(CMM)
CMM->disable();
@ -767,6 +774,30 @@ void CServerHandler::debugStartTest(std::string filename, bool save)
}
}
class ServerHandlerCPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
CServerHandler & handler;
public:
ServerHandlerCPackVisitor(CServerHandler & handler)
:handler(handler)
{
}
virtual bool callTyped() override { return false; }
virtual void visitForLobby(CPackForLobby & lobbyPack) override
{
handler.visitForLobby(lobbyPack);
}
virtual void visitForClient(CPackForClient & clientPack) override
{
handler.visitForClient(clientPack);
}
};
void CServerHandler::threadHandleConnection()
{
setThreadName("CServerHandler::threadHandleConnection");
@ -787,20 +818,10 @@ void CServerHandler::threadHandleConnection()
// Though currently they'll be delivered and might cause crash.
vstd::clear_pointer(pack);
}
else if(auto lobbyPack = dynamic_ptr_cast<CPackForLobby>(pack))
else
{
if(applier->getApplier(typeList.getTypeID(pack))->applyOnLobbyHandler(this, pack))
{
if(!settings["session"]["headless"].Bool())
{
boost::unique_lock<boost::recursive_mutex> lock(*mx);
packsForLobbyScreen.push_back(lobbyPack);
}
}
}
else if(auto clientPack = dynamic_ptr_cast<CPackForClient>(pack))
{
client->handlePack(clientPack);
ServerHandlerCPackVisitor visitor(*this);
pack->visit(visitor);
}
}
}
@ -836,6 +857,23 @@ void CServerHandler::threadHandleConnection()
}
}
void CServerHandler::visitForLobby(CPackForLobby & lobbyPack)
{
if(applier->getApplier(typeList.getTypeID(&lobbyPack))->applyOnLobbyHandler(this, &lobbyPack))
{
if(!settings["session"]["headless"].Bool())
{
boost::unique_lock<boost::recursive_mutex> lock(*mx);
packsForLobbyScreen.push_back(&lobbyPack);
}
}
}
void CServerHandler::visitForClient(CPackForClient & clientPack)
{
client->handlePack(&clientPack);
}
void CServerHandler::threadRunServer()
{
#if !defined(VCMI_ANDROID) && !defined(VCMI_IOS)

View File

@ -25,13 +25,13 @@ class CGameState;
struct ClientPlayer;
struct CPack;
struct CPackForLobby;
struct CPackForClient;
template<typename T> class CApplier;
VCMI_LIB_NAMESPACE_END
class CClient;
class CBaseForLobbyApply;
// TODO: Add mutex so we can't set CONNECTION_CANCELLED if client already connected, but thread not setup yet
@ -148,7 +148,7 @@ public:
void sendRestartGame() const override;
void sendStartGame(bool allowOnlyAI = false) const override;
void startGameplay(CGameState * gameState = nullptr);
void startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState = nullptr);
void endGameplay(bool closeConnection = true, bool restart = false);
void startCampaignScenario(std::shared_ptr<CCampaignState> cs = {});
void showServerError(std::string txt);
@ -159,6 +159,9 @@ public:
void debugStartTest(std::string filename, bool save = false);
void restoreLastSession();
void visitForLobby(CPackForLobby & lobbyPack);
void visitForClient(CPackForClient & clientPack);
};
extern CServerHandler * CSH;

View File

@ -32,6 +32,7 @@
#include "../lib/serializer/Connection.h"
#include "../lib/serializer/CLoadIntegrityValidator.h"
#include "../lib/NetPacks.h"
#include "ClientNetPackVisitors.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/VCMIDirs.h"
#include "../lib/mapping/CMap.h"
@ -80,12 +81,14 @@ public:
void applyOnClAfter(CClient * cl, void * pack) const override
{
T * ptr = static_cast<T *>(pack);
ptr->applyCl(cl);
ApplyClientNetPackVisitor visitor(*cl, *cl->gameState());
ptr->visit(visitor);
}
void applyOnClBefore(CClient * cl, void * pack) const override
{
T * ptr = static_cast<T *>(pack);
ptr->applyFirstCl(cl);
ApplyFirstClientNetPackVisitor visitor(*cl, *cl->gameState());
ptr->visit(visitor);
}
};

View File

@ -18,6 +18,7 @@
#include "CServerHandler.h"
#include "gui/CGuiHandler.h"
#include "../lib/NetPacks.h"
#include "ClientNetPackVisitors.h"
#include "../lib/CConfigHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CPlayerState.h"
@ -427,7 +428,9 @@ void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
YourTurn yt;
yt.player = colorIdentifier;
yt.daysWithoutCastle = CSH->client->getPlayerState(colorIdentifier)->daysWithoutCastle;
yt.applyCl(CSH->client);
ApplyClientNetPackVisitor visitor(*CSH->client, *CSH->client->gameState());
yt.visit(visitor);
}
void ClientCommandManager::printInfoAboutInterfaceObject(const CIntObject *obj, int level)

View File

@ -0,0 +1,132 @@
/*
* ClientNetPackVisitors.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../lib/NetPackVisitor.h"
class CClient;
VCMI_LIB_NAMESPACE_BEGIN
class CGameState;
VCMI_LIB_NAMESPACE_END
class ApplyClientNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
CClient & cl;
CGameState & gs;
public:
ApplyClientNetPackVisitor(CClient & cl, CGameState & gs)
:cl(cl), gs(gs)
{
}
void visitSetResources(SetResources & pack) override;
void visitSetPrimSkill(SetPrimSkill & pack) override;
void visitSetSecSkill(SetSecSkill & pack) override;
void visitHeroVisitCastle(HeroVisitCastle & pack) override;
void visitSetMana(SetMana & pack) override;
void visitSetMovePoints(SetMovePoints & pack) override;
void visitFoWChange(FoWChange & pack) override;
void visitChangeStackCount(ChangeStackCount & pack) override;
void visitSetStackType(SetStackType & pack) override;
void visitEraseStack(EraseStack & pack) override;
void visitSwapStacks(SwapStacks & pack) override;
void visitInsertNewStack(InsertNewStack & pack) override;
void visitRebalanceStacks(RebalanceStacks & pack) override;
void visitBulkRebalanceStacks(BulkRebalanceStacks & pack) override;
void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) override;
void visitPutArtifact(PutArtifact & pack) override;
void visitEraseArtifact(EraseArtifact & pack) override;
void visitMoveArtifact(MoveArtifact & pack) override;
void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) override;
void visitAssembledArtifact(AssembledArtifact & pack) override;
void visitDisassembledArtifact(DisassembledArtifact & pack) override;
void visitHeroVisit(HeroVisit & pack) override;
void visitNewTurn(NewTurn & pack) override;
void visitGiveBonus(GiveBonus & pack) override;
void visitChangeObjPos(ChangeObjPos & pack) override;
void visitPlayerEndsGame(PlayerEndsGame & pack) override;
void visitPlayerReinitInterface(PlayerReinitInterface & pack) override;
void visitRemoveBonus(RemoveBonus & pack) override;
void visitRemoveObject(RemoveObject & pack) override;
void visitTryMoveHero(TryMoveHero & pack) override;
void visitNewStructures(NewStructures & pack) override;
void visitRazeStructures(RazeStructures & pack) override;
void visitSetAvailableCreatures(SetAvailableCreatures & pack) override;
void visitSetHeroesInTown(SetHeroesInTown & pack) override;
void visitHeroRecruited(HeroRecruited & pack) override;
void visitGiveHero(GiveHero & pack) override;
void visitInfoWindow(InfoWindow & pack) override;
void visitSetObjectProperty(SetObjectProperty & pack) override;
void visitHeroLevelUp(HeroLevelUp & pack) override;
void visitCommanderLevelUp(CommanderLevelUp & pack) override;
void visitBlockingDialog(BlockingDialog & pack) override;
void visitGarrisonDialog(GarrisonDialog & pack) override;
void visitExchangeDialog(ExchangeDialog & pack) override;
void visitTeleportDialog(TeleportDialog & pack) override;
void visitMapObjectSelectDialog(MapObjectSelectDialog & pack) override;
void visitBattleStart(BattleStart & pack) override;
void visitBattleNextRound(BattleNextRound & pack) override;
void visitBattleSetActiveStack(BattleSetActiveStack & pack) override;
void visitBattleLogMessage(BattleLogMessage & pack) override;
void visitBattleTriggerEffect(BattleTriggerEffect & pack) override;
void visitBattleAttack(BattleAttack & pack) override;
void visitBattleSpellCast(BattleSpellCast & pack) override;
void visitSetStackEffect(SetStackEffect & pack) override;
void visitStacksInjured(StacksInjured & pack) override;
void visitBattleResultsApplied(BattleResultsApplied & pack) override;
void visitBattleUnitsChanged(BattleUnitsChanged & pack) override;
void visitBattleObstaclesChanged(BattleObstaclesChanged & pack) override;
void visitCatapultAttack(CatapultAttack & pack) override;
void visitEndAction(EndAction & pack) override;
void visitPackageApplied(PackageApplied & pack) override;
void visitSystemMessage(SystemMessage & pack) override;
void visitPlayerBlocked(PlayerBlocked & pack) override;
void visitYourTurn(YourTurn & pack) override;
void visitSaveGameClient(SaveGameClient & pack) override;
void visitPlayerMessageClient(PlayerMessageClient & pack) override;
void visitShowInInfobox(ShowInInfobox & pack) override;
void visitAdvmapSpellCast(AdvmapSpellCast & pack) override;
void visitShowWorldViewEx(ShowWorldViewEx & pack) override;
void visitOpenWindow(OpenWindow & pack) override;
void visitCenterView(CenterView & pack) override;
void visitNewObject(NewObject & pack) override;
void visitSetAvailableArtifacts(SetAvailableArtifacts & pack) override;
void visitEntitiesChanged(EntitiesChanged & pack) override;
};
class ApplyFirstClientNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
CClient & cl;
CGameState & gs;
public:
ApplyFirstClientNetPackVisitor(CClient & cl, CGameState & gs)
:cl(cl), gs(gs)
{
}
virtual void visitChangeObjPos(ChangeObjPos & pack) override;
virtual void visitRemoveObject(RemoveObject & pack) override;
virtual void visitTryMoveHero(TryMoveHero & pack) override;
virtual void visitGiveHero(GiveHero & pack) override;
virtual void visitBattleStart(BattleStart & pack) override;
virtual void visitBattleNextRound(BattleNextRound & pack) override;
virtual void visitBattleUpdateGateState(BattleUpdateGateState & pack) override;
virtual void visitBattleResult(BattleResult & pack) override;
virtual void visitBattleStackMoved(BattleStackMoved & pack) override;
virtual void visitBattleAttack(BattleAttack & pack) override;
virtual void visitStartAction(StartAction & pack) override;
};

View File

@ -0,0 +1,56 @@
/*
* ClientNetPackVisitors.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../lib/NetPackVisitor.h"
class CClient;
class CGameState;
class ApplyOnLobbyHandlerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
CServerHandler & handler;
bool result;
public:
ApplyOnLobbyHandlerNetPackVisitor(CServerHandler & handler)
:handler(handler), result(true)
{
}
bool getResult() const { return result; }
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override;
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyUpdateState(LobbyUpdateState & pack) override;
};
class ApplyOnLobbyScreenNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
CServerHandler & handler;
CLobbyScreen * lobby;
public:
ApplyOnLobbyScreenNetPackVisitor(CServerHandler & handler, CLobbyScreen * lobby)
:handler(handler), lobby(lobby)
{
}
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbyChatMessage(LobbyChatMessage & pack) override;
virtual void visitLobbyGuiAction(LobbyGuiAction & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyUpdateState(LobbyUpdateState & pack) override;
virtual void visitLobbyShowMessage(LobbyShowMessage & pack) override;
};

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
*/
#include "StdInc.h"
#include "LobbyClientNetPackVisitors.h"
#include "lobby/CSelectionBase.h"
#include "lobby/CLobbyScreen.h"
@ -28,123 +29,120 @@
#include "../lib/NetPacksLobby.h"
#include "../lib/serializer/Connection.h"
bool LobbyClientConnected::applyOnLobbyHandler(CServerHandler * handler)
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
{
result = false;
// Check if it's LobbyClientConnected for our client
if(uuid == handler->c->uuid)
if(pack.uuid == handler.c->uuid)
{
handler->c->connectionID = clientId;
handler.c->connectionID = pack.clientId;
if(!settings["session"]["headless"].Bool())
GH.pushIntT<CLobbyScreen>(static_cast<ESelectionScreen>(handler->screenType));
handler->state = EClientState::LOBBY;
return true;
GH.pushIntT<CLobbyScreen>(static_cast<ESelectionScreen>(handler.screenType));
handler.state = EClientState::LOBBY;
}
return false;
}
void LobbyClientConnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{
if(pack.clientId != pack.c->connectionID)
{
result = false;
return;
}
handler.stopServerConnection();
}
bool LobbyClientDisconnected::applyOnLobbyHandler(CServerHandler * handler)
{
if(clientId != c->connectionID)
return false;
handler->stopServerConnection();
return true;
}
void LobbyClientDisconnected::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
void ApplyOnLobbyScreenNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{
if(GH.listInt.size())
GH.popInts(1);
}
void LobbyChatMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
void ApplyOnLobbyScreenNetPackVisitor::visitLobbyChatMessage(LobbyChatMessage & pack)
{
if(lobby && lobby->card)
{
lobby->card->chat->addNewMessage(playerName + ": " + message);
lobby->card->chat->addNewMessage(pack.playerName + ": " + pack.message);
lobby->card->setChat(true);
if(lobby->buttonChat)
lobby->buttonChat->addTextOverlay(CGI->generaltexth->allTexts[531], FONT_SMALL);
}
}
void LobbyGuiAction::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
void ApplyOnLobbyScreenNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack)
{
if(!lobby || !handler->isGuest())
if(!lobby || !handler.isGuest())
return;
switch(action)
switch(pack.action)
{
case NO_TAB:
case LobbyGuiAction::NO_TAB:
lobby->toggleTab(lobby->curTab);
break;
case OPEN_OPTIONS:
case LobbyGuiAction::OPEN_OPTIONS:
lobby->toggleTab(lobby->tabOpt);
break;
case OPEN_SCENARIO_LIST:
case LobbyGuiAction::OPEN_SCENARIO_LIST:
lobby->toggleTab(lobby->tabSel);
break;
case OPEN_RANDOM_MAP_OPTIONS:
case LobbyGuiAction::OPEN_RANDOM_MAP_OPTIONS:
lobby->toggleTab(lobby->tabRand);
break;
}
}
bool LobbyEndGame::applyOnLobbyHandler(CServerHandler * handler)
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
{
if(handler->state == EClientState::GAMEPLAY)
if(handler.state == EClientState::GAMEPLAY)
{
handler->endGameplay(closeConnection, restart);
handler.endGameplay(pack.closeConnection, pack.restart);
}
if(restart)
handler->sendStartGame();
return true;
if(pack.restart)
handler.sendStartGame();
}
bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler)
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
{
if(clientId != -1 && clientId != handler->c->connectionID)
return false;
handler->state = EClientState::STARTING;
if(handler->si->mode != StartInfo::LOAD_GAME || clientId == handler->c->connectionID)
if(pack.clientId != -1 && pack.clientId != handler.c->connectionID)
{
auto modeBackup = handler->si->mode;
handler->si = initializedStartInfo;
handler->si->mode = modeBackup;
result = false;
return;
}
handler.state = EClientState::STARTING;
if(handler.si->mode != StartInfo::LOAD_GAME || pack.clientId == handler.c->connectionID)
{
auto modeBackup = handler.si->mode;
handler.si = pack.initializedStartInfo;
handler.si->mode = modeBackup;
}
if(settings["session"]["headless"].Bool())
handler->startGameplay(initializedGameState);
return true;
handler.startGameplay(pack.initializedGameState);
}
void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
void ApplyOnLobbyScreenNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
{
if(clientId != -1 && clientId != handler->c->connectionID)
if(pack.clientId != -1 && pack.clientId != handler.c->connectionID)
return;
GH.pushIntT<CLoadingScreen>(std::bind(&CServerHandler::startGameplay, handler, initializedGameState));
GH.pushIntT<CLoadingScreen>(std::bind(&CServerHandler::startGameplay, &handler, pack.initializedGameState));
}
bool LobbyUpdateState::applyOnLobbyHandler(CServerHandler * handler)
void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState & pack)
{
hostChanged = state.hostClientId != handler->hostClientId;
static_cast<LobbyState &>(*handler) = state;
return true;
pack.hostChanged = pack.state.hostClientId != handler.hostClientId;
static_cast<LobbyState &>(handler) = pack.state;
}
void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
void ApplyOnLobbyScreenNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState & pack)
{
if(!lobby) //stub: ignore message for game mode
return;
if(!lobby->bonusSel && handler->si->campState && handler->state == EClientState::LOBBY_CAMPAIGN)
if(!lobby->bonusSel && handler.si->campState && handler.state == EClientState::LOBBY_CAMPAIGN)
{
lobby->bonusSel = std::make_shared<CBonusSelection>();
GH.pushInt(lobby->bonusSel);
@ -155,15 +153,15 @@ void LobbyUpdateState::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler *
else
lobby->updateAfterStateChange();
if(hostChanged)
lobby->toggleMode(handler->isHost());
if(pack.hostChanged)
lobby->toggleMode(handler.isHost());
}
void LobbyShowMessage::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
void ApplyOnLobbyScreenNetPackVisitor::visitLobbyShowMessage(LobbyShowMessage & pack)
{
if(!lobby) //stub: ignore message for game mode
return;
lobby->buttonStart->block(false);
handler->showServerError(message);
handler.showServerError(pack.message);
}

View File

@ -439,6 +439,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/NetPacksBase.h
${MAIN_LIB_DIR}/NetPacks.h
${MAIN_LIB_DIR}/NetPacksLobby.h
${MAIN_LIB_DIR}/NetPackVisitor.h
${MAIN_LIB_DIR}/ObstacleHandler.h
${MAIN_LIB_DIR}/PathfinderUtil.h
${MAIN_LIB_DIR}/Point.h

165
lib/NetPackVisitor.h Normal file
View File

@ -0,0 +1,165 @@
/*
* CServerHandler.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "NetPacks.h"
#include "NetPacksLobby.h"
VCMI_LIB_NAMESPACE_BEGIN
class ICPackVisitor
{
public:
virtual bool callTyped() { return true; }
virtual void visitForLobby(CPackForLobby & pack) {}
virtual void visitForServer(CPackForServer & pack) {}
virtual void visitForClient(CPackForClient & pack) {}
virtual void visitPackageApplied(PackageApplied & pack) {}
virtual void visitSystemMessage(SystemMessage & pack) {}
virtual void visitPlayerBlocked(PlayerBlocked & pack) {}
virtual void visitPlayerCheated(PlayerCheated & pack) {}
virtual void visitYourTurn(YourTurn & pack) {}
virtual void visitEntitiesChanged(EntitiesChanged & pack) {}
virtual void visitSetResources(SetResources & pack) {}
virtual void visitSetPrimSkill(SetPrimSkill & pack) {}
virtual void visitSetSecSkill(SetSecSkill & pack) {}
virtual void visitHeroVisitCastle(HeroVisitCastle & pack) {}
virtual void visitChangeSpells(ChangeSpells & pack) {}
virtual void visitSetMana(SetMana & pack) {}
virtual void visitSetMovePoints(SetMovePoints & pack) {}
virtual void visitFoWChange(FoWChange & pack) {}
virtual void visitSetAvailableHeroes(SetAvailableHeroes & pack) {}
virtual void visitGiveBonus(GiveBonus & pack) {}
virtual void visitChangeObjPos(ChangeObjPos & pack) {}
virtual void visitPlayerEndsGame(PlayerEndsGame & pack) {}
virtual void visitPlayerReinitInterface(PlayerReinitInterface & pack) {}
virtual void visitRemoveBonus(RemoveBonus & pack) {}
virtual void visitSetCommanderProperty(SetCommanderProperty & pack) {}
virtual void visitAddQuest(AddQuest & pack) {}
virtual void visitUpdateArtHandlerLists(UpdateArtHandlerLists & pack) {}
virtual void visitUpdateMapEvents(UpdateMapEvents & pack) {}
virtual void visitUpdateCastleEvents(UpdateCastleEvents & pack) {}
virtual void visitChangeFormation(ChangeFormation & pack) {}
virtual void visitRemoveObject(RemoveObject & pack) {}
virtual void visitTryMoveHero(TryMoveHero & pack) {}
virtual void visitNewStructures(NewStructures & pack) {}
virtual void visitRazeStructures(RazeStructures & pack) {}
virtual void visitSetAvailableCreatures(SetAvailableCreatures & pack) {}
virtual void visitSetHeroesInTown(SetHeroesInTown & pack) {}
virtual void visitHeroRecruited(HeroRecruited & pack) {}
virtual void visitGiveHero(GiveHero & pack) {}
virtual void visitCatapultAttack(CatapultAttack & pack) {}
virtual void visitOpenWindow(OpenWindow & pack) {}
virtual void visitNewObject(NewObject & pack) {}
virtual void visitSetAvailableArtifacts(SetAvailableArtifacts & pack) {}
virtual void visitNewArtifact(NewArtifact & pack) {}
virtual void visitChangeStackCount(ChangeStackCount & pack) {}
virtual void visitSetStackType(SetStackType & pack) {}
virtual void visitEraseStack(EraseStack & pack) {}
virtual void visitSwapStacks(SwapStacks & pack) {}
virtual void visitInsertNewStack(InsertNewStack & pack) {}
virtual void visitRebalanceStacks(RebalanceStacks & pack) {}
virtual void visitBulkRebalanceStacks(BulkRebalanceStacks & pack) {}
virtual void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) {}
virtual void visitPutArtifact(PutArtifact & pack) {}
virtual void visitEraseArtifact(EraseArtifact & pack) {}
virtual void visitMoveArtifact(MoveArtifact & pack) {}
virtual void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) {}
virtual void visitAssembledArtifact(AssembledArtifact & pack) {}
virtual void visitDisassembledArtifact(DisassembledArtifact & pack) {}
virtual void visitHeroVisit(HeroVisit & pack) {}
virtual void visitNewTurn(NewTurn & pack) {}
virtual void visitInfoWindow(InfoWindow & pack) {}
virtual void visitSetObjectProperty(SetObjectProperty & pack) {}
virtual void visitChangeObjectVisitors(ChangeObjectVisitors & pack) {}
virtual void visitPrepareHeroLevelUp(PrepareHeroLevelUp & pack) {}
virtual void visitHeroLevelUp(HeroLevelUp & pack) {}
virtual void visitCommanderLevelUp(CommanderLevelUp & pack) {}
virtual void visitBlockingDialog(BlockingDialog & pack) {}
virtual void visitGarrisonDialog(GarrisonDialog & pack) {}
virtual void visitExchangeDialog(ExchangeDialog & pack) {}
virtual void visitTeleportDialog(TeleportDialog & pack) {}
virtual void visitMapObjectSelectDialog(MapObjectSelectDialog & pack) {}
virtual void visitBattleStart(BattleStart & pack) {}
virtual void visitBattleNextRound(BattleNextRound & pack) {}
virtual void visitBattleSetActiveStack(BattleSetActiveStack & pack) {}
virtual void visitBattleResult(BattleResult & pack) {}
virtual void visitBattleLogMessage(BattleLogMessage & pack) {}
virtual void visitBattleStackMoved(BattleStackMoved & pack) {}
virtual void visitBattleUnitsChanged(BattleUnitsChanged & pack) {}
virtual void visitBattleAttack(BattleAttack & pack) {}
virtual void visitStartAction(StartAction & pack) {}
virtual void visitEndAction(EndAction & pack) {}
virtual void visitBattleSpellCast(BattleSpellCast & pack) {}
virtual void visitSetStackEffect(SetStackEffect & pack) {}
virtual void visitStacksInjured(StacksInjured & pack) {}
virtual void visitBattleResultsApplied(BattleResultsApplied & pack) {}
virtual void visitBattleObstaclesChanged(BattleObstaclesChanged & pack) {}
virtual void visitBattleSetStackProperty(BattleSetStackProperty & pack) {}
virtual void visitBattleTriggerEffect(BattleTriggerEffect & pack) {}
virtual void visitBattleUpdateGateState(BattleUpdateGateState & pack) {}
virtual void visitShowInInfobox(ShowInInfobox & pack) {}
virtual void visitAdvmapSpellCast(AdvmapSpellCast & pack) {}
virtual void visitShowWorldViewEx(ShowWorldViewEx & pack) {}
virtual void visitEndTurn(EndTurn & pack) {}
virtual void visitDismissHero(DismissHero & pack) {}
virtual void visitMoveHero(MoveHero & pack) {}
virtual void visitCastleTeleportHero(CastleTeleportHero & pack) {}
virtual void visitArrangeStacks(ArrangeStacks & pack) {}
virtual void visitBulkMoveArmy(BulkMoveArmy & pack) {}
virtual void visitBulkSplitStack(BulkSplitStack & pack) {}
virtual void visitBulkMergeStacks(BulkMergeStacks & pack) {}
virtual void visitBulkSmartSplitStack(BulkSmartSplitStack & pack) {}
virtual void visitDisbandCreature(DisbandCreature & pack) {}
virtual void visitBuildStructure(BuildStructure & pack) {}
virtual void visitRazeStructure(RazeStructure & pack) {}
virtual void visitRecruitCreatures(RecruitCreatures & pack) {}
virtual void visitUpgradeCreature(UpgradeCreature & pack) {}
virtual void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) {}
virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) {}
virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) {}
virtual void visitAssembleArtifacts(AssembleArtifacts & pack) {}
virtual void visitBuyArtifact(BuyArtifact & pack) {}
virtual void visitTradeOnMarketplace(TradeOnMarketplace & pack) {}
virtual void visitSetFormation(SetFormation & pack) {}
virtual void visitHireHero(HireHero & pack) {}
virtual void visitBuildBoat(BuildBoat & pack) {}
virtual void visitQueryReply(QueryReply & pack) {}
virtual void visitMakeAction(MakeAction & pack) {}
virtual void visitMakeCustomAction(MakeCustomAction & pack) {}
virtual void visitDigWithHero(DigWithHero & pack) {}
virtual void visitCastAdvSpell(CastAdvSpell & pack) {}
virtual void visitSaveGame(SaveGame & pack) {}
virtual void visitSaveGameClient(SaveGameClient & pack) {}
virtual void visitPlayerMessage(PlayerMessage & pack) {}
virtual void visitPlayerMessageClient(PlayerMessageClient & pack) {}
virtual void visitCenterView(CenterView & pack) {}
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) {}
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) {}
virtual void visitLobbyChatMessage(LobbyChatMessage & pack) {}
virtual void visitLobbyGuiAction(LobbyGuiAction & pack) {}
virtual void visitLobbyEndGame(LobbyEndGame & pack) {}
virtual void visitLobbyStartGame(LobbyStartGame & pack) {}
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) {}
virtual void visitLobbyUpdateState(LobbyUpdateState & pack) {}
virtual void visitLobbySetMap(LobbySetMap & pack) {}
virtual void visitLobbySetCampaign(LobbySetCampaign & pack) {}
virtual void visitLobbySetCampaignMap(LobbySetCampaignMap & pack) {}
virtual void visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack) {}
virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) {}
virtual void visitLobbySetPlayer(LobbySetPlayer & pack) {}
virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) {}
virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) {}
virtual void visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack) {}
virtual void visitLobbyShowMessage(LobbyShowMessage & pack) {}
};
VCMI_LIB_NAMESPACE_END

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,9 @@
class CClient;
class CGameHandler;
class CLobbyScreen;
class CServerHandler;
class CVCMIServer;
VCMI_LIB_NAMESPACE_BEGIN
@ -30,6 +33,8 @@ class CArtifactSet;
class CBonusSystemNode;
struct ArtSlotInfo;
class ICPackVisitor;
struct DLL_LINKAGE CPack
{
std::shared_ptr<CConnection> c; // Pointer to connection that pack received from
@ -45,27 +50,31 @@ struct DLL_LINKAGE CPack
void applyGs(CGameState * gs)
{}
void visit(ICPackVisitor & cpackVisitor);
protected:
/// <summary>
/// For basic types of netpacks hierarchy like CPackForClient. Called first.
/// </summary>
virtual void visitBasic(ICPackVisitor & cpackVisitor);
/// <summary>
/// For leaf types of netpacks hierarchy. Called after visitBasic.
/// </summary>
virtual void visitTyped(ICPackVisitor & cpackVisitor);
};
struct CPackForClient : public CPack
struct DLL_LINKAGE CPackForClient : public CPack
{
CGameState* GS(CClient *cl);
void applyFirstCl(CClient *cl)//called before applying to gs
{}
void applyCl(CClient *cl)//called after applying to gs
{}
protected:
virtual void visitBasic(ICPackVisitor & cpackVisitor) override;
};
struct CPackForServer : public CPack
struct DLL_LINKAGE CPackForServer : public CPack
{
mutable PlayerColor player = PlayerColor::NEUTRAL;
mutable si32 requestID;
CGameState * GS(CGameHandler * gh);
bool applyGh(CGameHandler *gh) //called after applying to gs
{
logGlobal->error("Should not happen... applying plain CPackForServer");
return false;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -74,14 +83,15 @@ struct CPackForServer : public CPack
}
protected:
void throwNotAllowedAction();
void throwOnWrongOwner(CGameHandler * gh, ObjectInstanceID id);
void throwOnWrongPlayer(CGameHandler * gh, PlayerColor player);
void throwAndComplain(CGameHandler * gh, std::string txt);
bool isPlayerOwns(CGameHandler * gh, ObjectInstanceID id);
virtual void visitBasic(ICPackVisitor & cpackVisitor) override;
};
private:
void wrongPlayerMessage(CGameHandler * gh, PlayerColor expectedplayer);
struct DLL_LINKAGE CPackForLobby : public CPack
{
virtual bool isForServer() const;
protected:
virtual void visitBasic(ICPackVisitor & cpackVisitor) override;
};
struct DLL_LINKAGE MetaString

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@
#include "StartInfo.h"
class CLobbyScreen;
class CServerHandler;
class CVCMIServer;
@ -25,40 +24,16 @@ struct StartInfo;
class CMapGenOptions;
struct ClientPlayer;
struct CPackForLobby : public CPack
struct DLL_LINKAGE CLobbyPackToPropagate : public CPackForLobby
{
bool checkClientPermissions(CVCMIServer * srv) const
{
return false;
}
bool applyOnServer(CVCMIServer * srv)
{
return true;
}
void applyOnServerAfterAnnounce(CVCMIServer * srv) {}
bool applyOnLobbyHandler(CServerHandler * handler)
{
return true;
}
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler) {}
};
struct CLobbyPackToPropagate : public CPackForLobby
struct DLL_LINKAGE CLobbyPackToServer : public CPackForLobby
{
virtual bool isForServer() const override;
};
struct CLobbyPackToServer : public CPackForLobby
{
bool checkClientPermissions(CVCMIServer * srv) const;
void applyOnServerAfterAnnounce(CVCMIServer * srv);
};
struct LobbyClientConnected : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyClientConnected : public CLobbyPackToPropagate
{
// Set by client before sending pack to server
std::string uuid;
@ -68,11 +43,7 @@ struct LobbyClientConnected : public CLobbyPackToPropagate
int clientId = -1;
int hostClientId = -1;
bool checkClientPermissions(CVCMIServer * srv) const;
bool applyOnLobbyHandler(CServerHandler * handler);
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
bool applyOnServer(CVCMIServer * srv);
void applyOnServerAfterAnnounce(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h, const int version)
{
@ -85,16 +56,13 @@ struct LobbyClientConnected : public CLobbyPackToPropagate
}
};
struct LobbyClientDisconnected : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyClientDisconnected : public CLobbyPackToPropagate
{
int clientId;
bool shutdownServer = false;
bool checkClientPermissions(CVCMIServer * srv) const;
bool applyOnServer(CVCMIServer * srv);
void applyOnServerAfterAnnounce(CVCMIServer * srv);
bool applyOnLobbyHandler(CServerHandler * handler);
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -103,12 +71,11 @@ struct LobbyClientDisconnected : public CLobbyPackToPropagate
}
};
struct LobbyChatMessage : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyChatMessage : public CLobbyPackToPropagate
{
std::string playerName, message;
bool checkClientPermissions(CVCMIServer * srv) const;
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -117,14 +84,14 @@ struct LobbyChatMessage : public CLobbyPackToPropagate
}
};
struct LobbyGuiAction : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyGuiAction : public CLobbyPackToPropagate
{
enum EAction : ui8 {
NONE, NO_TAB, OPEN_OPTIONS, OPEN_SCENARIO_LIST, OPEN_RANDOM_MAP_OPTIONS
} action = NONE;
bool checkClientPermissions(CVCMIServer * srv) const;
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -132,14 +99,11 @@ struct LobbyGuiAction : public CLobbyPackToPropagate
}
};
struct LobbyEndGame : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyEndGame : public CLobbyPackToPropagate
{
bool closeConnection = false, restart = false;
bool checkClientPermissions(CVCMIServer * srv) const;
bool applyOnServer(CVCMIServer * srv);
void applyOnServerAfterAnnounce(CVCMIServer * srv);
bool applyOnLobbyHandler(CServerHandler * handler);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -148,18 +112,14 @@ struct LobbyEndGame : public CLobbyPackToPropagate
}
};
struct LobbyStartGame : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyStartGame : public CLobbyPackToPropagate
{
// Set by server
std::shared_ptr<StartInfo> initializedStartInfo = nullptr;
CGameState * initializedGameState = nullptr;
int clientId = -1; //-1 means to all clients
bool checkClientPermissions(CVCMIServer * srv) const;
bool applyOnServer(CVCMIServer * srv);
void applyOnServerAfterAnnounce(CVCMIServer * srv);
bool applyOnLobbyHandler(CServerHandler * handler);
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -172,13 +132,11 @@ struct LobbyStartGame : public CLobbyPackToPropagate
}
};
struct LobbyChangeHost : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyChangeHost : public CLobbyPackToPropagate
{
int newHostConnectionId = -1;
bool checkClientPermissions(CVCMIServer * srv) const;
bool applyOnServer(CVCMIServer * srv);
bool applyOnServerAfterAnnounce(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h, const int version)
{
@ -186,13 +144,12 @@ struct LobbyChangeHost : public CLobbyPackToPropagate
}
};
struct LobbyUpdateState : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyUpdateState : public CLobbyPackToPropagate
{
LobbyState state;
bool hostChanged = false; // Used on client-side only
bool applyOnLobbyHandler(CServerHandler * handler);
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -200,13 +157,14 @@ struct LobbyUpdateState : public CLobbyPackToPropagate
}
};
struct LobbySetMap : public CLobbyPackToServer
struct DLL_LINKAGE LobbySetMap : public CLobbyPackToServer
{
std::shared_ptr<CMapInfo> mapInfo;
std::shared_ptr<CMapGenOptions> mapGenOpts;
LobbySetMap() : mapInfo(nullptr), mapGenOpts(nullptr) {}
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -215,11 +173,11 @@ struct LobbySetMap : public CLobbyPackToServer
}
};
struct LobbySetCampaign : public CLobbyPackToServer
struct DLL_LINKAGE LobbySetCampaign : public CLobbyPackToServer
{
std::shared_ptr<CCampaignState> ourCampaign;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -227,11 +185,11 @@ struct LobbySetCampaign : public CLobbyPackToServer
}
};
struct LobbySetCampaignMap : public CLobbyPackToServer
struct DLL_LINKAGE LobbySetCampaignMap : public CLobbyPackToServer
{
int mapId = -1;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -239,11 +197,11 @@ struct LobbySetCampaignMap : public CLobbyPackToServer
}
};
struct LobbySetCampaignBonus : public CLobbyPackToServer
struct DLL_LINKAGE LobbySetCampaignBonus : public CLobbyPackToServer
{
int bonusId = -1;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -251,15 +209,14 @@ struct LobbySetCampaignBonus : public CLobbyPackToServer
}
};
struct LobbyChangePlayerOption : public CLobbyPackToServer
struct DLL_LINKAGE LobbyChangePlayerOption : public CLobbyPackToServer
{
enum EWhat : ui8 {UNKNOWN, TOWN, HERO, BONUS};
ui8 what = UNKNOWN;
si8 direction = 0; //-1 or +1
PlayerColor color = PlayerColor::CANNOT_DETERMINE;
bool checkClientPermissions(CVCMIServer * srv) const;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -269,11 +226,11 @@ struct LobbyChangePlayerOption : public CLobbyPackToServer
}
};
struct LobbySetPlayer : public CLobbyPackToServer
struct DLL_LINKAGE LobbySetPlayer : public CLobbyPackToServer
{
PlayerColor clickedColor = PlayerColor::CANNOT_DETERMINE;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -281,11 +238,11 @@ struct LobbySetPlayer : public CLobbyPackToServer
}
};
struct LobbySetTurnTime : public CLobbyPackToServer
struct DLL_LINKAGE LobbySetTurnTime : public CLobbyPackToServer
{
ui8 turnTime = 0;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -293,11 +250,11 @@ struct LobbySetTurnTime : public CLobbyPackToServer
}
};
struct LobbySetDifficulty : public CLobbyPackToServer
struct DLL_LINKAGE LobbySetDifficulty : public CLobbyPackToServer
{
ui8 difficulty = 0;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler &h, const int version)
{
@ -305,12 +262,12 @@ struct LobbySetDifficulty : public CLobbyPackToServer
}
};
struct LobbyForceSetPlayer : public CLobbyPackToServer
struct DLL_LINKAGE LobbyForceSetPlayer : public CLobbyPackToServer
{
ui8 targetConnectedPlayer = -1;
PlayerColor targetPlayerColor = PlayerColor::CANNOT_DETERMINE;
bool applyOnServer(CVCMIServer * srv);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h, const int version)
{
@ -319,11 +276,11 @@ struct LobbyForceSetPlayer : public CLobbyPackToServer
}
};
struct LobbyShowMessage : public CLobbyPackToPropagate
struct DLL_LINKAGE LobbyShowMessage : public CLobbyPackToPropagate
{
std::string message;
void applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler);
virtual void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h, const int version)
{

View File

@ -30,7 +30,7 @@
#include "../lib/CStack.h"
#include "../lib/battle/BattleInfo.h"
#include "../lib/CondSh.h"
#include "../lib/NetPacks.h"
#include "ServerNetPackVisitors.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/mapping/CMap.h"
#include "../lib/mapping/CMapService.h"
@ -196,7 +196,7 @@ template <typename T> class CApplyOnGH;
class CBaseForGHApply
{
public:
virtual bool applyOnGH(CGameHandler * gh, void * pack) const =0;
virtual bool applyOnGH(CGameHandler * gh, CGameState * gs, void * pack) const =0;
virtual ~CBaseForGHApply(){}
template<typename U> static CBaseForGHApply *getApplier(const U * t=nullptr)
{
@ -207,12 +207,16 @@ public:
template <typename T> class CApplyOnGH : public CBaseForGHApply
{
public:
bool applyOnGH(CGameHandler * gh, void * pack) const override
bool applyOnGH(CGameHandler * gh, CGameState * gs, void * pack) const override
{
T *ptr = static_cast<T*>(pack);
try
{
return ptr->applyGh(gh);
ApplyGhNetPackVisitor applier(*gh, *gs);
ptr->visit(applier);
return applier.getResult();
}
catch(ExceptionNotAllowedAction & e)
{
@ -230,7 +234,7 @@ template <>
class CApplyOnGH<CPack> : public CBaseForGHApply
{
public:
bool applyOnGH(CGameHandler * gh, void * pack) const override
bool applyOnGH(CGameHandler * gh, CGameState * gs, void * pack) const override
{
logGlobal->error("Cannot apply on GH plain CPack!");
assert(0);
@ -1358,7 +1362,7 @@ void CGameHandler::handleReceivedPack(CPackForServer * pack)
}
else if(apply)
{
const bool result = apply->applyOnGH(this, pack);
const bool result = apply->applyOnGH(this, this->gs, pack);
if(result)
logGlobal->trace("Message %s successfully applied!", typeid(*pack).name());
else
@ -2933,6 +2937,58 @@ void CGameHandler::sendAndApply(NewStructures * pack)
checkVictoryLossConditionsForPlayer(getTown(pack->tid)->tempOwner);
}
bool CGameHandler::isPlayerOwns(CPackForServer * pack, ObjectInstanceID id)
{
return getPlayerAt(pack->c) == getOwner(id);
}
void CGameHandler::throwNotAllowedAction(CPackForServer * pack)
{
if(pack->c)
{
SystemMessage temp_message("You are not allowed to perform this action!");
pack->c->sendPack(&temp_message);
}
logNetwork->error("Player is not allowed to perform this action!");
throw ExceptionNotAllowedAction();
}
void CGameHandler::wrongPlayerMessage(CPackForServer * pack, PlayerColor expectedplayer)
{
std::ostringstream oss;
oss << "You were identified as player " << getPlayerAt(pack->c) << " while expecting " << expectedplayer;
logNetwork->error(oss.str());
if(pack->c)
{
SystemMessage temp_message(oss.str());
pack->c->sendPack(&temp_message);
}
}
void CGameHandler::throwOnWrongOwner(CPackForServer * pack, ObjectInstanceID id)
{
if(!isPlayerOwns(pack, id))
{
wrongPlayerMessage(pack, getOwner(id));
throwNotAllowedAction(pack);
}
}
void CGameHandler::throwOnWrongPlayer(CPackForServer * pack, PlayerColor player)
{
if(!hasPlayerAt(player, pack->c) && player != getPlayerAt(pack->c))
{
wrongPlayerMessage(pack, player);
throwNotAllowedAction(pack);
}
}
void CGameHandler::throwAndComplain(CPackForServer * pack, std::string txt)
{
complain(txt);
throwNotAllowedAction(pack);
}
void CGameHandler::save(const std::string & filename)
{
logGlobal->info("Saving to %s", filename);

View File

@ -303,6 +303,13 @@ public:
void sendAndApply(SetResources * pack);
void sendAndApply(NewStructures * pack);
void wrongPlayerMessage(CPackForServer * pack, PlayerColor expectedplayer);
void throwNotAllowedAction(CPackForServer * pack);
void throwOnWrongOwner(CPackForServer * pack, ObjectInstanceID id);
void throwOnWrongPlayer(CPackForServer * pack, PlayerColor player);
void throwAndComplain(CPackForServer * pack, std::string txt);
bool isPlayerOwns(CPackForServer * pack, ObjectInstanceID id);
struct FinishingBattleHelper
{
FinishingBattleHelper();

View File

@ -14,6 +14,8 @@ set(server_HEADERS
CGameHandler.h
CQuery.h
CVCMIServer.h
LobbyNetPackVisitors.h
ServerNetPackVisitors.h
)
assign_source_group(${server_SRCS} ${server_HEADERS})

View File

@ -27,6 +27,8 @@
#include "../lib/StartInfo.h"
#include "../lib/mapping/CMap.h"
#include "../lib/rmg/CMapGenOptions.h"
#include "../lib/NetPackVisitor.h"
#include "LobbyNetPackVisitors.h"
#ifdef VCMI_ANDROID
#include <jni.h>
#include <android/log.h>
@ -81,10 +83,17 @@ public:
bool applyOnServerBefore(CVCMIServer * srv, void * pack) const override
{
T * ptr = static_cast<T *>(pack);
if(ptr->checkClientPermissions(srv))
ClientPermissionsCheckerNetPackVisitor checker(*srv);
ptr->visit(checker);
if(checker.getResult())
{
boost::unique_lock<boost::mutex> stateLock(srv->stateMutex);
return ptr->applyOnServer(srv);
ApplyOnServerNetPackVisitor applier(*srv);
ptr->visit(applier);
return applier.getResult();
}
else
return false;
@ -93,7 +102,8 @@ public:
void applyOnServerAfter(CVCMIServer * srv, void * pack) const override
{
T * ptr = static_cast<T *>(pack);
ptr->applyOnServerAfterAnnounce(srv);
ApplyOnServerAfterAnnounceNetPackVisitor applier(*srv);
ptr->visit(applier);
}
};
@ -363,6 +373,35 @@ void CVCMIServer::connectionAccepted(const boost::system::error_code & ec)
startAsyncAccept();
}
class CVCMIServerPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
CVCMIServer & handler;
CGameHandler & gh;
public:
CVCMIServerPackVisitor(CVCMIServer & handler, CGameHandler & gh)
:handler(handler), gh(gh)
{
}
virtual bool callTyped() override { return false; }
virtual void visitForLobby(CPackForLobby & packForLobby) override
{
handler.handleReceivedPack(std::unique_ptr<CPackForLobby>(&packForLobby));
}
virtual void visitForServer(CPackForServer & serverPack) override
{
gh.handleReceivedPack(&serverPack);
}
virtual void visitForClient(CPackForClient & clientPack) override
{
}
};
void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
{
setThreadName("CVCMIServer::handleConnection");
@ -394,15 +433,9 @@ void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
}
break;
}
if(auto lobbyPack = dynamic_ptr_cast<CPackForLobby>(pack))
{
handleReceivedPack(std::unique_ptr<CPackForLobby>(lobbyPack));
}
else if(auto serverPack = dynamic_ptr_cast<CPackForServer>(pack))
{
gh->handleReceivedPack(serverPack);
}
CVCMIServerPackVisitor visitor(*this, *this->gh);
pack->visit(visitor);
}
#ifndef _MSC_VER
}
@ -1051,8 +1084,16 @@ static void handleCommandOptions(int argc, char * argv[], boost::program_options
#ifdef SINGLE_PROCESS_APP
#define main server_main
#endif
#ifdef VCMI_ANDROID
void CVCMIServer::create()
{
const int argc = 1;
char * argv[argc] = { "android-server" };
#else
int main(int argc, char * argv[])
{
#endif
#if !defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP)
// Correct working dir executable folder (not bundle folder) so we can use executable relative paths
boost::filesystem::current_path(boost::filesystem::system_complete(argv[0]).parent_path());
@ -1120,7 +1161,10 @@ int main(int argc, char * argv[])
#endif
logConfig.deconfigure();
vstd::clear_pointer(VLC);
#ifndef VCMI_ANDROID
return 0;
#endif
}
#ifdef VCMI_ANDROID
@ -1129,14 +1173,8 @@ extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_createServer(J
{
__android_log_write(ANDROID_LOG_INFO, "VCMI", "Got jni call to init server");
CAndroidVMHelper::cacheVM(env);
CVCMIServer::create();
}
void CVCMIServer::create()
{
const char * foo = "android-server";
std::vector<const void *> argv = {foo};
main(argv.size(), reinterpret_cast<char **>(const_cast<void **>(&*argv.begin())));
CVCMIServer::create();
}
#elif defined(SINGLE_PROCESS_APP)

View File

@ -0,0 +1,92 @@
/*
* LobbyNetPackVisitors.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../lib/NetPackVisitor.h"
class ClientPermissionsCheckerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
bool result;
CVCMIServer & srv;
public:
ClientPermissionsCheckerNetPackVisitor(CVCMIServer & srv)
:srv(srv), result(false)
{
}
bool getResult() const
{
return result;
}
virtual void visitForLobby(CPackForLobby & pack) override;
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override;
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override;
virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) override;
virtual void visitLobbyChatMessage(LobbyChatMessage & pack) override;
virtual void visitLobbyGuiAction(LobbyGuiAction & pack) override;
};
class ApplyOnServerAfterAnnounceNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
CVCMIServer & srv;
public:
ApplyOnServerAfterAnnounceNetPackVisitor(CVCMIServer & srv)
:srv(srv)
{
}
virtual void visitForLobby(CPackForLobby & pack) override;
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override;
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override;
};
class ApplyOnServerNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
bool result;
CVCMIServer & srv;
public:
ApplyOnServerNetPackVisitor(CVCMIServer & srv)
:srv(srv), result(true)
{
}
bool getResult() const
{
return result;
}
virtual void visitLobbyClientConnected(LobbyClientConnected & pack) override;
virtual void visitLobbyClientDisconnected(LobbyClientDisconnected & pack) override;
virtual void visitLobbySetMap(LobbySetMap & pack) override;
virtual void visitLobbySetCampaign(LobbySetCampaign & pack) override;
virtual void visitLobbySetCampaignMap(LobbySetCampaignMap & pack) override;
virtual void visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack) override;
virtual void visitLobbyEndGame(LobbyEndGame & pack) override;
virtual void visitLobbyStartGame(LobbyStartGame & pack) override;
virtual void visitLobbyChangeHost(LobbyChangeHost & pack) override;
virtual void visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack) override;
virtual void visitLobbySetPlayer(LobbySetPlayer & pack) override;
virtual void visitLobbySetTurnTime(LobbySetTurnTime & pack) override;
virtual void visitLobbySetDifficulty(LobbySetDifficulty & pack) override;
virtual void visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack) override;
};

View File

@ -8,6 +8,7 @@
*
*/
#include "StdInc.h"
#include "LobbyNetPackVisitors.h"
#include "CVCMIServer.h"
#include "CGameHandler.h"
@ -21,328 +22,378 @@
#include "../lib/mapping/CMapService.h"
#include "../lib/mapping/CMapInfo.h"
bool CLobbyPackToServer::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitForLobby(CPackForLobby & pack)
{
return srv->isClientHost(c->connectionID);
if(pack.isForServer())
{
result = srv.isClientHost(pack.c->connectionID);
}
}
void CLobbyPackToServer::applyOnServerAfterAnnounce(CVCMIServer * srv)
void ApplyOnServerAfterAnnounceNetPackVisitor::visitForLobby(CPackForLobby & pack)
{
// Propogate options after every CLobbyPackToServer
srv->updateAndPropagateLobbyState();
if(pack.isForServer())
{
srv.updateAndPropagateLobbyState();
}
}
bool LobbyClientConnected::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
{
if(srv->gh)
if(srv.gh)
{
for(auto & connection : srv->hangingConnections)
for(auto & connection : srv.hangingConnections)
{
if(connection->uuid == uuid)
if(connection->uuid == pack.uuid)
{
return true;
{
result = true;
return;
}
}
}
}
if(srv->state == EServerState::LOBBY)
return true;
if(srv.state == EServerState::LOBBY)
{
result = true;
return;
}
//disconnect immediately and ignore this client
srv->connections.erase(c);
if(c && c->isOpen())
srv.connections.erase(pack.c);
if(pack.c && pack.c->isOpen())
{
c->close();
c->connected = false;
pack.c->close();
pack.c->connected = false;
}
{
result = false;
return;
}
return false;
}
bool LobbyClientConnected::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
{
if(srv->gh)
if(srv.gh)
{
for(auto & connection : srv->hangingConnections)
for(auto & connection : srv.hangingConnections)
{
if(connection->uuid == uuid)
if(connection->uuid == pack.uuid)
{
logNetwork->info("Reconnection player");
c->connectionID = connection->connectionID;
for(auto & playerConnection : srv->gh->connections)
pack.c->connectionID = connection->connectionID;
for(auto & playerConnection : srv.gh->connections)
{
for(auto & existingConnection : playerConnection.second)
{
if(existingConnection == connection)
{
playerConnection.second.erase(existingConnection);
playerConnection.second.insert(c);
playerConnection.second.insert(pack.c);
break;
}
}
}
srv->hangingConnections.erase(connection);
srv.hangingConnections.erase(connection);
break;
}
}
}
srv->clientConnected(c, names, uuid, mode);
srv.clientConnected(pack.c, pack.names, pack.uuid, pack.mode);
// Server need to pass some data to newly connected client
clientId = c->connectionID;
mode = srv->si->mode;
hostClientId = srv->hostClientId;
return true;
pack.clientId = pack.c->connectionID;
pack.mode = srv.si->mode;
pack.hostClientId = srv.hostClientId;
result = true;
}
void LobbyClientConnected::applyOnServerAfterAnnounce(CVCMIServer * srv)
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientConnected(LobbyClientConnected & pack)
{
// FIXME: we need to avoid senting something to client that not yet get answer for LobbyClientConnected
// Until UUID set we only pass LobbyClientConnected to this client
c->uuid = uuid;
srv->updateAndPropagateLobbyState();
if(srv->state == EServerState::GAMEPLAY)
pack.c->uuid = pack.uuid;
srv.updateAndPropagateLobbyState();
if(srv.state == EServerState::GAMEPLAY)
{
//immediately start game
std::unique_ptr<LobbyStartGame> startGameForReconnectedPlayer(new LobbyStartGame);
startGameForReconnectedPlayer->initializedStartInfo = srv->si;
startGameForReconnectedPlayer->initializedGameState = srv->gh->gameState();
startGameForReconnectedPlayer->clientId = c->connectionID;
srv->addToAnnounceQueue(std::move(startGameForReconnectedPlayer));
startGameForReconnectedPlayer->initializedStartInfo = srv.si;
startGameForReconnectedPlayer->initializedGameState = srv.gh->gameState();
startGameForReconnectedPlayer->clientId = pack.c->connectionID;
srv.addToAnnounceQueue(std::move(startGameForReconnectedPlayer));
}
}
bool LobbyClientDisconnected::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{
if(clientId != c->connectionID)
return false;
if(shutdownServer)
if(pack.clientId != pack.c->connectionID)
{
if(!srv->cmdLineOptions.count("run-by-client"))
return false;
if(c->uuid != srv->cmdLineOptions["uuid"].as<std::string>())
return false;
}
return true;
}
bool LobbyClientDisconnected::applyOnServer(CVCMIServer * srv)
{
srv->clientDisconnected(c);
c->close();
c->connected = false;
return true;
}
void LobbyClientDisconnected::applyOnServerAfterAnnounce(CVCMIServer * srv)
{
if(c && c->isOpen())
{
boost::unique_lock<boost::mutex> lock(*c->mutexWrite);
c->close();
c->connected = false;
}
if(shutdownServer)
{
logNetwork->info("Client requested shutdown, server will close itself...");
srv->state = EServerState::SHUTDOWN;
result = false;
return;
}
else if(srv->connections.empty())
if(pack.shutdownServer)
{
if(!srv.cmdLineOptions.count("run-by-client"))
{
result = false;
return;
}
if(pack.c->uuid != srv.cmdLineOptions["uuid"].as<std::string>())
{
result = false;
return;
}
}
result = true;
}
void ApplyOnServerNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{
srv.clientDisconnected(pack.c);
pack.c->close();
pack.c->connected = false;
result = true;
}
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyClientDisconnected(LobbyClientDisconnected & pack)
{
if(pack.c && pack.c->isOpen())
{
boost::unique_lock<boost::mutex> lock(*pack.c->mutexWrite);
pack.c->close();
pack.c->connected = false;
}
if(pack.shutdownServer)
{
logNetwork->info("Client requested shutdown, server will close itself...");
srv.state = EServerState::SHUTDOWN;
return;
}
else if(srv.connections.empty())
{
logNetwork->error("Last connection lost, server will close itself...");
srv->state = EServerState::SHUTDOWN;
srv.state = EServerState::SHUTDOWN;
}
else if(c == srv->hostClient)
else if(pack.c == srv.hostClient)
{
auto ph = std::make_unique<LobbyChangeHost>();
auto newHost = *RandomGeneratorUtil::nextItem(srv->connections, CRandomGenerator::getDefault());
auto newHost = *RandomGeneratorUtil::nextItem(srv.connections, CRandomGenerator::getDefault());
ph->newHostConnectionId = newHost->connectionID;
srv->addToAnnounceQueue(std::move(ph));
srv.addToAnnounceQueue(std::move(ph));
}
srv->updateAndPropagateLobbyState();
srv.updateAndPropagateLobbyState();
}
bool LobbyChatMessage::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitLobbyChatMessage(LobbyChatMessage & pack)
{
return true;
result = true;
}
bool LobbySetMap::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbySetMap(LobbySetMap & pack)
{
if(srv->state != EServerState::LOBBY)
return false;
srv->updateStartInfoOnMapChange(mapInfo, mapGenOpts);
return true;
}
bool LobbySetCampaign::applyOnServer(CVCMIServer * srv)
{
srv->si->mapname = ourCampaign->camp->header.filename;
srv->si->mode = StartInfo::CAMPAIGN;
srv->si->campState = ourCampaign;
srv->si->turnTime = 0;
bool isCurrentMapConquerable = ourCampaign->currentMap && ourCampaign->camp->conquerable(*ourCampaign->currentMap);
for(int i = 0; i < ourCampaign->camp->scenarios.size(); i++)
if(srv.state != EServerState::LOBBY)
{
if(ourCampaign->camp->conquerable(i))
result = false;
return;
}
srv.updateStartInfoOnMapChange(pack.mapInfo, pack.mapGenOpts);
result = true;
}
void ApplyOnServerNetPackVisitor::visitLobbySetCampaign(LobbySetCampaign & pack)
{
srv.si->mapname = pack.ourCampaign->camp->header.filename;
srv.si->mode = StartInfo::CAMPAIGN;
srv.si->campState = pack.ourCampaign;
srv.si->turnTime = 0;
bool isCurrentMapConquerable = pack.ourCampaign->currentMap && pack.ourCampaign->camp->conquerable(*pack.ourCampaign->currentMap);
for(int i = 0; i < pack.ourCampaign->camp->scenarios.size(); i++)
{
if(pack.ourCampaign->camp->conquerable(i))
{
if(!isCurrentMapConquerable || (isCurrentMapConquerable && i == *ourCampaign->currentMap))
if(!isCurrentMapConquerable || (isCurrentMapConquerable && i == *pack.ourCampaign->currentMap))
{
srv->setCampaignMap(i);
srv.setCampaignMap(i);
}
}
}
return true;
result = true;
}
bool LobbySetCampaignMap::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbySetCampaignMap(LobbySetCampaignMap & pack)
{
srv->setCampaignMap(mapId);
return true;
srv.setCampaignMap(pack.mapId);
result = true;
}
bool LobbySetCampaignBonus::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbySetCampaignBonus(LobbySetCampaignBonus & pack)
{
srv->setCampaignBonus(bonusId);
return true;
srv.setCampaignBonus(pack.bonusId);
result = true;
}
bool LobbyGuiAction::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitLobbyGuiAction(LobbyGuiAction & pack)
{
return srv->isClientHost(c->connectionID);
result = srv.isClientHost(pack.c->connectionID);
}
bool LobbyEndGame::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
{
return srv->isClientHost(c->connectionID);
result = srv.isClientHost(pack.c->connectionID);
}
bool LobbyEndGame::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
{
srv->prepareToRestart();
return true;
srv.prepareToRestart();
result = true;
}
void LobbyEndGame::applyOnServerAfterAnnounce(CVCMIServer * srv)
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyEndGame(LobbyEndGame & pack)
{
boost::unique_lock<boost::mutex> stateLock(srv->stateMutex);
for(auto & c : srv->connections)
boost::unique_lock<boost::mutex> stateLock(srv.stateMutex);
for(auto & c : srv.connections)
{
c->enterLobbyConnectionMode();
c->disableStackSendingByID();
}
}
bool LobbyStartGame::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
{
return srv->isClientHost(c->connectionID);
result = srv.isClientHost(pack.c->connectionID);
}
bool LobbyStartGame::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
{
try
{
srv->verifyStateBeforeStart(true);
srv.verifyStateBeforeStart(true);
}
catch(...)
{
return false;
result = false;
return;
}
// Server will prepare gamestate and we announce StartInfo to clients
if(!srv->prepareToStartGame())
return false;
if(!srv.prepareToStartGame())
{
result = false;
return;
}
initializedStartInfo = std::make_shared<StartInfo>(*srv->gh->getStartInfo(true));
initializedGameState = srv->gh->gameState();
pack.initializedStartInfo = std::make_shared<StartInfo>(*srv.gh->getStartInfo(true));
pack.initializedGameState = srv.gh->gameState();
return true;
result = true;
}
void LobbyStartGame::applyOnServerAfterAnnounce(CVCMIServer * srv)
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyStartGame(LobbyStartGame & pack)
{
if(clientId == -1) //do not restart game for single client only
srv->startGameImmidiately();
if(pack.clientId == -1) //do not restart game for single client only
srv.startGameImmidiately();
else
{
for(auto & c : srv->connections)
for(auto & c : srv.connections)
{
if(c->connectionID == clientId)
if(c->connectionID == pack.clientId)
{
c->enterGameplayConnectionMode(srv->gh->gameState());
srv->reconnectPlayer(clientId);
c->enterGameplayConnectionMode(srv.gh->gameState());
srv.reconnectPlayer(pack.clientId);
}
}
}
}
bool LobbyChangeHost::checkClientPermissions(CVCMIServer * srv) const
void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack)
{
return srv->isClientHost(c->connectionID);
result = srv.isClientHost(pack.c->connectionID);
}
bool LobbyChangeHost::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack)
{
return true;
result = true;
}
bool LobbyChangeHost::applyOnServerAfterAnnounce(CVCMIServer * srv)
void ApplyOnServerAfterAnnounceNetPackVisitor::visitLobbyChangeHost(LobbyChangeHost & pack)
{
return srv->passHost(newHostConnectionId);
}
bool LobbyChangePlayerOption::checkClientPermissions(CVCMIServer * srv) const
{
if(srv->isClientHost(c->connectionID))
return true;
if(vstd::contains(srv->getAllClientPlayers(c->connectionID), color))
return true;
return false;
}
bool LobbyChangePlayerOption::applyOnServer(CVCMIServer * srv)
{
switch(what)
auto result = srv.passHost(pack.newHostConnectionId);
if(!result)
{
case TOWN:
srv->optionNextCastle(color, direction);
logGlobal->error("passHost returned false. What does it mean?");
}
}
void ClientPermissionsCheckerNetPackVisitor::visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack)
{
if(srv.isClientHost(pack.c->connectionID))
{
result = true;
return;
}
if(vstd::contains(srv.getAllClientPlayers(pack.c->connectionID), pack.color))
{
result = true;
return;
}
result = false;
}
void ApplyOnServerNetPackVisitor::visitLobbyChangePlayerOption(LobbyChangePlayerOption & pack)
{
switch(pack.what)
{
case LobbyChangePlayerOption::TOWN:
srv.optionNextCastle(pack.color, pack.direction);
break;
case HERO:
srv->optionNextHero(color, direction);
case LobbyChangePlayerOption::HERO:
srv.optionNextHero(pack.color, pack.direction);
break;
case BONUS:
srv->optionNextBonus(color, direction);
case LobbyChangePlayerOption::BONUS:
srv.optionNextBonus(pack.color, pack.direction);
break;
}
return true;
result = true;
}
bool LobbySetPlayer::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbySetPlayer(LobbySetPlayer & pack)
{
srv->setPlayer(clickedColor);
return true;
srv.setPlayer(pack.clickedColor);
result = true;
}
bool LobbySetTurnTime::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbySetTurnTime(LobbySetTurnTime & pack)
{
srv->si->turnTime = turnTime;
return true;
srv.si->turnTime = pack.turnTime;
result = true;
}
bool LobbySetDifficulty::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbySetDifficulty(LobbySetDifficulty & pack)
{
srv->si->difficulty = vstd::abetween(difficulty, 0, 4);
return true;
srv.si->difficulty = vstd::abetween(pack.difficulty, 0, 4);
result = true;
}
bool LobbyForceSetPlayer::applyOnServer(CVCMIServer * srv)
void ApplyOnServerNetPackVisitor::visitLobbyForceSetPlayer(LobbyForceSetPlayer & pack)
{
srv->si->playerInfos[targetPlayerColor].connectedPlayerIDs.insert(targetConnectedPlayer);
return true;
srv.si->playerInfos[pack.targetPlayerColor].connectedPlayerIDs.insert(pack.targetConnectedPlayer);
result = true;
}

View File

@ -8,7 +8,7 @@
*
*/
#include "StdInc.h"
#include "../lib/NetPacks.h"
#include "ServerNetPackVisitors.h"
#include "CGameHandler.h"
#include "../lib/IGameCallback.h"
@ -22,384 +22,330 @@
#include "../lib/spells/ISpellMechanics.h"
#include "../lib/serializer/Cast.h"
bool CPackForServer::isPlayerOwns(CGameHandler * gh, ObjectInstanceID id)
void ApplyGhNetPackVisitor::visitSaveGame(SaveGame & pack)
{
return gh->getPlayerAt(c) == gh->getOwner(id);
gh.save(pack.fname);
logGlobal->info("Game has been saved as %s", pack.fname);
result = true;
}
void CPackForServer::throwNotAllowedAction()
void ApplyGhNetPackVisitor::visitEndTurn(EndTurn & pack)
{
if(c)
PlayerColor currentPlayer = gs.currentPlayer;
if(pack.player != currentPlayer)
{
SystemMessage temp_message("You are not allowed to perform this action!");
c->sendPack(&temp_message);
}
logNetwork->error("Player is not allowed to perform this action!");
throw ExceptionNotAllowedAction();
}
if(gh.getPlayerStatus(pack.player) == EPlayerStatus::INGAME)
gh.throwAndComplain(&pack, "pack.player attempted to end turn for another pack.player!");
void CPackForServer::wrongPlayerMessage(CGameHandler * gh, PlayerColor expectedplayer)
{
std::ostringstream oss;
oss << "You were identified as player " << gh->getPlayerAt(c) << " while expecting " << expectedplayer;
logNetwork->error(oss.str());
if(c)
{
SystemMessage temp_message(oss.str());
c->sendPack(&temp_message);
}
}
logGlobal->debug("pack.player attempted to end turn after game over. Ignoring this request.");
void CPackForServer::throwOnWrongOwner(CGameHandler * gh, ObjectInstanceID id)
{
if(!isPlayerOwns(gh, id))
{
wrongPlayerMessage(gh, gh->getOwner(id));
throwNotAllowedAction();
}
}
void CPackForServer::throwOnWrongPlayer(CGameHandler * gh, PlayerColor player)
{
if(!gh->hasPlayerAt(player, c) && player != gh->getPlayerAt(c))
{
wrongPlayerMessage(gh, player);
throwNotAllowedAction();
}
}
void CPackForServer::throwAndComplain(CGameHandler * gh, std::string txt)
{
gh->complain(txt);
throwNotAllowedAction();
}
CGameState * CPackForServer::GS(CGameHandler * gh)
{
return gh->gs;
}
bool SaveGame::applyGh(CGameHandler * gh)
{
gh->save(fname);
logGlobal->info("Game has been saved as %s", fname);
return true;
}
bool EndTurn::applyGh(CGameHandler * gh)
{
PlayerColor currentPlayer = GS(gh)->currentPlayer;
if(player != currentPlayer)
{
if(gh->getPlayerStatus(player) == EPlayerStatus::INGAME)
throwAndComplain(gh, "Player attempted to end turn for another player!");
logGlobal->debug("Player attempted to end turn after game over. Ignoring this request.");
return true;
result = true;
return;
}
throwOnWrongPlayer(gh, player);
if(gh->queries.topQuery(player))
throwAndComplain(gh, "Cannot end turn before resolving queries!");
gh.throwOnWrongPlayer(&pack, pack.player);
if(gh.queries.topQuery(pack.player))
gh.throwAndComplain(&pack, "Cannot end turn before resolving queries!");
gh->states.setFlag(GS(gh)->currentPlayer, &PlayerStatus::makingTurn, false);
return true;
gh.states.setFlag(gs.currentPlayer, &PlayerStatus::makingTurn, false);
result = true;
}
bool DismissHero::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitDismissHero(DismissHero & pack)
{
throwOnWrongOwner(gh, hid);
return gh->removeObject(gh->getObj(hid));
gh.throwOnWrongOwner(&pack, pack.hid);
result = gh.removeObject(gh.getObj(pack.hid));
}
bool MoveHero::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitMoveHero(MoveHero & pack)
{
throwOnWrongOwner(gh, hid);
return gh->moveHero(hid, dest, 0, transit, gh->getPlayerAt(c));
gh.throwOnWrongOwner(&pack, pack.hid);
result = gh.moveHero(pack.hid, pack.dest, 0, pack.transit, gh.getPlayerAt(pack.c));
}
bool CastleTeleportHero::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitCastleTeleportHero(CastleTeleportHero & pack)
{
throwOnWrongOwner(gh, hid);
gh.throwOnWrongOwner(&pack, pack.hid);
return gh->teleportHero(hid, dest, source, gh->getPlayerAt(c));
result = gh.teleportHero(pack.hid, pack.dest, pack.source, gh.getPlayerAt(pack.c));
}
bool ArrangeStacks::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitArrangeStacks(ArrangeStacks & pack)
{
//checks for owning in the gh func
return gh->arrangeStacks(id1, id2, what, p1, p2, val, gh->getPlayerAt(c));
result = gh.arrangeStacks(pack.id1, pack.id2, pack.what, pack.p1, pack.p2, pack.val, gh.getPlayerAt(pack.c));
}
bool BulkMoveArmy::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitBulkMoveArmy(BulkMoveArmy & pack)
{
return gh->bulkMoveArmy(srcArmy, destArmy, srcSlot);
result = gh.bulkMoveArmy(pack.srcArmy, pack.destArmy, pack.srcSlot);
}
bool BulkSplitStack::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitBulkSplitStack(BulkSplitStack & pack)
{
return gh->bulkSplitStack(src, srcOwner, amount);
result = gh.bulkSplitStack(pack.src, pack.srcOwner, pack.amount);
}
bool BulkMergeStacks::applyGh(CGameHandler* gh)
void ApplyGhNetPackVisitor::visitBulkMergeStacks(BulkMergeStacks & pack)
{
return gh->bulkMergeStacks(src, srcOwner);
result = gh.bulkMergeStacks(pack.src, pack.srcOwner);
}
bool BulkSmartSplitStack::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitBulkSmartSplitStack(BulkSmartSplitStack & pack)
{
return gh->bulkSmartSplitStack(src, srcOwner);
result = gh.bulkSmartSplitStack(pack.src, pack.srcOwner);
}
bool DisbandCreature::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitDisbandCreature(DisbandCreature & pack)
{
throwOnWrongOwner(gh, id);
return gh->disbandCreature(id, pos);
gh.throwOnWrongOwner(&pack, pack.id);
result = gh.disbandCreature(pack.id, pack.pos);
}
bool BuildStructure::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitBuildStructure(BuildStructure & pack)
{
throwOnWrongOwner(gh, tid);
return gh->buildStructure(tid, bid);
gh.throwOnWrongOwner(&pack, pack.tid);
result = gh.buildStructure(pack.tid, pack.bid);
}
bool RecruitCreatures::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitRecruitCreatures(RecruitCreatures & pack)
{
return gh->recruitCreatures(tid, dst, crid, amount, level);
result = gh.recruitCreatures(pack.tid, pack.dst, pack.crid, pack.amount, pack.level);
}
bool UpgradeCreature::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitUpgradeCreature(UpgradeCreature & pack)
{
throwOnWrongOwner(gh, id);
return gh->upgradeCreature(id, pos, cid);
gh.throwOnWrongOwner(&pack, pack.id);
result = gh.upgradeCreature(pack.id, pack.pos, pack.cid);
}
bool GarrisonHeroSwap::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
{
const CGTownInstance * town = gh->getTown(tid);
if(!isPlayerOwns(gh, tid) && !(town->garrisonHero && isPlayerOwns(gh, town->garrisonHero->id)))
throwNotAllowedAction(); //neither town nor garrisoned hero (if present) is ours
return gh->garrisonSwap(tid);
const CGTownInstance * town = gh.getTown(pack.tid);
if(!gh.isPlayerOwns(&pack, pack.tid) && !(town->garrisonHero && gh.isPlayerOwns(&pack, town->garrisonHero->id)))
gh.throwNotAllowedAction(&pack); //neither town nor garrisoned hero (if present) is ours
result = gh.garrisonSwap(pack.tid);
}
bool ExchangeArtifacts::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
{
throwOnWrongPlayer(gh, src.owningPlayer()); //second hero can be ally
return gh->moveArtifact(src, dst);
gh.throwOnWrongPlayer(&pack, pack.src.owningPlayer()); //second hero can be ally
result = gh.moveArtifact(pack.src, pack.dst);
}
bool BulkExchangeArtifacts::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
{
const CGHeroInstance * pSrcHero = gh->getHero(srcHero);
throwOnWrongPlayer(gh, pSrcHero->getOwner());
return gh->bulkMoveArtifacts(srcHero, dstHero, swap);
const CGHeroInstance * pSrcHero = gh.getHero(pack.srcHero);
gh.throwOnWrongPlayer(&pack, pSrcHero->getOwner());
result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap);
}
bool AssembleArtifacts::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
{
throwOnWrongOwner(gh, heroID);
return gh->assembleArtifacts(heroID, artifactSlot, assemble, assembleTo);
gh.throwOnWrongOwner(&pack, pack.heroID);
result = gh.assembleArtifacts(pack.heroID, pack.artifactSlot, pack.assemble, pack.assembleTo);
}
bool BuyArtifact::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitBuyArtifact(BuyArtifact & pack)
{
throwOnWrongOwner(gh, hid);
return gh->buyArtifact(hid, aid);
gh.throwOnWrongOwner(&pack, pack.hid);
result = gh.buyArtifact(pack.hid, pack.aid);
}
bool TradeOnMarketplace::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitTradeOnMarketplace(TradeOnMarketplace & pack)
{
const CGObjectInstance * market = gh->getObj(marketId);
const CGObjectInstance * market = gh.getObj(pack.marketId);
if(!market)
throwAndComplain(gh, "Invalid market object");
const CGHeroInstance * hero = gh->getHero(heroId);
gh.throwAndComplain(&pack, "Invalid market object");
const CGHeroInstance * hero = gh.getHero(pack.heroId);
//market must be owned or visited
const IMarket * m = IMarket::castFrom(market);
if(!m)
throwAndComplain(gh, "market is not-a-market! :/");
gh.throwAndComplain(&pack, "market is not-a-market! :/");
PlayerColor player = market->tempOwner;
if(player >= PlayerColor::PLAYER_LIMIT)
player = gh->getTile(market->visitablePos())->visitableObjects.back()->tempOwner;
player = gh.getTile(market->visitablePos())->visitableObjects.back()->tempOwner;
if(player >= PlayerColor::PLAYER_LIMIT)
throwAndComplain(gh, "No player can use this market!");
gh.throwAndComplain(&pack, "No player can use this market!");
bool allyTownSkillTrade = (mode == EMarketMode::RESOURCE_SKILL && gh->getPlayerRelations(player, hero->tempOwner) == PlayerRelations::ALLIES);
bool allyTownSkillTrade = (pack.mode == EMarketMode::RESOURCE_SKILL && gh.getPlayerRelations(player, hero->tempOwner) == PlayerRelations::ALLIES);
if(hero && (!(player == hero->tempOwner || allyTownSkillTrade)
|| hero->visitablePos() != market->visitablePos()))
throwAndComplain(gh, "This hero can't use this marketplace!");
gh.throwAndComplain(&pack, "This hero can't use this marketplace!");
if(!allyTownSkillTrade)
throwOnWrongPlayer(gh, player);
gh.throwOnWrongPlayer(&pack, player);
bool result = true;
result = true;
switch(mode)
switch(pack.mode)
{
case EMarketMode::RESOURCE_RESOURCE:
for(int i = 0; i < r1.size(); ++i)
result &= gh->tradeResources(m, val[i], player, r1[i], r2[i]);
for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.tradeResources(m, pack.val[i], player, pack.r1[i], pack.r2[i]);
break;
case EMarketMode::RESOURCE_PLAYER:
for(int i = 0; i < r1.size(); ++i)
result &= gh->sendResources(val[i], player, static_cast<Res::ERes>(r1[i]), PlayerColor(r2[i]));
for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.sendResources(pack.val[i], player, static_cast<Res::ERes>(pack.r1[i]), PlayerColor(pack.r2[i]));
break;
case EMarketMode::CREATURE_RESOURCE:
for(int i = 0; i < r1.size(); ++i)
result &= gh->sellCreatures(val[i], m, hero, SlotID(r1[i]), static_cast<Res::ERes>(r2[i]));
for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.sellCreatures(pack.val[i], m, hero, SlotID(pack.r1[i]), static_cast<Res::ERes>(pack.r2[i]));
break;
case EMarketMode::RESOURCE_ARTIFACT:
for(int i = 0; i < r1.size(); ++i)
result &= gh->buyArtifact(m, hero, static_cast<Res::ERes>(r1[i]), ArtifactID(r2[i]));
for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.buyArtifact(m, hero, static_cast<Res::ERes>(pack.r1[i]), ArtifactID(pack.r2[i]));
break;
case EMarketMode::ARTIFACT_RESOURCE:
for(int i = 0; i < r1.size(); ++i)
result &= gh->sellArtifact(m, hero, ArtifactInstanceID(r1[i]), static_cast<Res::ERes>(r2[i]));
for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.sellArtifact(m, hero, ArtifactInstanceID(pack.r1[i]), static_cast<Res::ERes>(pack.r2[i]));
break;
case EMarketMode::CREATURE_UNDEAD:
for(int i = 0; i < r1.size(); ++i)
result &= gh->transformInUndead(m, hero, SlotID(r1[i]));
for(int i = 0; i < pack.r1.size(); ++i)
result &= gh.transformInUndead(m, hero, SlotID(pack.r1[i]));
break;
case EMarketMode::RESOURCE_SKILL:
for(int i = 0; i < r2.size(); ++i)
result &= gh->buySecSkill(m, hero, SecondarySkill(r2[i]));
for(int i = 0; i < pack.r2.size(); ++i)
result &= gh.buySecSkill(m, hero, SecondarySkill(pack.r2[i]));
break;
case EMarketMode::CREATURE_EXP:
{
std::vector<SlotID> slotIDs(r1.begin(), r1.end());
std::vector<ui32> count(val.begin(), val.end());
return gh->sacrificeCreatures(m, hero, slotIDs, count);
std::vector<SlotID> slotIDs(pack.r1.begin(), pack.r1.end());
std::vector<ui32> count(pack.val.begin(), pack.val.end());
result = gh.sacrificeCreatures(m, hero, slotIDs, count);
return;
}
case EMarketMode::ARTIFACT_EXP:
{
std::vector<ArtifactPosition> positions(r1.begin(), r1.end());
return gh->sacrificeArtifact(m, hero, positions);
std::vector<ArtifactPosition> positions(pack.r1.begin(), pack.r1.end());
result = gh.sacrificeArtifact(m, hero, positions);
return;
}
default:
throwAndComplain(gh, "Unknown exchange mode!");
gh.throwAndComplain(&pack, "Unknown exchange pack.mode!");
}
return result;
}
bool SetFormation::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitSetFormation(SetFormation & pack)
{
throwOnWrongOwner(gh, hid);
return gh->setFormation(hid, formation);
gh.throwOnWrongOwner(&pack, pack.hid);
result = gh.setFormation(pack.hid, pack.formation);
}
bool HireHero::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitHireHero(HireHero & pack)
{
const CGObjectInstance * obj = gh->getObj(tid);
const CGObjectInstance * obj = gh.getObj(pack.tid);
const CGTownInstance * town = dynamic_ptr_cast<CGTownInstance>(obj);
if(town && PlayerRelations::ENEMIES == gh->getPlayerRelations(obj->tempOwner, gh->getPlayerAt(c)))
throwAndComplain(gh, "Can't buy hero in enemy town!");
if(town && PlayerRelations::ENEMIES == gh.getPlayerRelations(obj->tempOwner, gh.getPlayerAt(pack.c)))
gh.throwAndComplain(&pack, "Can't buy hero in enemy town!");
return gh->hireHero(obj, hid, player);
result = gh.hireHero(obj, pack.hid, pack.player);
}
bool BuildBoat::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitBuildBoat(BuildBoat & pack)
{
if(gh->getPlayerRelations(gh->getOwner(objid), gh->getPlayerAt(c)) == PlayerRelations::ENEMIES)
throwAndComplain(gh, "Can't build boat at enemy shipyard");
if(gh.getPlayerRelations(gh.getOwner(pack.objid), gh.getPlayerAt(pack.c)) == PlayerRelations::ENEMIES)
gh.throwAndComplain(&pack, "Can't build boat at enemy shipyard");
return gh->buildBoat(objid);
result = gh.buildBoat(pack.objid);
}
bool QueryReply::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitQueryReply(QueryReply & pack)
{
auto playerToConnection = gh->connections.find(player);
if(playerToConnection == gh->connections.end())
throwAndComplain(gh, "No such player!");
if(!vstd::contains(playerToConnection->second, c))
throwAndComplain(gh, "Message came from wrong connection!");
if(qid == QueryID(-1))
throwAndComplain(gh, "Cannot answer the query with id -1!");
auto playerToConnection = gh.connections.find(pack.player);
if(playerToConnection == gh.connections.end())
gh.throwAndComplain(&pack, "No such pack.player!");
if(!vstd::contains(playerToConnection->second, pack.c))
gh.throwAndComplain(&pack, "Message came from wrong connection!");
if(pack.qid == QueryID(-1))
gh.throwAndComplain(&pack, "Cannot answer the query with pack.id -1!");
assert(vstd::contains(gh->states.players, player));
return gh->queryReply(qid, reply, player);
assert(vstd::contains(gh.states.players, pack.player));
result = gh.queryReply(pack.qid, pack.reply, pack.player);
}
bool MakeAction::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitMakeAction(MakeAction & pack)
{
const BattleInfo * b = GS(gh)->curB;
const BattleInfo * b = gs.curB;
if(!b)
throwNotAllowedAction();
gh.throwNotAllowedAction(&pack);
if(b->tacticDistance)
{
if(ba.actionType != EActionType::WALK && ba.actionType != EActionType::END_TACTIC_PHASE
&& ba.actionType != EActionType::RETREAT && ba.actionType != EActionType::SURRENDER)
throwNotAllowedAction();
if(!vstd::contains(gh->connections[b->sides[b->tacticsSide].color], c))
throwNotAllowedAction();
if(pack.ba.actionType != EActionType::WALK && pack.ba.actionType != EActionType::END_TACTIC_PHASE
&& pack.ba.actionType != EActionType::RETREAT && pack.ba.actionType != EActionType::SURRENDER)
gh.throwNotAllowedAction(&pack);
if(!vstd::contains(gh.connections[b->sides[b->tacticsSide].color], pack.c))
gh.throwNotAllowedAction(&pack);
}
else
{
auto active = b->battleActiveUnit();
if(!active)
throwNotAllowedAction();
gh.throwNotAllowedAction(&pack);
auto unitOwner = b->battleGetOwner(active);
if(!vstd::contains(gh->connections[unitOwner], c))
throwNotAllowedAction();
if(!vstd::contains(gh.connections[unitOwner], pack.c))
gh.throwNotAllowedAction(&pack);
}
return gh->makeBattleAction(ba);
result = gh.makeBattleAction(pack.ba);
}
bool MakeCustomAction::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitMakeCustomAction(MakeCustomAction & pack)
{
const BattleInfo * b = GS(gh)->curB;
const BattleInfo * b = gs.curB;
if(!b)
throwNotAllowedAction();
gh.throwNotAllowedAction(&pack);
if(b->tacticDistance)
throwNotAllowedAction();
gh.throwNotAllowedAction(&pack);
auto active = b->battleActiveUnit();
if(!active)
throwNotAllowedAction();
gh.throwNotAllowedAction(&pack);
auto unitOwner = b->battleGetOwner(active);
if(!vstd::contains(gh->connections[unitOwner], c))
throwNotAllowedAction();
if(ba.actionType != EActionType::HERO_SPELL)
throwNotAllowedAction();
return gh->makeCustomAction(ba);
if(!vstd::contains(gh.connections[unitOwner], pack.c))
gh.throwNotAllowedAction(&pack);
if(pack.ba.actionType != EActionType::HERO_SPELL)
gh.throwNotAllowedAction(&pack);
result = gh.makeCustomAction(pack.ba);
}
bool DigWithHero::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitDigWithHero(DigWithHero & pack)
{
throwOnWrongOwner(gh, id);
return gh->dig(gh->getHero(id));
gh.throwOnWrongOwner(&pack, pack.id);
result = gh.dig(gh.getHero(pack.id));
}
bool CastAdvSpell::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitCastAdvSpell(CastAdvSpell & pack)
{
throwOnWrongOwner(gh, hid);
gh.throwOnWrongOwner(&pack, pack.hid);
const CSpell * s = sid.toSpell();
const CSpell * s = pack.sid.toSpell();
if(!s)
throwNotAllowedAction();
const CGHeroInstance * h = gh->getHero(hid);
gh.throwNotAllowedAction(&pack);
const CGHeroInstance * h = gh.getHero(pack.hid);
if(!h)
throwNotAllowedAction();
gh.throwNotAllowedAction(&pack);
AdventureSpellCastParameters p;
p.caster = h;
p.pos = pos;
p.pos = pack.pos;
return s->adventureCast(gh->spellEnv, p);
result = s->adventureCast(gh.spellEnv, p);
}
bool PlayerMessage::applyGh(CGameHandler * gh)
void ApplyGhNetPackVisitor::visitPlayerMessage(PlayerMessage & pack)
{
if(!player.isSpectator()) // TODO: clearly not a great way to verify permissions
throwOnWrongPlayer(gh, player);
if(!pack.player.isSpectator()) // TODO: clearly not a great way to verify permissions
gh.throwOnWrongPlayer(&pack, pack.player);
gh->playerMessage(player, text, currObj);
return true;
gh.playerMessage(pack.player, pack.text, pack.currObj);
result = true;
}

View File

@ -0,0 +1,61 @@
/*
* ServerNetPackVisitors.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../lib/NetPackVisitor.h"
class ApplyGhNetPackVisitor : public VCMI_LIB_WRAP_NAMESPACE(ICPackVisitor)
{
private:
bool result;
CGameHandler & gh;
CGameState & gs;
public:
ApplyGhNetPackVisitor(CGameHandler & gh, CGameState & gs)
:gh(gh), gs(gs), result(false)
{
}
bool getResult() const
{
return result;
}
virtual void visitSaveGame(SaveGame & pack) override;
virtual void visitEndTurn(EndTurn & pack) override;
virtual void visitDismissHero(DismissHero & pack) override;
virtual void visitMoveHero(MoveHero & pack) override;
virtual void visitCastleTeleportHero(CastleTeleportHero & pack) override;
virtual void visitArrangeStacks(ArrangeStacks & pack) override;
virtual void visitBulkMoveArmy(BulkMoveArmy & pack) override;
virtual void visitBulkSplitStack(BulkSplitStack & pack) override;
virtual void visitBulkMergeStacks(BulkMergeStacks & pack) override;
virtual void visitBulkSmartSplitStack(BulkSmartSplitStack & pack) override;
virtual void visitDisbandCreature(DisbandCreature & pack) override;
virtual void visitBuildStructure(BuildStructure & pack) override;
virtual void visitRecruitCreatures(RecruitCreatures & pack) override;
virtual void visitUpgradeCreature(UpgradeCreature & pack) override;
virtual void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) override;
virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) override;
virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) override;
virtual void visitAssembleArtifacts(AssembleArtifacts & pack) override;
virtual void visitBuyArtifact(BuyArtifact & pack) override;
virtual void visitTradeOnMarketplace(TradeOnMarketplace & pack) override;
virtual void visitSetFormation(SetFormation & pack) override;
virtual void visitHireHero(HireHero & pack) override;
virtual void visitBuildBoat(BuildBoat & pack) override;
virtual void visitQueryReply(QueryReply & pack) override;
virtual void visitMakeAction(MakeAction & pack) override;
virtual void visitMakeCustomAction(MakeCustomAction & pack) override;
virtual void visitDigWithHero(DigWithHero & pack) override;
virtual void visitCastAdvSpell(CastAdvSpell & pack) override;
virtual void visitPlayerMessage(PlayerMessage & pack) override;
};