// //////////////////////////////////////////////////////////////////////////// // give technologies. static void giftResearch(uint8_t from, uint8_t to, bool send) { int i; uint32_t dummy = 0; if (send) { uint8_t giftType = RESEARCH_GIFT; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_GIFT); NETuint8_t(&giftType); NETuint8_t(&from); NETuint8_t(&to); NETuint32_t(&dummy); NETend(); } else if (alliancesCanGiveResearchAndRadar(game.alliance)) { if (to == selectedPlayer) { CONPRINTF(ConsoleString, (ConsoleString, _("%s Gives You Technology Documents"), getPlayerName(from))); } // For each topic for (i = 0; i < asResearch.size(); i++) { // If they have it and we don't research it if (IsResearchCompleted(&asPlayerResList[from][i]) && !IsResearchCompleted(&asPlayerResList[to][i])) { MakeResearchCompleted(&asPlayerResList[to][i]); researchResult(i, to, false, NULL, true); } } } }
// //////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////// // 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; }
// //////////////////////////////////////////////////////////////////////////// // give radar information void giftRadar(uint8_t from, uint8_t to, bool send) { uint32_t dummy = 0; if (send) { uint8_t subType = RADAR_GIFT; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_GIFT); NETuint8_t(&subType); NETuint8_t(&from); NETuint8_t(&to); NETuint32_t(&dummy); NETend(); } // If we are recieving the gift else { hqReward(from, to); if (to == selectedPlayer) { CONPRINTF(ConsoleString, (ConsoleString, _("%s Gives You A Visibility Report"), getPlayerName(from))); } } }
// send a newly created template to other players bool sendTemplate(uint32_t player, DROID_TEMPLATE *pTempl) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_TEMPLATE); NETuint32_t(&player); NETtemplate(pTempl); return NETend(); }
static void giftAutoGame(uint8_t from, uint8_t to, bool send) { uint32_t dummy = 0; if (send) { uint8_t subType = AUTOGAME_GIFT; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_GIFT); NETuint8_t(&subType); NETuint8_t(&from); NETuint8_t(&to); NETuint32_t(&dummy); NETend(); debug(LOG_SYNC, "We (%d) are telling %d we want to enable/disable a autogame", from, to); } // If we are recieving the "gift" else { if (to == selectedPlayer) { NetPlay.players[from].autoGame = !NetPlay.players[from].autoGame ; CONPRINTF(ConsoleString, (ConsoleString, "%s has %s the autoGame command", getPlayerName(from), NetPlay.players[from].autoGame ? "Enabled" : "Disabled")); debug(LOG_SYNC, "We (%d) are being told that %d has %s autogame", selectedPlayer, from, NetPlay.players[from].autoGame ? "Enabled" : "Disabled"); } } }
// //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// // New research stuff, so you can see what others are up to! // inform others that I'm researching this. bool sendResearchStatus(STRUCTURE *psBuilding, uint32_t index, uint8_t player, bool bStart) { if (!myResponsibility(player) || gameTime < 5) { return true; } NETbeginEncode(NETgameQueue(selectedPlayer), GAME_RESEARCHSTATUS); NETuint8_t(&player); NETbool(&bStart); // If we know the building researching it then send its ID if (psBuilding) { NETuint32_t(&psBuilding->id); } else { uint32_t zero = 0; NETuint32_t(&zero); } // Finally the topic in question NETuint32_t(&index); NETend(); // Tell UI to remove from the list of available research. MakeResearchStartedPending(&asPlayerResList[player][index]); return true; }
// Actually send the droid info. void sendQueuedDroidInfo() { // Sort queued orders, to group the same order to multiple droids. std::sort(queuedOrders.begin(), queuedOrders.end()); std::vector<QueuedDroidInfo>::iterator eqBegin, eqEnd; for (eqBegin = queuedOrders.begin(); eqBegin != queuedOrders.end(); eqBegin = eqEnd) { // Find end of range of orders which differ only by the droid ID. for (eqEnd = eqBegin + 1; eqEnd != queuedOrders.end() && eqEnd->orderCompare(*eqBegin) == 0; ++eqEnd) {} NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DROIDINFO); NETQueuedDroidInfo(&*eqBegin); uint32_t num = eqEnd - eqBegin; NETuint32_t(&num); uint32_t prevDroidId = 0; for (unsigned n = 0; n < num; ++n) { uint32_t droidId = (eqBegin + n)->droidId; // Encode deltas between droid IDs, since the deltas are smaller than the actual droid IDs, and will encode to less bytes on average. uint32_t deltaDroidId = droidId - prevDroidId; NETuint32_t(&deltaDroidId); prevDroidId = droidId; } NETend(); } // Sent the orders. Don't send them again. queuedOrders.clear(); }
// //////////////////////////////////////////////////////////////////////////// // Send a new Droid to the other players bool SendDroid(DROID_TEMPLATE *pTemplate, uint32_t x, uint32_t y, uint8_t player, uint32_t id, const INITIAL_DROID_ORDERS *initialOrdersP) { if (!bMultiMessages) { return true; } ASSERT_OR_RETURN(false, x != 0 && y != 0, "SendDroid: Invalid droid coordinates"); ASSERT_OR_RETURN(false, player < MAX_PLAYERS, "invalid player %u", player); // Dont send other droids during campaign setup if (ingame.localJoiningInProgress) { return true; } // Only send the droid if we are responsible if (!myResponsibility(player)) { // Don't build if we are not responsible return false; } debug(LOG_SYNC, "Droid sent with id of %u", id); NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DEBUG_ADD_DROID); { Position pos(x, y, 0); bool haveInitialOrders = initialOrdersP != NULL; int32_t droidType = pTemplate->droidType; NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); NETqstring(pTemplate->name); NETint32_t(&droidType); NETuint8_t(&pTemplate->asParts[COMP_BODY]); NETuint8_t(&pTemplate->asParts[COMP_BRAIN]); NETuint8_t(&pTemplate->asParts[COMP_PROPULSION]); NETuint8_t(&pTemplate->asParts[COMP_REPAIRUNIT]); NETuint8_t(&pTemplate->asParts[COMP_ECM]); NETuint8_t(&pTemplate->asParts[COMP_SENSOR]); NETuint8_t(&pTemplate->asParts[COMP_CONSTRUCT]); NETint8_t(&pTemplate->numWeaps); for (int i = 0; i < pTemplate->numWeaps; i++) { NETuint8_t(&pTemplate->asWeaps[i]); } NETbool(&haveInitialOrders); if (haveInitialOrders) { INITIAL_DROID_ORDERS initialOrders = *initialOrdersP; NETuint32_t(&initialOrders.secondaryOrder); NETint32_t(&initialOrders.moveToX); NETint32_t(&initialOrders.moveToY); NETuint32_t(&initialOrders.factoryId); // For making scripts happy. } } debug(LOG_LIFE, "===> sending Droid from %u id of %u ", player, id); return NETend(); }
void sendAlliance(uint8_t from, uint8_t to, uint8_t state, int32_t value) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_ALLIANCE); NETuint8_t(&from); NETuint8_t(&to); NETuint8_t(&state); NETint32_t(&value); NETend(); }
bool SendDestroyTemplate(DROID_TEMPLATE *t, uint8_t player) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_TEMPLATEDEST); NETuint8_t(&player); NETuint32_t(&t->multiPlayerID); NETend(); return true; }
// //////////////////////////////////////////////////////////////////////////// // Inform others that a structure has been destroyed bool SendDestroyStructure(STRUCTURE *s) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DEBUG_REMOVE_STRUCTURE); // Struct to destroy NETuint32_t(&s->id); return NETend(); }
// //////////////////////////////////////////////////////////////////////////// // 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(); }
// //////////////////////////////////////////////////////////////////////////// // Inform others that a structure has been destroyed BOOL SendDestroyStructure(STRUCTURE *s) { technologyGiveAway(s); NETbeginEncode(NETgameQueue(selectedPlayer), GAME_STRUCTDEST); // Struct to destroy NETuint32_t(&s->id); return NETend(); }
// //////////////////////////////////////////////////////////////////////////// // Research Stuff. Nat games only send the result of research procedures. bool SendResearch(uint8_t player, uint32_t index, bool trigger) { // Send the player that is researching the topic and the topic itself NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DEBUG_FINISH_RESEARCH); NETuint8_t(&player); NETuint32_t(&index); NETend(); return true; }
// sendGiftDroids() // We give selected droid(s) as a gift to another player. // // \param from :player that sent us the droid // \param to :player that should be getting the droid static void sendGiftDroids(uint8_t from, uint8_t to) { DROID *psD; uint8_t giftType = DROID_GIFT; uint8_t totalToSend; if (apsDroidLists[from] == NULL) { return; } /* * Work out the number of droids to send. As well as making sure they are * selected we also need to make sure they will NOT put the receiving player * over their droid limit. */ for (totalToSend = 0, psD = apsDroidLists[from]; psD && getNumDroids(to) + totalToSend < getMaxDroids(to) && totalToSend != UINT8_MAX; psD = psD->psNext) { if (psD->selected) { ++totalToSend; } } /* * We must send one droid at a time, due to the fact that giftSingleDroid() * does its own net calls. */ for (psD = apsDroidLists[from]; psD && totalToSend != 0; psD = psD->psNext) { if (isTransporter(psD) && !transporterIsEmpty(psD)) { CONPRINTF(ConsoleString, (ConsoleString, _("Tried to give away a non-empty %s - but this is not allowed."), psD->aName)); continue; } if (psD->selected) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_GIFT); NETuint8_t(&giftType); NETuint8_t(&from); NETuint8_t(&to); // Add the droid to the packet NETuint32_t(&psD->id); NETend(); // Decrement the number of droids left to send --totalToSend; } } }
BOOL sendLasSat(UBYTE player, STRUCTURE *psStruct, BASE_OBJECT *psObj) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_LASSAT); NETuint8_t(&player); NETuint32_t(&psStruct->id); NETuint32_t(&psObj->id); // Target NETuint8_t(&psObj->player); // Target player return NETend(); }
/** Sends a build order for the given feature type to all players * \param subType the type of feature to build * \param x,y the coordinates to place the feature at */ void sendMultiPlayerFeature(uint32_t ref, uint32_t x, uint32_t y, uint32_t id) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DEBUG_ADD_FEATURE); { NETuint32_t(&ref); NETuint32_t(&x); NETuint32_t(&y); NETuint32_t(&id); } NETend(); }
/** Sends a build order for the given feature type to all players * \param subType the type of feature to build * \param x,y the coordinates to place the feature at */ void sendMultiPlayerFeature(FEATURE_TYPE subType, uint32_t x, uint32_t y, uint32_t id) { NETbeginEncode(NETgameQueue(selectedPlayer), GAME_FEATURES); { NETenum(&subType); NETuint32_t(&x); NETuint32_t(&y); NETuint32_t(&id); } NETend(); }
// //////////////////////////////////////////////////////////////////////////// // INFORM others that a building has been completed. BOOL SendBuildFinished(STRUCTURE *psStruct) { uint8_t player = psStruct->player; ASSERT( player < MAX_PLAYERS, "invalid player %u", player); NETbeginEncode(NETgameQueue(selectedPlayer), GAME_BUILDFINISHED); NETuint32_t(&psStruct->id); // ID of building // Along with enough info to build it (if needed) NETuint32_t(&psStruct->pStructureType->ref); NETPosition(&psStruct->pos); NETuint8_t(&player); return NETend(); }
/** 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. NETPACKAGED_CHECK(&pc); return NETend(); }
// //////////////////////////////////////////////////////////////////////////// // Inform other players that a droid has been destroyed BOOL SendDestroyDroid(const DROID* psDroid) { if (!bMultiMessages) { return true; } NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DROIDDEST); { uint32_t id = psDroid->id; // Send the droid's ID debug(LOG_DEATH, "Requested all players to destroy droid %u", (unsigned int)id); NETuint32_t(&id); } return NETend(); }
/** 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(); }
// Send BOOL sendDroidSecondary(const DROID* psDroid, SECONDARY_ORDER sec, SECONDARY_STATE state) { if (!bMultiMessages) return true; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_SECONDARY); { uint8_t player = psDroid->player; uint32_t droid = psDroid->id; NETuint8_t(&player); NETuint32_t(&droid); NETenum(&sec); NETenum(&state); } return NETend(); }
/** Broadcast that droid is being unloaded from a transporter * * \sa recvDroidDisEmbark() */ bool sendDroidDisembark(DROID const *psTransporter, DROID const *psDroid) { if (!bMultiMessages) return true; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DROIDDISEMBARK); { uint32_t player = psTransporter->player; uint32_t droidId = psDroid->id; uint32_t transportId = psTransporter->id; NETuint32_t(&player); NETuint32_t(&droidId); NETuint32_t(&transportId); } return NETend(); }
// //////////////////////////////////////////////////////////////////////////// // Send a new Droid to the other players BOOL SendDroid(const DROID_TEMPLATE* pTemplate, uint32_t x, uint32_t y, uint8_t player, uint32_t id, const INITIAL_DROID_ORDERS *initialOrdersP) { if (!bMultiMessages) return true; ASSERT(x != 0 && y != 0, "SendDroid: Invalid droid coordinates"); ASSERT( player < MAX_PLAYERS, "invalid player %u", player); // Dont send other droids during campaign setup if (ingame.localJoiningInProgress) { return true; } // Only send the droid if we are responsible if (!myResponsibility(player)) { // Don't build if we are not responsible return false; } debug(LOG_SYNC, "Droid sent with id of %u", id); NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DROID); { Position pos = { x, y, 0 }; uint32_t templateID = pTemplate->multiPlayerID; BOOL haveInitialOrders = initialOrdersP != NULL; NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); NETuint32_t(&templateID); NETbool(&haveInitialOrders); if (haveInitialOrders) { INITIAL_DROID_ORDERS initialOrders = *initialOrdersP; NETuint32_t(&initialOrders.secondaryOrder); NETint32_t(&initialOrders.moveToX); NETint32_t(&initialOrders.moveToY); NETuint32_t(&initialOrders.factoryId); // For making scripts happy. } } debug(LOG_LIFE, "===> sending Droid from %u id of %u ",player,id); return NETend(); }
void sendStructureInfo(STRUCTURE *psStruct, STRUCTURE_INFO structureInfo_, DROID_TEMPLATE *psTempl) { uint8_t player = psStruct->player; uint32_t structId = psStruct->id; uint8_t structureInfo = structureInfo_; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_STRUCTUREINFO); NETuint8_t(&player); NETuint32_t(&structId); NETuint8_t(&structureInfo); if (structureInfo_ == STRUCTUREINFO_MANUFACTURE) { uint32_t templateId = psTempl != NULL ? psTempl->multiPlayerID : 0; NETuint32_t(&templateId); } NETend(); }
// //////////////////////////////////////////////////////////////////////////// // give Power void giftPower(uint8_t from, uint8_t to, uint32_t amount, bool send) { if (send) { uint8_t giftType = POWER_GIFT; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_GIFT); NETuint8_t(&giftType); NETuint8_t(&from); NETuint8_t(&to); NETuint32_t(&amount); NETend(); } else { int value = 0; if (from == ANYPLAYER && !NetPlay.bComms) { // basically cheating power, so we check that we are not in multiplayer addPower(to, amount); } else if (from == ANYPLAYER && NetPlay.bComms) { debug(LOG_WARNING, "Someone tried to cheat power in multiplayer - ignored!"); } else if (amount == 0) // the GUI option { value = getPower(from) / 3; usePower(from, value); addPower(to, value); } else // for scripts etc that can give precise amounts { value = MIN(getPower(from), amount); usePower(from, value); addPower(to, value); } if (from != ANYPLAYER && to == selectedPlayer) { CONPRINTF(ConsoleString, (ConsoleString, _("%s Gives You %d Power"), getPlayerName(from), value)); } } }
/** Broadcast that droid is being unloaded from a transporter * * \sa sendDroidEmbark(),recvDroidEmbark(),recvDroidDisEmbark() */ BOOL sendDroidDisEmbark(const DROID* psDroid, const DROID* psTransporter) { if (!bMultiMessages) return true; NETbeginEncode(NETgameQueue(selectedPlayer), GAME_DROIDDISEMBARK); { uint8_t player = psDroid->player; uint32_t droidID = psDroid->id; uint32_t transporterID = psTransporter->id; Position pos = droidGetPrecisePosition(psDroid); NETuint8_t(&player); NETuint32_t(&droidID); NETuint32_t(&transporterID); NETPosition(&pos); } return NETend(); }
/////////////////////////////////////////////////////////////////////////////// // splatter artifact gifts randomly about. void addMultiPlayerRandomArtifacts(uint8_t quantity, FEATURE_TYPE type) { int i, count; uint32_t x, y; uint8_t player = ANYPLAYER; debug(LOG_FEATURE, "Sending %u artifact(s) type: (%s)", quantity, feature_names[type]); NETbeginEncode(NETgameQueue(selectedPlayer), GAME_ARTIFACTS); NETuint8_t(&quantity); NETenum(&type); ASSERT(mapWidth > 20, "map not big enough"); ASSERT(mapHeight > 20, "map not big enough"); for (count = 0; count < quantity; count++) { uint32_t id = generateNewObjectId(); for (i = 0; i < 3; i++) // try three times { // Between 10 and mapwidth - 10 x = (rand()%(mapWidth - 20)) + 10; y = (rand()%(mapHeight - 20)) + 10; if (pickATileGen(&x, &y, LOOK_FOR_EMPTY_TILE, zonedPAT)) { break; } else if (i == 2) { debug(LOG_FEATURE, "Unable to find a free location after 3 tries; giving up."); x = INVALID_XY; } } NETuint32_t(&x); NETuint32_t(&y); NETuint32_t(&id); NETuint8_t(&player); } NETend(); }
void sendPlayerGameTime() { unsigned player; uint32_t latencyTicks = discreteChosenLatency / GAME_TICKS_PER_UPDATE; uint32_t checkTime = gameTime; uint32_t checkCrc = nextDebugSync(); for (player = 0; player < game.maxPlayers; ++player) { if (!myResponsibility(player) && whosResponsible(player) != realSelectedPlayer) { continue; } NETbeginEncode(NETgameQueue(player), GAME_GAME_TIME); NETuint32_t(&latencyTicks); NETuint32_t(&checkTime); NETuint32_tLarge(&checkCrc); NETuint16_t(&wantedLatency); NETend(); } }