2018-09-27 00:22:41 +02:00

1817 lines
56 KiB
C++

// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include <map>
#include "commander.h"
#include "world.h"
#include "unit.h"
#include "conversion.h"
#include "upgrade.h"
#include "command.h"
#include "command_type.h"
#include "network_manager.h"
#include "console.h"
#include "config.h"
#include "platform_util.h"
#include "game.h"
#include "game_settings.h"
#include "game.h"
using namespace
Shared::Graphics;
using namespace
Shared::Util;
using namespace
Shared::Platform;
namespace
Glest {
namespace
Game {
// =====================================================
// class Commander
// =====================================================
Commander::Commander() {
this->world = NULL;
this->
pauseNetworkCommands = false;
}
Commander::~
Commander() {
}
void
Commander::init(World * world) {
this->world = world;
}
bool
Commander::canSubmitCommandType(const Unit * unit,
const CommandType * commandType) const {
bool
canSubmitCommand = true;
const MorphCommandType *
mct = dynamic_cast <const
MorphCommandType *>(commandType);
if (mct && unit->getCommandSize() > 0) {
Command *
cur_command = unit->getCurrCommand();
if (cur_command != NULL) {
const MorphCommandType *
cur_mct = dynamic_cast <const
MorphCommandType *>(cur_command->getCommandType());
if (cur_mct && unit->getCurrSkill()
&& unit->getCurrSkill()->getClass() == scMorph) {
const UnitType *
morphUnitType = mct->getMorphUnit();
const UnitType *
cur_morphUnitType = cur_mct->getMorphUnit();
if (morphUnitType != NULL && cur_morphUnitType != NULL
&& morphUnitType->getId() ==
cur_morphUnitType->getId()) {
canSubmitCommand = false;
}
}
}
}
return
canSubmitCommand;
}
std::pair < CommandResult,
string > Commander::tryGiveCommand(const Selection * selection,
const CommandType * commandType,
const Vec2i & pos,
const UnitType * unitType,
CardinalDir facing, bool tryQueue,
Unit * targetUnit) const {
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__);
if (this->pauseNetworkCommands == true) {
return std::pair < CommandResult, string >(crFailUndefined, "");
}
std::pair <
CommandResult,
string >
result(crFailUndefined, "");
if (selection->isEmpty() == false && commandType != NULL) {
Vec2i
refPos;
CommandResultContainer
results;
refPos = world->getMap()->computeRefPos(selection);
const Unit *
builderUnit =
world->getMap()->findClosestUnitToPos(selection, pos, unitType);
int
builderUnitId = builderUnit->getId();
CommandStateType
commandStateType = cst_None;
int
commandStateValue = -1;
int
unitCommandGroupId = -1;
if (selection->getCount() > 1) {
unitCommandGroupId = world->getNextCommandGroupId();
}
//give orders to all selected units
for (int i = 0; i < selection->getCount(); ++i) {
const Unit *
unit = selection->getUnit(i);
std::pair < CommandResult, string > resultCur(crFailUndefined,
"");
bool
canSubmitCommand = canSubmitCommandType(unit, commandType);
if (canSubmitCommand == true) {
int
unitId = unit->getId();
Vec2i
currPos =
world->getMap()->computeDestPos(refPos,
unit->
getPosNotThreadSafe(),
pos);
Vec2i
usePos = currPos;
const CommandType *
useCommandtype = commandType;
if (dynamic_cast <
const BuildCommandType *>(commandType) != NULL) {
usePos = pos;
if (builderUnit->getId() != unitId) {
useCommandtype =
unit->getType()->
getFirstRepairCommand(unitType);
commandStateType = cst_linkedUnit;
commandStateValue = builderUnitId;
} else {
commandStateType = cst_None;
commandStateValue = -1;
}
}
if (useCommandtype != NULL) {
NetworkCommand
networkCommand(this->world, nctGiveCommand, unitId,
useCommandtype->getId(), usePos,
unitType->getId(),
(targetUnit !=
NULL ? targetUnit->getId() : -1),
facing, tryQueue, commandStateType,
commandStateValue, unitCommandGroupId);
//every unit is ordered to a the position
resultCur = pushNetworkCommand(&networkCommand);
}
}
results.push_back(resultCur);
}
return computeResult(results);
}
return std::pair < CommandResult, string >(crFailUndefined, "");
}
std::pair < CommandResult,
string > Commander::tryGiveCommand(const Unit * unit,
const CommandType * commandType,
const Vec2i & pos,
const UnitType * unitType,
CardinalDir facing, bool tryQueue,
Unit * targetUnit,
int unitGroupCommandId) const {
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__);
if (this->pauseNetworkCommands == true) {
return std::pair < CommandResult, string >(crFailUndefined, "");
}
Chrono
chrono;
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled)
chrono.start();
assert(this->world != NULL);
assert(unit != NULL);
assert(commandType != NULL);
assert(unitType != NULL);
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s] Line: %d took msecs: %lld\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
std::pair < CommandResult, string > result(crFailUndefined, "");
bool
canSubmitCommand = canSubmitCommandType(unit, commandType);
if (canSubmitCommand == true) {
NetworkCommand
networkCommand(this->world, nctGiveCommand, unit->getId(),
commandType->getId(), pos, unitType->getId(),
(targetUnit != NULL ? targetUnit->getId() : -1),
facing, tryQueue, cst_None, -1, unitGroupCommandId);
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).enabled
&& chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s] Line: %d took msecs: %lld\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
result = pushNetworkCommand(&networkCommand);
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s] Line: %d took msecs: %lld\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
return result;
}
std::pair < CommandResult,
string > Commander::tryGiveCommand(const Selection * selection,
CommandClass commandClass,
const Vec2i & pos,
const Unit * targetUnit,
bool tryQueue) const {
if (this->pauseNetworkCommands == true) {
return std::pair < CommandResult, string >(crFailUndefined, "");
}
std::pair <
CommandResult,
string >
result(crFailUndefined, "");
if (selection->isEmpty() == false) {
Vec2i
refPos,
currPos;
CommandResultContainer
results;
refPos = world->getMap()->computeRefPos(selection);
int
unitCommandGroupId = -1;
if (selection->getCount() > 1) {
unitCommandGroupId = world->getNextCommandGroupId();
}
//give orders to all selected units
for (int i = 0; i < selection->getCount(); ++i) {
const Unit *
unit = selection->getUnit(i);
const CommandType *
ct = unit->getType()->getFirstCtOfClass(commandClass);
if (ct != NULL) {
std::pair < CommandResult,
string > resultCur(crFailUndefined, "");
bool
canSubmitCommand = canSubmitCommandType(unit, ct);
if (canSubmitCommand == true) {
int
targetId =
targetUnit ==
NULL ? Unit::invalidId : targetUnit->getId();
int
unitId = selection->getUnit(i)->getId();
Vec2i
currPos = world->getMap()->computeDestPos(refPos,
selection->
getUnit
(i)->
getPosNotThreadSafe
(), pos);
NetworkCommand
networkCommand(this->world, nctGiveCommand,
unitId, ct->getId(), currPos, -1,
targetId, -1, tryQueue, cst_None, -1,
unitCommandGroupId);
//every unit is ordered to a different pos
resultCur = pushNetworkCommand(&networkCommand);
}
results.push_back(resultCur);
} else {
results.push_back(std::pair < CommandResult,
string >(crFailUndefined, ""));
}
}
return computeResult(results);
} else {
return std::pair < CommandResult, string >(crFailUndefined, "");
}
}
std::pair < CommandResult,
string > Commander::tryGiveCommand(const Selection * selection,
const CommandType * commandType,
const Vec2i & pos,
const Unit * targetUnit,
bool tryQueue) const {
if (this->pauseNetworkCommands == true) {
return std::pair < CommandResult, string >(crFailUndefined, "");
}
std::pair <
CommandResult,
string >
result(crFailUndefined, "");
if (!selection->isEmpty() && commandType != NULL) {
Vec2i
refPos;
CommandResultContainer
results;
refPos = world->getMap()->computeRefPos(selection);
int
unitCommandGroupId = -1;
if (selection->getCount() > 1) {
unitCommandGroupId = world->getNextCommandGroupId();
}
//give orders to all selected units
for (int i = 0; i < selection->getCount(); ++i) {
const Unit *
unit = selection->getUnit(i);
assert(unit != NULL);
std::pair < CommandResult, string > resultCur(crFailUndefined,
"");
bool
canSubmitCommand = canSubmitCommandType(unit, commandType);
if (canSubmitCommand == true) {
int
targetId =
targetUnit ==
NULL ? Unit::invalidId : targetUnit->getId();
int
unitId = unit->getId();
Vec2i
currPos =
world->getMap()->computeDestPos(refPos,
unit->
getPosNotThreadSafe(),
pos);
NetworkCommand
networkCommand(this->world, nctGiveCommand, unitId,
commandType->getId(), currPos, -1,
targetId, -1, tryQueue, cst_None, -1,
unitCommandGroupId);
//every unit is ordered to a different position
resultCur = pushNetworkCommand(&networkCommand);
}
results.push_back(resultCur);
}
return computeResult(results);
} else {
return std::pair < CommandResult, string >(crFailUndefined, "");
}
}
//auto command
std::pair < CommandResult,
string > Commander::tryGiveCommand(const Selection * selection,
const Vec2i & pos,
const Unit * targetUnit,
bool tryQueue,
int unitCommandGroupId, bool isMove) const {
std::pair < CommandResult, string > result(crFailUndefined, "");
if (this->pauseNetworkCommands == true) {
return result;
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__);
if (selection->isEmpty() == false) {
Vec2i
refPos,
currPos;
CommandResultContainer
results;
if (unitCommandGroupId == -1 && selection->getCount() > 1) {
unitCommandGroupId = world->getNextCommandGroupId();
}
//give orders to all selected units
refPos = world->getMap()->computeRefPos(selection);
bool ignoreBuildings = false;
std::map<int, const CommandType*> command;
for (int i = 0; i < selection->getCount(); ++i) {
//every unit is ordered to a different pos
const Unit * unit = selection->getUnit(i);
assert(unit != NULL);
//get command type
const CommandType *commandType = unit->computeCommandType(pos, targetUnit);
if (commandType != NULL)
ignoreBuildings = true;
command[i] = commandType;
}
Game* game = world->getGame();
for (int i = 0; i < selection->getCount(); ++i) {
const Unit * unit = selection->getUnit(i);
const CommandType *commandType = command[i];
currPos = world->getMap()->computeDestPos(refPos, unit->getPosNotThreadSafe(), pos);
//give commands
if (commandType != NULL) {
if (isMove && commandType->commandTypeClass == CommandClass::ccAttack)
commandType = unit->getType()->getFirstCtOfClass(CommandClass::ccMove);
int targetId = targetUnit == NULL ? Unit::invalidId : targetUnit->getId();
int unitId = unit->getId();
std::pair < CommandResult, string> resultCur(crFailUndefined, "");
bool canSubmitCommand = canSubmitCommandType(unit, commandType);
if (canSubmitCommand == true) {
NetworkCommand
networkCommand(this->world, nctGiveCommand,
unitId, commandType->getId(), currPos,
-1, targetId, -1, tryQueue, cst_None,
-1, unitCommandGroupId);
resultCur = pushNetworkCommand(&networkCommand, isMove);
}
results.push_back(resultCur);
} else if (!ignoreBuildings && unit->isMeetingPointSettable()) {
NetworkCommand
command(this->world, nctSetMeetingPoint,
unit->getId(), -1, currPos, -1, -1, -1, false,
cst_None, -1, unitCommandGroupId);
std::pair < CommandResult, string > resultCur =
pushNetworkCommand(&command);
results.push_back(resultCur);
} else {
results.push_back(std::pair < CommandResult,
string >(crFailUndefined, ""));
}
}
result = computeResult(results);
}
return result;
}
CommandResult
Commander::tryCancelCommand(const Selection * selection) const {
if (this->pauseNetworkCommands == true) {
return crFailUndefined;
}
int
unitCommandGroupId = -1;
if (selection->getCount() > 1) {
unitCommandGroupId = world->getNextCommandGroupId();
}
for (int i = 0; i < selection->getCount(); ++i) {
NetworkCommand
command(this->world, nctCancelCommand,
selection->getUnit(i)->getId(), -1, Vec2i(0), -1, -1,
-1, false, cst_None, -1, unitCommandGroupId);
pushNetworkCommand(&command);
}
return crSuccess;
}
void
Commander::trySetMeetingPoint(const Unit * unit, const Vec2i & pos) const {
if (this->pauseNetworkCommands == true) {
return;
}
NetworkCommand
command(this->world, nctSetMeetingPoint, unit->getId(), -1, pos);
pushNetworkCommand(&command);
}
void
Commander::trySwitchTeam(const Faction * faction, int teamIndex) const {
if (this->pauseNetworkCommands == true) {
return;
}
NetworkCommand
command(this->world, nctSwitchTeam, faction->getIndex(), teamIndex);
pushNetworkCommand(&command);
}
void
Commander::trySwitchTeamVote(const Faction * faction,
SwitchTeamVote * vote) const {
if (this->pauseNetworkCommands == true) {
return;
}
NetworkCommand
command(this->world, nctSwitchTeamVote, faction->getIndex(),
vote->factionIndex, Vec2i(0), vote->allowSwitchTeam);
pushNetworkCommand(&command);
}
void
Commander::tryDisconnectNetworkPlayer(const Faction * faction,
int playerIndex) const {
NetworkCommand
command(this->world, nctDisconnectNetworkPlayer, faction->getIndex(),
playerIndex);
pushNetworkCommand(&command);
}
void
Commander::tryPauseGame(bool joinNetworkGame, bool clearCaches) const {
NetworkCommand
command(this->world, nctPauseResume, 1);
command.
commandTypeId = (clearCaches == true ? 1 : 0);
command.
unitTypeId = (joinNetworkGame == true ? 1 : 0);
pushNetworkCommand(&command);
}
void
Commander::tryResumeGame(bool joinNetworkGame, bool clearCaches) const {
NetworkCommand
command(this->world, nctPauseResume, 0);
command.
commandTypeId = (clearCaches == true ? 1 : 0);
command.
unitTypeId = (joinNetworkGame == true ? 1 : 0);
pushNetworkCommand(&command);
}
void
Commander::tryNetworkPlayerDisconnected(int factionIndex) const {
//printf("tryNetworkPlayerDisconnected factionIndex: %d\n",factionIndex);
//if(this->pauseNetworkCommands == true) {
// return;
//}
NetworkCommand
command(this->world, nctPlayerStatusChange, factionIndex,
npst_Disconnected);
pushNetworkCommand(&command);
}
// ==================== PRIVATE ====================
std::pair <
CommandResult,
string >
Commander::computeResult(const CommandResultContainer & results) const {
std::pair <
CommandResult,
string >
result(crFailUndefined, "");
switch (results.size()) {
case 0:
return std::pair < CommandResult, string >(crFailUndefined, "");
case
1:
return
results.
front();
default:for (int i = 0; i < (int) results.size(); ++i) {
if (results[i].first != crSuccess) {
return std::pair < CommandResult, string >(crSomeFailed,
results[i].
second);
}
}
break;
}
return std::pair < CommandResult, string >(crSuccess, "");
}
std::pair < CommandResult,
string >
Commander::pushNetworkCommand(const NetworkCommand *
networkCommand, bool insertAtStart) const {
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
std::pair <
CommandResult,
string >
result(crSuccess, "");
//validate unit
const Unit *
unit = NULL;
if (networkCommand->getNetworkCommandType() != nctSwitchTeam &&
networkCommand->getNetworkCommandType() != nctSwitchTeamVote &&
networkCommand->getNetworkCommandType() != nctPauseResume &&
networkCommand->getNetworkCommandType() != nctPlayerStatusChange &&
networkCommand->getNetworkCommandType() !=
nctDisconnectNetworkPlayer) {
unit = world->findUnitById(networkCommand->getUnitId());
if (unit == NULL) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"In [%s::%s - %d] Command refers to non existent unit id = %d. Game out of sync",
extractFileFromDirectoryPath(__FILE__).c_str(),
__FUNCTION__, __LINE__, networkCommand->getUnitId());
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
char
szMsg[8096] = "";
snprintf(szMsg, 8096, "Error: Command refers to non-existent unit id %d. Game out of sync, try leaving and rejoining",
networkCommand->getUnitId());
gameNetworkInterface->
sendTextMessage(szMsg, -1, true, "");
}
/*throw
megaglest_runtime_error(szBuf);*/
return std::pair<CommandResult, string>(crFailUndefined, "");
}
}
//add the command to the interface
gameNetworkInterface->requestCommand(networkCommand, insertAtStart);
//calculate the result of the command
if (unit != NULL
&& networkCommand->getNetworkCommandType() == nctGiveCommand) {
//printf("In [%s::%s Line: %d] result.first = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,result.first);
Command *
command = buildCommand(networkCommand);
result = unit->checkCommand(command);
delete
command;
}
return result;
}
void
Commander::signalNetworkUpdate(Game * game) {
updateNetwork(game);
}
bool
Commander::getReplayCommandListForFrame(int worldFrameCount) {
bool
haveReplyCommands = false;
if (replayCommandList.empty() == false) {
if (SystemFlags::VERBOSE_MODE_ENABLED)
printf("worldFrameCount = %d replayCommandList.size() = "
MG_SIZE_T_SPECIFIER "\n", worldFrameCount,
replayCommandList.size());
std::vector < NetworkCommand > replayList;
for (unsigned int i = 0; i < replayCommandList.size(); ++i) {
std::pair < int,
NetworkCommand > &
cmd = replayCommandList[i];
if (cmd.first <= worldFrameCount) {
replayList.push_back(cmd.second);
haveReplyCommands = true;
}
}
if (haveReplyCommands == true) {
replayCommandList.erase(replayCommandList.begin(),
replayCommandList.begin() +
replayList.size());
if (SystemFlags::VERBOSE_MODE_ENABLED)
printf
("worldFrameCount = %d GIVING COMMANDS replayList.size() = "
MG_SIZE_T_SPECIFIER "\n", worldFrameCount,
replayList.size());
for (int i = 0; i < (int) replayList.size(); ++i) {
giveNetworkCommand(&replayList[i]);
}
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
gameNetworkInterface->setKeyframe(worldFrameCount);
}
}
return haveReplyCommands;
}
bool
Commander::hasReplayCommandListForFrame() const {
return (replayCommandList.empty() == false);
}
int
Commander::getReplayCommandListForFrameCount() const {
return (int)
replayCommandList.
size();
}
void
Commander::updateNetwork(Game * game) {
if (world == NULL) {
return;
}
NetworkManager & networkManager = NetworkManager::getInstance();
//check that this is a keyframe
if (game != NULL) {
GameSettings *
gameSettings = game->getGameSettings();
if (networkManager.isNetworkGame() == false ||
(world->getFrameCount() %
gameSettings->getNetworkFramePeriod()) == 0) {
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] networkManager.isNetworkGame() = %d,world->getFrameCount() = %d, gameSettings->getNetworkFramePeriod() = %d\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__,
networkManager.isNetworkGame(),
world->getFrameCount(),
gameSettings->
getNetworkFramePeriod());
if (getReplayCommandListForFrame(world->getFrameCount()) ==
false) {
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled)
perfTimer.start();
//update the keyframe
gameNetworkInterface->updateKeyframe(world->
getFrameCount());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled && perfTimer.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] gameNetworkInterface->updateKeyframe for %d took %lld msecs\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
world->getFrameCount(),
perfTimer.getMillis());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled)
perfTimer.start();
//give pending commands
if (SystemFlags::VERBOSE_MODE_ENABLED)
printf
("START process: %d network commands in frame: %d\n",
gameNetworkInterface->getPendingCommandCount(),
this->world->getFrameCount());
for (int i = 0;
i < gameNetworkInterface->getPendingCommandCount();
++i) {
giveNetworkCommand(gameNetworkInterface->
getPendingCommand(i));
}
if (SystemFlags::VERBOSE_MODE_ENABLED)
printf("END process: %d network commands in frame: %d\n",
gameNetworkInterface->getPendingCommandCount(),
this->world->getFrameCount());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled && perfTimer.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] giveNetworkCommand took %lld msecs, PendingCommandCount = %d\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
perfTimer.getMillis(),
gameNetworkInterface->
getPendingCommandCount());
gameNetworkInterface->clearPendingCommands();
if (SystemFlags::VERBOSE_MODE_ENABLED)
printf("Cleared network commands in frame: %d\n",
this->world->getFrameCount());
}
}
}
}
void
Commander::addToReplayCommandList(NetworkCommand & command,
int worldFrameCount) {
replayCommandList.push_back(make_pair(worldFrameCount, command));
}
std::pair<CommandResult, string> Commander::giveNetworkCommand(NetworkCommand * networkCommand) const {
Chrono
chrono;
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled)
chrono.
start();
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [START]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
world->
getGame()->
addNetworkCommandToReplayList(networkCommand, world->getFrameCount());
networkCommand->
preprocessNetworkCommand(this->world);
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after networkCommand->preprocessNetworkCommand]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
bool
commandWasHandled = false;
// Handle special commands first (that just use network command members as placeholders)
switch (networkCommand->getNetworkCommandType()) {
case nctSwitchTeam:
{
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctSwitchTeam\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
commandWasHandled = true;
int
factionIndex = networkCommand->getUnitId();
int
newTeam = networkCommand->getCommandTypeId();
// Auto join empty team or ask players to join
bool
autoJoinTeam = true;
for (int i = 0; i < world->getFactionCount(); ++i) {
if (newTeam == world->getFaction(i)->getTeam()) {
autoJoinTeam = false;
break;
}
}
if (autoJoinTeam == true) {
Faction *
faction = world->getFaction(factionIndex);
int
oldTeam = faction->getTeam();
faction->setTeam(newTeam);
GameSettings *
settings = world->getGameSettingsPtr();
settings->setTeam(factionIndex, newTeam);
world->getStats()->setTeam(factionIndex, newTeam);
if (factionIndex == world->getThisFactionIndex()) {
world->setThisTeamIndex(newTeam);
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().
getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
Lang & lang = Lang::getInstance();
const
vector <
string >
languageList =
settings->getUniqueNetworkPlayerLanguages();
for (unsigned int i = 0; i < languageList.size();
++i) {
char
szMsg[8096] = "";
if (lang.
hasString("PlayerSwitchedTeam",
languageList[i]) == true) {
snprintf(szMsg, 8096,
lang.
getString("PlayerSwitchedTeam",
languageList[i]).
c_str(),
settings->
getNetworkPlayerName(factionIndex).
c_str(), oldTeam, newTeam);
} else {
snprintf(szMsg, 8096,
"Player %s switched from team# %d to team# %d.",
settings->
getNetworkPlayerName(factionIndex).
c_str(), oldTeam, newTeam);
}
bool
localEcho =
lang.isLanguageLocal(languageList[i]);
gameNetworkInterface->sendTextMessage(szMsg, -1,
localEcho,
languageList
[i]);
}
}
world->getGame()->reInitGUI();
}
} else {
for (int i = 0; i < world->getFactionCount(); ++i) {
if (newTeam == world->getFaction(i)->getTeam()) {
Faction *
faction = world->getFaction(factionIndex);
SwitchTeamVote
vote;
vote.factionIndex = factionIndex;
vote.allowSwitchTeam = false;
vote.oldTeam = faction->getTeam();
vote.newTeam = newTeam;
vote.voted = false;
world->getFaction(i)->setSwitchTeamVote(vote);
}
}
}
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).enabled
&& chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after unit->setMeetingPos]\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__, chrono.getMillis());
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctSetMeetingPoint\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
}
break;
case nctSwitchTeamVote:
{
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctSwitchTeamVote\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
commandWasHandled = true;
int
votingFactionIndex = networkCommand->getUnitId();
int
factionIndex = networkCommand->getCommandTypeId();
bool
allowSwitchTeam = networkCommand->getUnitTypeId() != 0;
Faction *
faction = world->getFaction(votingFactionIndex);
SwitchTeamVote *
vote = faction->getSwitchTeamVote(factionIndex);
if (vote == NULL) {
throw
megaglest_runtime_error("vote == NULL");
}
vote->voted = true;
vote->allowSwitchTeam = allowSwitchTeam;
// Join the new team if > 50 % said yes
int
newTeamTotalMemberCount = 0;
int
newTeamVotedYes = 0;
int
newTeamVotedNo = 0;
for (int i = 0; i < world->getFactionCount(); ++i) {
if (vote->newTeam == world->getFaction(i)->getTeam()) {
newTeamTotalMemberCount++;
SwitchTeamVote *
teamVote =
world->getFaction(i)->getSwitchTeamVote(factionIndex);
if (teamVote != NULL && teamVote->voted == true) {
if (teamVote->allowSwitchTeam == true) {
newTeamVotedYes++;
} else {
newTeamVotedNo++;
}
}
}
}
// If > 50% of team vote yes, switch th eplayers team
if (newTeamTotalMemberCount > 0 && newTeamVotedYes > 0 &&
static_cast <float>(newTeamVotedYes) / static_cast <
float>(newTeamTotalMemberCount) > 0.5) {
Faction *
faction = world->getFaction(factionIndex);
int
oldTeam = faction->getTeam();
faction->setTeam(vote->newTeam);
GameSettings *
settings = world->getGameSettingsPtr();
settings->setTeam(factionIndex, vote->newTeam);
world->getStats()->setTeam(factionIndex, vote->newTeam);
if (factionIndex == world->getThisFactionIndex()) {
world->setThisTeamIndex(vote->newTeam);
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().
getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
Lang & lang = Lang::getInstance();
const
vector <
string >
languageList =
settings->getUniqueNetworkPlayerLanguages();
for (unsigned int i = 0; i < languageList.size();
++i) {
char
szMsg[8096] = "";
if (lang.
hasString("PlayerSwitchedTeam",
languageList[i]) == true) {
snprintf(szMsg, 8096,
lang.
getString("PlayerSwitchedTeam",
languageList[i]).
c_str(),
settings->
getNetworkPlayerName(factionIndex).
c_str(), oldTeam, vote->newTeam);
} else {
snprintf(szMsg, 8096,
"Player %s switched from team# %d to team# %d.",
settings->
getNetworkPlayerName(factionIndex).
c_str(), oldTeam, vote->newTeam);
}
bool
localEcho =
lang.isLanguageLocal(languageList[i]);
gameNetworkInterface->sendTextMessage(szMsg, -1,
localEcho,
languageList
[i]);
}
}
world->getGame()->reInitGUI();
}
} else if (newTeamTotalMemberCount ==
(newTeamVotedYes + newTeamVotedNo)) {
if (factionIndex == world->getThisFactionIndex()) {
GameSettings *
settings = world->getGameSettingsPtr();
Faction *
faction = world->getFaction(factionIndex);
int
oldTeam = faction->getTeam();
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().
getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
Lang & lang = Lang::getInstance();
const
vector <
string >
languageList =
settings->getUniqueNetworkPlayerLanguages();
for (unsigned int i = 0; i < languageList.size();
++i) {
char
szMsg[8096] = "";
if (lang.
hasString("PlayerSwitchedTeamDenied",
languageList[i]) == true) {
snprintf(szMsg, 8096,
lang.
getString
("PlayerSwitchedTeamDenied",
languageList[i]).c_str(),
settings->
getNetworkPlayerName(factionIndex).
c_str(), oldTeam, vote->newTeam);
} else {
snprintf(szMsg, 8096,
"Player %s was denied the request to switch from team# %d to team# %d.",
settings->
getNetworkPlayerName(factionIndex).
c_str(), oldTeam, vote->newTeam);
}
bool
localEcho =
lang.isLanguageLocal(languageList[i]);
gameNetworkInterface->sendTextMessage(szMsg, -1,
localEcho,
languageList
[i]);
}
}
}
}
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).enabled
&& chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after unit->setMeetingPos]\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__, chrono.getMillis());
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctSetMeetingPoint\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
}
break;
case nctDisconnectNetworkPlayer:
{
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctDisconnectNetworkPlayer\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
commandWasHandled = true;
NetworkManager & networkManager = NetworkManager::getInstance();
NetworkRole
role = networkManager.getNetworkRole();
//GameSettings *settings = world->getGameSettingsPtr();
if (role == nrServer) {
//int factionIndex = networkCommand->getUnitId();
int
playerIndex = networkCommand->getCommandTypeId();
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
ServerInterface *
server = networkManager.getServerInterface();
if (server != NULL
&& server->isClientConnected(playerIndex) == true) {
MutexSafeWrapper
safeMutex(server->getSlotMutex(playerIndex),
CODE_AT_LINE);
ConnectionSlot *
slot = server->getSlot(playerIndex, false);
if (slot != NULL) {
safeMutex.ReleaseLock();
NetworkMessageQuit
networkMessageQuit;
slot->sendMessage(&networkMessageQuit);
sleep(5);
//printf("Sending nctDisconnectNetworkPlayer\n");
server =
networkManager.getServerInterface(false);
if (server != NULL) {
MutexSafeWrapper
safeMutex2(server->
getSlotMutex(playerIndex),
CODE_AT_LINE);
slot = server->getSlot(playerIndex, false);
if (slot != NULL) {
safeMutex2.ReleaseLock();
slot->close();
}
}
}
}
}
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctDisconnectNetworkPlayer\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
}
break;
case nctPauseResume:
{
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctPauseResume\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
commandWasHandled = true;
bool
pauseGame = networkCommand->getUnitId() != 0;
bool
clearCaches = (networkCommand->getCommandTypeId() == 1);
bool
joinNetworkGame = (networkCommand->getUnitTypeId() == 1);
Game *
game = this->world->getGame();
//printf("nctPauseResume pauseGame = %d\n",pauseGame);
game->setPaused(pauseGame, true, clearCaches, joinNetworkGame);
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctPauseResume\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
}
break;
case nctPlayerStatusChange:
{
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctPlayerStatusChange\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
commandWasHandled = true;
int
factionIndex = networkCommand->getUnitId();
int
playerStatus = networkCommand->getCommandTypeId();
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"nctPlayerStatusChange factionIndex = %d playerStatus = %d\n",
factionIndex, playerStatus);
//printf("#1 nctPlayerStatusChange factionIndex = %d playerStatus = %d\n",factionIndex,playerStatus);
GameSettings *
settings = world->getGameSettingsPtr();
if (playerStatus == npst_Disconnected) {
//printf("Commander nctPlayerStatusChange factionIndex: %d\n",factionIndex);
settings->setNetworkPlayerStatuses(factionIndex,
npst_Disconnected);
//printf("nctPlayerStatusChange -> faction->getPersonalityType() = %d index [%d] control [%d] networkstatus [%d]\n",
// world->getFaction(factionIndex)->getPersonalityType(),world->getFaction(factionIndex)->getIndex(),world->getFaction(factionIndex)->getControlType(),settings->getNetworkPlayerStatuses(factionIndex));
//printf("#2 nctPlayerStatusChange factionIndex = %d playerStatus = %d\n",factionIndex,playerStatus);
settings->setFactionControl(factionIndex, ctCpuUltra);
settings->setResourceMultiplierIndex(factionIndex,
settings->
getFallbackCpuMultiplier
());
//Game *game = this->world->getGame();
//game->get
Faction *
faction = this->world->getFaction(factionIndex);
faction->setControlType(ctCpuUltra);
if (!world->getGame()->getGameOver()
&& !this->world->getGame()->
factionLostGame(factionIndex)) {
// use the fallback multiplier here
// mark player as "leaver"
this->world->getStats()->
setPlayerLeftBeforeEnd(factionIndex, true);
// set disconnect time for endgame stats
this->world->getStats()->setTimePlayerLeft(factionIndex,
this->world->
getStats()->
getFramesToCalculatePlaytime
());
}
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctPlayerStatusChange\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__);
}
break;
default:
break;
}
if (commandWasHandled == false) {
Unit *
unit = world->findUnitById(networkCommand->getUnitId());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).enabled
&& chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after world->findUnitById]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
if (SystemFlags::VERBOSE_MODE_ENABLED)
printf
("Running command NetworkCommandType = %d, unitid = %d [%p] factionindex = %d\n",
networkCommand->getNetworkCommandType(),
networkCommand->getUnitId(), unit,
(unit != NULL ? unit->getFactionIndex() : -1));
//execute command, if unit is still alive
if (unit != NULL) {
switch (networkCommand->getNetworkCommandType()) {
case nctGiveCommand:
{
assert(networkCommand->getCommandTypeId() !=
CommandType::invalidId);
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
networkCommand->getUnitId());
Command *
command = buildCommand(networkCommand);
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after buildCommand]\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
chrono.getMillis());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] command = %p\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
command);
unit->giveCommand(command,
(networkCommand->getWantQueue() !=
0));
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after unit->giveCommand]\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
chrono.getMillis());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
networkCommand->getUnitId());
}
break;
case nctCancelCommand:
{
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctCancelCommand\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__);
unit->cancelCommand();
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after unit->cancelCommand]\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
chrono.getMillis());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctCancelCommand\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__);
}
break;
case nctSetMeetingPoint:
{
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctSetMeetingPoint\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__);
unit->setMeetingPos(networkCommand->getPosition());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [after unit->setMeetingPos]\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__,
chrono.getMillis());
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] found nctSetMeetingPoint\n",
extractFileFromDirectoryPath
(__FILE__).c_str(),
__FUNCTION__, __LINE__);
}
break;
default:
return std::pair<CommandResult, string>(crFailUndefined, "");
}
} else {
if (SystemFlags::
getSystemSettingType(SystemFlags::debugSystem).enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] NULL Unit for id = %d, networkCommand->getNetworkCommandType() = %d\n",
extractFileFromDirectoryPath
(__FILE__).c_str(), __FUNCTION__,
__LINE__,
networkCommand->getUnitId(),
networkCommand->
getNetworkCommandType());
return std::pair<CommandResult, string>(crFailUndefined, "");
}
}
if (SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).
enabled && chrono.getMillis() > 0)
SystemFlags::OutputDebug(SystemFlags::debugPerformance,
"In [%s::%s Line: %d] took msecs: %lld [END]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
chrono.getMillis());
return std::pair<CommandResult, string>(crSuccess, "");
}
// Reconstruct a network command received.
Command *
Commander::buildCommand(const NetworkCommand * networkCommand) const {
// Check a new command is actually being given (and not a cancel command, switch team etc.).
assert(networkCommand->getNetworkCommandType() == nctGiveCommand);
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d] networkCommand [%s]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__,
networkCommand->toString().c_str());
// Check there is a world.
if (world == NULL) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"In [%s::%s Line: %d] world == NULL for unit with id: %d",
extractFileFromDirectoryPath(__FILE__).c_str(),
__FUNCTION__, __LINE__, networkCommand->getUnitId());
throw
megaglest_runtime_error(szBuf);
}
// Create the command.
Command *
command = NULL;
// Get the unit.
Unit *
target = NULL;
const CommandType *
ct = NULL;
const Unit *
unit = world->findUnitById(networkCommand->getUnitId());
// Validate unit is in game.
if (unit == NULL) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"In [%s::%s Line: %d] Can not find unit with id: %d. Game out of synch.",
extractFileFromDirectoryPath(__FILE__).c_str(),
__FUNCTION__, __LINE__, networkCommand->getUnitId());
SystemFlags::OutputDebug(SystemFlags::debugError, "%s\n", szBuf);
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem, "%s\n",
szBuf);
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
char
szMsg[8096] = "";
snprintf(szMsg, 8096,
"Error: Cannot find unit with id %d. Game out of sync, try leaving and rejoining",
networkCommand->getUnitId());
gameNetworkInterface->sendTextMessage(szMsg, -1, true, "");
}
/*throw
megaglest_runtime_error(szBuf);*/
return command;
}
// Get the command type for the unit.
ct =
unit->getType()->findCommandTypeById(networkCommand->
getCommandTypeId());
// Check that the unit from the network command is the same faction as the unit in the local game.
if (unit->getFaction()->getIndex() !=
networkCommand->getUnitFactionIndex()) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"In [%s::%s Line: %d]\nUnit/Faction mismatch for network command = [%s]\nfor unit = %d\n[%s]\n[%s]\nactual local factionIndex = %d.\nGame out of sync",
__FILE__, __FUNCTION__, __LINE__,
networkCommand->toString().c_str(),
unit->getId(), unit->getFullName(false).c_str(),
unit->getDesc(false).c_str(),
unit->getFaction()->getIndex());
SystemFlags::OutputDebug(SystemFlags::debugError, "%s\n", szBuf);
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem, "%s\n",
szBuf);
//world->DumpWorldToLog();
// Broadcast the error if player is still connected and print locally.
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
char szMsg[8096] = "";
snprintf(szMsg, 8096,
"Error: Unit/Faction mismatch for unitId %d, local faction index %d, remote index %d. Game out of sync, try leaving and rejoining",
networkCommand->getUnitId(),
unit->getFaction()->getIndex(),
networkCommand->getUnitFactionIndex());
gameNetworkInterface->sendTextMessage(szMsg, -1, true, "");
}
/*// Kill the game.
std::string sError =
"Error [#1]: Game is out of sync (Unit / Faction mismatch)\nplease check log files for details.";
throw
megaglest_runtime_error(sError);*/
return command;
}
const UnitType *
unitType =
world->findUnitTypeById(unit->getFaction()->getType(),
networkCommand->getUnitTypeId());
//validate command type
// Check if the command was for the unit before it morphed, if so cancel it.
bool
isCancelPreMorphCommand = false;
if (ct == NULL && unit->getPreMorphType() != NULL) {
const CommandType *
ctPreMorph =
unit->getPreMorphType()->findCommandTypeById(networkCommand->
getCommandTypeId
());
if (ctPreMorph != NULL) {
ct = unit->getType()->getFirstCtOfClass(ccStop);
isCancelPreMorphCommand = true;
}
}
// Throw an error if a valid command for the unit is still not found.
if (ct == NULL) {
char
szBuf[8096] = "";
snprintf(szBuf, 8096,
"In [%s::%s Line: %d]\nCannot find command type for network command = [%s]\nfor unit = %d\n[%s]\n[%s]\nactual local factionIndex = %d.\nUnit Type Info:\n[%s]\nNetwork unit type:\n[%s]\nGame out of sync",
extractFileFromDirectoryPath(__FILE__).c_str(),
__FUNCTION__, __LINE__,
networkCommand->toString().c_str(),
unit->getId(), unit->getFullName(false).c_str(),
unit->getDesc(false).c_str(),
unit->getFaction()->getIndex(),
unit->getType()->toString().c_str(),
(unitType !=
NULL ? unitType->getName(false).c_str() : "null"));
SystemFlags::OutputDebug(SystemFlags::debugSystem, "%s\n", szBuf);
SystemFlags::OutputDebug(SystemFlags::debugError, "%s\n", szBuf);
//world->DumpWorldToLog();
GameNetworkInterface *
gameNetworkInterface =
NetworkManager::getInstance().getGameNetworkInterface();
if (gameNetworkInterface != NULL) {
char szMsg[8096] = "";
snprintf(szMsg, 8096, "Error: Cannot find command type %d for unitId %d [%s]. Game out of sync, try leaving and rejoining",
networkCommand->getCommandTypeId(),
networkCommand->getUnitId(),
(unitType !=
NULL ? unitType->getName(false).c_str() : "null"));
gameNetworkInterface->sendTextMessage(szMsg, -1, true, "");
}
/*std::string sError =
"Error [#3]: Game is out of sync, please check log files for details.";
throw
megaglest_runtime_error(sError);*/
return command;
}
CardinalDir
facing;
// Get direction of the command target unit.
if (isCancelPreMorphCommand == false) {
// If target is a building.
if (ct->getClass() == ccBuild) {
// Check the target building ID is valid. If not, throw an error.
/// TODO: What is happening here? The error returned does not match the condition. Why is there a constant of 4?
if (networkCommand->getTargetId() < 0
|| networkCommand->getTargetId() >= 4) {
printf("networkCommand->getTargetId() >= 0 && networkCommand->getTargetId() < 4, [%s]", networkCommand->toString().c_str());
/*throw
megaglest_runtime_error(szBuf);*/
return command;
}
facing = CardinalDir(networkCommand->getTargetId());
}
// Get the target unit if the ID is valid.
else if (networkCommand->getTargetId() != Unit::invalidId) {
target = world->findUnitById(networkCommand->getTargetId());
}
}
if (isCancelPreMorphCommand == false) {
if (unitType != NULL) {
command =
new Command(ct, networkCommand->getPosition(), unitType,
facing);
} else if (target == NULL) {
command = new Command(ct, networkCommand->getPosition());
} else {
command = new Command(ct, target);
}
} else {
command = new Command(ct, NULL);
}
// Add in any special state
CommandStateType
commandStateType = networkCommand->getCommandStateType();
int
commandStateValue = networkCommand->getCommandStateValue();
command->setStateType(commandStateType);
command->setStateValue(commandStateValue);
command->setUnitCommandGroupId(networkCommand->
getUnitCommandGroupId());
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).
enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"In [%s::%s Line: %d]\n",
extractFileFromDirectoryPath(__FILE__).
c_str(), __FUNCTION__, __LINE__);
//issue command
return command;
}
}
} //end namespace