mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
1817 lines
56 KiB
C++
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
|