| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- // NetMessageStream.cpp
- // Holds misc functions to encapsulate GameMessages into Command Packets to send
- // over the network.
- // Author: Matthew D. Campbell, July 2001
- /*
- #include "stdlib.h" // VC++ wants this here, or gives compile error...
- #include "Common/GameType.h"
- #include "Common/MessageStream.h"
- #include "Common/GameEngine.h"
- #include "GameLogic/GameLogic.h"
- #include "GameNetwork/NetworkInterface.h"
- #include "GameNetwork/NetworkDefs.h"
- // The per-player pointers for the list of commands
- static CommandMsg *CommandHead[MAX_SLOTS] = { /// @todo: remove static initialization
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- };
- static CommandMsg *CommandTail[MAX_SLOTS] = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- };
- /**
- * AddToNetCommandList adds a CommandMsg to a list of commands.
- *
- static Bool AddToNetCommandList(GameMessage *msg, UnsignedInt timestamp, CommandMsg *& CommandHead, CommandMsg *& CommandTail)
- {
- CommandMsg *cmdMsg = NEW CommandMsg(timestamp, msg);
- if (!cmdMsg)
- {
- DEBUG_LOG(("Alloc failed!\n"));
- return false;
- }
- if (CommandTail == NULL)
- {
- CommandHead = cmdMsg;
- CommandTail = cmdMsg;
- }
- else
- {
- cmdMsg->SetPrevCommandMsg(CommandTail);
- CommandTail->SetNextCommandMsg(cmdMsg);
- CommandTail = cmdMsg;
- }
- return true;
- }
- /**
- * AddToRemoteNetCommandList is used by TheNetwork to queue up commands recieved from other players.
- *
- Bool AddToNetCommandList(Int playerNum, GameMessage *msg, UnsignedInt timestamp)
- {
- if (playerNum < 0 || playerNum >= MAX_SLOTS)
- return false;
- DEBUG_LOG(("Adding msg to NetCommandList %d\n", playerNum));
- return AddToNetCommandList(msg, timestamp, CommandHead[playerNum], CommandTail[playerNum]);
- }
- /**
- * GetCommandMsg returns a GameMessage (deleting its CommandMsg wrapper) that is valid
- * for the current frame, or NULL.
- *
- static GameMessage * GetCommandMsg(UnsignedInt timestamp, CommandMsg *& CommandHead, CommandMsg *& CommandTail)
- {
- if (!CommandHead)
- return NULL;
- if (CommandHead->GetTimestamp() < timestamp)
- {
- DEBUG_LOG(("Time is %d, yet message timestamp is %d!\n", timestamp, CommandHead->GetTimestamp()));
- return NULL;
- }
- if (CommandHead->GetTimestamp() != timestamp)
- return NULL;
- CommandMsg *theMsg = CommandHead;
- if (CommandHead->GetNextCommandMsg())
- {
- CommandHead->GetNextCommandMsg()->SetPrevCommandMsg(NULL);
- CommandHead = CommandHead->GetNextCommandMsg();
- }
- else
- {
- CommandHead = CommandTail = NULL;
- }
- GameMessage *msg = theMsg->GetGameMessage();
- delete theMsg;
- return msg;
- }
- /**
- * GetCommandMsg returns a message from the command list.
- *
- GameMessage * GetCommandMsg(UnsignedInt timestamp, Int playerNum)
- {
- if (playerNum < 0 || playerNum >= MAX_SLOTS)
- return NULL;
- //DEBUG_LOG(("Adding msg to NetCommandList %d\n", playerNum));
- return GetCommandMsg(timestamp, CommandHead[playerNum], CommandTail[playerNum]);
- }
- //====================================================================================
- // The commandBuf & commandPacket hold the commands we're building up for the frame.
- static unsigned char commandBuf[sizeof(CommandPacket)+1];
- static CommandPacket *commandPacket = (CommandPacket *)(commandBuf+1);
- /**
- * ClearCommandPacket clears the command packet at the start of the frame.
- *
- void ClearCommandPacket(UnsignedInt frame)
- {
- commandPacket->m_frame = frame;
- commandPacket->m_numCommands = 0;
- }
- /**
- * AddCommandToPacket creates a packet containing all move/attack/etc commands
- * for the current frame.
- *
- Bool AddCommandToPacket(const GameMessage *msg)
- {
- int messageSize = sizeofMessageHeader + sizeofMessageArg * msg->getArgumentCount();
- // If we have too much, send what we have
- if (bytesUsed && (bytesUsed + sizeof(CommandPacketHeader) + messageSize >= MAX_MESSAGE_LEN))
- {
- commandBuf[0] = MSGTYPE_PARTIALCOMMAND;
- if (!TheNetwork->queueSend(BROADCAST_CON, commandBuf, bytesUsed + sizeof(CommandPacketHeader) + 1, MSG_NEEDACK | MSG_SEQUENCED))
- {
- //DEBUG_ASSERTCRASH(false, ("Too many commands in one frame! Some will be dropped."));
- DEBUG_LOG(("Too many commands in one frame! Some will be dropped."));
- return false;
- }
- commandBuf[0] = MSGTYPE_COMMANDCOUNT;
- commandPacket->header.m_numCommands = 0;
- bytesUsed = 0;
- }
- if (bytesUsed + sizeof(CommandPacketHeader) + messageSize >= MAX_MESSAGE_LEN)
- {
- //DEBUG_ASSERTCRASH(false, ("Too many commands in one frame! Some will be dropped."));
- DEBUG_LOG(("Too many commands in one frame! Some will be dropped."));
- return false;
- }
- // We have room, so add the message
- commandPacket->header.m_numCommands++;
- commandPacket->m_commands[bytesUsed++] = (unsigned char)msg->getType();
- commandPacket->m_commands[bytesUsed++] = msg->getArgumentCount();
- for (int i=0; i<msg->getArgumentCount(); ++i)
- {
- memcpy((unsigned char *)(commandPacket->m_commands + bytesUsed), (unsigned char *)msg->getArgument(i), sizeofMessageArg);
- bytesUsed += sizeofMessageArg;
- }
- //DEBUG_ASSERTCRASH(bytesUsed + sizeof(CommandPacketHeader) < MAX_MESSAGE_LEN, ("Memory overwrite constructing command packet!"));
- //DEBUG_LOG(("Memory overwrite constructing command packet!"));
- return true;
- }
- /**
- * TheNetwork calls GetCommandPacket to get commands to send.
- *
- CommandPacket *GetCommandPacket(void)
- {
- commandBuf[0] = MSGTYPE_COMMANDCOUNT;
- return commandPacket;
- }
- //====================================================================================
- */
|