2010-03-18 21:26:40 +00:00
// ==============================================================
// This file is part of Glest (www.glest.org)
//
2010-04-18 06:01:20 +00:00
// Copyright (C) 2001-2008 Martio Figueroa
2010-03-18 21:26:40 +00:00
//
// 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 "leak_dumper.h"
# include "game.h"
using namespace Shared : : Graphics ;
using namespace Shared : : Util ;
using namespace Shared : : Platform ;
namespace Glest { namespace Game {
// =====================================================
// class Commander
// =====================================================
// ===================== PUBLIC ========================
void Commander : : init ( World * world ) {
this - > world = world ;
}
2010-04-18 07:35:48 +00:00
CommandResult Commander : : tryGiveCommand ( const Unit * unit , const CommandType * commandType , const Vec2i & pos , const UnitType * unitType , CardinalDir facing , bool tryQueue ) const {
NetworkCommand networkCommand ( this - > world , nctGiveCommand , unit - > getId ( ) , commandType - > getId ( ) , pos , unitType - > getId ( ) , - 1 , facing , tryQueue ) ;
2010-03-18 21:26:40 +00:00
return pushNetworkCommand ( & networkCommand ) ;
}
2010-04-18 07:35:48 +00:00
CommandResult Commander : : tryGiveCommand ( const Selection * selection , CommandClass commandClass , const Vec2i & pos , const Unit * targetUnit , bool tryQueue ) const {
2010-03-18 21:26:40 +00:00
if ( ! selection - > isEmpty ( ) ) {
Vec2i refPos , currPos ;
CommandResultContainer results ;
refPos = computeRefPos ( selection ) ;
//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 ) {
int targetId = targetUnit = = NULL ? Unit : : invalidId : targetUnit - > getId ( ) ;
int unitId = selection - > getUnit ( i ) - > getId ( ) ;
Vec2i currPos = computeDestPos ( refPos , selection - > getUnit ( i ) - > getPos ( ) , pos ) ;
2010-04-18 07:35:48 +00:00
NetworkCommand networkCommand ( this - > world , nctGiveCommand , unitId , ct - > getId ( ) , currPos , - 1 , targetId , - 1 , tryQueue ) ;
2010-03-18 21:26:40 +00:00
//every unit is ordered to a different pos
CommandResult result = pushNetworkCommand ( & networkCommand ) ;
results . push_back ( result ) ;
}
else {
results . push_back ( crFailUndefined ) ;
}
}
return computeResult ( results ) ;
}
else {
return crFailUndefined ;
}
}
2010-04-18 07:35:48 +00:00
CommandResult Commander : : tryGiveCommand ( const Selection * selection , const CommandType * commandType , const Vec2i & pos , const Unit * targetUnit , bool tryQueue ) const {
2010-03-18 21:26:40 +00:00
if ( ! selection - > isEmpty ( ) & & commandType ! = NULL ) {
Vec2i refPos ;
CommandResultContainer results ;
refPos = computeRefPos ( selection ) ;
//give orders to all selected units
for ( int i = 0 ; i < selection - > getCount ( ) ; + + i ) {
int targetId = targetUnit = = NULL ? Unit : : invalidId : targetUnit - > getId ( ) ;
int unitId = selection - > getUnit ( i ) - > getId ( ) ;
Vec2i currPos = computeDestPos ( refPos , selection - > getUnit ( i ) - > getPos ( ) , pos ) ;
2010-04-18 07:35:48 +00:00
NetworkCommand networkCommand ( this - > world , nctGiveCommand , unitId , commandType - > getId ( ) , currPos , - 1 , targetId , - 1 , tryQueue ) ;
2010-03-18 21:26:40 +00:00
//every unit is ordered to a different position
CommandResult result = pushNetworkCommand ( & networkCommand ) ;
results . push_back ( result ) ;
}
return computeResult ( results ) ;
}
else {
return crFailUndefined ;
}
}
//auto command
2010-04-18 07:35:48 +00:00
CommandResult Commander : : tryGiveCommand ( const Selection * selection , const Vec2i & pos , const Unit * targetUnit , bool tryQueue ) const {
2010-03-18 21:26:40 +00:00
if ( ! selection - > isEmpty ( ) ) {
Vec2i refPos , currPos ;
CommandResultContainer results ;
//give orders to all selected units
refPos = computeRefPos ( selection ) ;
for ( int i = 0 ; i < selection - > getCount ( ) ; + + i ) {
//every unit is ordered to a different pos
currPos = computeDestPos ( refPos , selection - > getUnit ( i ) - > getPos ( ) , pos ) ;
//get command type
const CommandType * commandType = selection - > getUnit ( i ) - > computeCommandType ( pos , targetUnit ) ;
//give commands
if ( commandType ! = NULL ) {
int targetId = targetUnit = = NULL ? Unit : : invalidId : targetUnit - > getId ( ) ;
int unitId = selection - > getUnit ( i ) - > getId ( ) ;
2010-04-18 07:35:48 +00:00
NetworkCommand networkCommand ( this - > world , nctGiveCommand , unitId , commandType - > getId ( ) , currPos , - 1 , targetId , - 1 , tryQueue ) ;
2010-03-18 21:26:40 +00:00
CommandResult result = pushNetworkCommand ( & networkCommand ) ;
results . push_back ( result ) ;
}
else {
results . push_back ( crFailUndefined ) ;
}
}
return computeResult ( results ) ;
}
else {
return crFailUndefined ;
}
}
CommandResult Commander : : tryCancelCommand ( const Selection * selection ) const {
for ( int i = 0 ; i < selection - > getCount ( ) ; + + i ) {
2010-03-22 04:47:16 +00:00
NetworkCommand command ( this - > world , nctCancelCommand , selection - > getUnit ( i ) - > getId ( ) ) ;
2010-03-18 21:26:40 +00:00
pushNetworkCommand ( & command ) ;
}
return crSuccess ;
}
void Commander : : trySetMeetingPoint ( const Unit * unit , const Vec2i & pos ) const {
2010-03-22 04:47:16 +00:00
NetworkCommand command ( this - > world , nctSetMeetingPoint , unit - > getId ( ) , - 1 , pos ) ;
2010-03-18 21:26:40 +00:00
pushNetworkCommand ( & command ) ;
}
// ==================== PRIVATE ====================
Vec2i Commander : : computeRefPos ( const Selection * selection ) const {
Vec2i total = Vec2i ( 0 ) ;
for ( int i = 0 ; i < selection - > getCount ( ) ; + + i ) {
total = total + selection - > getUnit ( i ) - > getPos ( ) ;
}
return Vec2i ( total . x / selection - > getCount ( ) , total . y / selection - > getCount ( ) ) ;
}
Vec2i Commander : : computeDestPos ( const Vec2i & refUnitPos , const Vec2i & unitPos , const Vec2i & commandPos ) const {
Vec2i pos ;
Vec2i posDiff = unitPos - refUnitPos ;
if ( abs ( posDiff . x ) > = 3 ) {
posDiff . x = posDiff . x % 3 ;
}
if ( abs ( posDiff . y ) > = 3 ) {
posDiff . y = posDiff . y % 3 ;
}
pos = commandPos + posDiff ;
world - > getMap ( ) - > clampPos ( pos ) ;
return pos ;
}
CommandResult Commander : : computeResult ( const CommandResultContainer & results ) const {
switch ( results . size ( ) ) {
case 0 :
return crFailUndefined ;
case 1 :
return results . front ( ) ;
default :
for ( int i = 0 ; i < results . size ( ) ; + + i ) {
if ( results [ i ] ! = crSuccess ) {
return crSomeFailed ;
}
2010-04-18 07:35:48 +00:00
} http : //de.wikipedia.org/wiki/Iatrogen
2010-03-18 21:26:40 +00:00
return crSuccess ;
}
}
CommandResult Commander : : pushNetworkCommand ( const NetworkCommand * networkCommand ) const {
GameNetworkInterface * gameNetworkInterface = NetworkManager : : getInstance ( ) . getGameNetworkInterface ( ) ;
const Unit * unit = world - > findUnitById ( networkCommand - > getUnitId ( ) ) ;
CommandResult cr = crSuccess ;
//validate unit
if ( unit = = NULL ) {
char szBuf [ 1024 ] = " " ;
sprintf ( szBuf , " In [%s::%s - %d] Command refers to non existant unit id = %d. Game out of synch. " ,
__FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) ) ;
throw runtime_error ( szBuf ) ;
}
//add the command to the interface
gameNetworkInterface - > requestCommand ( networkCommand ) ;
//calculate the result of the command
if ( networkCommand - > getNetworkCommandType ( ) = = nctGiveCommand ) {
Command * command = buildCommand ( networkCommand ) ;
cr = unit - > checkCommand ( command ) ;
delete command ;
}
return cr ;
}
void Commander : : updateNetwork ( ) {
NetworkManager & networkManager = NetworkManager : : getInstance ( ) ;
//chech that this is a keyframe
if ( ! networkManager . isNetworkGame ( ) | | ( world - > getFrameCount ( ) % GameConstants : : networkFramePeriod ) = = 0 ) {
GameNetworkInterface * gameNetworkInterface = NetworkManager : : getInstance ( ) . getGameNetworkInterface ( ) ;
2010-04-15 01:19:00 +00:00
perfTimer . start ( ) ;
2010-03-18 21:26:40 +00:00
//update the keyframe
gameNetworkInterface - > updateKeyframe ( world - > getFrameCount ( ) ) ;
2010-05-07 06:46:55 +00:00
if ( perfTimer . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] gameNetworkInterface->updateKeyframe for %d took %d msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , world - > getFrameCount ( ) , perfTimer . getMillis ( ) ) ;
2010-03-18 21:26:40 +00:00
2010-04-15 01:19:00 +00:00
perfTimer . start ( ) ;
2010-03-18 21:26:40 +00:00
//give pending commands
for ( int i = 0 ; i < gameNetworkInterface - > getPendingCommandCount ( ) ; + + i ) {
giveNetworkCommand ( gameNetworkInterface - > getPendingCommand ( i ) ) ;
}
2010-05-07 06:46:55 +00:00
if ( perfTimer . getMillis ( ) > 0 ) SystemFlags : : OutputDebug ( SystemFlags : : debugPerformance , " In [%s::%s Line: %d] giveNetworkCommand took %d msecs \n " , __FILE__ , __FUNCTION__ , __LINE__ , perfTimer . getMillis ( ) ) ;
2010-03-18 21:26:40 +00:00
gameNetworkInterface - > clearPendingCommands ( ) ;
}
}
2010-03-22 04:47:16 +00:00
/*
2010-03-18 21:26:40 +00:00
void Commander : : giveNetworkCommandSpecial ( const NetworkCommand * networkCommand ) const {
switch ( networkCommand - > getNetworkCommandType ( ) ) {
case nctNetworkCommand : {
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctNetworkCommand \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-18 21:26:40 +00:00
switch ( networkCommand - > getCommandTypeId ( ) ) {
case ncstRotateUnit : {
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found ncstRotateUnit [%d] \n " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getTargetId ( ) ) ;
2010-03-18 21:26:40 +00:00
int unitTypeId = networkCommand - > getUnitId ( ) ;
int factionIndex = networkCommand - > getUnitTypeId ( ) ;
int rotateAmount = networkCommand - > getTargetId ( ) ;
//const Faction *faction = world->getFaction(factionIndex);
//const UnitType* unitType= world->findUnitTypeById(faction->getType(), factionIndex);
char unitKey [ 50 ] = " " ;
sprintf ( unitKey , " %d_%d " , unitTypeId , factionIndex ) ;
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] unitKey = [%s] \n " , __FILE__ , __FUNCTION__ , __LINE__ , unitKey ) ;
2010-03-18 21:26:40 +00:00
Game * game = this - > world - > getGame ( ) ;
Gui * gui = game - > getGui ( ) ;
gui - > setUnitTypeBuildRotation ( unitKey , rotateAmount ) ;
//unit->setRotateAmount(networkCommand->getTargetId());
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found ncstRotateUnit [%d] \n " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getTargetId ( ) ) ;
2010-03-18 21:26:40 +00:00
}
break ;
}
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctNetworkCommand \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-18 21:26:40 +00:00
}
break ;
default :
assert ( false ) ;
}
}
2010-03-22 04:47:16 +00:00
*/
2010-03-18 21:26:40 +00:00
2010-03-22 04:47:16 +00:00
void Commander : : giveNetworkCommand ( NetworkCommand * networkCommand ) const {
2010-03-18 21:26:40 +00:00
2010-03-22 04:47:16 +00:00
networkCommand - > preprocessNetworkCommand ( this - > world ) ;
/*
2010-03-18 21:26:40 +00:00
if ( networkCommand - > getNetworkCommandType ( ) = = nctNetworkCommand ) {
giveNetworkCommandSpecial ( networkCommand ) ;
}
2010-03-22 04:47:16 +00:00
else
*/
{
2010-03-18 21:26:40 +00:00
Unit * unit = world - > findUnitById ( networkCommand - > getUnitId ( ) ) ;
//exec ute command, if unit is still alive
if ( unit ! = NULL ) {
switch ( networkCommand - > getNetworkCommandType ( ) ) {
case nctGiveCommand : {
assert ( networkCommand - > getCommandTypeId ( ) ! = CommandType : : invalidId ) ;
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) ) ;
2010-03-18 21:26:40 +00:00
Command * command = buildCommand ( networkCommand ) ;
2010-05-01 09:27:08 +00:00
2010-04-18 07:35:48 +00:00
unit - > giveCommand ( command , networkCommand - > getWantQueue ( ) ) ;
2010-03-18 21:26:40 +00:00
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) ) ;
2010-03-18 21:26:40 +00:00
}
break ;
case nctCancelCommand : {
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctCancelCommand \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-18 21:26:40 +00:00
unit - > cancelCommand ( ) ;
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctCancelCommand \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-18 21:26:40 +00:00
}
break ;
case nctSetMeetingPoint : {
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctSetMeetingPoint \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-18 21:26:40 +00:00
unit - > setMeetingPos ( networkCommand - > getPosition ( ) ) ;
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] found nctSetMeetingPoint \n " , __FILE__ , __FUNCTION__ , __LINE__ ) ;
2010-03-18 21:26:40 +00:00
}
break ;
default :
assert ( false ) ;
}
}
else {
2010-03-19 23:26:00 +00:00
SystemFlags : : OutputDebug ( SystemFlags : : debugSystem , " In [%s::%s Line: %d] NULL Unit for id = %d, networkCommand->getNetworkCommandType() = %d \n " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) , networkCommand - > getNetworkCommandType ( ) ) ;
2010-03-18 21:26:40 +00:00
}
}
}
Command * Commander : : buildCommand ( const NetworkCommand * networkCommand ) const {
assert ( networkCommand - > getNetworkCommandType ( ) = = nctGiveCommand ) ;
2010-04-20 02:19:37 +00:00
if ( world = = NULL ) {
char szBuf [ 1024 ] = " " ;
sprintf ( szBuf , " In [%s::%s Line: %d] world == NULL for unit with id: %d " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) ) ;
throw runtime_error ( szBuf ) ;
}
2010-03-18 21:26:40 +00:00
Unit * target = NULL ;
const CommandType * ct = NULL ;
const Unit * unit = world - > findUnitById ( networkCommand - > getUnitId ( ) ) ;
//validate unit
if ( unit = = NULL ) {
char szBuf [ 1024 ] = " " ;
2010-04-20 02:19:37 +00:00
sprintf ( szBuf , " In [%s::%s - %d] Can not find unit with id: %d. Game out of synch. " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) ) ;
throw runtime_error ( szBuf ) ;
}
else if ( unit - > getType ( ) = = NULL ) {
char szBuf [ 1024 ] = " " ;
sprintf ( szBuf , " In [%s::%s - %d] unit->getType() == NULL for unit with id: %d " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) ) ;
throw runtime_error ( szBuf ) ;
}
else if ( unit - > getFaction ( ) = = NULL ) {
char szBuf [ 1024 ] = " " ;
sprintf ( szBuf , " In [%s::%s - %d] unit->getFaction() == NULL for unit with id: %d " , __FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getUnitId ( ) ) ;
2010-03-18 21:26:40 +00:00
throw runtime_error ( szBuf ) ;
}
const UnitType * unitType = world - > findUnitTypeById ( unit - > getFaction ( ) - > getType ( ) , networkCommand - > getUnitTypeId ( ) ) ;
ct = unit - > getType ( ) - > findCommandTypeById ( networkCommand - > getCommandTypeId ( ) ) ;
//validate command type
if ( ct = = NULL ) {
char szBuf [ 1024 ] = " " ;
2010-04-20 02:19:37 +00:00
sprintf ( szBuf , " In [%s::%s - %d] Can not find command type with id = %d \n %s \n in unit = %d [%s][%s]. \n Game out of synch. " ,
__FILE__ , __FUNCTION__ , __LINE__ , networkCommand - > getCommandTypeId ( ) , unit - > getType ( ) - > getCommandTypeListDesc ( ) . c_str ( ) , unit - > getId ( ) , unit - > getFullName ( ) . c_str ( ) , unit - > getDesc ( ) . c_str ( ) ) ;
2010-03-18 21:26:40 +00:00
throw runtime_error ( szBuf ) ;
}
2010-03-25 12:15:10 +00:00
CardinalDir facing ;
// get facing/target ... the target might be dead due to lag, cope with it
if ( ct - > getClass ( ) = = ccBuild ) {
assert ( networkCommand - > getTargetId ( ) > = 0 & & networkCommand - > getTargetId ( ) < 4 ) ;
facing = CardinalDir ( networkCommand - > getTargetId ( ) ) ;
2010-04-20 02:19:37 +00:00
}
else if ( networkCommand - > getTargetId ( ) ! = Unit : : invalidId ) {
2010-03-18 21:26:40 +00:00
target = world - > findUnitById ( networkCommand - > getTargetId ( ) ) ;
}
//create command
Command * command = NULL ;
if ( unitType ! = NULL ) {
2010-03-25 12:15:10 +00:00
command = new Command ( ct , networkCommand - > getPosition ( ) , unitType , facing ) ;
2010-03-18 21:26:40 +00:00
}
else if ( target = = NULL ) {
command = new Command ( ct , networkCommand - > getPosition ( ) ) ;
}
else {
command = new Command ( ct , target ) ;
}
//issue command
return command ;
}
} } //end namespace