Remove legacy synch code.
Some of it would run in the case of desynchs, but didn't help with anything.master
parent
a369971dbf
commit
24db01ae10
|
@ -452,8 +452,3 @@ void setPlayerGameTime(unsigned player, uint32_t time)
|
||||||
gameQueueTime[player] = time;
|
gameQueueTime[player] = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInSync(void)
|
|
||||||
{
|
|
||||||
return !crcError;
|
|
||||||
}
|
|
||||||
|
|
|
@ -201,6 +201,4 @@ void recvPlayerGameTime(NETQUEUE queue); ///< Processes a GAME_
|
||||||
bool checkPlayerGameTime(unsigned player); ///< Checks that we are not waiting for a GAME_GAME_TIME message from this player. (player can be NET_ALL_PLAYERS.)
|
bool checkPlayerGameTime(unsigned player); ///< Checks that we are not waiting for a GAME_GAME_TIME message from this player. (player can be NET_ALL_PLAYERS.)
|
||||||
void setPlayerGameTime(unsigned player, uint32_t time); ///< Sets the player's time.
|
void setPlayerGameTime(unsigned player, uint32_t time); ///< Sets the player's time.
|
||||||
|
|
||||||
bool isInSync(void); ///< Returns true unless there was a CRC mismatch between the last GAME_GAME_TIME messages.
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -118,16 +118,6 @@ bool NETstopLogging(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
PHYSFS_write(pFileHandle, dash_line, strlen(dash_line), 1);
|
PHYSFS_write(pFileHandle, dash_line, strlen(dash_line), 1);
|
||||||
snprintf(buf, sizeof(buf), "sent/unsent DroidCheck %"PRIu64" / %"PRIu64"\n", sync_counter.sentDroidCheck, sync_counter.unsentDroidCheck);
|
|
||||||
PHYSFS_write(pFileHandle, buf, strlen(buf), 1);
|
|
||||||
snprintf(buf, sizeof(buf), "sent/unsent StructureCheck %"PRIu64" / %"PRIu64"\n", sync_counter.sentStructureCheck, sync_counter.unsentStructureCheck);
|
|
||||||
PHYSFS_write(pFileHandle, buf, strlen(buf), 1);
|
|
||||||
snprintf(buf, sizeof(buf), "sent/unsent PowerCheck %"PRIu64" / %"PRIu64"\n", sync_counter.sentPowerCheck, sync_counter.unsentPowerCheck);
|
|
||||||
PHYSFS_write(pFileHandle, buf, strlen(buf), 1);
|
|
||||||
snprintf(buf, sizeof(buf), "sent/unsent ScoreCheck %"PRIu64" / %"PRIu64"\n", sync_counter.sentScoreCheck, sync_counter.unsentScoreCheck);
|
|
||||||
PHYSFS_write(pFileHandle, buf, strlen(buf), 1);
|
|
||||||
snprintf(buf, sizeof(buf), "sent/unsent Ping %"PRIu64" / %"PRIu64"\n", sync_counter.sentPing, sync_counter.unsentPing);
|
|
||||||
PHYSFS_write(pFileHandle, buf, strlen(buf), 1);
|
|
||||||
PHYSFS_write(pFileHandle, dash_line, strlen(dash_line), 1);
|
PHYSFS_write(pFileHandle, dash_line, strlen(dash_line), 1);
|
||||||
|
|
||||||
if (!PHYSFS_close(pFileHandle))
|
if (!PHYSFS_close(pFileHandle))
|
||||||
|
|
|
@ -3484,11 +3484,6 @@ const char *messageTypeToString(unsigned messageType_)
|
||||||
case GAME_STRUCTDEST: return "GAME_STRUCTDEST";
|
case GAME_STRUCTDEST: return "GAME_STRUCTDEST";
|
||||||
case GAME_FEATUREDEST: return "GAME_FEATUREDEST";
|
case GAME_FEATUREDEST: return "GAME_FEATUREDEST";
|
||||||
case GAME_RESEARCH: return "GAME_RESEARCH";
|
case GAME_RESEARCH: return "GAME_RESEARCH";
|
||||||
case GAME_CHECK_DROID: return "GAME_CHECK_DROID";
|
|
||||||
case GAME_CHECK_STRUCT: return "GAME_CHECK_STRUCT";
|
|
||||||
case GAME_CHECK_POWER: return "GAME_CHECK_POWER";
|
|
||||||
case GAME_DEMOLISH: return "GAME_DEMOLISH";
|
|
||||||
case GAME_DROIDEMBARK: return "GAME_DROIDEMBARK";
|
|
||||||
case GAME_DROIDDISEMBARK: return "GAME_DROIDDISEMBARK";
|
case GAME_DROIDDISEMBARK: return "GAME_DROIDDISEMBARK";
|
||||||
// End of redundant messages.
|
// End of redundant messages.
|
||||||
case GAME_MAX_TYPE: return "GAME_MAX_TYPE";
|
case GAME_MAX_TYPE: return "GAME_MAX_TYPE";
|
||||||
|
|
|
@ -112,11 +112,6 @@ enum MESSAGE_TYPES
|
||||||
GAME_STRUCTDEST, ///< specify a strucutre to destroy, will be sent by all players at the same time, and have no effect, if synchronised.
|
GAME_STRUCTDEST, ///< specify a strucutre to destroy, will be sent by all players at the same time, and have no effect, if synchronised.
|
||||||
GAME_FEATUREDEST, ///< destroy a game feature.
|
GAME_FEATUREDEST, ///< destroy a game feature.
|
||||||
GAME_RESEARCH, ///< Research has been completed.
|
GAME_RESEARCH, ///< Research has been completed.
|
||||||
GAME_CHECK_DROID, ///< check & update bot position and damage.
|
|
||||||
GAME_CHECK_STRUCT, ///< check & update struct damage.
|
|
||||||
GAME_CHECK_POWER, ///< power levels for a player.
|
|
||||||
GAME_DEMOLISH, ///< a demolish is complete.
|
|
||||||
GAME_DROIDEMBARK, ///< droid embarked on a Transporter
|
|
||||||
GAME_DROIDDISEMBARK, ///< droid disembarked from a Transporter
|
GAME_DROIDDISEMBARK, ///< droid disembarked from a Transporter
|
||||||
// End of redundant messages.
|
// End of redundant messages.
|
||||||
GAME_MAX_TYPE ///< Maximum+1 valid GAME_ type, *MUST* be last.
|
GAME_MAX_TYPE ///< Maximum+1 valid GAME_ type, *MUST* be last.
|
||||||
|
@ -191,16 +186,6 @@ struct GAMESTRUCT
|
||||||
// the following structure is going to be used to track if we sync or not
|
// the following structure is going to be used to track if we sync or not
|
||||||
struct SYNC_COUNTER
|
struct SYNC_COUNTER
|
||||||
{
|
{
|
||||||
uint64_t sentDroidCheck;
|
|
||||||
uint64_t unsentDroidCheck;
|
|
||||||
uint64_t sentStructureCheck;
|
|
||||||
uint64_t unsentStructureCheck;
|
|
||||||
uint64_t sentPowerCheck;
|
|
||||||
uint64_t unsentPowerCheck;
|
|
||||||
uint64_t sentScoreCheck;
|
|
||||||
uint64_t unsentScoreCheck;
|
|
||||||
uint64_t sentPing;
|
|
||||||
uint64_t unsentPing;
|
|
||||||
uint16_t kicks;
|
uint16_t kicks;
|
||||||
uint16_t joins;
|
uint16_t joins;
|
||||||
uint16_t left;
|
uint16_t left;
|
||||||
|
|
|
@ -73,7 +73,6 @@ static CHEAT_ENTRY cheatCodes[] =
|
||||||
{"showlevelname", kf_ToggleLevelName}, // shows the current level name on screen
|
{"showlevelname", kf_ToggleLevelName}, // shows the current level name on screen
|
||||||
{"logical", kf_ToggleLogical}, //logical game updates separated from graphics updates.
|
{"logical", kf_ToggleLogical}, //logical game updates separated from graphics updates.
|
||||||
{"pause", kf_TogglePauseMode}, // Pause the game.
|
{"pause", kf_TogglePauseMode}, // Pause the game.
|
||||||
{"sync me", kf_ForceSync},
|
|
||||||
{"power info", kf_PowerInfo},
|
{"power info", kf_PowerInfo},
|
||||||
{"reload me", kf_Reload}, // reload selected weapons immediately
|
{"reload me", kf_Reload}, // reload selected weapons immediately
|
||||||
{"desync me", kf_ForceDesync},
|
{"desync me", kf_ForceDesync},
|
||||||
|
|
|
@ -291,7 +291,6 @@ DROID::DROID(uint32_t id, unsigned player)
|
||||||
, action(DACTION_NONE)
|
, action(DACTION_NONE)
|
||||||
, actionPos(0, 0)
|
, actionPos(0, 0)
|
||||||
, psCurAnim(NULL)
|
, psCurAnim(NULL)
|
||||||
, gameCheckDroid(NULL)
|
|
||||||
{
|
{
|
||||||
order.type = DORDER_NONE;
|
order.type = DORDER_NONE;
|
||||||
order.pos = Vector2i(0, 0);
|
order.pos = Vector2i(0, 0);
|
||||||
|
@ -345,8 +344,6 @@ DROID::~DROID()
|
||||||
clustRemoveObject((BASE_OBJECT *)psDroid);
|
clustRemoveObject((BASE_OBJECT *)psDroid);
|
||||||
|
|
||||||
free(sMove.asPath);
|
free(sMove.asPath);
|
||||||
|
|
||||||
delete gameCheckDroid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -413,15 +410,6 @@ void removeDroidBase(DROID *psDel)
|
||||||
|
|
||||||
syncDebugDroid(psDel, '#');
|
syncDebugDroid(psDel, '#');
|
||||||
|
|
||||||
//ajl, inform others of destruction.
|
|
||||||
// Everyone else should be doing this at the same time, assuming it's in synch (so everyone sends a GAME_DROIDDEST message at once)...
|
|
||||||
if (!isInSync() && bMultiMessages
|
|
||||||
&& !(psDel->player != selectedPlayer && psDel->order.type == DORDER_RECYCLE))
|
|
||||||
{
|
|
||||||
ASSERT_OR_RETURN( , droidOnMap(psDel), "Asking other players to destroy droid driving off the map");
|
|
||||||
SendDestroyDroid(psDel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove animation if present */
|
/* remove animation if present */
|
||||||
if (psDel->psCurAnim != NULL)
|
if (psDel->psCurAnim != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,7 +122,6 @@ struct DROID_TEMPLATE : public BASE_STATS
|
||||||
bool enabled; ///< Has been enabled
|
bool enabled; ///< Has been enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PACKAGED_CHECK;
|
|
||||||
class DROID_GROUP;
|
class DROID_GROUP;
|
||||||
struct STRUCTURE;
|
struct STRUCTURE;
|
||||||
|
|
||||||
|
@ -205,9 +204,6 @@ struct DROID : public BASE_OBJECT
|
||||||
/* anim data */
|
/* anim data */
|
||||||
ANIM_OBJECT *psCurAnim;
|
ANIM_OBJECT *psCurAnim;
|
||||||
SDWORD iAudioID;
|
SDWORD iAudioID;
|
||||||
|
|
||||||
// Synch checking
|
|
||||||
PACKAGED_CHECK *gameCheckDroid; ///< Last PACKAGED_CHECK, for synchronisation use only (see multisync.c). TODO Make synch perfect, so that this isn't needed at all.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __INCLUDED_DROIDDEF_H__
|
#endif // __INCLUDED_DROIDDEF_H__
|
||||||
|
|
|
@ -378,11 +378,6 @@ bool removeFeature(FEATURE *psDel)
|
||||||
ASSERT_OR_RETURN(false, psDel != NULL, "Invalid feature pointer");
|
ASSERT_OR_RETURN(false, psDel != NULL, "Invalid feature pointer");
|
||||||
ASSERT_OR_RETURN(false, !psDel->died, "Feature already dead");
|
ASSERT_OR_RETURN(false, !psDel->died, "Feature already dead");
|
||||||
|
|
||||||
if (bMultiMessages && !ingame.localJoiningInProgress && !isInSync())
|
|
||||||
{
|
|
||||||
SendDestroyFeature(psDel); // inform other players of destruction
|
|
||||||
}
|
|
||||||
|
|
||||||
//remove from the map data
|
//remove from the map data
|
||||||
StructureBounds b = getStructureBounds(psDel);
|
StructureBounds b = getStructureBounds(psDel);
|
||||||
for (int breadth = 0; breadth < b.size.y; ++breadth)
|
for (int breadth = 0; breadth < b.size.y; ++breadth)
|
||||||
|
|
|
@ -164,21 +164,6 @@ void kf_ToggleRadarJump( void )
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
void kf_ForceSync( void )
|
|
||||||
{
|
|
||||||
DROID *psCDroid, *psNDroid;
|
|
||||||
|
|
||||||
for(psCDroid = apsDroidLists[selectedPlayer]; psCDroid; psCDroid = psNDroid)
|
|
||||||
{
|
|
||||||
psNDroid = psCDroid->psNext;
|
|
||||||
if (psCDroid->selected)
|
|
||||||
{
|
|
||||||
ForceDroidSync(psCDroid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void kf_ForceDesync(void)
|
void kf_ForceDesync(void)
|
||||||
{
|
{
|
||||||
syncDebug("Oh no!!! I went out of sync!!!");
|
syncDebug("Oh no!!! I went out of sync!!!");
|
||||||
|
|
|
@ -259,7 +259,6 @@ extern void kf_ToggleWatchWindow( void );
|
||||||
|
|
||||||
bool runningMultiplayer(void);
|
bool runningMultiplayer(void);
|
||||||
|
|
||||||
void kf_ForceSync( void );
|
|
||||||
void kf_ForceDesync(void);
|
void kf_ForceDesync(void);
|
||||||
void kf_PowerInfo( void );
|
void kf_PowerInfo( void );
|
||||||
void kf_BuildNextPage( void );
|
void kf_BuildNextPage( void );
|
||||||
|
|
|
@ -635,12 +635,6 @@ static void gameStateUpdate()
|
||||||
|
|
||||||
objmemUpdate();
|
objmemUpdate();
|
||||||
|
|
||||||
// Do completely useless stuff.
|
|
||||||
if (!isInSync())
|
|
||||||
{
|
|
||||||
sendCheck(); // send some pointless checking info if we're doomed anyway
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must end update, since we may or may not have ticked, and some message queue processing code may vary depending on whether it's in an update.
|
// Must end update, since we may or may not have ticked, and some message queue processing code may vary depending on whether it's in an update.
|
||||||
gameTimeUpdateEnd();
|
gameTimeUpdateEnd();
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,95 +165,6 @@ bool sendDroidSecondary(const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STA
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Broadcast droid and transporter loading information
|
|
||||||
*
|
|
||||||
* \sa recvDroidEmbark(),sendDroidDisEmbark(),recvDroidDisEmbark()
|
|
||||||
*/
|
|
||||||
bool sendDroidEmbark(const DROID* psDroid, const DROID* psTransporter)
|
|
||||||
{
|
|
||||||
if (!bMultiMessages)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DROIDEMBARK);
|
|
||||||
{
|
|
||||||
uint8_t player = psDroid->player;
|
|
||||||
uint32_t droidID = psDroid->id;
|
|
||||||
uint32_t transporterID = psTransporter->id;
|
|
||||||
|
|
||||||
NETuint8_t(&player);
|
|
||||||
NETuint32_t(&droidID);
|
|
||||||
NETuint32_t(&transporterID);
|
|
||||||
}
|
|
||||||
return NETend();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Receive droid and transporter loading information
|
|
||||||
*
|
|
||||||
* \sa sendDroidEmbark(),sendDroidDisEmbark(),recvDroidDisEmbark()
|
|
||||||
*/
|
|
||||||
bool recvDroidEmbark(NETQUEUE queue)
|
|
||||||
{
|
|
||||||
DROID* psDroid;
|
|
||||||
DROID* psTransporterDroid;
|
|
||||||
bool bDroidRemoved;
|
|
||||||
|
|
||||||
NETbeginDecode(queue, GAME_DROIDEMBARK);
|
|
||||||
{
|
|
||||||
uint8_t player;
|
|
||||||
uint32_t droidID;
|
|
||||||
uint32_t transporterID;
|
|
||||||
|
|
||||||
NETuint8_t(&player);
|
|
||||||
NETuint32_t(&droidID);
|
|
||||||
NETuint32_t(&transporterID);
|
|
||||||
|
|
||||||
// we have to find the droid on our (local) list first.
|
|
||||||
psDroid = IdToDroid(droidID, player);
|
|
||||||
if (!psDroid)
|
|
||||||
{
|
|
||||||
NETend();
|
|
||||||
// Possible it already died? (sync error?)
|
|
||||||
debug(LOG_WARNING, "player's %d droid %d wasn't found?", player,droidID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
psTransporterDroid = IdToDroid(transporterID, player);
|
|
||||||
if (!psTransporterDroid)
|
|
||||||
{
|
|
||||||
NETend();
|
|
||||||
// Possible it already died? (sync error?)
|
|
||||||
debug(LOG_WARNING, "player's %d transport droid %d wasn't found?", player,transporterID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psDroid == NULL)
|
|
||||||
{
|
|
||||||
// how can this happen?
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take it out of the world without destroying it (just removes it from the droid list)
|
|
||||||
bDroidRemoved = droidRemove(psDroid, apsDroidLists);
|
|
||||||
|
|
||||||
// Init the order for when disembark
|
|
||||||
psDroid->order.type = DORDER_NONE;
|
|
||||||
setDroidTarget(psDroid, NULL);
|
|
||||||
psDroid->order.psStats = NULL;
|
|
||||||
|
|
||||||
if (bDroidRemoved)
|
|
||||||
{
|
|
||||||
// and now we need to add it to their transporter group!
|
|
||||||
psTransporterDroid->psGroup->add(psDroid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// possible sync error?
|
|
||||||
debug(LOG_WARNING, "Eh? Where did unit %d go? Couldn't load droid onto transporter.", droidID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NETend();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Broadcast that droid is being unloaded from a transporter
|
/** Broadcast that droid is being unloaded from a transporter
|
||||||
*
|
*
|
||||||
* \sa sendDroidEmbark(),recvDroidEmbark(),recvDroidDisEmbark()
|
* \sa sendDroidEmbark(),recvDroidEmbark(),recvDroidDisEmbark()
|
||||||
|
|
|
@ -582,15 +582,6 @@ bool recvMessage(void)
|
||||||
case GAME_DROIDDEST: // droid destroy
|
case GAME_DROIDDEST: // droid destroy
|
||||||
recvDestroyDroid(queue);
|
recvDestroyDroid(queue);
|
||||||
break;
|
break;
|
||||||
case GAME_CHECK_DROID: // droid damage and position checks
|
|
||||||
recvDroidCheck(queue);
|
|
||||||
break;
|
|
||||||
case GAME_CHECK_STRUCT: // structure damage checks.
|
|
||||||
recvStructureCheck(queue);
|
|
||||||
break;
|
|
||||||
case GAME_CHECK_POWER: // Power level syncing.
|
|
||||||
recvPowerCheck(queue);
|
|
||||||
break;
|
|
||||||
case NET_TEXTMSG: // simple text message
|
case NET_TEXTMSG: // simple text message
|
||||||
recvTextMessage(queue);
|
recvTextMessage(queue);
|
||||||
break;
|
break;
|
||||||
|
@ -609,9 +600,6 @@ bool recvMessage(void)
|
||||||
case GAME_STRUCTDEST: // structure destroy
|
case GAME_STRUCTDEST: // structure destroy
|
||||||
recvDestroyStructure(queue);
|
recvDestroyStructure(queue);
|
||||||
break;
|
break;
|
||||||
case GAME_DROIDEMBARK:
|
|
||||||
recvDroidEmbark(queue); //droid has embarked on a Transporter
|
|
||||||
break;
|
|
||||||
case GAME_DROIDDISEMBARK:
|
case GAME_DROIDDISEMBARK:
|
||||||
recvDroidDisEmbark(queue); //droid has disembarked from a Transporter
|
recvDroidDisEmbark(queue); //droid has disembarked from a Transporter
|
||||||
break;
|
break;
|
||||||
|
@ -643,9 +631,6 @@ bool recvMessage(void)
|
||||||
case NET_PING: // diagnostic ping msg.
|
case NET_PING: // diagnostic ping msg.
|
||||||
recvPing(queue);
|
recvPing(queue);
|
||||||
break;
|
break;
|
||||||
case GAME_DEMOLISH: // structure demolished.
|
|
||||||
recvDemolishFinished(queue);
|
|
||||||
break;
|
|
||||||
case GAME_RESEARCH: // some research has been done.
|
case GAME_RESEARCH: // some research has been done.
|
||||||
recvResearch(queue);
|
recvResearch(queue);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -82,22 +82,6 @@ enum STRUCTURE_INFO
|
||||||
STRUCTUREINFO_RELEASERESEARCH
|
STRUCTUREINFO_RELEASERESEARCH
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PACKAGED_CHECK
|
|
||||||
{
|
|
||||||
uint32_t gameTime; ///< Game time that this synch check was made. Not touched by NETauto().
|
|
||||||
uint8_t player;
|
|
||||||
uint32_t droidID;
|
|
||||||
int32_t order;
|
|
||||||
uint32_t secondaryOrder;
|
|
||||||
uint32_t body;
|
|
||||||
uint32_t experience;
|
|
||||||
Position pos;
|
|
||||||
Rotation rot;
|
|
||||||
uint32_t targetID; ///< Defined iff order == DORDER_ATTACK.
|
|
||||||
uint16_t orderX; ///< Defined iff order == DORDER_MOVE.
|
|
||||||
uint16_t orderY; ///< Defined iff order == DORDER_MOVE.
|
|
||||||
};
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////////
|
||||||
// Game Options and stats.
|
// Game Options and stats.
|
||||||
extern MULTIPLAYERGAME game; // the game description.
|
extern MULTIPLAYERGAME game; // the game description.
|
||||||
|
@ -203,14 +187,12 @@ void sendStructureInfo (STRUCTURE *psStruct, STRUCTURE_INFO str
|
||||||
// droids . multibot
|
// droids . multibot
|
||||||
extern bool SendDroid (const DROID_TEMPLATE* pTemplate, uint32_t x, uint32_t y, uint8_t player, uint32_t id, const INITIAL_DROID_ORDERS *initialOrders);
|
extern bool SendDroid (const DROID_TEMPLATE* pTemplate, uint32_t x, uint32_t y, uint8_t player, uint32_t id, const INITIAL_DROID_ORDERS *initialOrders);
|
||||||
extern bool SendDestroyDroid (const DROID* psDroid);
|
extern bool SendDestroyDroid (const DROID* psDroid);
|
||||||
extern bool SendDemolishFinished(STRUCTURE *psS,DROID *psD);
|
|
||||||
void sendQueuedDroidInfo(void); ///< Actually sends the droid orders which were queued by SendDroidInfo.
|
void sendQueuedDroidInfo(void); ///< Actually sends the droid orders which were queued by SendDroidInfo.
|
||||||
void sendDroidInfo(DROID *psDroid, DroidOrder const &order, bool add);
|
void sendDroidInfo(DROID *psDroid, DroidOrder const &order, bool add);
|
||||||
extern bool SendCmdGroup (DROID_GROUP *psGroup, UWORD x, UWORD y, BASE_OBJECT *psObj);
|
extern bool SendCmdGroup (DROID_GROUP *psGroup, UWORD x, UWORD y, BASE_OBJECT *psObj);
|
||||||
|
|
||||||
|
|
||||||
extern bool sendDroidSecondary (const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STATE state);
|
extern bool sendDroidSecondary (const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STATE state);
|
||||||
extern bool sendDroidEmbark (const DROID* psDroid, const DROID* psTransporter);
|
|
||||||
bool sendDroidDisembark(DROID const *psTransporter, DROID const *psDroid);
|
bool sendDroidDisembark(DROID const *psTransporter, DROID const *psDroid);
|
||||||
|
|
||||||
// Startup. mulitopt
|
// Startup. mulitopt
|
||||||
|
@ -228,11 +210,9 @@ extern bool addTemplateToList(DROID_TEMPLATE *psNew, DROID_TEMPLATE **ppList);
|
||||||
void addTemplateBack(unsigned player, DROID_TEMPLATE *psNew);
|
void addTemplateBack(unsigned player, DROID_TEMPLATE *psNew);
|
||||||
|
|
||||||
// syncing.
|
// syncing.
|
||||||
void sendCheck(); //send/recv check info
|
|
||||||
extern bool sendScoreCheck (void); //score check only(frontend)
|
extern bool sendScoreCheck (void); //score check only(frontend)
|
||||||
extern bool sendPing (void); // allow game to request pings.
|
extern bool sendPing (void); // allow game to request pings.
|
||||||
|
|
||||||
extern bool ForceDroidSync(const DROID *droidToSend);
|
|
||||||
// multijoin
|
// multijoin
|
||||||
extern bool sendResearchStatus (STRUCTURE *psBuilding, UDWORD index, UBYTE player, bool bStart);
|
extern bool sendResearchStatus (STRUCTURE *psBuilding, UDWORD index, UBYTE player, bool bStart);
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,10 @@ extern bool recvDestroyStructure (NETQUEUE queue);
|
||||||
extern bool recvBuildFinished (NETQUEUE queue);
|
extern bool recvBuildFinished (NETQUEUE queue);
|
||||||
extern bool recvTemplate (NETQUEUE queue);
|
extern bool recvTemplate (NETQUEUE queue);
|
||||||
extern bool recvDestroyFeature (NETQUEUE queue);
|
extern bool recvDestroyFeature (NETQUEUE queue);
|
||||||
extern bool recvDemolishFinished (NETQUEUE queue);
|
|
||||||
extern bool recvPing (NETQUEUE queue);
|
extern bool recvPing (NETQUEUE queue);
|
||||||
extern bool recvRequestDroid (NETQUEUE queue);
|
extern bool recvRequestDroid (NETQUEUE queue);
|
||||||
extern bool recvTextMessage (NETQUEUE queue);
|
extern bool recvTextMessage (NETQUEUE queue);
|
||||||
extern bool recvDroidEmbark (NETQUEUE queue);
|
|
||||||
extern bool recvDroidDisEmbark (NETQUEUE queue);
|
extern bool recvDroidDisEmbark (NETQUEUE queue);
|
||||||
extern bool recvDroidCheck (NETQUEUE queue);
|
|
||||||
extern bool recvStructureCheck (NETQUEUE queue);
|
|
||||||
extern bool recvPowerCheck (NETQUEUE queue);
|
|
||||||
extern bool recvColourRequest (NETQUEUE queue);
|
extern bool recvColourRequest (NETQUEUE queue);
|
||||||
extern bool recvPositionRequest (NETQUEUE queue);
|
extern bool recvPositionRequest (NETQUEUE queue);
|
||||||
extern void recvOptions (NETQUEUE queue);
|
extern void recvOptions (NETQUEUE queue);
|
||||||
|
|
|
@ -151,53 +151,6 @@ bool recvBuildFinished(NETQUEUE queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
|
||||||
// demolish message.
|
|
||||||
bool SendDemolishFinished(STRUCTURE *psStruct, DROID *psDroid)
|
|
||||||
{
|
|
||||||
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DEMOLISH);
|
|
||||||
|
|
||||||
// Send what is being demolish and who is doing it
|
|
||||||
NETuint32_t(&psStruct->id);
|
|
||||||
NETuint32_t(&psDroid->id);
|
|
||||||
|
|
||||||
return NETend();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool recvDemolishFinished(NETQUEUE queue)
|
|
||||||
{
|
|
||||||
STRUCTURE *psStruct;
|
|
||||||
DROID *psDroid;
|
|
||||||
uint32_t structID, droidID;
|
|
||||||
|
|
||||||
NETbeginDecode(queue, GAME_DEMOLISH);
|
|
||||||
NETuint32_t(&structID);
|
|
||||||
NETuint32_t(&droidID);
|
|
||||||
NETend();
|
|
||||||
|
|
||||||
psStruct = IdToStruct(structID, ANYPLAYER);
|
|
||||||
psDroid = IdToDroid(droidID, ANYPLAYER);
|
|
||||||
if (!psDroid)
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "recvDemolishFinished: Packet with bad droid ID received. Discarding!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (psStruct)
|
|
||||||
{
|
|
||||||
// Demolish it
|
|
||||||
// Should never get here, if in synch.
|
|
||||||
removeStruct(psStruct, true);
|
|
||||||
if (psDroid && psDroid->order.psStats)
|
|
||||||
{
|
|
||||||
// Update droid if reqd
|
|
||||||
psDroid->order.psStats = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////////
|
||||||
// Inform others that a structure has been destroyed
|
// Inform others that a structure has been destroyed
|
||||||
bool SendDestroyStructure(STRUCTURE *s)
|
bool SendDestroyStructure(STRUCTURE *s)
|
||||||
|
|
|
@ -53,704 +53,16 @@
|
||||||
#include "multirecv.h"
|
#include "multirecv.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
|
||||||
static void NETauto(PACKAGED_CHECK *v)
|
|
||||||
{
|
|
||||||
NETauto(&v->player);
|
|
||||||
NETauto(&v->droidID);
|
|
||||||
NETauto(&v->order);
|
|
||||||
NETauto(&v->secondaryOrder);
|
|
||||||
NETauto(&v->body);
|
|
||||||
NETauto(&v->experience);
|
|
||||||
NETauto(&v->pos);
|
|
||||||
NETauto(&v->rot);
|
|
||||||
if (v->order == DORDER_ATTACK)
|
|
||||||
{
|
|
||||||
NETauto(&v->targetID);
|
|
||||||
}
|
|
||||||
else if (v->order == DORDER_MOVE)
|
|
||||||
{
|
|
||||||
NETauto(&v->orderX);
|
|
||||||
NETauto(&v->orderY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////////
|
||||||
// function definitions
|
// function definitions
|
||||||
|
|
||||||
static bool sendStructureCheck (void); //Structure
|
|
||||||
static PACKAGED_CHECK packageCheck(const DROID *pD);
|
|
||||||
static bool sendDroidCheck (void); //droids
|
|
||||||
|
|
||||||
static bool sendPowerCheck(void);
|
|
||||||
static UDWORD averagePing(void);
|
static UDWORD averagePing(void);
|
||||||
|
|
||||||
#define AV_PING_FREQUENCY 20000 // how often to update average pingtimes. in approx millisecs.
|
#define AV_PING_FREQUENCY 20000 // how often to update average pingtimes. in approx millisecs.
|
||||||
#define PING_FREQUENCY 4000 // how often to update pingtimes. in approx millisecs.
|
#define PING_FREQUENCY 4000 // how often to update pingtimes. in approx millisecs.
|
||||||
#define STRUCT_PERIOD 4000 // how often (ms) to send a structure check.
|
|
||||||
#define DROID_PERIOD 315 // how often (ms) to send droid checks
|
|
||||||
#define POWER_PERIOD 5000 // how often to send power levels
|
|
||||||
#define SCORE_FREQUENCY 108000 // how often to update global score.
|
|
||||||
|
|
||||||
static UDWORD PingSend[MAX_PLAYERS]; //stores the time the ping was called.
|
static UDWORD PingSend[MAX_PLAYERS]; //stores the time the ping was called.
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
|
||||||
// test traffic level.
|
|
||||||
static bool okToSend(void)
|
|
||||||
{
|
|
||||||
// Update checks and go no further if any exceeded.
|
|
||||||
// removing the received check again ... add NETgetRecentBytesRecvd() to left hand side of equation if this works badly
|
|
||||||
if (NETgetRecentBytesSent() >= MAX_BYTESPERSEC)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Droid checking info. keep position and damage in sync.
|
|
||||||
void sendCheck()
|
|
||||||
{
|
|
||||||
NETgetBytesSent(); // update stats.
|
|
||||||
NETgetBytesRecvd();
|
|
||||||
NETgetPacketsSent();
|
|
||||||
NETgetPacketsRecvd();
|
|
||||||
|
|
||||||
// dont send checks till all players are present.
|
|
||||||
for (unsigned i = 0; i < MAX_PLAYERS; ++i)
|
|
||||||
{
|
|
||||||
if(isHumanPlayer(i) && ingame.JoiningInProgress[i])
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// send Checks. note each send has it's own send criteria, so might not send anything.
|
|
||||||
// Priority is droids -> structures -> power -> score -> ping
|
|
||||||
|
|
||||||
sendDroidCheck();
|
|
||||||
sync_counter.sentDroidCheck++;
|
|
||||||
sendStructureCheck();
|
|
||||||
sync_counter.sentStructureCheck++;
|
|
||||||
sendPowerCheck();
|
|
||||||
sync_counter.sentPowerCheck++;
|
|
||||||
if(okToSend())
|
|
||||||
{
|
|
||||||
sendScoreCheck();
|
|
||||||
sync_counter.sentScoreCheck++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sync_counter.unsentScoreCheck++;
|
|
||||||
}
|
|
||||||
if(okToSend())
|
|
||||||
{
|
|
||||||
sendPing();
|
|
||||||
sync_counter.sentPing++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sync_counter.unsentPing++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
|
||||||
// pick a droid to send, NULL otherwise.
|
|
||||||
static DROID* pickADroid(void)
|
|
||||||
{
|
|
||||||
DROID *pD, *ret = NULL; // ret: dummy initialisation.
|
|
||||||
unsigned player = MAX_PLAYERS;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
// Pick a random player who has at least one droid.
|
|
||||||
for (i = 0; i < 200; ++i)
|
|
||||||
{
|
|
||||||
unsigned p = gameRand(MAX_PLAYERS);
|
|
||||||
if (apsDroidLists[p] != NULL)
|
|
||||||
{
|
|
||||||
player = p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player == MAX_PLAYERS)
|
|
||||||
{
|
|
||||||
return NULL; // No players have any droids, with high probability...
|
|
||||||
}
|
|
||||||
|
|
||||||
// O(n) where n is number of droids. Slow, but hard to beat on a linked list. (One call of a pick n droids function would be just as fast.)
|
|
||||||
i = 0;
|
|
||||||
for (pD = apsDroidLists[player]; pD != NULL; pD = pD->psNext)
|
|
||||||
{
|
|
||||||
if (gameRand(++i) == 0)
|
|
||||||
{
|
|
||||||
ret = pD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Force a droid to be synced
|
|
||||||
*
|
|
||||||
* Call this when you need to update the given droid right now.
|
|
||||||
*/
|
|
||||||
bool ForceDroidSync(const DROID* droidToSend)
|
|
||||||
{
|
|
||||||
uint8_t count = 1; // *always* one
|
|
||||||
PACKAGED_CHECK pc = packageCheck(droidToSend);
|
|
||||||
|
|
||||||
ASSERT(droidToSend != NULL, "NULL pointer passed");
|
|
||||||
|
|
||||||
debug(LOG_SYNC, "Force sync of droid %u from player %u", droidToSend->id, droidToSend->player);
|
|
||||||
|
|
||||||
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_DROID);
|
|
||||||
NETuint8_t(&count);
|
|
||||||
NETuint32_t(&gameTime); // Send game time.
|
|
||||||
NETauto(&pc);
|
|
||||||
return NETend();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ///////////////////////////////////////////////////////////////////////////
|
|
||||||
// send a droid info packet.
|
|
||||||
static bool sendDroidCheck(void)
|
|
||||||
{
|
|
||||||
DROID *pD, **ppD;
|
|
||||||
uint8_t i, count;
|
|
||||||
static UDWORD lastSent = 0; // Last time a struct was sent.
|
|
||||||
UDWORD toSend = 12;
|
|
||||||
|
|
||||||
if (lastSent > gameTime)
|
|
||||||
{
|
|
||||||
lastSent= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only send a struct send if not done recently
|
|
||||||
if (gameTime - lastSent < DROID_PERIOD)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastSent = gameTime;
|
|
||||||
|
|
||||||
|
|
||||||
if (!isInSync()) // Don't really send anything, unless out of synch.
|
|
||||||
{
|
|
||||||
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_DROID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate space for the list of droids to send
|
|
||||||
ppD = (DROID **)alloca(sizeof(DROID *) * toSend);
|
|
||||||
|
|
||||||
// Get the list of droids to sent
|
|
||||||
for (i = 0, count = 0; i < toSend; i++)
|
|
||||||
{
|
|
||||||
pD = pickADroid();
|
|
||||||
|
|
||||||
if (pD == NULL || (pD->gameCheckDroid != NULL && pD->gameCheckDroid->gameTime > gameTime))
|
|
||||||
{
|
|
||||||
continue; // Didn't find a droid, or droid was synched recently.
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the droid is ours add it to the list
|
|
||||||
if (myResponsibility(pD->player))
|
|
||||||
{
|
|
||||||
ppD[count++] = pD;
|
|
||||||
}
|
|
||||||
delete pD->gameCheckDroid;
|
|
||||||
pD->gameCheckDroid = new PACKAGED_CHECK(packageCheck(pD));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isInSync()) // Don't really send anything, unless out of synch.
|
|
||||||
{
|
|
||||||
// Send the number of droids to expect
|
|
||||||
NETuint8_t(&count);
|
|
||||||
NETuint32_t(&gameTime); // Send game time.
|
|
||||||
|
|
||||||
// Add the droids to the packet
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
NETauto(ppD[i]->gameCheckDroid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isInSync()) // Don't really send anything, unless out of synch.
|
|
||||||
{
|
|
||||||
return NETend();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MIN_DELAY_BETWEEN_DROID_SYNCHS 5000 // Must be longer than maximum possible latency.
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Send a Single Droid Check message
|
|
||||||
static PACKAGED_CHECK packageCheck(const DROID *pD)
|
|
||||||
{
|
|
||||||
PACKAGED_CHECK pc;
|
|
||||||
memset(&pc, 0xFF, sizeof(pc)); // Dummy initialisation.
|
|
||||||
pc.gameTime = gameTime + MIN_DELAY_BETWEEN_DROID_SYNCHS;
|
|
||||||
|
|
||||||
pc.player = pD->player;
|
|
||||||
pc.droidID = pD->id;
|
|
||||||
pc.order = pD->order.type;
|
|
||||||
pc.secondaryOrder = pD->secondaryOrder;
|
|
||||||
pc.body = pD->body;
|
|
||||||
if (pD->body > pD->originalBody)
|
|
||||||
{
|
|
||||||
ASSERT(false, "Droid %u body is too high before synch, is %u, which is more than %u.", pc.droidID, pD->body, pD->originalBody);
|
|
||||||
}
|
|
||||||
pc.experience = pD->experience;
|
|
||||||
pc.pos = pD->pos;
|
|
||||||
pc.rot = pD->rot;
|
|
||||||
if (pD->order.type == DORDER_ATTACK)
|
|
||||||
{
|
|
||||||
pc.targetID = pD->order.psObj->id;
|
|
||||||
}
|
|
||||||
else if (pD->order.type == DORDER_MOVE)
|
|
||||||
{
|
|
||||||
pc.orderX = pD->order.pos.x;
|
|
||||||
pc.orderY = pD->order.pos.y;
|
|
||||||
}
|
|
||||||
return pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////
|
|
||||||
// receive a check and update the local world state accordingly
|
|
||||||
bool recvDroidCheck(NETQUEUE queue)
|
|
||||||
{
|
|
||||||
uint8_t count;
|
|
||||||
int i;
|
|
||||||
uint32_t synchTime;
|
|
||||||
|
|
||||||
NETbeginDecode(queue, GAME_CHECK_DROID);
|
|
||||||
|
|
||||||
// Get the number of droids to expect
|
|
||||||
NETuint8_t(&count);
|
|
||||||
NETuint32_t(&synchTime); // Get game time.
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
DROID * pD;
|
|
||||||
PACKAGED_CHECK pc;
|
|
||||||
|
|
||||||
NETauto(&pc);
|
|
||||||
|
|
||||||
// Find the droid in question
|
|
||||||
pD = IdToDroid(pc.droidID, pc.player);
|
|
||||||
if (!pD)
|
|
||||||
{
|
|
||||||
NETlogEntry("Recvd Unknown droid info. val=player", SYNC_FLAG, pc.player);
|
|
||||||
debug(LOG_SYNC, "Received checking info for an unknown (as yet) droid. player:%d ref:%d", pc.player, pc.droidID);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
syncDebugDroid(pD, '<');
|
|
||||||
|
|
||||||
if (pD->gameCheckDroid == NULL)
|
|
||||||
{
|
|
||||||
debug(LOG_SYNC, "We got a droid %u synch, but we couldn't find the droid!", pc.droidID);
|
|
||||||
continue; // Can't synch, since we didn't save data to be able to calculate a delta.
|
|
||||||
}
|
|
||||||
|
|
||||||
PACKAGED_CHECK const pc2 = *pD->gameCheckDroid;
|
|
||||||
|
|
||||||
if (pc2.gameTime != synchTime + MIN_DELAY_BETWEEN_DROID_SYNCHS)
|
|
||||||
{
|
|
||||||
debug(LOG_SYNC, "We got a droid %u synch, but we didn't choose the same droid to synch.", pc.droidID);
|
|
||||||
pD->gameCheckDroid->gameTime = synchTime + MIN_DELAY_BETWEEN_DROID_SYNCHS; // Get droid synch time back in synch.
|
|
||||||
continue; // Can't synch, since we didn't save data to be able to calculate a delta.
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MERGECOPYSYNC(x, y, z) if (pc.y != pc2.y) { debug(LOG_SYNC, "Droid %u out of synch, changing "#x" from %"z" to %"z".", pc.droidID, x, pc.y); x = pc.y; }
|
|
||||||
#define MERGEDELTA(x, y, z) if (pc.y != pc2.y) { debug(LOG_SYNC, "Droid %u out of synch, changing "#x" from %"z" to %"z".", pc.droidID, x, x + pc.y - pc2.y); x += pc.y - pc2.y; }
|
|
||||||
// player not synched here...
|
|
||||||
MERGEDELTA(pD->pos.x, pos.x, "d");
|
|
||||||
MERGEDELTA(pD->pos.y, pos.y, "d");
|
|
||||||
MERGEDELTA(pD->pos.z, pos.z, "d");
|
|
||||||
MERGEDELTA(pD->rot.direction, rot.direction, "d");
|
|
||||||
MERGEDELTA(pD->rot.pitch, rot.pitch, "d");
|
|
||||||
MERGEDELTA(pD->rot.roll, rot.roll, "d");
|
|
||||||
MERGEDELTA(pD->body, body, "u");
|
|
||||||
if (pD->body > pD->originalBody)
|
|
||||||
{
|
|
||||||
pD->body = pD->originalBody;
|
|
||||||
debug(LOG_SYNC, "Droid %u body was too high after synch, reducing to %u.", pc.droidID, pD->body);
|
|
||||||
}
|
|
||||||
MERGEDELTA(pD->experience, experience, "u");
|
|
||||||
|
|
||||||
if (pc.pos.x != pc2.pos.x || pc.pos.y != pc2.pos.y)
|
|
||||||
{
|
|
||||||
// snap droid(if on ground) to terrain level at x,y.
|
|
||||||
if ((asPropulsionStats + pD->asBits[COMP_PROPULSION].nStat)->propulsionType != PROPULSION_TYPE_LIFT) // if not airborne.
|
|
||||||
{
|
|
||||||
pD->pos.z = map_Height(pD->pos.x, pD->pos.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Doesn't cover all cases, but at least doesn't actively break stuff randomly.
|
|
||||||
switch (pc.order)
|
|
||||||
{
|
|
||||||
case DORDER_MOVE:
|
|
||||||
if (pc.order != pc2.order || pc.orderX != pc2.orderX || pc.orderY != pc2.orderY)
|
|
||||||
{
|
|
||||||
debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s(%d, %d).", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order), pc.orderX, pc.orderY);
|
|
||||||
// reroute the droid.
|
|
||||||
orderDroidLoc(pD, (DROID_ORDER)pc.order, pc.orderX, pc.orderY, ModeImmediate);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DORDER_ATTACK:
|
|
||||||
if (pc.order != pc2.order || pc.targetID != pc2.targetID)
|
|
||||||
{
|
|
||||||
BASE_OBJECT *obj = IdToPointer(pc.targetID, ANYPLAYER);
|
|
||||||
if (obj != NULL)
|
|
||||||
{
|
|
||||||
debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s(%u).", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order), pc.targetID);
|
|
||||||
// remote droid is attacking, not here tho!
|
|
||||||
orderDroidObj(pD, (DROID_ORDER)pc.order, IdToPointer(pc.targetID, ANYPLAYER), ModeImmediate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debug(LOG_SYNC, "Droid %u out of synch, would change order from %s to %s(%u), but can't find target.", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order), pc.targetID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DORDER_NONE:
|
|
||||||
case DORDER_GUARD:
|
|
||||||
if (pc.order != pc2.order)
|
|
||||||
{
|
|
||||||
DROID_ORDER_DATA sOrder;
|
|
||||||
memset(&sOrder, 0, sizeof(DROID_ORDER_DATA));
|
|
||||||
sOrder.type = (DROID_ORDER)pc.order;
|
|
||||||
|
|
||||||
debug(LOG_SYNC, "Droid %u out of synch, changing order from %s to %s.", pc.droidID, getDroidOrderName((DROID_ORDER)pc2.order), getDroidOrderName((DROID_ORDER)pc.order));
|
|
||||||
turnOffMultiMsg(true);
|
|
||||||
moveStopDroid(pD);
|
|
||||||
orderDroidBase(pD, &sOrder);
|
|
||||||
turnOffMultiMsg(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break; // Don't know what to do, but at least won't be actively breaking anything.
|
|
||||||
}
|
|
||||||
|
|
||||||
MERGECOPYSYNC(pD->secondaryOrder, secondaryOrder, "u"); // The old code set this after changing orders, so doing that in case.
|
|
||||||
#undef MERGECOPYSYNC
|
|
||||||
#undef MERGEDELTA
|
|
||||||
pD->secondaryOrderPending = pD->secondaryOrder; // These droid checks are useless. TODO Completely remove recvDroidCheck and related code, since it's useless for synch, anyway?
|
|
||||||
|
|
||||||
syncDebugDroid(pD, '>');
|
|
||||||
|
|
||||||
// ...and repeat!
|
|
||||||
}
|
|
||||||
|
|
||||||
NETend();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
// Structure Checking, to ensure smoke and stuff is consistent across machines.
|
|
||||||
// this func is recursive!
|
|
||||||
static STRUCTURE *pickAStructure(unsigned player)
|
|
||||||
{
|
|
||||||
STRUCTURE *pS, *ret = NULL;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
// O(n) where n is number of structures. Slow, but hard to beat on a linked list.
|
|
||||||
i = 0;
|
|
||||||
for (pS = apsStructLists[player]; pS != NULL; pS = pS->psNext)
|
|
||||||
{
|
|
||||||
if (gameRand(++i) == 0)
|
|
||||||
{
|
|
||||||
ret = pS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t structureCheckLastSent = 0; // Last time a struct was sent
|
|
||||||
static uint32_t structureCheckLastId[MAX_PLAYERS];
|
|
||||||
static uint32_t structureCheckLastBody[MAX_PLAYERS];
|
|
||||||
static Rotation structureCheckLastDirection[MAX_PLAYERS];
|
|
||||||
static uint32_t structureCheckLastType[MAX_PLAYERS];
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
// Send structure information.
|
|
||||||
static bool sendStructureCheck(void)
|
|
||||||
{
|
|
||||||
uint8_t player;
|
|
||||||
|
|
||||||
if (structureCheckLastSent > gameTime)
|
|
||||||
{
|
|
||||||
structureCheckLastSent = 0;
|
|
||||||
}
|
|
||||||
// Only send a struct send if not done recently
|
|
||||||
if (gameTime - structureCheckLastSent < STRUCT_PERIOD)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
structureCheckLastSent = gameTime;
|
|
||||||
|
|
||||||
for (player = 0; player < MAX_PLAYERS; ++player)
|
|
||||||
{
|
|
||||||
STRUCTURE *pS = pickAStructure(player);
|
|
||||||
bool hasCapacity = true;
|
|
||||||
uint8_t capacity;
|
|
||||||
|
|
||||||
// Only send info about complete buildings
|
|
||||||
if (pS == NULL || pS->status != SS_BUILT)
|
|
||||||
{
|
|
||||||
structureCheckLastId[player] = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pS->pStructureType->type)
|
|
||||||
{
|
|
||||||
case REF_RESEARCH:
|
|
||||||
capacity = pS->pFunctionality->researchFacility.capacity;
|
|
||||||
break;
|
|
||||||
case REF_FACTORY:
|
|
||||||
case REF_VTOL_FACTORY:
|
|
||||||
capacity = pS->pFunctionality->factory.capacity;
|
|
||||||
break;
|
|
||||||
case REF_POWER_GEN:
|
|
||||||
capacity = pS->pFunctionality->powerGenerator.capacity;
|
|
||||||
default:
|
|
||||||
hasCapacity = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
structureCheckLastId[player] = pS->id;
|
|
||||||
structureCheckLastBody[player] = pS->body;
|
|
||||||
structureCheckLastDirection[player] = pS->rot;
|
|
||||||
structureCheckLastType[player] = pS->pStructureType->type;
|
|
||||||
|
|
||||||
if (myResponsibility(player))
|
|
||||||
{
|
|
||||||
if (!isInSync()) // Don't really send anything, unless out of synch.
|
|
||||||
{
|
|
||||||
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_STRUCT);
|
|
||||||
NETuint8_t(&player);
|
|
||||||
NETuint32_t(&gameTime);
|
|
||||||
NETuint32_t(&pS->id);
|
|
||||||
NETuint32_t(&pS->body);
|
|
||||||
NETenum(&pS->pStructureType->type);
|
|
||||||
NETRotation(&pS->rot);
|
|
||||||
if (hasCapacity)
|
|
||||||
{
|
|
||||||
NETuint8_t(&capacity);
|
|
||||||
}
|
|
||||||
NETend();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive checking info about a structure and update local world state
|
|
||||||
bool recvStructureCheck(NETQUEUE queue)
|
|
||||||
{
|
|
||||||
uint32_t synchTime;
|
|
||||||
STRUCTURE *pS;
|
|
||||||
bool hasCapacity = true;
|
|
||||||
int j;
|
|
||||||
Rotation rot;
|
|
||||||
uint8_t player, ourCapacity;
|
|
||||||
uint32_t body;
|
|
||||||
uint32_t ref;
|
|
||||||
STRUCTURE_TYPE type = REF_HQ; // Dummy initialisation.
|
|
||||||
|
|
||||||
NETbeginDecode(queue, GAME_CHECK_STRUCT);
|
|
||||||
NETuint8_t(&player);
|
|
||||||
NETuint32_t(&synchTime);
|
|
||||||
NETuint32_t(&ref);
|
|
||||||
NETuint32_t(&body);
|
|
||||||
NETenum(&type);
|
|
||||||
NETRotation(&rot);
|
|
||||||
|
|
||||||
if (player >= MAX_PLAYERS)
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "Bad GAME_CHECK_STRUCT received!");
|
|
||||||
NETend();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (structureCheckLastSent != synchTime)
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "We got a structure synch at the wrong time.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ref != structureCheckLastId[player])
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "We got a structure %u synch, but had chosen %u instead.", ref, structureCheckLastId[player]);
|
|
||||||
NETend();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the structure exists our job is easy
|
|
||||||
pS = IdToStruct(ref, player);
|
|
||||||
if (pS)
|
|
||||||
{
|
|
||||||
syncDebugStructure(pS, '<');
|
|
||||||
if (pS->pStructureType->type != structureCheckLastType[player] || type != structureCheckLastType[player])
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "GAME_CHECK_STRUCT received, wrong structure type!");
|
|
||||||
NETend();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check its finished
|
|
||||||
if (pS->status != SS_BUILT)
|
|
||||||
{
|
|
||||||
pS->rot = rot;
|
|
||||||
pS->id = ref;
|
|
||||||
pS->status = SS_BUILT;
|
|
||||||
buildingComplete(pS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the structure has a capacity
|
|
||||||
switch (pS->pStructureType->type)
|
|
||||||
{
|
|
||||||
case REF_RESEARCH:
|
|
||||||
ourCapacity = ((RESEARCH_FACILITY *) pS->pFunctionality)->capacity;
|
|
||||||
j = researchModuleStat;
|
|
||||||
break;
|
|
||||||
case REF_FACTORY:
|
|
||||||
case REF_VTOL_FACTORY:
|
|
||||||
ourCapacity = ((FACTORY *) pS->pFunctionality)->capacity;
|
|
||||||
j = factoryModuleStat;
|
|
||||||
break;
|
|
||||||
case REF_POWER_GEN:
|
|
||||||
ourCapacity = ((POWER_GEN *) pS->pFunctionality)->capacity;
|
|
||||||
j = powerModuleStat;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
hasCapacity = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// So long as the struct has a capacity fetch it from the packet
|
|
||||||
if (hasCapacity)
|
|
||||||
{
|
|
||||||
uint8_t actualCapacity = 0;
|
|
||||||
|
|
||||||
NETuint8_t(&actualCapacity);
|
|
||||||
|
|
||||||
// If our capacity is different upgrade ourself
|
|
||||||
for (; ourCapacity < actualCapacity; ourCapacity++)
|
|
||||||
{
|
|
||||||
debug(LOG_SYNC, "Structure %u out of synch, adding module.", ref);
|
|
||||||
buildStructure(&asStructureStats[j], pS->pos.x, pS->pos.y, pS->player, false);
|
|
||||||
|
|
||||||
// Check it is finished
|
|
||||||
if (pS->status != SS_BUILT)
|
|
||||||
{
|
|
||||||
pS->id = ref;
|
|
||||||
pS->status = SS_BUILT;
|
|
||||||
buildingComplete(pS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MERGEDELTA(x, y, ya, z) if (y != ya) { debug(LOG_SYNC, "Structure %u out of synch, changing "#x" from %"z" to %"z".", ref, x, x + y - ya); x += y - ya; }
|
|
||||||
MERGEDELTA(pS->body, body, structureCheckLastBody[player], "u");
|
|
||||||
MERGEDELTA(pS->rot.direction, rot.direction, structureCheckLastDirection[player].direction, "d");
|
|
||||||
MERGEDELTA(pS->rot.pitch, rot.pitch, structureCheckLastDirection[player].pitch, "d");
|
|
||||||
MERGEDELTA(pS->rot.roll, rot.roll, structureCheckLastDirection[player].roll, "d");
|
|
||||||
#undef MERGEDELTA
|
|
||||||
|
|
||||||
syncDebugStructure(pS, '>');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "We got a structure %u synch, but can't find the structure.", ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
NETend();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t powerCheckLastSent = 0;
|
|
||||||
static int64_t powerCheckLastPower[MAX_PLAYERS];
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
// Power Checking. Send a power level check every now and again.
|
|
||||||
static bool sendPowerCheck()
|
|
||||||
{
|
|
||||||
uint8_t player;
|
|
||||||
|
|
||||||
if (powerCheckLastSent > gameTime)
|
|
||||||
{
|
|
||||||
powerCheckLastSent = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only send if not done recently
|
|
||||||
if (gameTime - powerCheckLastSent < POWER_PERIOD)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
powerCheckLastSent = gameTime;
|
|
||||||
for (player = 0; player < MAX_PLAYERS; ++player)
|
|
||||||
{
|
|
||||||
powerCheckLastPower[player] = getPrecisePower(player);
|
|
||||||
if (myResponsibility(player))
|
|
||||||
{
|
|
||||||
if (!isInSync()) // Don't really send anything, unless out of synch.
|
|
||||||
{
|
|
||||||
NETbeginEncode(NETgameQueue(selectedPlayer), GAME_CHECK_POWER);
|
|
||||||
NETuint8_t(&player);
|
|
||||||
NETuint32_t(&gameTime);
|
|
||||||
NETint64_t(&powerCheckLastPower[player]);
|
|
||||||
NETend();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool recvPowerCheck(NETQUEUE queue)
|
|
||||||
{
|
|
||||||
uint8_t player;
|
|
||||||
uint32_t synchTime;
|
|
||||||
int64_t power;
|
|
||||||
|
|
||||||
NETbeginDecode(queue, GAME_CHECK_POWER);
|
|
||||||
NETuint8_t(&player);
|
|
||||||
NETuint32_t(&synchTime);
|
|
||||||
NETint64_t(&power);
|
|
||||||
NETend();
|
|
||||||
|
|
||||||
if (powerCheckLastSent != synchTime)
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "Power synch check out of synch!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player >= MAX_PLAYERS)
|
|
||||||
{
|
|
||||||
debug(LOG_ERROR, "Bad GAME_CHECK_POWER packet: player is %d : %s",
|
|
||||||
(int)player, isHumanPlayer(player) ? "Human" : "AI");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (power != powerCheckLastPower[player])
|
|
||||||
{
|
|
||||||
int64_t powerFrom = getPrecisePower(player);
|
|
||||||
int64_t powerTo = powerFrom + power - powerCheckLastPower[player];
|
|
||||||
debug(LOG_SYNC, "GAME_CHECK_POWER: Adjusting power for player %d (%s) from %lf to %lf",
|
|
||||||
(int)player, isHumanPlayer(player) ? "Human" : "AI", powerFrom/4294967296., powerTo/4294967296.);
|
|
||||||
syncDebug("Adjusting power for player %d (%s) from %"PRId64" to %"PRId64"", (int)player, isHumanPlayer(player) ? "Human" : "AI", powerFrom, powerTo);
|
|
||||||
setPrecisePower(player, powerTo);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
// ////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -758,20 +70,6 @@ bool recvPowerCheck(NETQUEUE queue)
|
||||||
// We use setMultiStats() to broadcast the score when needed.
|
// We use setMultiStats() to broadcast the score when needed.
|
||||||
bool sendScoreCheck(void)
|
bool sendScoreCheck(void)
|
||||||
{
|
{
|
||||||
static UDWORD lastsent = 0;
|
|
||||||
|
|
||||||
if (lastsent > gameTime)
|
|
||||||
{
|
|
||||||
lastsent= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gameTime - lastsent < SCORE_FREQUENCY)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastsent = gameTime;
|
|
||||||
|
|
||||||
// Broadcast any changes in other players, but not in FRONTEND!!!
|
// Broadcast any changes in other players, but not in FRONTEND!!!
|
||||||
if (titleMode != MULTIOPTION && titleMode != MULTILIMIT)
|
if (titleMode != MULTIOPTION && titleMode != MULTILIMIT)
|
||||||
{
|
{
|
||||||
|
|
|
@ -723,11 +723,6 @@ void researchResult(UDWORD researchIndex, UBYTE player, bool bDisplay, STRUCTURE
|
||||||
|
|
||||||
ASSERT_OR_RETURN( , researchIndex < asResearch.size(), "Invalid research index %u", researchIndex);
|
ASSERT_OR_RETURN( , researchIndex < asResearch.size(), "Invalid research index %u", researchIndex);
|
||||||
|
|
||||||
if (!isInSync())
|
|
||||||
{
|
|
||||||
sendResearchStatus(NULL, researchIndex, player, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
MakeResearchCompleted(&asPlayerResList[player][researchIndex]);
|
MakeResearchCompleted(&asPlayerResList[player][researchIndex]);
|
||||||
|
|
||||||
//check for structures to be made available
|
//check for structures to be made available
|
||||||
|
|
|
@ -824,11 +824,6 @@ void structureBuild(STRUCTURE *psStruct, DROID *psDroid, int buildPoints, int bu
|
||||||
intBuildFinished(psDroid);
|
intBuildFinished(psDroid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isInSync() && bMultiMessages && myResponsibility(psStruct->player))
|
|
||||||
{
|
|
||||||
SendBuildFinished(psStruct);
|
|
||||||
}
|
|
||||||
|
|
||||||
//only play the sound if selected player
|
//only play the sound if selected player
|
||||||
if (psDroid &&
|
if (psDroid &&
|
||||||
psStruct->player == selectedPlayer
|
psStruct->player == selectedPlayer
|
||||||
|
@ -3138,15 +3133,6 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission)
|
||||||
{
|
{
|
||||||
int prevState = intGetResearchState();
|
int prevState = intGetResearchState();
|
||||||
|
|
||||||
if(bMultiMessages)
|
|
||||||
{
|
|
||||||
if (myResponsibility(psStructure->player) && !isInSync())
|
|
||||||
{
|
|
||||||
// This message should have no effect if in synch.
|
|
||||||
SendResearch(psStructure->player, researchIndex, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//store the last topic researched - if its the best
|
//store the last topic researched - if its the best
|
||||||
if (psResFacility->psBestTopic == NULL)
|
if (psResFacility->psBestTopic == NULL)
|
||||||
{
|
{
|
||||||
|
@ -4636,12 +4622,6 @@ bool destroyStruct(STRUCTURE *psDel, unsigned impactTime)
|
||||||
|
|
||||||
CHECK_STRUCTURE(psDel);
|
CHECK_STRUCTURE(psDel);
|
||||||
|
|
||||||
if (bMultiMessages && !isInSync())
|
|
||||||
{
|
|
||||||
// Every player should be sending this message at once, and ignoring it later.
|
|
||||||
SendDestroyStructure(psDel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Firstly, are we dealing with a wall section */
|
/* Firstly, are we dealing with a wall section */
|
||||||
bMinor = psDel->pStructureType->type == REF_WALL || psDel->pStructureType->type == REF_WALLCORNER;
|
bMinor = psDel->pStructureType->type == REF_WALL || psDel->pStructureType->type == REF_WALLCORNER;
|
||||||
|
|
||||||
|
|
|
@ -1425,12 +1425,6 @@ void transporterAddDroid(DROID *psTransporter, DROID *psDroidToAdd)
|
||||||
// adding to transporter unit's group list
|
// adding to transporter unit's group list
|
||||||
psTransporter->psGroup->add(psDroidToAdd);
|
psTransporter->psGroup->add(psDroidToAdd);
|
||||||
psDroidToAdd->selected = false; // Display in transporter interface.
|
psDroidToAdd->selected = false; // Display in transporter interface.
|
||||||
|
|
||||||
if (bMultiMessages && !isInSync())
|
|
||||||
{
|
|
||||||
//inform all other players to update their local lists
|
|
||||||
sendDroidEmbark(psDroidToAdd,psTransporter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue