Skip to content

Commit

Permalink
Human droid production using default templates caused immediate desync.
Browse files Browse the repository at this point in the history
Solved by not sending templates for factory production any more. Instead
we send the template contents, and create a temporary template in the
factory when the network packet is received. Once the droid is produced,
the temporary template is discarded.

Fixes ticket:4304
  • Loading branch information
perim committed Jan 3, 2016
1 parent c6e96a7 commit ff14b93
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 24 deletions.
57 changes: 34 additions & 23 deletions src/multistruct.cpp
Expand Up @@ -271,7 +271,7 @@ bool recvLasSat(NETQUEUE queue)
return true;
}

void sendStructureInfo(STRUCTURE *psStruct, STRUCTURE_INFO structureInfo_, DROID_TEMPLATE *psTempl)
void sendStructureInfo(STRUCTURE *psStruct, STRUCTURE_INFO structureInfo_, DROID_TEMPLATE *pT)
{
uint8_t player = psStruct->player;
uint32_t structId = psStruct->id;
Expand All @@ -283,9 +283,21 @@ void sendStructureInfo(STRUCTURE *psStruct, STRUCTURE_INFO structureInfo_, DROID
NETuint8_t(&structureInfo);
if (structureInfo_ == STRUCTUREINFO_MANUFACTURE)
{
uint32_t templateId = psTempl != NULL ? psTempl->multiPlayerID : 0;

NETuint32_t(&templateId);
int32_t droidType = pT->droidType;
NETqstring(pT->name);
NETint32_t(&droidType);
NETuint8_t(&pT->asParts[COMP_BODY]);
NETuint8_t(&pT->asParts[COMP_BRAIN]);
NETuint8_t(&pT->asParts[COMP_PROPULSION]);
NETuint8_t(&pT->asParts[COMP_REPAIRUNIT]);
NETuint8_t(&pT->asParts[COMP_ECM]);
NETuint8_t(&pT->asParts[COMP_SENSOR]);
NETuint8_t(&pT->asParts[COMP_CONSTRUCT]);
NETint8_t(&pT->numWeaps);
for (int i = 0; i < pT->numWeaps; i++)
{
NETuint8_t(&pT->asWeaps[i]);
}
}
NETend();
}
Expand All @@ -297,41 +309,40 @@ void recvStructureInfo(NETQUEUE queue)
uint32_t templateId = 0;
uint8_t structureInfo;
STRUCTURE *psStruct;
DROID_TEMPLATE *psTempl = NULL;
DROID_TEMPLATE t, *pT = &t;
int32_t droidType;

NETbeginDecode(queue, GAME_STRUCTUREINFO);
NETuint8_t(&player);
NETuint32_t(&structId);
NETuint8_t(&structureInfo);
if (structureInfo == STRUCTUREINFO_MANUFACTURE)
{
NETuint32_t(&templateId);
if (templateId != 0)
NETqstring(pT->name);
NETint32_t(&droidType);
NETuint8_t(&pT->asParts[COMP_BODY]);
NETuint8_t(&pT->asParts[COMP_BRAIN]);
NETuint8_t(&pT->asParts[COMP_PROPULSION]);
NETuint8_t(&pT->asParts[COMP_REPAIRUNIT]);
NETuint8_t(&pT->asParts[COMP_ECM]);
NETuint8_t(&pT->asParts[COMP_SENSOR]);
NETuint8_t(&pT->asParts[COMP_CONSTRUCT]);
NETint8_t(&pT->numWeaps);
for (int i = 0; i < pT->numWeaps; i++)
{
// For autogames, where we want the AI to take us over, our templates are not setup... so let's use any AI's templates.
if (!NetPlay.players[player].autoGame)
{
psTempl = IdToTemplate(templateId, player);
}
else
{
psTempl = IdToTemplate(templateId, ANYPLAYER);
}
if (psTempl == NULL)
{
debug(LOG_SYNC, "Synch error, don't have tempate id %u, so can't change production of factory %u!", templateId, structId);
}
NETuint8_t(&pT->asWeaps[i]);
}
pT->droidType = (DROID_TYPE)droidType;
}
NETend();

psStruct = IdToStruct(structId, player);

syncDebug("player%d,structId%u%c,structureInfo%u,templateId%u%c", player, structId, psStruct == NULL ? '^' : '*', structureInfo, templateId, psTempl == NULL ? '^' : '*');
syncDebug("player%d,structId%u%c,structureInfo%u,templateId%u", player, structId, psStruct == NULL? '^' : '*', structureInfo, templateId);

if (psStruct == NULL)
{
debug(LOG_SYNC, "Couldn't find structure %u to change production.", structId);
debug(LOG_ERROR, "Could not find structure %u to change production for", structId);
return;
}
if (!canGiveOrdersFor(queue.index, psStruct->player))
Expand All @@ -355,7 +366,7 @@ void recvStructureInfo(NETQUEUE queue)

switch (structureInfo)
{
case STRUCTUREINFO_MANUFACTURE: structSetManufacture(psStruct, psTempl, ModeImmediate); break;
case STRUCTUREINFO_MANUFACTURE: structSetManufacture(psStruct, pT, ModeImmediate); break;
case STRUCTUREINFO_CANCELPRODUCTION: cancelProduction(psStruct, ModeImmediate, false); break;
case STRUCTUREINFO_HOLDPRODUCTION: holdProduction(psStruct, ModeImmediate); break;
case STRUCTUREINFO_RELEASEPRODUCTION: releaseProduction(psStruct, ModeImmediate); break;
Expand Down
5 changes: 4 additions & 1 deletion src/structure.cpp
Expand Up @@ -966,7 +966,7 @@ bool structSetManufacture(STRUCTURE *psStruct, DROID_TEMPLATE *psTempl, QUEUE_MO
}

//assign it to the Factory
psFact->psSubject = psTempl;
psFact->psSubject = new DROID_TEMPLATE(*psTempl);

//set up the start time and build time
if (psTempl != NULL)
Expand Down Expand Up @@ -1879,6 +1879,7 @@ static bool setFunctionality(STRUCTURE *psBuilding, STRUCTURE_TYPE functionType)
FACTORY *psFactory = &psBuilding->pFunctionality->factory;
unsigned int x, y;

delete psFactory->psSubject;
psFactory->psSubject = NULL;

// Default the secondary order - AB 22/04/99
Expand Down Expand Up @@ -3245,6 +3246,7 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission)

//reset the start time
psFactory->timeStarted = ACTION_START_TIME;
delete psFactory->psSubject;
psFactory->psSubject = NULL;

doNextProduction(psStructure, (DROID_TEMPLATE *)pSubject, ModeImmediate);
Expand Down Expand Up @@ -6211,6 +6213,7 @@ void cancelProduction(STRUCTURE *psBuilding, QUEUE_MODE mode, bool mayClearProdu
}

//clear the factory's subject
delete psFactory->psSubject;
psFactory->psSubject = NULL;
}

Expand Down

0 comments on commit ff14b93

Please sign in to comment.