1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Full rework of pre-game interface and networking

New features for players:
* Loading for multiplayer. Any save could be used for multiplayer.
* Restart for multiplayer. All clients will restart together.
* Loading from single save.
* Hotseat mixed with network game. Multiple players per client.
* Now connection to server could be cancelled.
* Return to menu on disconnections instead of crashes.
* Restoring of last selected map, save or campaign on next run.

TLDR on important changes in engine code:
* UI: work with server separated from UI
* UI: all explitic blitting replaced with IntObject's
* UI: all new code use smart pointers instead of DISPOSE
* Gameplay always start through lobby controlled by server.
* Threads receiving netpacks now shared for lobby and gameplay.
* Campaigns: heroes for crossover now serialized as JsonNode.
This commit is contained in:
Arseniy Shestakov
2018-01-05 20:21:07 +03:00
parent 14f03e22da
commit ac66fc7f42
85 changed files with 8808 additions and 7938 deletions

View File

@@ -31,7 +31,7 @@ void CPackForServer::throwNotAllowedAction()
if(c)
{
SystemMessage temp_message("You are not allowed to perform this action!");
*c << &temp_message;
c->sendPack(&temp_message);
}
logNetwork->error("Player is not allowed to perform this action!");
throw ExceptionNotAllowedAction();
@@ -45,7 +45,7 @@ void CPackForServer::wrongPlayerMessage(CGameHandler * gh, PlayerColor expectedp
if(c)
{
SystemMessage temp_message(oss.str());
*c << &temp_message;
c->sendPack(&temp_message);
}
}
@@ -92,18 +92,6 @@ bool CommitPackage::applyGh(CGameHandler * gh)
return true;
}
bool CloseServer::applyGh(CGameHandler * gh)
{
gh->close();
return true;
}
bool LeaveGame::applyGh(CGameHandler * gh)
{
gh->playerLeftGame(c->connectionID);
return true;
}
bool EndTurn::applyGh(CGameHandler * gh)
{
PlayerColor player = GS(gh)->currentPlayer;
@@ -292,7 +280,7 @@ bool QueryReply::applyGh(CGameHandler * gh)
auto playerToConnection = gh->connections.find(player);
if(playerToConnection == gh->connections.end())
throwAndCompain(gh, "No such player!");
if(playerToConnection->second != c)
if(!vstd::contains(playerToConnection->second, c))
throwAndCompain(gh, "Message came from wrong connection!");
if(qid == QueryID(-1))
throwAndCompain(gh, "Cannot answer the query with id -1!");
@@ -312,17 +300,18 @@ bool MakeAction::applyGh(CGameHandler * gh)
if(ba.actionType != EActionType::WALK && ba.actionType != EActionType::END_TACTIC_PHASE
&& ba.actionType != EActionType::RETREAT && ba.actionType != EActionType::SURRENDER)
throwNotAllowedAction();
if(gh->connections[b->sides[b->tacticsSide].color] != c)
if(!vstd::contains(gh->connections[b->sides[b->tacticsSide].color], c))
throwNotAllowedAction();
}
else
{
auto active = b->battleActiveUnit();
if(!active) throwNotAllowedAction();
if(!active)
throwNotAllowedAction();
auto unitOwner = b->battleGetOwner(active);
if(gh->connections[unitOwner] != c) throwNotAllowedAction();
if(!vstd::contains(gh->connections[unitOwner], c))
throwNotAllowedAction();
}
return gh->makeBattleAction(ba);
}
@@ -337,7 +326,7 @@ bool MakeCustomAction::applyGh(CGameHandler * gh)
if(!active)
throwNotAllowedAction();
auto unitOwner = b->battleGetOwner(active);
if(gh->connections[unitOwner] != c)
if(!vstd::contains(gh->connections[unitOwner], c))
throwNotAllowedAction();
if(ba.actionType != EActionType::HERO_SPELL)
throwNotAllowedAction();
@@ -373,7 +362,7 @@ bool PlayerMessage::applyGh(CGameHandler * gh)
if(!player.isSpectator()) // TODO: clearly not a great way to verify permissions
{
throwOnWrongPlayer(gh, player);
if(gh->getPlayerAt(c) != player)
if(gh->getPlayerAt(this->c) != player)
throwNotAllowedAction();
}
gh->playerMessage(player, text, currObj);