bool recvResearchStatus(NETQUEUE queue) { STRUCTURE *psBuilding; PLAYER_RESEARCH *pPlayerRes; RESEARCH_FACILITY *psResFacilty; RESEARCH *pResearch; uint8_t player; bool bStart; uint32_t index, structRef; NETbeginDecode(queue, GAME_RESEARCHSTATUS); NETuint8_t(&player); NETbool(&bStart); NETuint32_t(&structRef); NETuint32_t(&index); NETend(); syncDebug("player%d, bStart%d, structRef%u, index%u", player, bStart, structRef, index); if (player >= MAX_PLAYERS || index >= asResearch.size()) { debug(LOG_ERROR, "Bad GAME_RESEARCHSTATUS received, player is %d, index is %u", (int)player, index); return false; } if (!canGiveOrdersFor(queue.index, player)) { debug(LOG_WARNING, "Droid order for wrong player."); syncDebug("Wrong player."); return false; } int prevResearchState = 0; if (aiCheckAlliances(selectedPlayer, player)) { prevResearchState = intGetResearchState(); } pPlayerRes = &asPlayerResList[player][index]; // psBuilding may be null if finishing if (bStart) // Starting research { psBuilding = IdToStruct(structRef, player); // Set that facility to research if (psBuilding && psBuilding->pFunctionality) { psResFacilty = (RESEARCH_FACILITY *) psBuilding->pFunctionality; popStatusPending(*psResFacilty); // Research is no longer pending, as it's actually starting now. if (psResFacilty->psSubject) { cancelResearch(psBuilding, ModeImmediate); } // Set the subject up pResearch = &asResearch[index]; psResFacilty->psSubject = pResearch; // Start the research MakeResearchStarted(pPlayerRes); psResFacilty->timeStartHold = 0; } } // Finished/cancelled research else { // If they completed the research, we're done if (IsResearchCompleted(pPlayerRes)) { return true; } // If they did not say what facility it was, look it up orselves if (!structRef) { // Go through the structs to find the one doing this topic for (psBuilding = apsStructLists[player]; psBuilding; psBuilding = psBuilding->psNext) { if (psBuilding->pStructureType->type == REF_RESEARCH && psBuilding->status == SS_BUILT && ((RESEARCH_FACILITY *) psBuilding->pFunctionality)->psSubject && ((RESEARCH_FACILITY *) psBuilding->pFunctionality)->psSubject->ref - REF_RESEARCH_START == index) { break; } } } else { psBuilding = IdToStruct(structRef, player); } // Stop the facility doing any research if (psBuilding) { cancelResearch(psBuilding, ModeImmediate); popStatusPending(*(RESEARCH_FACILITY *)psBuilding->pFunctionality); // Research cancellation is no longer pending, as it's actually cancelling now. } } if (aiCheckAlliances(selectedPlayer, player)) { intAlliedResearchChanged(); intNotifyResearchButton(prevResearchState); } return true; }
void recvStructureInfo(NETQUEUE queue) { uint8_t player = 0; uint32_t structId = 0; uint32_t templateId = 0; uint8_t structureInfo; STRUCTURE *psStruct; DROID_TEMPLATE *psTempl = NULL; NETbeginDecode(queue, GAME_STRUCTUREINFO); NETuint8_t(&player); NETuint32_t(&structId); NETuint8_t(&structureInfo); if (structureInfo == STRUCTUREINFO_MANUFACTURE) { NETuint32_t(&templateId); if (templateId != 0) { // 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); } } } NETend(); psStruct = IdToStruct(structId, player); syncDebug("player%d,structId%u%c,structureInfo%u,templateId%u%c", player, structId, psStruct == NULL ? '^' : '*', structureInfo, templateId, psTempl == NULL ? '^' : '*'); if (psStruct == NULL) { debug(LOG_SYNC, "Couldn't find structure %u to change production.", structId); return; } if (!canGiveOrdersFor(queue.index, psStruct->player)) { syncDebug("Wrong player."); return; } CHECK_STRUCTURE(psStruct); if (StructIsFactory(psStruct)) { popStatusPending(psStruct->pFunctionality->factory); } else if (psStruct->pStructureType->type == REF_RESEARCH) { popStatusPending(psStruct->pFunctionality->researchFacility); } syncDebugStructure(psStruct, '<'); switch (structureInfo) { case STRUCTUREINFO_MANUFACTURE: structSetManufacture(psStruct, psTempl, ModeImmediate); break; case STRUCTUREINFO_CANCELPRODUCTION: cancelProduction(psStruct, ModeImmediate, false); break; case STRUCTUREINFO_HOLDPRODUCTION: holdProduction(psStruct, ModeImmediate); break; case STRUCTUREINFO_RELEASEPRODUCTION: releaseProduction(psStruct, ModeImmediate); break; case STRUCTUREINFO_HOLDRESEARCH: holdResearch(psStruct, ModeImmediate); break; case STRUCTUREINFO_RELEASERESEARCH: releaseResearch(psStruct, ModeImmediate); break; default: debug(LOG_ERROR, "Invalid structureInfo %d", structureInfo); } syncDebugStructure(psStruct, '>'); CHECK_STRUCTURE(psStruct); }