mirror of
https://github.com/glest/glest-source.git
synced 2025-02-24 19:52:25 +01:00
1065 lines
49 KiB
C++
1065 lines
49 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 "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) const {
|
|
|
|
if(this->pauseNetworkCommands == true) {
|
|
return std::pair<CommandResult,string>(crFailUndefined,"");
|
|
}
|
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
|
|
|
|
std::pair<CommandResult,string> result(crFailUndefined,"");
|
|
|
|
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);
|
|
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);
|
|
|
|
currPos= world->getMap()->computeDestPos(refPos, unit->getPosNotThreadSafe(), pos);
|
|
|
|
//get command type
|
|
const CommandType *commandType= unit->computeCommandType(pos, targetUnit);
|
|
|
|
//give commands
|
|
if(commandType != NULL) {
|
|
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);
|
|
}
|
|
results.push_back(resultCur);
|
|
}
|
|
else if(unit->isMeetingPointSettable() == true) {
|
|
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 < 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) 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 synch.",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkCommand->getUnitId());
|
|
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
|
|
if(gameNetworkInterface != NULL) {
|
|
char szMsg[8096]="";
|
|
snprintf(szMsg,8096,"Player detected an error: Command refers to non existent unit id = %d. Game out of synch.",networkCommand->getUnitId());
|
|
gameNetworkInterface->sendTextMessage(szMsg,-1, true, "");
|
|
}
|
|
throw megaglest_runtime_error(szBuf);
|
|
}
|
|
}
|
|
|
|
//add the command to the interface
|
|
gameNetworkInterface->requestCommand(networkCommand);
|
|
|
|
//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 < 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));
|
|
}
|
|
|
|
void 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]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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 &&
|
|
newTeamVotedYes / 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]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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->isClientConnected(playerIndex) == true) {
|
|
ConnectionSlot *slot = server->getSlot(playerIndex);
|
|
if(slot != NULL) {
|
|
NetworkMessageQuit networkMessageQuit;
|
|
slot->sendMessage(&networkMessageQuit);
|
|
sleep(5);
|
|
|
|
//printf("Sending nctDisconnectNetworkPlayer\n");
|
|
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;
|
|
|
|
}
|
|
|
|
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:
|
|
assert(false);
|
|
break;
|
|
}
|
|
}
|
|
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());
|
|
}
|
|
}
|
|
|
|
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());
|
|
}
|
|
|
|
Command* Commander::buildCommand(const NetworkCommand* networkCommand) const {
|
|
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());
|
|
|
|
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);
|
|
}
|
|
|
|
Unit* target= NULL;
|
|
const CommandType* ct= NULL;
|
|
const Unit* unit= world->findUnitById(networkCommand->getUnitId());
|
|
|
|
//validate unit
|
|
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,"Player detected an error: Can not find unit with id: %d. Game out of synch.",networkCommand->getUnitId());
|
|
gameNetworkInterface->sendTextMessage(szMsg,-1, true, "");
|
|
}
|
|
|
|
throw megaglest_runtime_error(szBuf);
|
|
}
|
|
|
|
ct = unit->getType()->findCommandTypeById(networkCommand->getCommandTypeId());
|
|
|
|
if(unit->getFaction()->getIndex() != networkCommand->getUnitFactionIndex()) {
|
|
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"In [%s::%s Line: %d]\nUnit / Faction mismatch for network command = [%s]\n%s\nfor unit = %d\n[%s]\n[%s]\nactual local factionIndex = %d.\nGame out of synch.",
|
|
__FILE__,__FUNCTION__,__LINE__,networkCommand->toString().c_str(),unit->getType()->getCommandTypeListDesc().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);
|
|
//std::string worldLog = world->DumpWorldToLog();
|
|
world->DumpWorldToLog();
|
|
|
|
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
|
|
if(gameNetworkInterface != NULL && gameNetworkInterface->isConnected() == true) {
|
|
char szMsg[8096]="";
|
|
snprintf(szMsg,8096,"Player detected an error: Unit / Faction mismatch for unitId: %d",networkCommand->getUnitId());
|
|
gameNetworkInterface->sendTextMessage(szMsg,-1, true, "");
|
|
snprintf(szMsg,8096,"Local faction index = %d, remote index = %d. Game out of synch.",unit->getFaction()->getIndex(),networkCommand->getUnitFactionIndex());
|
|
gameNetworkInterface->sendTextMessage(szMsg,-1, true, "");
|
|
|
|
}
|
|
else if(gameNetworkInterface != NULL) {
|
|
char szMsg[8096]="";
|
|
snprintf(szMsg,8096,"Player detected an error: Connection lost, possible Unit / Faction mismatch for unitId: %d",networkCommand->getUnitId());
|
|
gameNetworkInterface->sendTextMessage(szMsg,-1, true,"");
|
|
snprintf(szMsg,8096,"Local faction index = %d, remote index = %d. Game out of synch.",unit->getFaction()->getIndex(),networkCommand->getUnitFactionIndex());
|
|
gameNetworkInterface->sendTextMessage(szMsg,-1, true,"");
|
|
}
|
|
|
|
std::string sError = "Error [#1]: Game is out of sync (Unit / Faction mismatch)\nplease check log files for details.";
|
|
throw megaglest_runtime_error(sError);
|
|
}
|
|
|
|
const UnitType* unitType= world->findUnitTypeById(unit->getFaction()->getType(), networkCommand->getUnitTypeId());
|
|
|
|
// debug test!
|
|
//throw megaglest_runtime_error("Test missing command type!");
|
|
|
|
//validate command type
|
|
|
|
// !!!Test out of synch behaviour
|
|
//ct = NULL;
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
if(ct == NULL) {
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"In [%s::%s Line: %d]\nCan not find command type for network command = [%s]\n%s\nfor unit = %d\n[%s]\n[%s]\nactual local factionIndex = %d.\nUnit Type Info:\n[%s]\nNetwork unit type:\n[%s]\nisCancelPreMorphCommand: %d\nGame out of synch.",
|
|
extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkCommand->toString().c_str(),unit->getType()->getCommandTypeListDesc().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"),isCancelPreMorphCommand);
|
|
|
|
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,"Player detected an error: Can not find command type: %d for unitId: %d [%s]. isCancelPreMorphCommand: %d Game out of synch.",networkCommand->getCommandTypeId(),networkCommand->getUnitId(),(unitType != NULL ? unitType->getName(false).c_str() : "null"),isCancelPreMorphCommand);
|
|
gameNetworkInterface->sendTextMessage(szMsg,-1, true, "");
|
|
}
|
|
|
|
std::string sError = "Error [#3]: Game is out of sync, please check log files for details.";
|
|
//abort();
|
|
throw megaglest_runtime_error(sError);
|
|
}
|
|
|
|
CardinalDir facing;
|
|
// get facing/target ... the target might be dead due to lag, cope with it
|
|
if(isCancelPreMorphCommand == false) {
|
|
if(ct->getClass() == ccBuild) {
|
|
if(networkCommand->getTargetId() < 0 || networkCommand->getTargetId() >= 4) {
|
|
char szBuf[8096]="";
|
|
snprintf(szBuf,8096,"networkCommand->getTargetId() >= 0 && networkCommand->getTargetId() < 4, [%s]",networkCommand->toString().c_str());
|
|
throw megaglest_runtime_error(szBuf);
|
|
}
|
|
facing = CardinalDir(networkCommand->getTargetId());
|
|
}
|
|
else if (networkCommand->getTargetId() != Unit::invalidId ) {
|
|
target= world->findUnitById(networkCommand->getTargetId());
|
|
}
|
|
}
|
|
|
|
//create command
|
|
Command *command= NULL;
|
|
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
|