static void ParseResendCommand(const CNetworkPacket &packet) { // Destination cycle (time to execute). unsigned long n = ((GameCycle + 128) & ~0xFF) | packet.Header.Cycle; if (n > GameCycle + 128) { n -= 0x100; } const unsigned long gameNetCycle = n; // FIXME: not necessary to send this packet multiple times!!!! // other side sends re-send until it gets an answer. if (n != NetworkIn[gameNetCycle & 0xFF][ThisPlayer->Index][0].Time) { // Asking for a cycle we haven't gotten to yet, ignore for now return; } NetworkSendPacket(NetworkIn[gameNetCycle & 0xFF][ThisPlayer->Index]); // Check if a player quit this cycle for (int j = 0; j < HostsCount; ++j) { for (int c = 0; c < MaxNetworkCommands; ++c) { const CNetworkCommandQueue *ncq; ncq = &NetworkIn[gameNetCycle & 0xFF][Hosts[j].PlyNr][c]; if (ncq->Time && ncq->Type == MessageQuit) { CNetworkPacket np; np.Header.Cycle = ncq->Time & 0xFF; np.Header.Type[0] = MessageQuit; np.Command[0] = ncq->Data; for (int k = 1; k < MaxNetworkCommands; ++k) { np.Header.Type[k] = MessageNone; } NetworkBroadcast(np, 1); break; } } } }
static void CheckPlayerThatTimeOut(int hostIndex) { const int playerIndex = Hosts[hostIndex].PlyNr; const unsigned long lastFrame = NetworkLastFrame[playerIndex]; if (!lastFrame) { return; } const int framesPerSecond = FRAMES_PER_SECOND * VideoSyncSpeed / 100; const int secs = (FrameCounter - lastFrame) / framesPerSecond; // FIXME: display a menu while we wait const int timeoutInS = CNetworkParameter::Instance.timeoutInS; if (3 <= secs && secs < timeoutInS && FrameCounter % framesPerSecond == 0) { SetMessage(_("Waiting for player \"%s\": %d:%02d"), Hosts[hostIndex].PlyName, (timeoutInS - secs) / 60, (timeoutInS - secs) % 60); } if (secs >= timeoutInS) { const unsigned int nextGameNetCycle = GameCycle / CNetworkParameter::Instance.gameCyclesPerUpdate + 1; CNetworkCommandQuit nc; nc.player = playerIndex; CNetworkCommandQueue *ncq = &NetworkIn[nextGameNetCycle & 0xFF][playerIndex][0]; ncq->Time = nextGameNetCycle * CNetworkParameter::Instance.gameCyclesPerUpdate; ncq->Type = MessageQuit; ncq->Data.resize(nc.Size()); nc.Serialize(&ncq->Data[0]); PlayerQuit[playerIndex] = 1; SetMessage("%s", _("Timed out")); CNetworkPacket np; np.Header.Cycle = ncq->Time & 0xFF; np.Header.Type[0] = ncq->Type; np.Header.Type[1] = MessageNone; NetworkBroadcast(np, 1); } }
//------------------------------------------------------------------------------------------------------- int main( int argc, char const **argv ) { if (!NetSystemInit()) { printf( "Failed to initialize net system.\n" ); _getch(); return false; } // List Addresses char const *hostname = AllocLocalHostName(); ListAddressesForHost( hostname, gHostPort ); FreeLocalHostName(hostname); // Host/Client Logic if ((argc <= 1) || (_strcmpi( argv[1], "sock" ) == 0)) { printf( "Hosting...\n" ); NetworkHost( gHostPort ); } else if (argc > 2) { char const *addr = argv[1]; char const *msg = argv[2]; printf( "Sending message \"%s\" to [%s]\n", msg, addr ); NetworkClient( addr, gHostPort, msg ); } else { char const *msg = argv[1]; printf( "Broadcast message \"%s\".\n", msg ); NetworkBroadcast( msg ); } NetSystemDeinit(); printf( "Press any key to continue...\n" ); _getch(); return 0; }
/** ** Network resend commands, we have a missing packet send to all clients ** what packet we are missing. ** ** @todo ** We need only send to the clients, that have not delivered the packet. */ static void NetworkResendCommands() { #ifdef DEBUG ++NetworkStat.resentPacketCount; #endif const int networkUpdates = CNetworkParameter::Instance.gameCyclesPerUpdate; const int nextGameCycle = ((GameCycle / networkUpdates) + 1) * networkUpdates; // Build packet CNetworkPacket packet; packet.Header.Type[0] = MessageResend; packet.Header.Type[1] = MessageNone; packet.Header.Cycle = uint8_t(nextGameCycle & 0xFF); NetworkBroadcast(packet, 1); }
/** ** Network send packet. Build it from queue and broadcast. ** ** @param ncq Outgoing network queue start. */ static void NetworkSendPacket(const CNetworkCommandQueue(&ncq)[MaxNetworkCommands]) { CNetworkPacket packet; // Build packet of up to MaxNetworkCommands messages. int numcommands = 0; packet.Header.Cycle = ncq[0].Time & 0xFF; packet.Header.OrigPlayer = ThisPlayer->Index; int i; for (i = 0; i < MaxNetworkCommands && ncq[i].Type != MessageNone; ++i) { packet.Header.Type[i] = ncq[i].Type; packet.Command[i] = ncq[i].Data; ++numcommands; } for (; i < MaxNetworkCommands; ++i) { packet.Header.Type[i] = MessageNone; } NetworkBroadcast(packet, numcommands); }
static void NetworkParseInGameEvent(const unsigned char *buf, int len, const CHost &host) { CNetworkPacket packet; int commands; packet.Deserialize(buf, len, &commands); int player = packet.Header.OrigPlayer; if (player == 255) { const int index = FindHostIndexBy(host); if (index == -1 || PlayerQuit[Hosts[index].PlyNr]) { #ifdef DEBUG const std::string hostStr = host.toString(); DebugPrint("Not a host in play: %s\n" _C_ hostStr.c_str()); #endif return; } player = Hosts[index].PlyNr; } if (NetConnectType == 1) { if (player != 255) { NetworkBroadcast(packet, commands, player); } } if (commands < 0) { DebugPrint("Bad packet read\n"); return; } NetworkLastCycle[player] = packet.Header.Cycle; // Parse the packet commands. for (int i = 0; i != commands; ++i) { // Handle some messages. if (packet.Header.Type[i] == MessageQuit) { CNetworkCommandQuit nc; nc.Deserialize(&packet.Command[i][0]); const int playerNum = nc.player; if (playerNum >= 0 && playerNum < NumPlayers) { PlayerQuit[playerNum] = 1; } } if (packet.Header.Type[i] == MessageResend) { ParseResendCommand(packet); return; } // Receive statistic NetworkLastFrame[player] = FrameCounter; bool validCommand = IsAValidCommand(packet, i, player); // Place in network in if (validCommand) { // Destination cycle (time to execute). unsigned long n = ((GameCycle + 128) & ~0xFF) | packet.Header.Cycle; if (n > GameCycle + 128) { n -= 0x100; } NetworkIn[packet.Header.Cycle][player][i].Time = n; NetworkIn[packet.Header.Cycle][player][i].Type = packet.Header.Type[i]; NetworkIn[packet.Header.Cycle][player][i].Data = packet.Command[i]; } else { SetMessage(_("%s sent bad command"), Players[player].Name.c_str()); DebugPrint("%s sent bad command: 0x%x\n" _C_ Players[player].Name.c_str() _C_ packet.Header.Type[i] & 0x7F); } } for (int i = commands; i != MaxNetworkCommands; ++i) { NetworkIn[packet.Header.Cycle][player][i].Time = 0; } // Waiting for this time slot if (!NetworkInSync) { const int networkUpdates = CNetworkParameter::Instance.gameCyclesPerUpdate; unsigned long n = ((GameCycle / networkUpdates) + 1) * networkUpdates; if (IsNetworkCommandReady(n) == true) { NetworkInSync = true; } } }