// //////////////////////////////////////////////////////////////////////////// // 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(); }
// // At this time, we do NOT support messages for beacons // bool sendBeacon(int32_t locX, int32_t locY, int32_t forPlayer, int32_t sender, const char* pStr) { int sendPlayer; //debug(LOG_WZ, "sendBeacon: '%s'",pStr); //find machine that is hosting this human or AI sendPlayer = whosResponsible(forPlayer); if(sendPlayer >= MAX_PLAYERS) { debug(LOG_ERROR, "sendAIMessage() - whosResponsible() failed."); return false; } // I assume this is correct, looks like it sends it to ONLY that person, and the routine // kf_AddHelpBlip() iterates for each player it needs. NETbeginEncode(NETnetQueue(sendPlayer), NET_BEACONMSG); // send to the player who is hosting 'to' player (might be himself if human and not AI) NETint32_t(&sender); // save the actual sender // save the actual player that is to get this msg on the source machine (source can host many AIs) NETint32_t(&forPlayer); // save the actual receiver (might not be the same as the one we are actually sending to, in case of AIs) NETint32_t(&locX); // save location NETint32_t(&locY); // const_cast: need to cast away constness because of the const-incorrectness of NETstring (const-incorrect when sending/encoding a packet) NETstring((char*)pStr, MAX_CONSOLE_STRING_LENGTH); // copy message in. NETend(); return true; }
BOOL recvAlliance(BOOL allowAudio) { uint8_t to, from, state; int32_t value; NETbeginDecode(NET_ALLIANCE); NETuint8_t(&from); NETuint8_t(&to); NETuint8_t(&state); NETint32_t(&value); NETend(); switch (state) { case ALLIANCE_NULL: break; case ALLIANCE_REQUESTED: requestAlliance(from, to, false, allowAudio); break; case ALLIANCE_FORMED: formAlliance(from, to, false, allowAudio, true); break; case ALLIANCE_BROKEN: breakAlliance(from, to, false, allowAudio); break; default: debug(LOG_ERROR, "Unknown alliance state recvd."); return false; break; } return true; }
static void NETcoder(PACKETDIR dir) { static const char original[] = "THIS IS A TEST STRING"; char str[sizeof(original)]; BOOL b = true; uint32_t u32 = 32; uint16_t u16 = 16; uint8_t u8 = 8; int32_t i32 = -32; int16_t i16 = -16; int8_t i8 = -8; test_enum te = test_b; sstrcpy(str, original); if (dir == PACKET_ENCODE) NETbeginEncode(0, 0); else NETbeginDecode(0); NETbool(&b); assert(b == true); NETuint32_t(&u32); assert(u32 == 32); NETuint16_t(&u16); assert(u16 == 16); NETuint8_t(&u8); assert(u8 == 8); NETint32_t(&i32); assert(i32 == -32); NETint16_t(&i16); assert(i16 == -16); NETint8_t(&i8); assert(i8 == -8); NETstring(str, sizeof(str)); assert(strncmp(str, original, sizeof(str) - 1) == 0); NETenum(&te); assert(te == test_b); }
// //////////////////////////////////////////////////////////////////////////// // 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 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(); }
void sendAlliance(uint8_t from, uint8_t to, uint8_t state, int32_t value) { NETbeginEncode(NET_ALLIANCE, NET_ALL_PLAYERS); NETuint8_t(&from); NETuint8_t(&to); NETuint8_t(&state); NETint32_t(&value); NETend(); }
static bool recvBeacon(NETQUEUE queue) { int32_t sender, receiver,locX, locY; char msg[MAX_CONSOLE_STRING_LENGTH]; NETbeginDecode(queue, NET_BEACONMSG); NETint32_t(&sender); // the actual sender NETint32_t(&receiver); // the actual receiver (might not be the same as the one we are actually sending to, in case of AIs) NETint32_t(&locX); NETint32_t(&locY); NETstring(msg, sizeof(msg)); // Receive the actual message NETend(); debug(LOG_WZ, "Received beacon for player: %d, from: %d",receiver, sender); sstrcat(msg, NetPlay.players[sender].name); // name sstrcpy(beaconReceiveMsg[sender], msg); return addBeaconBlip(locX, locY, receiver, sender, beaconReceiveMsg[sender]); }
// //////////////////////////////////////////////////////////////////////////// // INFORM others that a building has been started, and base plate should be put down. BOOL sendBuildStarted(STRUCTURE *psStruct, DROID *psDroid) { NETbeginEncode(NET_BUILD, NET_ALL_PLAYERS); // Who is building it NETuint8_t(&psDroid->player); // What they are building NETuint32_t(&psDroid->psTarStats->ref); // Where it is being built NETuint16_t(&psDroid->orderX); NETuint16_t(&psDroid->orderY); // The droid building it NETuint32_t(&psDroid->id); // The ID assigned to the structure being built NETuint32_t(&psStruct->id); // The droids order NETint32_t(&psDroid->order); if (psDroid->psTarget && psDroid->psTarget->type == OBJ_STRUCTURE) { // The ID of the droids target (== psStruct->id ?) NETuint32_t(&psDroid->psTarget->id); } else { NETnull(); } // Z coord NETint32_t(&psStruct->pos.z); return NETend(); }
bool recvAlliance(NETQUEUE queue, bool allowAudio) { uint8_t to, from, state; int32_t value; NETbeginDecode(queue, GAME_ALLIANCE); NETuint8_t(&from); NETuint8_t(&to); NETuint8_t(&state); NETint32_t(&value); NETend(); switch (state) { case ALLIANCE_NULL: break; case ALLIANCE_REQUESTED: turnOffMultiMsg(true); requestAlliance(from, to, false, allowAudio); turnOffMultiMsg(false); break; case ALLIANCE_FORMED: turnOffMultiMsg(true); formAlliance(from, to, false, allowAudio, true); turnOffMultiMsg(false); break; case ALLIANCE_BROKEN: turnOffMultiMsg(true); breakAlliance(from, to, false, allowAudio); turnOffMultiMsg(false); break; default: debug(LOG_ERROR, "Unknown alliance state recvd."); return false; break; } return true; }
BOOL NETfloat(float *fp) { /* * NB: Not portable. * This routine only works on machines with IEEE754 floating point numbers. */ #if !defined(__STDC_IEC_559__) \ && !defined(__m68k__) && !defined(__sparc__) && !defined(__i386__) \ && !defined(__mips__) && !defined(__ns32k__) && !defined(__alpha__) \ && !defined(__arm__) && !defined(__ppc__) && !defined(__ia64__) \ && !defined(__arm26__) && !defined(__sparc64__) && !defined(__amd64__) \ && !defined(WZ_CC_MSVC) // Assume that all platforms supported by // MSVC provide IEEE754 floating point numbers # error "this platform hasn't been confirmed to support IEEE754 floating point numbers" #endif // IEEE754 floating point numbers can be treated the same as 32-bit integers // with regards to endian conversion STATIC_ASSERT(sizeof(float) == sizeof(int32_t)); return NETint32_t((int32_t *) fp); }
static void NETtemplate(DROID_TEMPLATE *pTempl) { NETstring(pTempl->aName, sizeof(pTempl->aName)); for (unsigned i = 0; i < ARRAY_SIZE(pTempl->asParts); ++i) { // signed, but sent as a bunch of bits... NETint32_t(&pTempl->asParts[i]); } NETuint32_t(&pTempl->buildPoints); NETuint32_t(&pTempl->powerPoints); NETuint32_t(&pTempl->storeCount); NETuint32_t(&pTempl->numWeaps); NETbool(&pTempl->stored); // other players don't need to know, but we need to keep the knowledge in the loop somehow... for (int i = 0; i < DROID_MAXWEAPS; ++i) { NETuint32_t(&pTempl->asWeaps[i]); } NETenum(&pTempl->droidType); NETuint32_t(&pTempl->multiPlayerID); }
// //////////////////////////////////////////////////////////////////////////// // receive droid creation information from other players BOOL recvDroid(NETQUEUE queue) { DROID_TEMPLATE* pT; DROID* psDroid; uint8_t player; uint32_t id; Position pos; uint32_t templateID; BOOL haveInitialOrders; INITIAL_DROID_ORDERS initialOrders; NETbeginDecode(queue, GAME_DROID); { NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); NETuint32_t(&templateID); NETbool(&haveInitialOrders); if (haveInitialOrders) { NETuint32_t(&initialOrders.secondaryOrder); NETint32_t(&initialOrders.moveToX); NETint32_t(&initialOrders.moveToY); NETuint32_t(&initialOrders.factoryId); // For making scripts happy. } pT = IdToTemplate(templateID, player); } NETend(); ASSERT( player < MAX_PLAYERS, "invalid player %u", player); debug(LOG_LIFE, "<=== getting Droid from %u id of %u ",player,id); if ((pos.x == 0 && pos.y == 0) || pos.x > world_coord(mapWidth) || pos.y > world_coord(mapHeight)) { debug(LOG_ERROR, "Received bad droid position (%d, %d) from %d about p%d (%s)", (int)pos.x, (int)pos.y, queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); return false; } // If we can not find the template ask for the entire droid instead if (!pT) { debug(LOG_ERROR, "Packet from %d refers to non-existent template %u, [%s : p%d]", queue.index, templateID, isHumanPlayer(player) ? "Human" : "AI", player); return false; } // Create that droid on this machine. psDroid = reallyBuildDroid(pT, pos.x, pos.y, player, false); // If we were able to build the droid set it up if (psDroid) { psDroid->id = id; addDroid(psDroid, apsDroidLists); if (haveInitialOrders) { psDroid->secondaryOrder = initialOrders.secondaryOrder; orderDroidLoc(psDroid, DORDER_MOVE, initialOrders.moveToX, initialOrders.moveToY, ModeImmediate); cbNewDroid(IdToStruct(initialOrders.factoryId, ANYPLAYER), psDroid); } } else { debug(LOG_ERROR, "Packet from %d cannot create droid for p%d (%s)!", queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); #ifdef DEBUG CONPRINTF(ConsoleString, (ConsoleString, "MULTIPLAYER: Couldn't build a remote droid, relying on checking to resync")); #endif return false; } return true; }
// //////////////////////////////////////////////////////////////////////////// BOOL recvBuildFinished() { uint32_t structId; STRUCTURE *psStruct; int32_t x,y,z; uint32_t type,typeindex; uint8_t player; uint32_t power; NETbeginDecode(NET_BUILDFINISHED); NETuint32_t(&power); // get the player's power level NETuint32_t(&structId); // get the struct id. NETuint32_t(&type); // Kind of building. NETint32_t(&x); // x pos NETint32_t(&y); // y pos NETint32_t(&z); // z pos NETuint8_t(&player); NETend(); ASSERT( player < MAX_PLAYERS, "invalid player %u", player); psStruct = IdToStruct(structId,ANYPLAYER); setPower( (uint32_t)player, power); // we sync the power level as well if (psStruct) { // make it complete. psStruct->currentBuildPts = psStruct->pStructureType->buildPoints+1; if (psStruct->status != SS_BUILT) { psStruct->status = SS_BUILT; buildingComplete(psStruct); } debug(LOG_SYNC, "Created normal building %u for player %u", psStruct->id, player); return true; } // The building wasn't started, so we'll have to just plonk it down in the map. // Find the structures stats for (typeindex=0; // Find structure target (typeindex<numStructureStats ) && (asStructureStats[typeindex].ref != type); typeindex++); // Check for similar buildings, to avoid overlaps if (TileHasStructure(mapTile(map_coord(x), map_coord(y)))) { // Get the current structure psStruct = getTileStructure(map_coord(x), map_coord(y)); if (asStructureStats[typeindex].type == psStruct->pStructureType->type) { // Correct type, correct location, just rename the id's to sync it.. (urgh) psStruct->id = structId; psStruct->status = SS_BUILT; buildingComplete(psStruct); debug(LOG_SYNC, "Created modified building %u for player %u", psStruct->id, player); #if defined (DEBUG) NETlogEntry("structure id modified", SYNC_FLAG, player); #endif return true; } } // Build the structure psStruct = buildStructure(&(asStructureStats[typeindex]), x, y, player, true); if (psStruct) { psStruct->id = structId; psStruct->status = SS_BUILT; buildingComplete(psStruct); debug(LOG_SYNC, "Forced to create building %u for player %u", psStruct->id, player); #if defined (DEBUG) NETlogEntry("had to plonk down a building" ,SYNC_FLAG, player); #endif } else { debug(LOG_SYNC, "Unable to create building for player %u", player); NETlogEntry("had to plonk down a building, BUT FAILED!" , SYNC_FLAG, player); } return false; }
// //////////////////////////////////////////////////////////////////////////// // put down a base plate and start droid building it! BOOL recvBuildStarted() { STRUCTURE_STATS *psStats; DROID *psDroid; UDWORD actionX,actionY; unsigned int typeIndex; uint8_t player; uint16_t x, y, z; int32_t order; uint32_t structRef, structId, targetId,droidID; NETbeginDecode(NET_BUILD); NETuint8_t(&player); NETuint32_t(&structRef); NETuint16_t(&x); NETuint16_t(&y); NETuint32_t(&droidID); NETuint32_t(&structId); NETint32_t(&order); NETuint32_t(&targetId); NETuint16_t(&z); NETend(); // Find structure target for (typeIndex = 0; typeIndex < numStructureStats && asStructureStats[typeIndex].ref != structRef; typeIndex++); psStats = &asStructureStats[typeIndex]; if (IdToDroid(droidID, player, &psDroid)) { // Tell the droid to go to where it needs to in order to build the struct if (getDroidDestination((BASE_STATS *) psStats, x, y, &actionX, &actionY)) { psDroid->order = order; if (psDroid->order == DORDER_LINEBUILD) { psDroid->order = DORDER_BUILD; } psDroid->orderX = x; psDroid->orderY = y; psDroid->psTarStats = (BASE_STATS *) psStats; if (targetId) { setDroidTarget(psDroid, IdToPointer(targetId, ANYPLAYER)); } else { setDroidTarget(psDroid, NULL); } if (IsStatExpansionModule(psStats)) { setUpBuildModule(psDroid); } else { droidStartBuild(psDroid); psDroid->action = DACTION_BUILD; } } // Sync IDs if (psDroid->psTarget) { ((STRUCTURE *) psDroid->psTarget)->id = structId; } } return true; }
// //////////////////////////////////////////////////////////////////////////// // receive droid creation information from other players bool recvDroid(NETQUEUE queue) { DROID_TEMPLATE t, *pT = &t; DROID *psDroid; uint8_t player; uint32_t id; Position pos; bool haveInitialOrders; INITIAL_DROID_ORDERS initialOrders; NETbeginDecode(queue, GAME_DEBUG_ADD_DROID); { int32_t droidType; NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); NETqstring(pT->name); pT->id = 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]); } NETbool(&haveInitialOrders); if (haveInitialOrders) { NETuint32_t(&initialOrders.secondaryOrder); NETint32_t(&initialOrders.moveToX); NETint32_t(&initialOrders.moveToY); NETuint32_t(&initialOrders.factoryId); // For making scripts happy. } pT->droidType = (DROID_TYPE)droidType; } NETend(); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to add droid for player %u.", NetPlay.players[queue.index].position); return false; } ASSERT_OR_RETURN(false, player < MAX_PLAYERS, "invalid player %u", player); debug(LOG_LIFE, "<=== getting Droid from %u id of %u ", player, id); if ((pos.x == 0 && pos.y == 0) || pos.x > world_coord(mapWidth) || pos.y > world_coord(mapHeight)) { debug(LOG_ERROR, "Received bad droid position (%d, %d) from %d about p%d (%s)", (int)pos.x, (int)pos.y, queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); return false; } // Create that droid on this machine. psDroid = reallyBuildDroid(pT, pos, player, false); // If we were able to build the droid set it up if (psDroid) { psDroid->id = id; addDroid(psDroid, apsDroidLists); if (haveInitialOrders) { psDroid->secondaryOrder = initialOrders.secondaryOrder; psDroid->secondaryOrderPending = psDroid->secondaryOrder; orderDroidLoc(psDroid, DORDER_MOVE, initialOrders.moveToX, initialOrders.moveToY, ModeImmediate); cbNewDroid(IdToStruct(initialOrders.factoryId, ANYPLAYER), psDroid); } syncDebugDroid(psDroid, '+'); } else { debug(LOG_ERROR, "Packet from %d cannot create droid for p%d (%s)!", queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); #ifdef DEBUG CONPRINTF(ConsoleString, (ConsoleString, "MULTIPLAYER: Couldn't build a remote droid, relying on checking to resync")); #endif return false; } return true; }
BOOL NETPosition(Position *vp) { return (NETint32_t(&vp->x) && NETint32_t(&vp->y) && NETint32_t(&vp->z)); }