diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt
index 0a58dfc4315..8bf3158e5b5 100644
--- a/Core/GameEngine/CMakeLists.txt
+++ b/Core/GameEngine/CMakeLists.txt
@@ -501,58 +501,58 @@ set(GAMEENGINE_SRC
# Include/GameLogic/WeaponSetFlags.h
# Include/GameLogic/WeaponSetType.h
# Include/GameLogic/WeaponStatus.h
-# Include/GameNetwork/Connection.h
-# Include/GameNetwork/ConnectionManager.h
-# Include/GameNetwork/DisconnectManager.h
-# Include/GameNetwork/DownloadManager.h
-# Include/GameNetwork/FileTransfer.h
-# Include/GameNetwork/FirewallHelper.h
-# Include/GameNetwork/FrameData.h
-# Include/GameNetwork/FrameDataManager.h
-# Include/GameNetwork/FrameMetrics.h
-# Include/GameNetwork/GameInfo.h
-# Include/GameNetwork/GameMessageParser.h
-# Include/GameNetwork/GameSpy/BuddyDefs.h
-# Include/GameNetwork/GameSpy/BuddyThread.h
-# Include/GameNetwork/GameSpy/GameResultsThread.h
-# Include/GameNetwork/GameSpy/GSConfig.h
-# Include/GameNetwork/GameSpy/LadderDefs.h
-# Include/GameNetwork/GameSpy/LobbyUtils.h
-# Include/GameNetwork/GameSpy/MainMenuUtils.h
-# Include/GameNetwork/GameSpy/PeerDefs.h
-# Include/GameNetwork/GameSpy/PeerDefsImplementation.h
-# Include/GameNetwork/GameSpy/PeerThread.h
-# Include/GameNetwork/GameSpy/PersistentStorageDefs.h
-# Include/GameNetwork/GameSpy/PersistentStorageThread.h
-# Include/GameNetwork/GameSpy/PingThread.h
-# Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
-# Include/GameNetwork/GameSpy/ThreadUtils.h
-# Include/GameNetwork/GameSpyChat.h
-# Include/GameNetwork/GameSpyGameInfo.h
-# Include/GameNetwork/GameSpyGP.h
-# Include/GameNetwork/GameSpyOverlay.h
-# Include/GameNetwork/GameSpyThread.h
+ Include/GameNetwork/Connection.h
+ Include/GameNetwork/ConnectionManager.h
+ Include/GameNetwork/DisconnectManager.h
+ Include/GameNetwork/DownloadManager.h
+ Include/GameNetwork/FileTransfer.h
+ Include/GameNetwork/FirewallHelper.h
+ Include/GameNetwork/FrameData.h
+ Include/GameNetwork/FrameDataManager.h
+ Include/GameNetwork/FrameMetrics.h
+ Include/GameNetwork/GameInfo.h
+ Include/GameNetwork/GameMessageParser.h
+ Include/GameNetwork/GameSpy/BuddyDefs.h
+ Include/GameNetwork/GameSpy/BuddyThread.h
+ Include/GameNetwork/GameSpy/GameResultsThread.h
+ Include/GameNetwork/GameSpy/GSConfig.h
+ Include/GameNetwork/GameSpy/LadderDefs.h
+ Include/GameNetwork/GameSpy/LobbyUtils.h
+ Include/GameNetwork/GameSpy/MainMenuUtils.h
+ Include/GameNetwork/GameSpy/PeerDefs.h
+ Include/GameNetwork/GameSpy/PeerDefsImplementation.h
+ Include/GameNetwork/GameSpy/PeerThread.h
+ Include/GameNetwork/GameSpy/PersistentStorageDefs.h
+ Include/GameNetwork/GameSpy/PersistentStorageThread.h
+ Include/GameNetwork/GameSpy/PingThread.h
+ Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
+ Include/GameNetwork/GameSpy/ThreadUtils.h
+# Include/GameNetwork/GameSpyChat.h # unused
+# Include/GameNetwork/GameSpyGameInfo.h # unused
+# Include/GameNetwork/GameSpyGP.h # unused
+ Include/GameNetwork/GameSpyOverlay.h
+ Include/GameNetwork/GameSpyThread.h
# Include/GameNetwork/GUIUtil.h
-# Include/GameNetwork/IPEnumeration.h
-# Include/GameNetwork/LANAPI.h
-# Include/GameNetwork/LANAPICallbacks.h
-# Include/GameNetwork/LANGameInfo.h
-# Include/GameNetwork/LANPlayer.h
-# Include/GameNetwork/NAT.h
-# Include/GameNetwork/NetCommandList.h
-# Include/GameNetwork/NetCommandMsg.h
-# Include/GameNetwork/NetCommandRef.h
-# Include/GameNetwork/NetCommandWrapperList.h
-# Include/GameNetwork/NetPacket.h
-# Include/GameNetwork/NetworkDefs.h
-# Include/GameNetwork/NetworkInterface.h
-# Include/GameNetwork/networkutil.h
-# Include/GameNetwork/RankPointValue.h
-# Include/GameNetwork/Transport.h
-# Include/GameNetwork/udp.h
-# Include/GameNetwork/User.h
-# Include/GameNetwork/WOLBrowser/FEBDispatch.h
-# Include/GameNetwork/WOLBrowser/WebBrowser.h
+ Include/GameNetwork/IPEnumeration.h
+ Include/GameNetwork/LANAPI.h
+ Include/GameNetwork/LANAPICallbacks.h
+ Include/GameNetwork/LANGameInfo.h
+ Include/GameNetwork/LANPlayer.h
+ Include/GameNetwork/NAT.h
+ Include/GameNetwork/NetCommandList.h
+ Include/GameNetwork/NetCommandMsg.h
+ Include/GameNetwork/NetCommandRef.h
+ Include/GameNetwork/NetCommandWrapperList.h
+ Include/GameNetwork/NetPacket.h
+ Include/GameNetwork/NetworkDefs.h
+ Include/GameNetwork/NetworkInterface.h
+ Include/GameNetwork/networkutil.h
+ Include/GameNetwork/RankPointValue.h
+ Include/GameNetwork/Transport.h
+ Include/GameNetwork/udp.h
+ Include/GameNetwork/User.h
+ Include/GameNetwork/WOLBrowser/FEBDispatch.h
+ Include/GameNetwork/WOLBrowser/WebBrowser.h
# Include/Precompiled/PreRTS.h
Source/Common/Audio/AudioEventRTS.cpp
Source/Common/Audio/AudioRequest.cpp
@@ -1091,53 +1091,53 @@ set(GAMEENGINE_SRC
# Source/GameLogic/System/GameLogic.cpp
# Source/GameLogic/System/GameLogicDispatch.cpp
# Source/GameLogic/System/RankInfo.cpp
-# Source/GameNetwork/Connection.cpp
-# Source/GameNetwork/ConnectionManager.cpp
-# Source/GameNetwork/DisconnectManager.cpp
-# Source/GameNetwork/DownloadManager.cpp
-# Source/GameNetwork/FileTransfer.cpp
-# Source/GameNetwork/FirewallHelper.cpp
-# Source/GameNetwork/FrameData.cpp
-# Source/GameNetwork/FrameDataManager.cpp
-# Source/GameNetwork/FrameMetrics.cpp
-# Source/GameNetwork/GameInfo.cpp
-# Source/GameNetwork/GameMessageParser.cpp
+ Source/GameNetwork/Connection.cpp
+ Source/GameNetwork/ConnectionManager.cpp
+ Source/GameNetwork/DisconnectManager.cpp
+ Source/GameNetwork/DownloadManager.cpp
+ Source/GameNetwork/FileTransfer.cpp
+ Source/GameNetwork/FirewallHelper.cpp
+ Source/GameNetwork/FrameData.cpp
+ Source/GameNetwork/FrameDataManager.cpp
+ Source/GameNetwork/FrameMetrics.cpp
+ Source/GameNetwork/GameInfo.cpp
+ Source/GameNetwork/GameMessageParser.cpp
#Source/GameNetwork/GameSpyChat.cpp # unused
#Source/GameNetwork/GameSpyGameInfo.cpp # unused
#Source/GameNetwork/GameSpyGP.cpp # unused
-# Source/GameNetwork/GameSpy/Chat.cpp
-# Source/GameNetwork/GameSpy/GSConfig.cpp
-# Source/GameNetwork/GameSpy/LadderDefs.cpp
-# Source/GameNetwork/GameSpy/LobbyUtils.cpp
-# Source/GameNetwork/GameSpy/MainMenuUtils.cpp
-# Source/GameNetwork/GameSpy/PeerDefs.cpp
-# Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
-# Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
-# Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
-# Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
-# Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
-# Source/GameNetwork/GameSpy/Thread/PingThread.cpp
-# Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
-# Source/GameNetwork/GameSpyOverlay.cpp
+ Source/GameNetwork/GameSpy/Chat.cpp
+ Source/GameNetwork/GameSpy/GSConfig.cpp
+ Source/GameNetwork/GameSpy/LadderDefs.cpp
+ Source/GameNetwork/GameSpy/LobbyUtils.cpp
+ Source/GameNetwork/GameSpy/MainMenuUtils.cpp
+ Source/GameNetwork/GameSpy/PeerDefs.cpp
+ Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
+ Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
+ Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
+ Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
+ Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
+ Source/GameNetwork/GameSpy/Thread/PingThread.cpp
+ Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
+ Source/GameNetwork/GameSpyOverlay.cpp
# Source/GameNetwork/GUIUtil.cpp
-# Source/GameNetwork/IPEnumeration.cpp
-# Source/GameNetwork/LANAPI.cpp
-# Source/GameNetwork/LANAPICallbacks.cpp
-# Source/GameNetwork/LANAPIhandlers.cpp
-# Source/GameNetwork/LANGameInfo.cpp
-# Source/GameNetwork/NAT.cpp
-# Source/GameNetwork/NetCommandList.cpp
-# Source/GameNetwork/NetCommandMsg.cpp
-# Source/GameNetwork/NetCommandRef.cpp
-# Source/GameNetwork/NetCommandWrapperList.cpp
-# Source/GameNetwork/NetMessageStream.cpp
-# Source/GameNetwork/NetPacket.cpp
-# Source/GameNetwork/Network.cpp
-# Source/GameNetwork/NetworkUtil.cpp
-# Source/GameNetwork/Transport.cpp
-# Source/GameNetwork/udp.cpp
-# Source/GameNetwork/User.cpp
-# Source/GameNetwork/WOLBrowser/WebBrowser.cpp
+ Source/GameNetwork/IPEnumeration.cpp
+ Source/GameNetwork/LANAPI.cpp
+ Source/GameNetwork/LANAPICallbacks.cpp
+ Source/GameNetwork/LANAPIhandlers.cpp
+ Source/GameNetwork/LANGameInfo.cpp
+ Source/GameNetwork/NAT.cpp
+ Source/GameNetwork/NetCommandList.cpp
+ Source/GameNetwork/NetCommandMsg.cpp
+ Source/GameNetwork/NetCommandRef.cpp
+ Source/GameNetwork/NetCommandWrapperList.cpp
+ Source/GameNetwork/NetMessageStream.cpp
+ Source/GameNetwork/NetPacket.cpp
+ Source/GameNetwork/Network.cpp
+ Source/GameNetwork/NetworkUtil.cpp
+ Source/GameNetwork/Transport.cpp
+ Source/GameNetwork/udp.cpp
+ Source/GameNetwork/User.cpp
+ Source/GameNetwork/WOLBrowser/WebBrowser.cpp
# Source/Precompiled/PreRTS.cpp
)
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/Connection.h b/Core/GameEngine/Include/GameNetwork/Connection.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/Connection.h
rename to Core/GameEngine/Include/GameNetwork/Connection.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/ConnectionManager.h b/Core/GameEngine/Include/GameNetwork/ConnectionManager.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/ConnectionManager.h
rename to Core/GameEngine/Include/GameNetwork/ConnectionManager.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/DisconnectManager.h b/Core/GameEngine/Include/GameNetwork/DisconnectManager.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/DisconnectManager.h
rename to Core/GameEngine/Include/GameNetwork/DisconnectManager.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/DownloadManager.h b/Core/GameEngine/Include/GameNetwork/DownloadManager.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/DownloadManager.h
rename to Core/GameEngine/Include/GameNetwork/DownloadManager.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/FileTransfer.h b/Core/GameEngine/Include/GameNetwork/FileTransfer.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/FileTransfer.h
rename to Core/GameEngine/Include/GameNetwork/FileTransfer.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/FirewallHelper.h b/Core/GameEngine/Include/GameNetwork/FirewallHelper.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/FirewallHelper.h
rename to Core/GameEngine/Include/GameNetwork/FirewallHelper.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/FrameData.h b/Core/GameEngine/Include/GameNetwork/FrameData.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/FrameData.h
rename to Core/GameEngine/Include/GameNetwork/FrameData.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/FrameDataManager.h b/Core/GameEngine/Include/GameNetwork/FrameDataManager.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/FrameDataManager.h
rename to Core/GameEngine/Include/GameNetwork/FrameDataManager.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/FrameMetrics.h b/Core/GameEngine/Include/GameNetwork/FrameMetrics.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/FrameMetrics.h
rename to Core/GameEngine/Include/GameNetwork/FrameMetrics.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h b/Core/GameEngine/Include/GameNetwork/GameInfo.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameInfo.h
rename to Core/GameEngine/Include/GameNetwork/GameInfo.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameMessageParser.h b/Core/GameEngine/Include/GameNetwork/GameMessageParser.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameMessageParser.h
rename to Core/GameEngine/Include/GameNetwork/GameMessageParser.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h b/Core/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h b/Core/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h b/Core/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h b/Core/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h b/Core/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h b/Core/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h b/Core/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h b/Core/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h b/Core/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h b/Core/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h b/Core/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h b/Core/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h b/Core/GameEngine/Include/GameNetwork/GameSpy/PingThread.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/PingThread.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h b/Core/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h b/Core/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h
rename to Core/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h b/Core/GameEngine/Include/GameNetwork/GameSpyOverlay.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h
rename to Core/GameEngine/Include/GameNetwork/GameSpyOverlay.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyThread.h b/Core/GameEngine/Include/GameNetwork/GameSpyThread.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpyThread.h
rename to Core/GameEngine/Include/GameNetwork/GameSpyThread.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/IPEnumeration.h b/Core/GameEngine/Include/GameNetwork/IPEnumeration.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/IPEnumeration.h
rename to Core/GameEngine/Include/GameNetwork/IPEnumeration.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h b/Core/GameEngine/Include/GameNetwork/LANAPI.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPI.h
rename to Core/GameEngine/Include/GameNetwork/LANAPI.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPICallbacks.h b/Core/GameEngine/Include/GameNetwork/LANAPICallbacks.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/LANAPICallbacks.h
rename to Core/GameEngine/Include/GameNetwork/LANAPICallbacks.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANGameInfo.h b/Core/GameEngine/Include/GameNetwork/LANGameInfo.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/LANGameInfo.h
rename to Core/GameEngine/Include/GameNetwork/LANGameInfo.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h b/Core/GameEngine/Include/GameNetwork/LANPlayer.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/LANPlayer.h
rename to Core/GameEngine/Include/GameNetwork/LANPlayer.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NAT.h b/Core/GameEngine/Include/GameNetwork/NAT.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NAT.h
rename to Core/GameEngine/Include/GameNetwork/NAT.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandList.h b/Core/GameEngine/Include/GameNetwork/NetCommandList.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandList.h
rename to Core/GameEngine/Include/GameNetwork/NetCommandList.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandMsg.h b/Core/GameEngine/Include/GameNetwork/NetCommandMsg.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandMsg.h
rename to Core/GameEngine/Include/GameNetwork/NetCommandMsg.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandRef.h b/Core/GameEngine/Include/GameNetwork/NetCommandRef.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandRef.h
rename to Core/GameEngine/Include/GameNetwork/NetCommandRef.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandWrapperList.h b/Core/GameEngine/Include/GameNetwork/NetCommandWrapperList.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NetCommandWrapperList.h
rename to Core/GameEngine/Include/GameNetwork/NetCommandWrapperList.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NetPacket.h b/Core/GameEngine/Include/GameNetwork/NetPacket.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NetPacket.h
rename to Core/GameEngine/Include/GameNetwork/NetPacket.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NetworkDefs.h b/Core/GameEngine/Include/GameNetwork/NetworkDefs.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NetworkDefs.h
rename to Core/GameEngine/Include/GameNetwork/NetworkDefs.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/NetworkInterface.h b/Core/GameEngine/Include/GameNetwork/NetworkInterface.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/NetworkInterface.h
rename to Core/GameEngine/Include/GameNetwork/NetworkInterface.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/RankPointValue.h b/Core/GameEngine/Include/GameNetwork/RankPointValue.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/RankPointValue.h
rename to Core/GameEngine/Include/GameNetwork/RankPointValue.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/Transport.h b/Core/GameEngine/Include/GameNetwork/Transport.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/Transport.h
rename to Core/GameEngine/Include/GameNetwork/Transport.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/User.h b/Core/GameEngine/Include/GameNetwork/User.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/User.h
rename to Core/GameEngine/Include/GameNetwork/User.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/WOLBrowser/FEBDispatch.h b/Core/GameEngine/Include/GameNetwork/WOLBrowser/FEBDispatch.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/WOLBrowser/FEBDispatch.h
rename to Core/GameEngine/Include/GameNetwork/WOLBrowser/FEBDispatch.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/WOLBrowser/WebBrowser.h b/Core/GameEngine/Include/GameNetwork/WOLBrowser/WebBrowser.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/WOLBrowser/WebBrowser.h
rename to Core/GameEngine/Include/GameNetwork/WOLBrowser/WebBrowser.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/networkutil.h b/Core/GameEngine/Include/GameNetwork/networkutil.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/networkutil.h
rename to Core/GameEngine/Include/GameNetwork/networkutil.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/udp.h b/Core/GameEngine/Include/GameNetwork/udp.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameNetwork/udp.h
rename to Core/GameEngine/Include/GameNetwork/udp.h
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/Connection.cpp b/Core/GameEngine/Source/GameNetwork/Connection.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/Connection.cpp
rename to Core/GameEngine/Source/GameNetwork/Connection.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/ConnectionManager.cpp b/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/ConnectionManager.cpp
rename to Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/DisconnectManager.cpp b/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/DisconnectManager.cpp
rename to Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/DownloadManager.cpp b/Core/GameEngine/Source/GameNetwork/DownloadManager.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/DownloadManager.cpp
rename to Core/GameEngine/Source/GameNetwork/DownloadManager.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/FileTransfer.cpp b/Core/GameEngine/Source/GameNetwork/FileTransfer.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/FileTransfer.cpp
rename to Core/GameEngine/Source/GameNetwork/FileTransfer.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/FirewallHelper.cpp b/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/FirewallHelper.cpp
rename to Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/FrameData.cpp b/Core/GameEngine/Source/GameNetwork/FrameData.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/FrameData.cpp
rename to Core/GameEngine/Source/GameNetwork/FrameData.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/FrameDataManager.cpp b/Core/GameEngine/Source/GameNetwork/FrameDataManager.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/FrameDataManager.cpp
rename to Core/GameEngine/Source/GameNetwork/FrameDataManager.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/FrameMetrics.cpp b/Core/GameEngine/Source/GameNetwork/FrameMetrics.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/FrameMetrics.cpp
rename to Core/GameEngine/Source/GameNetwork/FrameMetrics.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/Core/GameEngine/Source/GameNetwork/GameInfo.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameInfo.cpp
rename to Core/GameEngine/Source/GameNetwork/GameInfo.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameMessageParser.cpp b/Core/GameEngine/Source/GameNetwork/GameMessageParser.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameMessageParser.cpp
rename to Core/GameEngine/Source/GameNetwork/GameMessageParser.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp b/Core/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp
rename to Core/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/IPEnumeration.cpp b/Core/GameEngine/Source/GameNetwork/IPEnumeration.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/IPEnumeration.cpp
rename to Core/GameEngine/Source/GameNetwork/IPEnumeration.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp b/Core/GameEngine/Source/GameNetwork/LANAPI.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPI.cpp
rename to Core/GameEngine/Source/GameNetwork/LANAPI.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp b/Core/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
rename to Core/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp b/Core/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
rename to Core/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp b/Core/GameEngine/Source/GameNetwork/LANGameInfo.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp
rename to Core/GameEngine/Source/GameNetwork/LANGameInfo.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NAT.cpp b/Core/GameEngine/Source/GameNetwork/NAT.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NAT.cpp
rename to Core/GameEngine/Source/GameNetwork/NAT.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandList.cpp b/Core/GameEngine/Source/GameNetwork/NetCommandList.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandList.cpp
rename to Core/GameEngine/Source/GameNetwork/NetCommandList.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandMsg.cpp b/Core/GameEngine/Source/GameNetwork/NetCommandMsg.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandMsg.cpp
rename to Core/GameEngine/Source/GameNetwork/NetCommandMsg.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandRef.cpp b/Core/GameEngine/Source/GameNetwork/NetCommandRef.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandRef.cpp
rename to Core/GameEngine/Source/GameNetwork/NetCommandRef.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandWrapperList.cpp b/Core/GameEngine/Source/GameNetwork/NetCommandWrapperList.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NetCommandWrapperList.cpp
rename to Core/GameEngine/Source/GameNetwork/NetCommandWrapperList.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetMessageStream.cpp b/Core/GameEngine/Source/GameNetwork/NetMessageStream.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NetMessageStream.cpp
rename to Core/GameEngine/Source/GameNetwork/NetMessageStream.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetPacket.cpp b/Core/GameEngine/Source/GameNetwork/NetPacket.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NetPacket.cpp
rename to Core/GameEngine/Source/GameNetwork/NetPacket.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/Network.cpp b/Core/GameEngine/Source/GameNetwork/Network.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/Network.cpp
rename to Core/GameEngine/Source/GameNetwork/Network.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/NetworkUtil.cpp b/Core/GameEngine/Source/GameNetwork/NetworkUtil.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/NetworkUtil.cpp
rename to Core/GameEngine/Source/GameNetwork/NetworkUtil.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/Transport.cpp b/Core/GameEngine/Source/GameNetwork/Transport.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/Transport.cpp
rename to Core/GameEngine/Source/GameNetwork/Transport.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/User.cpp b/Core/GameEngine/Source/GameNetwork/User.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/User.cpp
rename to Core/GameEngine/Source/GameNetwork/User.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/WOLBrowser/WebBrowser.cpp b/Core/GameEngine/Source/GameNetwork/WOLBrowser/WebBrowser.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/WOLBrowser/WebBrowser.cpp
rename to Core/GameEngine/Source/GameNetwork/WOLBrowser/WebBrowser.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/udp.cpp b/Core/GameEngine/Source/GameNetwork/udp.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameNetwork/udp.cpp
rename to Core/GameEngine/Source/GameNetwork/udp.cpp
diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt
index 64236aa60d3..a9395f9b124 100644
--- a/Generals/Code/GameEngine/CMakeLists.txt
+++ b/Generals/Code/GameEngine/CMakeLists.txt
@@ -457,60 +457,60 @@ set(GAMEENGINE_SRC
Include/GameLogic/WeaponSetFlags.h
Include/GameLogic/WeaponSetType.h
Include/GameLogic/WeaponStatus.h
- Include/GameNetwork/Connection.h
- Include/GameNetwork/ConnectionManager.h
- Include/GameNetwork/DisconnectManager.h
- Include/GameNetwork/DownloadManager.h
- Include/GameNetwork/FileTransfer.h
- Include/GameNetwork/FirewallHelper.h
- Include/GameNetwork/FrameData.h
- Include/GameNetwork/FrameDataManager.h
- Include/GameNetwork/FrameMetrics.h
- Include/GameNetwork/GameInfo.h
- Include/GameNetwork/GameMessageParser.h
+# Include/GameNetwork/Connection.h
+# Include/GameNetwork/ConnectionManager.h
+# Include/GameNetwork/DisconnectManager.h
+# Include/GameNetwork/DownloadManager.h
+# Include/GameNetwork/FileTransfer.h
+# Include/GameNetwork/FirewallHelper.h
+# Include/GameNetwork/FrameData.h
+# Include/GameNetwork/FrameDataManager.h
+# Include/GameNetwork/FrameMetrics.h
+# Include/GameNetwork/GameInfo.h
+# Include/GameNetwork/GameMessageParser.h
Include/GameNetwork/GameSpy.h
- Include/GameNetwork/GameSpy/BuddyDefs.h
- Include/GameNetwork/GameSpy/BuddyThread.h
- Include/GameNetwork/GameSpy/GameResultsThread.h
- Include/GameNetwork/GameSpy/GSConfig.h
- Include/GameNetwork/GameSpy/LadderDefs.h
- Include/GameNetwork/GameSpy/LobbyUtils.h
- Include/GameNetwork/GameSpy/MainMenuUtils.h
- Include/GameNetwork/GameSpy/PeerDefs.h
- Include/GameNetwork/GameSpy/PeerDefsImplementation.h
- Include/GameNetwork/GameSpy/PeerThread.h
- Include/GameNetwork/GameSpy/PersistentStorageDefs.h
- Include/GameNetwork/GameSpy/PersistentStorageThread.h
- Include/GameNetwork/GameSpy/PingThread.h
- Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
- Include/GameNetwork/GameSpy/ThreadUtils.h
+# Include/GameNetwork/GameSpy/BuddyDefs.h
+# Include/GameNetwork/GameSpy/BuddyThread.h
+# Include/GameNetwork/GameSpy/GameResultsThread.h
+# Include/GameNetwork/GameSpy/GSConfig.h
+# Include/GameNetwork/GameSpy/LadderDefs.h
+# Include/GameNetwork/GameSpy/LobbyUtils.h
+# Include/GameNetwork/GameSpy/MainMenuUtils.h
+# Include/GameNetwork/GameSpy/PeerDefs.h
+# Include/GameNetwork/GameSpy/PeerDefsImplementation.h
+# Include/GameNetwork/GameSpy/PeerThread.h
+# Include/GameNetwork/GameSpy/PersistentStorageDefs.h
+# Include/GameNetwork/GameSpy/PersistentStorageThread.h
+# Include/GameNetwork/GameSpy/PingThread.h
+# Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
+# Include/GameNetwork/GameSpy/ThreadUtils.h
Include/GameNetwork/GameSpyChat.h
Include/GameNetwork/GameSpyGameInfo.h
Include/GameNetwork/GameSpyGP.h
- Include/GameNetwork/GameSpyOverlay.h
+# Include/GameNetwork/GameSpyOverlay.h
Include/GameNetwork/GameSpyPersistentStorage.h
- Include/GameNetwork/GameSpyThread.h
+# Include/GameNetwork/GameSpyThread.h
Include/GameNetwork/GUIUtil.h
- Include/GameNetwork/IPEnumeration.h
- Include/GameNetwork/LANAPI.h
- Include/GameNetwork/LANAPICallbacks.h
- Include/GameNetwork/LANGameInfo.h
- Include/GameNetwork/LANPlayer.h
- Include/GameNetwork/NAT.h
- Include/GameNetwork/NetCommandList.h
- Include/GameNetwork/NetCommandMsg.h
- Include/GameNetwork/NetCommandRef.h
- Include/GameNetwork/NetCommandWrapperList.h
- Include/GameNetwork/NetPacket.h
- Include/GameNetwork/NetworkDefs.h
- Include/GameNetwork/NetworkInterface.h
- Include/GameNetwork/networkutil.h
- Include/GameNetwork/RankPointValue.h
- Include/GameNetwork/Transport.h
- Include/GameNetwork/udp.h
- Include/GameNetwork/User.h
- Include/GameNetwork/WOLBrowser/FEBDispatch.h
- Include/GameNetwork/WOLBrowser/WebBrowser.h
+# Include/GameNetwork/IPEnumeration.h
+# Include/GameNetwork/LANAPI.h
+# Include/GameNetwork/LANAPICallbacks.h
+# Include/GameNetwork/LANGameInfo.h
+# Include/GameNetwork/LANPlayer.h
+# Include/GameNetwork/NAT.h
+# Include/GameNetwork/NetCommandList.h
+# Include/GameNetwork/NetCommandMsg.h
+# Include/GameNetwork/NetCommandRef.h
+# Include/GameNetwork/NetCommandWrapperList.h
+# Include/GameNetwork/NetPacket.h
+# Include/GameNetwork/NetworkDefs.h
+# Include/GameNetwork/NetworkInterface.h
+# Include/GameNetwork/networkutil.h
+# Include/GameNetwork/RankPointValue.h
+# Include/GameNetwork/Transport.h
+# Include/GameNetwork/udp.h
+# Include/GameNetwork/User.h
+# Include/GameNetwork/WOLBrowser/FEBDispatch.h
+# Include/GameNetwork/WOLBrowser/WebBrowser.h
Include/Precompiled/PreRTS.h
# Source/Common/Audio/AudioEventRTS.cpp
# Source/Common/Audio/AudioRequest.cpp
@@ -1005,55 +1005,55 @@ set(GAMEENGINE_SRC
Source/GameLogic/System/GameLogic.cpp
Source/GameLogic/System/GameLogicDispatch.cpp
Source/GameLogic/System/RankInfo.cpp
- Source/GameNetwork/Connection.cpp
- Source/GameNetwork/ConnectionManager.cpp
- Source/GameNetwork/DisconnectManager.cpp
- Source/GameNetwork/DownloadManager.cpp
- Source/GameNetwork/FileTransfer.cpp
- Source/GameNetwork/FirewallHelper.cpp
- Source/GameNetwork/FrameData.cpp
- Source/GameNetwork/FrameDataManager.cpp
- Source/GameNetwork/FrameMetrics.cpp
- Source/GameNetwork/GameInfo.cpp
- Source/GameNetwork/GameMessageParser.cpp
+# Source/GameNetwork/Connection.cpp
+# Source/GameNetwork/ConnectionManager.cpp
+# Source/GameNetwork/DisconnectManager.cpp
+# Source/GameNetwork/DownloadManager.cpp
+# Source/GameNetwork/FileTransfer.cpp
+# Source/GameNetwork/FirewallHelper.cpp
+# Source/GameNetwork/FrameData.cpp
+# Source/GameNetwork/FrameDataManager.cpp
+# Source/GameNetwork/FrameMetrics.cpp
+# Source/GameNetwork/GameInfo.cpp
+# Source/GameNetwork/GameMessageParser.cpp
#Source/GameNetwork/GameSpy.cpp
#Source/GameNetwork/GameSpyChat.cpp
#Source/GameNetwork/GameSpyGameInfo.cpp
#Source/GameNetwork/GameSpyGP.cpp
#Source/GameNetwork/GameSpyPersistentStorage.cpp
- Source/GameNetwork/GameSpy/Chat.cpp
- Source/GameNetwork/GameSpy/GSConfig.cpp
- Source/GameNetwork/GameSpy/LadderDefs.cpp
- Source/GameNetwork/GameSpy/LobbyUtils.cpp
- Source/GameNetwork/GameSpy/MainMenuUtils.cpp
- Source/GameNetwork/GameSpy/PeerDefs.cpp
- Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
- Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
- Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
- Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
- Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
- Source/GameNetwork/GameSpy/Thread/PingThread.cpp
- Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
- Source/GameNetwork/GameSpyOverlay.cpp
+# Source/GameNetwork/GameSpy/Chat.cpp
+# Source/GameNetwork/GameSpy/GSConfig.cpp
+# Source/GameNetwork/GameSpy/LadderDefs.cpp
+# Source/GameNetwork/GameSpy/LobbyUtils.cpp
+# Source/GameNetwork/GameSpy/MainMenuUtils.cpp
+# Source/GameNetwork/GameSpy/PeerDefs.cpp
+# Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
+# Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
+# Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
+# Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
+# Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
+# Source/GameNetwork/GameSpy/Thread/PingThread.cpp
+# Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
+# Source/GameNetwork/GameSpyOverlay.cpp
Source/GameNetwork/GUIUtil.cpp
- Source/GameNetwork/IPEnumeration.cpp
- Source/GameNetwork/LANAPI.cpp
- Source/GameNetwork/LANAPICallbacks.cpp
- Source/GameNetwork/LANAPIhandlers.cpp
- Source/GameNetwork/LANGameInfo.cpp
- Source/GameNetwork/NAT.cpp
- Source/GameNetwork/NetCommandList.cpp
- Source/GameNetwork/NetCommandMsg.cpp
- Source/GameNetwork/NetCommandRef.cpp
- Source/GameNetwork/NetCommandWrapperList.cpp
- Source/GameNetwork/NetMessageStream.cpp
- Source/GameNetwork/NetPacket.cpp
- Source/GameNetwork/Network.cpp
- Source/GameNetwork/NetworkUtil.cpp
- Source/GameNetwork/Transport.cpp
- Source/GameNetwork/udp.cpp
- Source/GameNetwork/User.cpp
- Source/GameNetwork/WOLBrowser/WebBrowser.cpp
+# Source/GameNetwork/IPEnumeration.cpp
+# Source/GameNetwork/LANAPI.cpp
+# Source/GameNetwork/LANAPICallbacks.cpp
+# Source/GameNetwork/LANAPIhandlers.cpp
+# Source/GameNetwork/LANGameInfo.cpp
+# Source/GameNetwork/NAT.cpp
+# Source/GameNetwork/NetCommandList.cpp
+# Source/GameNetwork/NetCommandMsg.cpp
+# Source/GameNetwork/NetCommandRef.cpp
+# Source/GameNetwork/NetCommandWrapperList.cpp
+# Source/GameNetwork/NetMessageStream.cpp
+# Source/GameNetwork/NetPacket.cpp
+# Source/GameNetwork/Network.cpp
+# Source/GameNetwork/NetworkUtil.cpp
+# Source/GameNetwork/Transport.cpp
+# Source/GameNetwork/udp.cpp
+# Source/GameNetwork/User.cpp
+# Source/GameNetwork/WOLBrowser/WebBrowser.cpp
Source/Precompiled/PreRTS.cpp
)
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/Connection.h b/Generals/Code/GameEngine/Include/GameNetwork/Connection.h
deleted file mode 100644
index 1cd335e367a..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/Connection.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-/**
- * The Connection class handles queues for individual players, one connection per player.
- * Connections are identified by their names (m_name). This should accomodate changing IPs
- * in the face of modem disconnects, NAT irregularities, etc.
- * Messages can be guaranteed or non-guaranteed, sequenced or not.
- *
- *
- * So how this works is this:
- * The connection contains the incoming and outgoing commands to and from the player this
- * connection object represents. The incoming packets are separated into the different frames
- * of execution. This is done for efficiency reasons since we will be keeping track of commands
- * that are to be executed on many different frames, and they will need to be retrieved by the
- * connection manager on a per-frame basis. We don't really care what frame the outgoing
- * commands are executed on as they all need to be sent out right away to ensure that the commands
- * get to their destination in time.
- */
-
-#pragma once
-
-#include "GameNetwork/NetCommandList.h"
-#include "GameNetwork/User.h"
-#include "GameNetwork/Transport.h"
-#include "GameNetwork/NetPacket.h"
-
-#define CONNECTION_LATENCY_HISTORY_LENGTH 200
-
-class Connection : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Connection, "Connection")
-public:
- Connection();
- //~Connection();
-
- void update();
- void init();
- void reset();
-
- UnsignedInt doSend();
- void doRecv();
-
- Bool allCommandsReady(UnsignedInt frame);
- Bool isQueueEmpty();
- void attachTransport(Transport *transport);
- void setUser(User *user);
- User *getUser();
- void setFrameGrouping(time_t frameGrouping);
-
- void sendNetCommandMsg(NetCommandMsg *msg, UnsignedByte relay);
-
- // These two processAck calls do the same thing, just take different types of ACK commands.
- NetCommandRef * processAck(NetAckBothCommandMsg *msg);
- NetCommandRef * processAck(NetAckStage1CommandMsg *msg);
- NetCommandRef * processAck(NetCommandMsg *msg);
- NetCommandRef * processAck(UnsignedShort commandID, UnsignedByte originalPlayerID);
-
- void clearCommandsExceptFrom( Int playerIndex );
-
- void setQuitting( void );
- Bool isQuitting( void ) { return m_isQuitting; }
-
-#if defined(RTS_DEBUG)
- void debugPrintCommands();
-#endif
-
-protected:
- void doRetryMetrics();
-
- Bool m_isQuitting;
- UnsignedInt m_quitTime;
-
- Transport *m_transport;
- User *m_user;
-
- NetCommandList *m_netCommandList;
- time_t m_retryTime; ///< The time between sending retry packets for this connection. Time is in milliseconds.
- Real m_averageLatency; ///< The average time between sending a command and receiving an ACK.
- Real m_latencies[CONNECTION_LATENCY_HISTORY_LENGTH]; ///< List of the last 100 latencies.
-
- time_t m_frameGrouping; ///< The minimum time between packet sends.
- time_t m_lastTimeSent; ///< The time of the last packet send.
- Int m_numRetries; ///< The number of retries for the last second.
- time_t m_retryMetricsTime; ///< The start time of the current retry metrics thing.
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/ConnectionManager.h b/Generals/Code/GameEngine/Include/GameNetwork/ConnectionManager.h
deleted file mode 100644
index 8588a3350b4..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/ConnectionManager.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * The connection manager maintains a collection of Connections to each player. Messages are queued up
- * from here, as well as removed through here.
- */
-
-#pragma once
-
-#include "GameNetwork/Connection.h"
-#include "GameNetwork/NetCommandList.h"
-#include "GameNetwork/Transport.h"
-#include "GameNetwork/FrameDataManager.h"
-#include "GameNetwork/FrameMetrics.h"
-#include "GameNetwork/NetworkDefs.h"
-#include "GameNetwork/DisconnectManager.h"
-
-class GameInfo;
-class NetCommandWrapperList;
-
-typedef std::map FileCommandMap;
-typedef std::map FileMaskMap;
-typedef std::map FileProgressMap;
-
-class ConnectionManager
-{
-public:
- ConnectionManager();
- ~ConnectionManager();
-
- virtual void init(); ///< Initialize this instance.
- virtual void reset(); ///< Take this instance back to the initial state.
- virtual void update(Bool isInGame); ///< Service the Connections being managed by this instance.
-
- // End SubsystemInterface functions
-
- void updateRunAhead(Int oldRunAhead, Int frameRate, Bool didSelfSlug, Int nextExecutionFrame); ///< Update the run ahead value. If we are the current packet router, issue the command.
-
- void attachTransport(Transport *transport);
-
- void parseUserList(const GameInfo *game);
- void sendChat(UnicodeString text, Int playerMask, UnsignedInt executionFrame);
- void sendDisconnectChat(UnicodeString text);
- void sendLocalCommand(NetCommandMsg *msg, UnsignedByte relay = 0xff); ///< Send command to the players specified in the relay, goes through packet router.
- void sendLocalCommandDirect(NetCommandMsg *msg, UnsignedByte relay); ///< Send command directly to the players specified, doesn't go through packet router.
- void sendLocalGameMessage(GameMessage *msg, UnsignedInt frame);
- void sendCommand(NetCommandMsg *msg);
- Bool allCommandsReady(UnsignedInt frame, Bool justTesting = FALSE);
- void handleAllCommandsReady(void);
- NetCommandList *getFrameCommandList(UnsignedInt frame);
-// void AddConnection(User *user, UnsignedInt slot);
- void determineRouterFallbackPlan();
- void zeroFrames(UnsignedInt startingFrame, UnsignedInt numFrames);
- void destroyGameMessages();
-// void createConnections(UnsignedInt numberOfPlayers, UnsignedInt localSlot);
- void setLocalAddress(UnsignedInt ip, UnsignedInt port);
- void initTransport();
- void processFrameTick(UnsignedInt frame);
- void handleLocalPlayerLeaving(UnsignedInt frame);
-
- void sendFile(AsciiString path, UnsignedByte playerMask, UnsignedShort commandID);
- UnsignedShort sendFileAnnounce(AsciiString path, UnsignedByte playerMask);
- Int getFileTransferProgress(Int playerID, AsciiString path);
- Bool areAllQueuesEmpty(void);
-
- UnsignedInt getLocalPlayerID();
- UnicodeString getPlayerName(Int playerNum);
- Int getNumPlayers();
-
- UnsignedInt getPacketRouterFallbackSlot(Int packetRouterNumber); ///< Returns the slot of the given packet router number in the fallback plan.
- UnsignedInt getPacketRouterSlot(); ///< Returns the current packet router's slot.
- PlayerLeaveCode disconnectPlayer(Int slot); ///< Disconnect this player immediately. This should only be called by the disconnect manager.
- void disconnectLocalPlayer(); ///< Does whatever is necessary to get TheNetwork to realize that it should be leaving the game now.
- void quitGame(); ///< Disconnect from the game RIGHT NOW!! Tell everyone else we are disconnecting.
-
- void voteForPlayerDisconnect(Int slot); ///< Register a vote for a player to be disconnected.
-
- void resendPendingCommands(); ///< Resend the pending commands to the packet router.
-
- void setFrameGrouping(time_t frameGrouping); ///< Set the number of frames that are grouped together into packets.
-
- PlayerLeaveCode processPlayerLeave(NetPlayerLeaveCommandMsg *msg);
- Bool canILeave(); ///< Returns true if the local player is allowed to leave.
-
- // Bandwidth metrics
- Real getIncomingBytesPerSecond( void );
- Real getIncomingPacketsPerSecond( void );
- Real getOutgoingBytesPerSecond( void );
- Real getOutgoingPacketsPerSecond( void );
- Real getUnknownBytesPerSecond( void );
- Real getUnknownPacketsPerSecond( void );
- UnsignedInt getPacketArrivalCushion( void );
-
- UnsignedInt getMinimumCushion();
-
- void flushConnections();
-
- void processChat(NetChatCommandMsg *msg); // this actually needs to be public because it is frame-synchronized
-
- void updateLoadProgress( Int progress );
- void loadProgressComplete( void );
- void sendTimeOutGameStart( void );
-
- Bool isPacketRouter( void );
-
- Bool isPlayerConnected( Int playerID );
-
- void notifyOthersOfCurrentFrame(Int frame);
- void sendFrameDataToPlayer(UnsignedInt playerID, UnsignedInt startingFrame);
- void sendSingleFrameToPlayer(UnsignedInt playerID, UnsignedInt frame);
- void notifyOthersOfNewFrame(UnsignedInt frame);
-
- UnsignedInt getNextPacketRouterSlot(UnsignedInt playerID); ///< returns the packet router player that comes after the given player.
-
- Int getAverageFPS( void );
- Int getSlotAverageFPS(Int slot);
-
-#if defined(RTS_DEBUG)
- void debugPrintConnectionCommands();
-#endif
-
- // For disconnect blame assignment
- UnsignedInt getPingFrame();
- Int getPingsSent();
- Int getPingsRecieved();
-
-private:
- void doRelay();
- void doKeepAlive();
- void sendRemoteCommand(NetCommandRef *msg);
- void ackCommand(NetCommandRef *ref, UnsignedInt localSlot);
-
- Bool processNetCommand(NetCommandRef *ref);
- void processAckStage1(NetCommandMsg *msg);
- void processAckStage2(NetCommandMsg *msg);
- void processAck(NetCommandMsg *msg);
- void processFrameInfo(NetFrameCommandMsg *msg);
- void processRunAheadMetrics(NetRunAheadMetricsCommandMsg *msg);
- void processDisconnectChat(NetDisconnectChatCommandMsg *msg);
- void processProgress( NetProgressCommandMsg *msg );
- void processLoadComplete( NetCommandMsg *msg );
- void processTimeOutGameStart( NetCommandMsg *msg );
- void processWrapper(NetCommandRef *ref);
- void processFrameResendRequest(NetFrameResendRequestCommandMsg *msg);
-
- void processFile(NetFileCommandMsg *ref);
- void processFileAnnounce(NetFileAnnounceCommandMsg *ref);
- void processFileProgress(NetFileProgressCommandMsg *ref);
-
- // void doPerFrameMetrics(UnsignedInt frame);
- void getMinimumFps(Int &minFps, Int &minFpsPlayer); ///< Returns the smallest FPS in the m_fpsAverages list.
- Real getMaximumLatency(); ///< Returns the highest average latency between players.
-
- void requestFrameDataResend(Int playerID, UnsignedInt frame); ///< request of this player that he send the specified frame's data.
-
- // The connections are set up like the slot list. The connection corresponding to the local
- // player's position in the slot list will be NULL. Connections corresponding to slots that
- // do not have a player will also be NULL.
- Connection *m_connections[MAX_SLOTS];
-
- Transport *m_transport;
- UnsignedInt m_localSlot;
- UnsignedInt m_packetRouterSlot;
- UnsignedInt m_packetRouterFallback[MAX_SLOTS];
- UnsignedInt m_localAddr;
- UnsignedInt m_localPort;
- User* m_localUser;
-
- DisconnectManager *m_disconnectManager; ///< Controls the disconnect dialog.
-
- FrameDataManager *m_frameData[MAX_SLOTS];
-
- NetCommandList *m_pendingCommands;
- NetCommandList *m_relayedCommands;
-
- FrameMetrics m_frameMetrics;
-
- NetCommandWrapperList *m_netCommandWrapperList;
-
- // These variables are used to keep track of the other players' average fps and latency.
- // yup.
- Real m_latencyAverages[MAX_SLOTS];
- Int m_fpsAverages[MAX_SLOTS];
- Int m_minFpsPlayer;
- Int m_minFps;
- UnsignedInt m_smallestPacketArrivalCushion;
- Bool m_didSelfSlug;
-
- // -----------------------------------------------------------------------------
- FileCommandMap s_fileCommandMap;
- FileMaskMap s_fileRecipientMaskMap;
- FileProgressMap s_fileProgressMap[MAX_SLOTS];
- // -----------------------------------------------------------------------------
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/DisconnectManager.h b/Generals/Code/GameEngine/Include/GameNetwork/DisconnectManager.h
deleted file mode 100644
index 0448566d884..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/DisconnectManager.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "GameNetwork/NetCommandRef.h"
-#include "Lib/BaseType.h"
-//#include "GameNetwork/ConnectionManager.h"
-
-enum DisconnectStateType CPP_11(: Int) {
- DISCONNECTSTATETYPE_SCREENON,
- DISCONNECTSTATETYPE_SCREENOFF
-// DISCONNECTSTATETYPE_WAITINGFORPACKETROUTER
-};
-
-class ConnectionManager;
-
-struct DisconnectVoteStruct {
- Bool vote;
- UnsignedInt frame;
-};
-
-class DisconnectManager
-{
-public:
- DisconnectManager();
- virtual ~DisconnectManager();
-
- void init();
- void update(ConnectionManager *conMgr);
-
- void processDisconnectCommand(NetCommandRef *ref, ConnectionManager *conMgr);
- void allCommandsReady(UnsignedInt frame, ConnectionManager *conMgr, Bool waitForPacketRouter = TRUE);
- void nextFrame(UnsignedInt frame, ConnectionManager *conMgr);
- Bool allowedToContinue(); ///< Allow the next frame to go through?
- void playerHasAdvancedAFrame(Int slot, UnsignedInt frame); ///< this player has advanced to that frame.
-
- void voteForPlayerDisconnect(Int slot, ConnectionManager *conMgr);
-
- // For disconnect blame assignment
- UnsignedInt getPingFrame();
- Int getPingsSent();
- Int getPingsRecieved();
-
-protected:
- void sendKeepAlive(ConnectionManager *conMgr);
- void populateDisconnectScreen(ConnectionManager *conMgr);
- Int translatedSlotPosition(Int slot, Int localSlot);
- Int untranslatedSlotPosition(Int slot, Int localSlot);
- void resetPlayerTimeouts(ConnectionManager *conMgr);
- void resetPlayerTimeout(Int slot);
- void resetPacketRouterTimeout();
- void updateDisconnectStatus(ConnectionManager *conMgr);
- void disconnectPlayer(Int slot, ConnectionManager *conMgr);
- void sendDisconnectCommand(Int slot, ConnectionManager *conMgr);
- void sendVoteCommand(Int slot, ConnectionManager *conMgr);
- void updateWaitForPacketRouter(ConnectionManager *conMgr);
- void recalculatePacketRouterIndex(ConnectionManager *conMgr);
- Bool allOnSameFrame(ConnectionManager *conMgr); ///< returns true if all players are stuck on the same frame.
- Bool isLocalPlayerNextPacketRouter(ConnectionManager *conMgr); ///< returns true if the local player is next in line to be the packet router with all the players that have timed out being taken out of the picture.
- Bool hasPlayerTimedOut(Int slot); ///< returns true if this player has timed out.
- void sendPlayerDestruct(Int slot, ConnectionManager *conMgr); ///< send a destruct player network message.
- Bool isPlayerVotedOut(Int slot, ConnectionManager *conMgr); ///< returns true if this player has been voted out.
- Bool isPlayerInGame(Int slot, ConnectionManager *conMgr); ///< returns true if the player has neither timed out or been voted out.
- UnsignedInt getMaxDisconnectFrame(); ///< returns the highest frame that people have got to.
- Int countVotesForPlayer(Int slot); ///< return the number of disconnect votes a player has.
- void resetPlayersVotes(Int playerID, UnsignedInt frame, ConnectionManager *conMgr); ///< reset the votes for this player.
-
- void turnOnScreen(ConnectionManager *conMgr); ///< This gets called when the disconnect screen is first turned on.
-
- void processDisconnectKeepAlive(NetCommandMsg *msg, ConnectionManager *conMgr);
- void processDisconnectPlayer(NetCommandMsg *msg, ConnectionManager *conMgr);
- void processPacketRouterQuery(NetCommandMsg *msg, ConnectionManager *conMgr);
- void processPacketRouterAck(NetCommandMsg *msg, ConnectionManager *conMgr);
- void processDisconnectVote(NetCommandMsg *msg, ConnectionManager *conMgr);
- void processDisconnectFrame(NetCommandMsg *msg, ConnectionManager *conMgr);
- void processDisconnectScreenOff(NetCommandMsg *msg, ConnectionManager *conMgr);
-
- void applyDisconnectVote(Int slot, UnsignedInt frame, Int castingSlot, ConnectionManager *conMgr);
-
- UnsignedInt m_lastFrame;
- time_t m_lastFrameTime;
- DisconnectStateType m_disconnectState;
-
- UnsignedInt m_packetRouterFallback[MAX_SLOTS];
- UnsignedInt m_currentPacketRouterIndex;
-
- time_t m_lastKeepAliveSendTime;
-
- time_t m_playerTimeouts[MAX_SLOTS - 1];
- time_t m_packetRouterTimeout;
-
- DisconnectVoteStruct m_playerVotes[MAX_SLOTS][MAX_SLOTS];
-// Bool m_myVotes[MAX_SLOTS - 1];
-
- UnsignedInt m_disconnectFrames[MAX_SLOTS];
- Bool m_disconnectFramesReceived[MAX_SLOTS];
- Bool m_haveNotifiedOtherPlayersOfCurrentFrame;
-
- time_t m_timeOfDisconnectScreenOn;
- Int m_pingsSent;
- Int m_pingsRecieved;
- UnsignedInt m_pingFrame;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/DownloadManager.h b/Generals/Code/GameEngine/Include/GameNetwork/DownloadManager.h
deleted file mode 100644
index 25dc35b13b4..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/DownloadManager.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: DownloadManager.h //////////////////////////////////////////////////////
-// Generals download class definitions
-// Author: Matthew D. Campbell, July 2002
-
-#pragma once
-
-#include "WWDownload/downloaddefs.h"
-#include "WWDownload/Download.h"
-
-class CDownload;
-class QueuedDownload
-{
-public:
- AsciiString server;
- AsciiString userName;
- AsciiString password;
- AsciiString file;
- AsciiString localFile;
- AsciiString regKey;
- Bool tryResume;
-};
-
-/////////////////////////////////////////////////////////////////////////////
-// DownloadManager
-
-class DownloadManager : public IDownload
-{
-public:
- DownloadManager();
- virtual ~DownloadManager();
-
-public:
- void init( void );
- HRESULT update( void );
- void reset( void );
-
- virtual HRESULT OnError( Int error );
- virtual HRESULT OnEnd();
- virtual HRESULT OnQueryResume();
- virtual HRESULT OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft );
- virtual HRESULT OnStatusUpdate( Int status );
-
- virtual HRESULT downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume );
- AsciiString getLastLocalFile( void );
-
- Bool isDone( void ) { return m_sawEnd || m_wasError; }
- Bool isOk( void ) { return m_sawEnd; }
- Bool wasError( void ) { return m_wasError; }
-
- UnicodeString getStatusString( void ) { return m_statusString; }
- UnicodeString getErrorString( void ) { return m_errorString; }
-
- void queueFileForDownload( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume );
- Bool isFileQueuedForDownload( void ) { return !m_queuedDownloads.empty(); }
- HRESULT downloadNextQueuedFile( void );
-
-private:
- Bool m_winsockInit;
- CDownload *m_download;
- Bool m_wasError;
- Bool m_sawEnd;
- UnicodeString m_errorString;
- UnicodeString m_statusString;
-
-protected:
- std::list m_queuedDownloads;
-};
-
-extern DownloadManager *TheDownloadManager;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/FileTransfer.h b/Generals/Code/GameEngine/Include/GameNetwork/FileTransfer.h
deleted file mode 100644
index e1ca2d1e272..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/FileTransfer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: FileTransfer.h
-// Author: Matthew D. Campbell, December 2002
-// Description: File Transfer wrapper using TheNetwork
-///////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-class GameInfo;
-
-// Convenience functions
-AsciiString GetBasePathFromPath( AsciiString path );
-AsciiString GetFileFromPath( AsciiString path );
-AsciiString GetExtensionFromFile( AsciiString fname );
-AsciiString GetBaseFileFromFile( AsciiString fname );
-AsciiString GetPreviewFromMap( AsciiString path );
-AsciiString GetINIFromMap( AsciiString path );
-AsciiString GetStrFileFromMap( AsciiString path );
-AsciiString GetSoloINIFromMap( AsciiString path );
-AsciiString GetAssetUsageFromMap( AsciiString path );
-AsciiString GetReadmeFromMap( AsciiString path );
-
-// The meat of file (map) transfers
-Bool DoAnyMapTransfers(GameInfo *game);
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/FirewallHelper.h b/Generals/Code/GameEngine/Include/GameNetwork/FirewallHelper.h
deleted file mode 100644
index 70a9cfcab2e..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/FirewallHelper.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-/***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * $Archive:: /RedAlert2/NAT.cpp $*
- * *
- * $Author:: Steve_t $*
- * *
- * $Modtime:: 3/15/01 12:00PM $*
- * *
- * $Revision:: 1 $*
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-#pragma once
-
-class UDP;
-
-#define NUM_TEST_PORTS 4
-#define MAX_SPARE_SOCKETS 8
-
-/*
-**
-** Class to help in dealing with firewalls.
-**
-**
-**
-*/
-
-struct SpareSocketStruct {
- UDP *udp;
- UnsignedShort port;
-};
-
-enum FirewallDetectionState CPP_11(: Int) {
- DETECTIONSTATE_IDLE,
- DETECTIONSTATE_BEGIN,
- DETECTIONSTATE_TEST1,
- DETECTIONSTATE_TEST2,
- DETECTIONSTATE_TEST3,
- DETECTIONSTATE_TEST3_WAITFORRESPONSES,
- DETECTIONSTATE_TEST4_1,
- DETECTIONSTATE_TEST4_2,
- DETECTIONSTATE_TEST5,
- DETECTIONSTATE_DONE
-};
-
-#pragma pack(push, 1)
-
-// size = 16 bytes
-struct ManglerData {
- unsigned int CRC;
- unsigned short magic;
- unsigned short PacketID;
- unsigned short MyMangledPortNumber;
- unsigned short OriginalPortNumber;
- unsigned char MyMangledAddress[4];
- unsigned char NetCommandType;
- unsigned char BlitzMe;
- unsigned short Padding;
-};
-
-// size = TransportMessageHeader + ManglerData + 10 bytes = 26 bytes
-struct ManglerMessage {
- ManglerData data;
- int length;
- unsigned int ip;
- unsigned short port;
-};
-
-#pragma pack(pop)
-
-static const Int MAX_NUM_MANGLERS = 4;
-static const UnsignedShort MANGLER_PORT = 4321;
-
-class FirewallHelperClass {
-
- public:
-
- /*
- ** Enumeration of firewall behaviors we can detect.
- **
- ** It is assumed that all port mangling firewalls change the mangled source port in response to
- ** an application source port change.
- */
- typedef enum tFirewallBehaviorType {
-
- FIREWALL_MIN = 0,
-
- /*
- ** Just used as an initialiser.
- */
- FIREWALL_TYPE_UNKNOWN = 0,
-
- /*
- ** This is a simple, non-port translating firewall, or there is no firewall at all.
- */
- FIREWALL_TYPE_SIMPLE = 1,
-
- /*
- ** This is a firewall/NAT with port mangling but it's pretty dumb - it uses the same mangled
- ** source port regardless of the destination address.
- */
- FIREWALL_TYPE_DUMB_MANGLING = 2,
-
- /*
- ** This is a smarter firewall/NAT with port mangling that uses different mangled source ports
- ** for different destination IPs.
- */
- FIREWALL_TYPE_SMART_MANGLING = 4,
-
- /*
- ** This is a firewall that exhibits the bug as seen in the Netgear firewalls. A previously good
- ** source port mapping will change in response to unsolicited traffic from a known IP.
- */
- FIREWALL_TYPE_NETGEAR_BUG = 8,
-
- /*
- ** This firewall has a simple absolute offset port allocation scheme.
- */
- FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION = 16,
-
- /*
- ** This firewall has a relative offset port allocation scheme. For these firewalls, we have to
- ** subtract the actual source port from the mangled source port to discover the allocation scheme.
- ** The mangled port number is based in part on the original source port number.
- */
- FIREWALL_TYPE_RELATIVE_PORT_ALLOCATION = 32,
-
- /*
- ** This firewall mangles source ports differently depending on the destination port.
- */
- FIREWALL_TYPE_DESTINATION_PORT_DELTA = 64,
-
- FIREWALL_MAX = 128
-
- } FirewallBehaviorType;
-
-
-
- FirewallHelperClass(void);
- virtual ~FirewallHelperClass(void);
- Bool detectFirewall(void);
- UnsignedShort getRawFirewallBehavior(void) {return((UnsignedShort)m_behavior);}
- Short getSourcePortAllocationDelta(void);
- Int getFirewallHardness(FirewallBehaviorType behavior);
- Int getFirewallRetries(FirewallBehaviorType behavior);
- void setSourcePortPoolStart(Int port) {m_sourcePortPool = port;};
- Int getSourcePortPool(void) {return(m_sourcePortPool);};
- void readFirewallBehavior(void);
- void reset(void);
- Bool behaviorDetectionUpdate(void);
-
- FirewallBehaviorType getFirewallBehavior(void);
- void writeFirewallBehavior(void);
-
- void flagNeedToRefresh(Bool flag);
-
- static void getManglerName(Int manglerIndex, Char *nameBuf);
- Bool sendToManglerFromPort(UnsignedInt address, UnsignedShort port, UnsignedShort packetID, Bool blitzme = FALSE);
- UnsignedShort getManglerResponse(UnsignedShort packetID, Int time = 0);
- Bool openSpareSocket(UnsignedShort port);
- void closeSpareSocket(UnsignedShort port);
- void closeAllSpareSockets();
- UnsignedShort getNextTemporarySourcePort(Int skip);
-
- Bool detectionBeginUpdate(void);
- Bool detectionTest1Update(void);
- Bool detectionTest2Update(void);
- Bool detectionTest3Update(void);
- Bool detectionTest3WaitForResponsesUpdate(void);
- Bool detectionTest4Stage1Update(void);
- Bool detectionTest4Stage2Update(void);
- Bool detectionTest5Update(void);
-
-
- /*
- ** Behavior query functions.
- */
- inline Bool isNAT(void) {
- if (m_behavior == FIREWALL_TYPE_UNKNOWN || (m_behavior & FIREWALL_TYPE_SIMPLE) != 0) {
- return(FALSE);
- }
- return(TRUE);
- };
-
- inline Bool isNAT(FirewallBehaviorType behavior) {
- if (behavior == FIREWALL_TYPE_UNKNOWN || (behavior & FIREWALL_TYPE_SIMPLE) != 0) {
- return(FALSE);
- }
- return(TRUE);
- };
-
- inline Bool isNetgear(FirewallBehaviorType behavior) {
- if ((behavior & FIREWALL_TYPE_NETGEAR_BUG) != 0) {
- return(TRUE);
- }
- return(FALSE);
- };
-
- inline Bool isNetgear(void) {
- if ((m_behavior & FIREWALL_TYPE_NETGEAR_BUG) != 0) {
- return(TRUE);
- }
- return(FALSE);
- };
-
-
-
- private:
-
- Int getNATPortAllocationScheme(Int numPorts, UnsignedShort *originalPorts, UnsignedShort *mangledPorts, Bool &relativeDelta, Bool &looksGood);
- void detectFirewallBehavior(/*Bool &canRecord*/);
- Bool getReferencePort(void);
-
- SpareSocketStruct * findSpareSocketByPort(UnsignedShort port);
- ManglerMessage * findEmptyMessage();
-
- void byteAdjust(ManglerData *data);
-
- /*
- ** How does our firewall behave?
- */
- FirewallBehaviorType m_behavior;
-
- /*
- ** How did the firewall behave the last time we ran the game.
- */
- FirewallBehaviorType m_lastBehavior;
-
- /*
- ** What is the delta in our firewalls NAT port allocation scheme.
- */
- Int m_sourcePortAllocationDelta;
-
- /*
- ** What was the delta the last time we ran?
- */
- Int m_lastSourcePortAllocationDelta;
-
- /*
- ** Source ports used only to discover port allocation patterns.
- ** Needs to be static so that previous communications with the manglers
- ** don't affect the current one.
- */
- static Int m_sourcePortPool;
-
- /*
- ** Spare sockets used for detecting mangling and such.
- */
- SpareSocketStruct m_spareSockets[MAX_SPARE_SOCKETS];
-
- UnsignedInt m_manglers[MAX_NUM_MANGLERS];
- Int m_numManglers;
-
- UnsignedShort m_sparePorts[MAX_SPARE_SOCKETS];
- UnsignedShort m_mangledPorts[MAX_SPARE_SOCKETS];
- UnsignedShort m_packetID;
-
- ManglerMessage m_messages[MAX_SPARE_SOCKETS];
-
- FirewallDetectionState m_currentState;
- time_t m_timeoutStart;
- time_t m_timeoutLength;
-
- Int m_numResponses;
- Int m_currentTry;
-};
-
-
-
-extern FirewallHelperClass *TheFirewallHelper;
-FirewallHelperClass * createFirewallHelper();
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/FrameData.h b/Generals/Code/GameEngine/Include/GameNetwork/FrameData.h
deleted file mode 100644
index 51e0428e91a..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/FrameData.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Lib/BaseType.h"
-#include "GameNetwork/NetCommandList.h"
-
-enum FrameDataReturnType CPP_11(: Int) {
- FRAMEDATA_NOTREADY,
- FRAMEDATA_RESEND,
- FRAMEDATA_READY
-};
-
-class FrameData {
-public:
- FrameData();
- ~FrameData();
-
- void init();
- void reset();
- void update();
-
- UnsignedInt getFrame();
- void setFrame(UnsignedInt frame);
- FrameDataReturnType allCommandsReady(Bool debugSpewage);
- NetCommandList * getCommandList();
- void setFrameCommandCount(UnsignedInt totalCommandCount);
- UnsignedInt getFrameCommandCount();
- void addCommand(NetCommandMsg *msg);
- UnsignedInt getCommandCount();
- void zeroFrame();
- void destroyGameMessages();
-
-protected:
- UnsignedInt m_frame;
- UnsignedInt m_frameCommandCount;
- UnsignedInt m_commandCount;
- NetCommandList *m_commandList;
- UnsignedInt m_lastFailedCC;
- UnsignedInt m_lastFailedFrameCC;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/FrameDataManager.h b/Generals/Code/GameEngine/Include/GameNetwork/FrameDataManager.h
deleted file mode 100644
index 2069b496731..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/FrameDataManager.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "GameNetwork/NetworkDefs.h"
-#include "GameNetwork/FrameData.h"
-
-class FrameDataManager : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(FrameDataManager, "FrameDataManager")
-public:
- FrameDataManager(Bool isLocal);
- //virtual ~FrameDataManager();
-
- void init();
- void reset();
- void update();
-
- void addNetCommandMsg(NetCommandMsg *msg);
- void setIsLocal(Bool isLocal);
- FrameDataReturnType allCommandsReady(UnsignedInt frame, Bool debugSpewage);
- NetCommandList * getFrameCommandList(UnsignedInt frame);
- UnsignedInt getCommandCount(UnsignedInt frame);
- void setFrameCommandCount(UnsignedInt frame, UnsignedInt commandCount);
- UnsignedInt getFrameCommandCount(UnsignedInt frame);
- void zeroFrames(UnsignedInt startingFrame, UnsignedInt numFrames);
- void destroyGameMessages();
- void resetFrame(UnsignedInt frame, Bool isAdvancing = TRUE);
- void setQuitFrame(UnsignedInt frame);
- UnsignedInt getQuitFrame();
- Bool getIsQuitting();
-
-protected:
- FrameData *m_frameData;
- Bool m_isLocal;
-
- Bool m_isQuitting;
- UnsignedInt m_quitFrame;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/FrameMetrics.h b/Generals/Code/GameEngine/Include/GameNetwork/FrameMetrics.h
deleted file mode 100644
index 7661f3a16ea..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/FrameMetrics.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-/** FrameMetrics.h */
-
-#pragma once
-
-#include "Lib/BaseType.h"
-#include "GameNetwork/NetworkDefs.h"
-
-class FrameMetrics {
-public:
- FrameMetrics();
- virtual ~FrameMetrics();
-
- void init();
- void reset();
-
- void doPerFrameMetrics(UnsignedInt frame);
- void processLatencyResponse(UnsignedInt frame);
- void addCushion(Int cushion);
-
- Real getAverageLatency();
- Int getAverageFPS();
- Int getMinimumCushion();
-
-protected:
- // These are used for keeping track of parameters to the run ahead equation.
- // frames per second history variables.
- Real *m_fpsList; ///< A record of how many game logic frames per second there were for the last 60 seconds.
- time_t m_lastFpsTimeThing; ///< The time when the last fps entry started being recorded.
- Int m_fpsListIndex; ///< Index into the array of the current fps list entry being measured.
- Real m_averageFps; ///< The current average logic fps, computed just like m_averageLatency below but with the fps numbers.
-
- // round trip time to packet router variables.
- // The lists are indexed off the frame number of the frame info packet they are associated with.
- // The index used should be the frame number mod the array length.
- Real *m_latencyList; ///< A record of the round trip latencies of the frame info packets to the packet router. Values in seconds.
- time_t *m_pendingLatencies; ///< The latencies of frame info packets that are "in the air."
- Real m_averageLatency; ///< The current average latency, this is used to save calculation time.
- ///< When a new latency value is received, the old one is subtracted out and the new
- ///< one is added in.
-
- // packet arrival cushion variables.
- // Keeps track of the cushion for the incoming commands.
- UnsignedInt m_cushionIndex; ///< The next index to use for the cushion list.
- Int m_minimumCushion; ///< The average cushion for the history.
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameInfo.h b/Generals/Code/GameEngine/Include/GameNetwork/GameInfo.h
deleted file mode 100644
index 21aab5bc521..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameInfo.h
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameInfo.h //////////////////////////////////////////////////////
-// Generals game setup information
-// Author: Matthew D. Campbell, December 2001
-
-#pragma once
-
-#include "Common/Snapshot.h"
-#include "Common/Money.h"
-#include "GameNetwork/NetworkDefs.h"
-#include "GameNetwork/FirewallHelper.h"
-
-enum SlotState CPP_11(: Int)
-{
- SLOT_OPEN,
- SLOT_CLOSED,
- SLOT_EASY_AI,
- SLOT_MED_AI,
- SLOT_BRUTAL_AI,
- SLOT_PLAYER
-};
-
-enum
-{
- PLAYERTEMPLATE_RANDOM = -1,
- PLAYERTEMPLATE_OBSERVER = -2,
- PLAYERTEMPLATE_MIN = PLAYERTEMPLATE_OBSERVER
-};
-
-/**
- * GameSlot class - maintains information about the contents of a
- * game slot. This persists throughout the game.
- */
-class GameSlot
-{
-public:
- GameSlot();
- virtual void reset();
-
- void setAccept( void ) { m_isAccepted = true; } ///< Accept the current options
- void unAccept( void ); ///< Unaccept (options changed, etc)
- Bool isAccepted( void ) const { return m_isAccepted; } ///< Non-human slots are always accepted
-
- void setMapAvailability( Bool hasMap ); ///< Set whether the slot has the map
- Bool hasMap( void ) const { return m_hasMap; } ///< Non-human slots always have the map
-
- void setState( SlotState state,
- UnicodeString name = UnicodeString::TheEmptyString,
- UnsignedInt IP = 0); ///< Set the slot's state (human, AI, open, etc)
- SlotState getState( void ) const { return m_state; } ///< Get the slot state
-
- void setColor( Int color ) { m_color = color; }
- Int getColor( void ) const { return m_color; }
-
- void setStartPos( Int startPos ) { m_startPos = startPos; }
- Int getStartPos( void ) const { return m_startPos; }
-
- void setPlayerTemplate( Int playerTemplate )
- { m_playerTemplate = playerTemplate;
- if (playerTemplate <= PLAYERTEMPLATE_MIN)
- m_startPos = -1;
- }
- Int getPlayerTemplate( void ) const { return m_playerTemplate; }
-
- void setTeamNumber( Int teamNumber ) { m_teamNumber = teamNumber; }
- Int getTeamNumber( void ) const { return m_teamNumber; }
-
- inline void setName( UnicodeString name ) { m_name = name; }
- inline UnicodeString getName( void ) const { return m_name; }
-
- inline void setIP( UnsignedInt IP ) { m_IP = IP; }
- inline UnsignedInt getIP( void ) const { return m_IP; }
-
- inline void setPort( UnsignedShort port ) { m_port = port; }
- inline UnsignedShort getPort( void ) const { return m_port; }
-
- inline void setNATBehavior( FirewallHelperClass::FirewallBehaviorType NATBehavior) { m_NATBehavior = NATBehavior; }
- inline FirewallHelperClass::FirewallBehaviorType getNATBehavior() const { return m_NATBehavior; }
-
- void saveOffOriginalInfo( void );
- inline Int getOriginalPlayerTemplate( void ) const { return m_origPlayerTemplate; }
- inline Int getOriginalColor( void ) const { return m_origColor; }
- inline Int getOriginalStartPos( void ) const { return m_origStartPos; }
- Int getApparentPlayerTemplate( void ) const;
- Int getApparentColor( void ) const;
- Int getApparentStartPos( void ) const;
- UnicodeString getApparentPlayerTemplateDisplayName( void ) const;
-
- // Various tests
- Bool isHuman( void ) const; ///< Is this slot occupied by a human player?
- Bool isOccupied( void ) const; ///< Is this slot occupied (by a human or an AI)?
- Bool isAI( void ) const; ///< Is this slot occupied by an AI?
- Bool isPlayer( AsciiString userName ) const; ///< Does this slot contain the given user?
- Bool isPlayer( UnicodeString userName ) const; ///< Does this slot contain the given user?
- Bool isPlayer( UnsignedInt ip ) const; ///< Is this slot at this IP?
- Bool isOpen( void ) const;
-
- void setLastFrameInGame( UnsignedInt frame ) { m_lastFrameInGame = frame; }
- void markAsDisconnected( void ) { m_disconnected = TRUE; }
- UnsignedInt lastFrameInGame( void ) const { return m_lastFrameInGame; }
- Bool disconnected( void ) const { return isHuman() && m_disconnected; }
-
- void mute( Bool isMuted ) { m_isMuted = isMuted; }
- Bool isMuted( void ) const { return m_isMuted; }
-protected:
- SlotState m_state;
- Bool m_isAccepted;
- Bool m_hasMap;
- Bool m_isMuted;
- Int m_color; ///< color, or -1 for random
- Int m_startPos; ///< start position, or -1 for random
- Int m_playerTemplate; ///< PlayerTemplate
- Int m_teamNumber; ///< alliance, -1 for none
- Int m_origColor; ///< color, or -1 for random
- Int m_origStartPos; ///< start position, or -1 for random
- Int m_origPlayerTemplate; ///< PlayerTemplate
- UnicodeString m_name; ///< Only valid for human players
- UnsignedInt m_IP; ///< Only valid for human players in LAN/WOL
- UnsignedShort m_port; ///< Only valid for human players in LAN/WOL
- FirewallHelperClass::FirewallBehaviorType m_NATBehavior; ///< The NAT behavior for this slot's player.
- UnsignedInt m_lastFrameInGame; // only valid for human players
- Bool m_disconnected; // only valid for human players
-};
-
-/**
- * GameInfo class - maintains information about the game setup and
- * the contents of its slot list hroughout the game.
- */
-class GameInfo
-{
-public:
- GameInfo();
-
- void init( void );
- virtual void reset( void );
-
- void clearSlotList( void );
-
- Int getNumPlayers( void ) const; ///< How many players (human and AI) are in the game?
- Int getNumNonObserverPlayers( void ) const; ///< How many non-observer players (human and AI) are in the game?
- Int getMaxPlayers( void ) const; ///< How many players (human and AI) can be in the game?
-
- void enterGame( void ); ///< Mark us as having entered the game
- void leaveGame( void ); ///< Mark us as having left the game
- virtual void startGame( Int gameID ); ///< Mark our game as started, and record the game ID
- void endGame( void ); ///< Mark us as out of game
- inline Int getGameID( void ) const; ///< Get the game ID of the current game or the last one if we're not in game
-
- inline void setInGame( void ); ///< set the m_inGame flag
- inline Bool isInGame( void ) const; ///< Are we (in game or in game setup)? As opposed to chatting, matching, etc
- inline Bool isGameInProgress( void ) const; ///< Is the game in progress?
- inline void setGameInProgress( Bool inProgress ); ///< Set whether the game is in progress or not.
- void setSlot( Int slotNum, GameSlot slotInfo ); ///< Set the slot state (human, open, AI, etc)
- GameSlot* getSlot( Int slotNum ); ///< Get the slot
- const GameSlot* getConstSlot( Int slotNum ) const; ///< Get the slot
- virtual Bool amIHost( void ) const; ///< Convenience function - is the local player the game host?
- virtual Int getLocalSlotNum( void ) const; ///< Get the local slot number, or -1 if we're not present
- Int getSlotNum( AsciiString userName ) const; ///< Get the slot number corresponding to a specific user, or -1 if he's not present
-
- // Game options
- void setMap( AsciiString mapName ); ///< Set the map to play on
- void setMapCRC( UnsignedInt mapCRC ); ///< Set the map CRC
- void setMapSize( UnsignedInt mapSize ); ///< Set the map size
- void setMapContentsMask( Int mask ); ///< Set the map contents mask (1=map,2=preview,4=map.ini)
- inline AsciiString getMap( void ) const; ///< Get the game map
- inline UnsignedInt getMapCRC( void ) const; ///< Get the map CRC
- inline UnsignedInt getMapSize( void ) const; ///< Get the map size
- inline Int getMapContentsMask( void ) const; ///< Get the map contents mask
- void setSeed( Int seed ); ///< Set the random seed for the game
- inline Int getSeed( void ) const; ///< Get the game seed
- inline Int getUseStats( void ) const; ///< Does this game count towards gamespy stats?
- inline void setUseStats( Int useStats );
-
- inline UnsignedShort getSuperweaponRestriction( void ) const; ///< Get any optional limits on superweapons
- void setSuperweaponRestriction( UnsignedShort restriction ); ///< Set the optional limits on superweapons
- inline const Money & getStartingCash(void) const;
- void setStartingCash( const Money & startingCash );
-
- void setSlotPointer( Int index, GameSlot *slot ); ///< Set the slot info pointer
-
- void setLocalIP( UnsignedInt ip ) { m_localIP =ip; } ///< Set the local IP
- UnsignedInt getLocalIP( void ) const { return m_localIP; } ///< Get the local IP
-
- Bool isColorTaken(Int colorIdx, Int slotToIgnore = -1 ) const;
- Bool isStartPositionTaken(Int positionIdx, Int slotToIgnore = -1 ) const;
-
- virtual void resetAccepted(void); ///< Reset the accepted flag on all players
- virtual void resetStartSpots(void); ///< reset the start spots for the new map.
- virtual void adjustSlotsForMap(void); ///< adjusts the slots to open and closed depending on the players in the game and the number of players the map can hold.
-
- virtual void closeOpenSlots(void); ///< close all slots that are currently unoccupied.
-
- // CRC checking hack
- void setCRCInterval( Int val ) { m_crcInterval = (val<100)?val:100; }
- inline Int getCRCInterval( void ) const { return m_crcInterval; }
-
- Bool haveWeSurrendered(void) { return m_surrendered; }
- void markAsSurrendered(void) { m_surrendered = TRUE; }
-
- Bool isSkirmish(void); // TRUE if 1 human & 1+ AI are present && !isSandbox()
- Bool isMultiPlayer(void); // TRUE if 2+ human are present
- Bool isSandbox(void); // TRUE if everybody is on the same team
-
- Bool isPlayerPreorder(Int index);
- void markPlayerAsPreorder(Int index);
-
- inline Bool oldFactionsOnly(void) const;
- inline void setOldFactionsOnly( Bool oldFactionsOnly );
-
-protected:
- Int m_preorderMask;
- Int m_crcInterval;
- Bool m_inGame;
- Bool m_inProgress;
- Bool m_surrendered;
- Int m_gameID;
- GameSlot *m_slot[MAX_SLOTS];
-
- UnsignedInt m_localIP;
-
- // Game options
- AsciiString m_mapName;
- UnsignedInt m_mapCRC;
- UnsignedInt m_mapSize;
- Int m_mapMask;
- Int m_seed;
- Int m_useStats;
- Money m_startingCash;
- UnsignedShort m_superweaponRestriction;
- Bool m_oldFactionsOnly; // Only USA, China, GLA -- not USA Air Force General, GLA Toxic General, et al
-};
-
-extern GameInfo *TheGameInfo;
-
-// Inline functions
-Int GameInfo::getGameID( void ) const { return m_gameID; }
-AsciiString GameInfo::getMap( void ) const { return m_mapName; }
-UnsignedInt GameInfo::getMapCRC( void ) const { return m_mapCRC; }
-UnsignedInt GameInfo::getMapSize( void ) const { return m_mapSize; }
-Int GameInfo::getMapContentsMask( void ) const { return m_mapMask; }
-Int GameInfo::getSeed( void ) const { return m_seed; }
-Bool GameInfo::isInGame( void ) const { return m_inGame; }
-void GameInfo::setInGame( void ) { m_inGame = true; }
-Bool GameInfo::isGameInProgress( void ) const { return m_inProgress; }
-void GameInfo::setGameInProgress( Bool inProgress ) { m_inProgress = inProgress; }
-Int GameInfo::getUseStats( void ) const { return m_useStats; }
-void GameInfo::setUseStats( Int useStats ) { m_useStats = useStats; }
-const Money&GameInfo::getStartingCash( void ) const { return m_startingCash; }
-UnsignedShort GameInfo::getSuperweaponRestriction( void ) const { return m_superweaponRestriction; }
-Bool GameInfo::oldFactionsOnly(void) const { return m_oldFactionsOnly; }
-void GameInfo::setOldFactionsOnly( Bool oldFactionsOnly ) { m_oldFactionsOnly = oldFactionsOnly; }
-
-AsciiString GameInfoToAsciiString( const GameInfo *game );
-Bool ParseAsciiStringToGameInfo( GameInfo *game, AsciiString options );
-
-
-/**
- * The SkirmishGameInfo class holds information about the skirmish game and
- * the contents of its slot list.
- */
-
-class SkirmishGameInfo : public GameInfo, public Snapshot
-{
-private:
- GameSlot m_skirmishSlot[MAX_SLOTS];
-
-protected:
- // snapshot methods
- virtual void crc( Xfer *xfer );
- virtual void xfer( Xfer *xfer );
- virtual void loadPostProcess( void );
-
-public:
- SkirmishGameInfo()
- {
- for (Int i = 0; i< MAX_SLOTS; ++i)
- setSlotPointer(i, &m_skirmishSlot[i]);
- }
-};
-
-extern SkirmishGameInfo *TheSkirmishGameInfo;
-extern SkirmishGameInfo *TheChallengeGameInfo;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameMessageParser.h b/Generals/Code/GameEngine/Include/GameNetwork/GameMessageParser.h
deleted file mode 100644
index 25783f27405..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameMessageParser.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/MessageStream.h"
-#include "Common/GameMemory.h"
-
-//----------------------------------------------------------------------------
-class GameMessageParserArgumentType : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessageParserArgumentType, "GameMessageParserArgumentType")
-public:
- GameMessageParserArgumentType(GameMessageArgumentDataType type, Int argCount);
- //virtual ~GameMessageParserArgumentType();
-
- GameMessageParserArgumentType *getNext();
- void setNext(GameMessageParserArgumentType *next);
- Int getArgCount();
- GameMessageArgumentDataType getType();
-
-protected:
- GameMessageParserArgumentType* m_next;
- GameMessageArgumentDataType m_type;
- Int m_argCount;
-};
-
-//----------------------------------------------------------------------------
-inline GameMessageParserArgumentType * GameMessageParserArgumentType::getNext()
-{
- return m_next;
-}
-
-//----------------------------------------------------------------------------
-inline void GameMessageParserArgumentType::setNext(GameMessageParserArgumentType *next)
-{
- m_next = next;
-}
-
-//----------------------------------------------------------------------------
-inline GameMessageArgumentDataType GameMessageParserArgumentType::getType()
-{
- return m_type;
-}
-
-//----------------------------------------------------------------------------
-inline Int GameMessageParserArgumentType::getArgCount()
-{
- return m_argCount;
-}
-
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-class GameMessageParser : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessageParser, "GameMessageParser")
-public:
- GameMessageParser();
- GameMessageParser(GameMessage *msg);
- //virtual ~GameMessageParser();
-
- GameMessageParserArgumentType *getFirstArgumentType();
- void addArgType(GameMessageArgumentDataType type, Int argCount);
- Int getNumTypes();
-
-protected:
- GameMessageParserArgumentType *m_first, *m_last;
- Int m_argTypeCount;
-};
-
-//----------------------------------------------------------------------------
-inline GameMessageParserArgumentType * GameMessageParser::getFirstArgumentType()
-{
- return m_first;
-}
-
-//----------------------------------------------------------------------------
-inline Int GameMessageParser::getNumTypes()
-{
- return m_argTypeCount;
-}
-
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h
deleted file mode 100644
index d9cd0fe2ede..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyDefs.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: BuddyDefs.h //////////////////////////////////////////////////////
-// Generals GameSpy Buddy (GP) definitions
-// Author: Matthew D. Campbell, July 2002
-
-#pragma once
-
-void HandleBuddyResponses(void);
-void PopulateOldBuddyMessages(void);
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h
deleted file mode 100644
index 1aea93930be..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/BuddyThread.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: BuddyThread.h //////////////////////////////////////////////////////
-// Generals GameSpy BuddyList thread class interface
-// Author: Matthew D. Campbell, June 2002
-
-#pragma once
-
-#include "gamespy/gp/gp.h"
-
-#define MAX_BUDDY_CHAT_LEN 128
-
-// this class encapsulates a request for the buddy thread
-class BuddyRequest
-{
-public:
- enum
- {
- BUDDYREQUEST_LOGIN, // attempt to login
- BUDDYREQUEST_RELOGIN, // log in after being disconnected
- BUDDYREQUEST_LOGOUT, // log out if connected
- BUDDYREQUEST_MESSAGE,
- BUDDYREQUEST_LOGINNEW, // attempt to create a new nick and login
- //BUDDYREQUEST_DELETELOGIN,
- BUDDYREQUEST_ADDBUDDY, // add someone to your buddy list
- BUDDYREQUEST_DELBUDDY, // delete someone from your buddy list
- BUDDYREQUEST_OKADD, // allow someone to add you to their buddy list
- BUDDYREQUEST_DENYADD, // don't allow someone to add you to their buddy list
- BUDDYREQUEST_SETSTATUS, // Set our status
- BUDDYREQUEST_DELETEACCT, // Delete our account
- } buddyRequestType;
-
- union
- {
- struct
- {
- GPProfile recipient;
- WideChar text[MAX_BUDDY_CHAT_LEN];
- } message;
-
- struct
- {
- char nick[GP_NICK_LEN];
- char email[GP_EMAIL_LEN];
- char password[GP_PASSWORD_LEN];
- Bool hasFirewall;
- } login;
-
- struct
- {
- GPProfile id;
- WideChar text[MAX_BUDDY_CHAT_LEN];
- } addbuddy;
-
- struct
- {
- GPProfile id;
- } profile;
-
- struct
- {
- GPEnum status;
- char statusString[GP_STATUS_STRING_LEN];
- char locationString[GP_LOCATION_STRING_LEN];
- } status;
-
- } arg;
-};
-
-//-------------------------------------------------------------------------
-
-// this class encapsulates an action the buddy thread wants from the UI
-class BuddyResponse
-{
-public:
- enum
- {
- BUDDYRESPONSE_LOGIN,
- BUDDYRESPONSE_DISCONNECT,
- BUDDYRESPONSE_MESSAGE,
- BUDDYRESPONSE_REQUEST,
- BUDDYRESPONSE_STATUS,
- } buddyResponseType;
-
- GPProfile profile;
- GPResult result;
-
- union
- {
- struct
- {
- UnsignedInt date;
- char nick[GP_NICK_LEN];
- WideChar text[MAX_BUDDY_CHAT_LEN];
- } message;
-
- struct
- {
- char nick[GP_NICK_LEN];
- char email[GP_EMAIL_LEN];
- char countrycode[GP_COUNTRYCODE_LEN];
- WideChar text[GP_REASON_LEN];
- } request;
-
- struct
- {
- //GPResult result;
- GPErrorCode errorCode;
- char errorString[MAX_BUDDY_CHAT_LEN];
- GPEnum fatal;
- } error;
-
- struct
- {
- char nick[GP_NICK_LEN];
- char email[GP_EMAIL_LEN];
- char countrycode[GP_COUNTRYCODE_LEN];
- char location[GP_LOCATION_STRING_LEN];
- GPEnum status;
- char statusString[GP_STATUS_STRING_LEN];
- } status;
- } arg;
-};
-
-//-------------------------------------------------------------------------
-
-// this is the actual message queue used to pass messages between threads
-class GameSpyBuddyMessageQueueInterface
-{
-public:
- virtual ~GameSpyBuddyMessageQueueInterface() {}
- virtual void startThread( void ) = 0;
- virtual void endThread( void ) = 0;
- virtual Bool isThreadRunning( void ) = 0;
- virtual Bool isConnected( void ) = 0;
- virtual Bool isConnecting( void ) = 0;
-
- virtual void addRequest( const BuddyRequest& req ) = 0;
- virtual Bool getRequest( BuddyRequest& req ) = 0;
-
- virtual void addResponse( const BuddyResponse& resp ) = 0;
- virtual Bool getResponse( BuddyResponse& resp ) = 0;
-
- virtual GPProfile getLocalProfileID( void ) = 0;
-
- static GameSpyBuddyMessageQueueInterface* createNewMessageQueue( void );
-};
-
-extern GameSpyBuddyMessageQueueInterface *TheGameSpyBuddyMessageQueue;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h
deleted file mode 100644
index b16659e7759..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GSConfig.h ///////////////////////////////////////////////////////////
-// Author: Matthew D. Campbell, Sept 2002
-// Description: GameSpy online config
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/AsciiString.h"
-#include "Common/STLTypedefs.h"
-
-class GameSpyConfigInterface
-{
-public:
- virtual ~GameSpyConfigInterface() {}
-
- // Pings
- virtual std::list getPingServers(void) = 0;
- virtual Int getNumPingRepetitions(void) = 0;
- virtual Int getPingTimeoutInMs(void) = 0;
- virtual Int getPingCutoffGood( void ) = 0;
- virtual Int getPingCutoffBad( void ) = 0;
-
- // QM
- virtual std::list getQMMaps(void) = 0;
- virtual Int getQMBotID(void) = 0;
- virtual Int getQMChannel(void) = 0;
- virtual void setQMChannel(Int channel) = 0;
-
- // Player Info
- virtual Int getPointsForRank(Int rank) = 0;
- virtual Bool isPlayerVIP(Int id) = 0;
-
- // mangler Info
- virtual Bool getManglerLocation(Int index, AsciiString& host, UnsignedShort& port) = 0;
-
- // Ladder / Any other external parsing
- virtual AsciiString getLeftoverConfig(void) = 0;
-
- // NAT Timeouts
- virtual Int getTimeBetweenRetries() = 0;
- virtual Int getMaxManglerRetries() = 0;
- virtual time_t getRetryInterval() = 0;
- virtual time_t getKeepaliveInterval() = 0;
- virtual time_t getPortTimeout() = 0;
- virtual time_t getRoundTimeout() = 0;
-
- // Custom match
- virtual Bool restrictGamesToLobby() = 0;
-
- static GameSpyConfigInterface* create(AsciiString config);
-};
-
-extern GameSpyConfigInterface *TheGameSpyConfig;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h
deleted file mode 100644
index b9cc6af3b2e..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GameResultsThread.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameResultsThread.h //////////////////////////////////////////////////////
-// Generals game results thread class interface
-// Author: Matthew D. Campbell, August 2002
-
-#pragma once
-
-#include "Common/SubsystemInterface.h"
-
-// this class encapsulates a request for the thread
-class GameResultsRequest
-{
-public:
- std::string hostname;
- UnsignedShort port;
- std::string results;
-};
-
-//-------------------------------------------------------------------------
-
-// this class encapsulates a response from the thread
-class GameResultsResponse
-{
-public:
- std::string hostname;
- UnsignedShort port;
- Bool sentOk;
-};
-
-//-------------------------------------------------------------------------
-
-// this is the actual message queue used to pass messages between threads
-class GameResultsInterface : public SubsystemInterface
-{
-public:
- virtual ~GameResultsInterface() {}
- virtual void startThreads( void ) = 0;
- virtual void endThreads( void ) = 0;
- virtual Bool areThreadsRunning( void ) = 0;
-
- virtual void addRequest( const GameResultsRequest& req ) = 0;
- virtual Bool getRequest( GameResultsRequest& resp ) = 0;
-
- virtual void addResponse( const GameResultsResponse& resp ) = 0;
- virtual Bool getResponse( GameResultsResponse& resp ) = 0;
-
- static GameResultsInterface* createNewGameResultsInterface( void );
-
- virtual Bool areGameResultsBeingSent( void ) = 0;
-};
-
-extern GameResultsInterface *TheGameResultsQueue;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h
deleted file mode 100644
index c9944902c99..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LadderDefs.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: LadderDefs.h //////////////////////////////////////////////////////
-// Generals ladder definitions
-// Author: Matthew D. Campbell, August 2002
-
-#pragma once
-
-#include "Common/UnicodeString.h"
-#include "Common/AsciiString.h"
-#include "Common/STLTypedefs.h"
-
-class GameWindow;
-
-class LadderInfo
-{
-public:
- LadderInfo();
- UnicodeString name;
- UnicodeString description;
- UnicodeString location;
- Int playersPerTeam;
- Int minWins;
- Int maxWins;
- Bool randomMaps;
- Bool randomFactions;
- Bool validQM;
- Bool validCustom;
- std::list validMaps;
- std::list validFactions;
- AsciiString cryptedPassword;
- AsciiString address;
- UnsignedShort port;
- AsciiString homepageURL;
- Bool submitReplay; // with game results
- Int index;
-};
-
-typedef std::list LadderInfoList;
-
-class LadderList
-{
-public:
- LadderList();
- ~LadderList();
-
- const LadderInfo* findLadder( const AsciiString& addr, UnsignedShort port );
- const LadderInfo* findLadderByIndex( Int index ); // doesn't look in local ladders
- const LadderInfoList* getLocalLadders( void );
- const LadderInfoList* getSpecialLadders( void );
- const LadderInfoList* getStandardLadders( void );
-
-private:
- void loadLocalLadders( void );
- void checkLadder( AsciiString fname, Int index );
- LadderInfoList m_localLadders;
- LadderInfoList m_specialLadders;
- LadderInfoList m_standardLadders;
-};
-
-extern LadderList *TheLadderList;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h
deleted file mode 100644
index 805b46dedef..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/LobbyUtils.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: LobbyUtils.h //////////////////////////////////////////////////////
-// Generals lobby utils
-// Author: Matthew D. Campbell, Sept 2002
-
-#pragma once
-
-class GameWindow;
-
-GameWindow *GetGameListBox( void );
-GameWindow *GetGameInfoListBox( void );
-NameKeyType GetGameListBoxID( void );
-NameKeyType GetGameInfoListBoxID( void );
-void GrabWindowInfo( void );
-void ReleaseWindowInfo( void );
-void RefreshGameInfoListBox( GameWindow *mainWin, GameWindow *win );
-void RefreshGameListBoxes( void );
-void ToggleGameListType( void );
-
-void playerTemplateComboBoxTooltip(GameWindow *wndComboBox, WinInstanceData *instData, UnsignedInt mouse);
-void playerTemplateListBoxTooltip(GameWindow *wndListBox, WinInstanceData *instData, UnsignedInt mouse);
-
-enum GameSortType CPP_11(: Int)
-{
- GAMESORT_ALPHA_ASCENDING = 0,
- GAMESORT_ALPHA_DESCENDING,
- GAMESORT_PING_ASCENDING,
- GAMESORT_PING_DESCENDING,
-};
-
-Bool HandleSortButton( NameKeyType sortButton );
-void PopulateLobbyPlayerListbox(void);
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h
deleted file mode 100644
index 84a75eac45d..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/MainMenuUtils.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: MainMenuUtils.h //////////////////////////////////////////////////////
-// Author: Matthew D. Campbell, Sept 2002
-// Description: GameSpy version check, patch download, etc utils
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-void HTTPThinkWrapper( void );
-void StopAsyncDNSCheck( void );
-void StartPatchCheck( void );
-void CancelPatchCheckCallback( void );
-void StartDownloadingPatches( void );
-void HandleCanceledDownload( Bool resetDropDown = TRUE );
-
-#if RTS_GENERALS
-enum OverallStatsPeriod CPP_11(: Int)
-{
- STATS_TODAY = 0,
- STATS_YESTERDAY,
- STATS_ALLTIME,
- STATS_LASTWEEK,
- STATS_MAX
-};
-
-struct OverallStats
-{
- OverallStats();
- Int wins[STATS_MAX];
- Int losses[STATS_MAX];
-};
-#endif
-
-void CheckOverallStats( void );
-#if RTS_GENERALS
-void HandleOverallStats( const OverallStats& USA, const OverallStats& China, const OverallStats& GLA );
-#else
-void HandleOverallStats( const char* szHTTPStats, unsigned len );
-#endif
-
-void CheckNumPlayersOnline( void );
-void HandleNumPlayersOnline( Int numPlayersOnline );
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h
deleted file mode 100644
index 5ed37aa8f72..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefs.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PeerDefs.h //////////////////////////////////////////////////////
-// Generals GameSpy Peer (chat) definitions
-// Author: Matthew D. Campbell, June 2002
-
-#pragma once
-
-#include "gamespy/peer/peer.h"
-#include "gamespy/gp/gp.h"
-
-#include "GameClient/Color.h"
-#include "Common/STLTypedefs.h"
-#include "GameNetwork/GameSpy/StagingRoomGameInfo.h"
-
-class GameWindow;
-class PSPlayerStats;
-
-typedef std::set IgnoreList;
-typedef std::map SavedIgnoreMap;
-
-enum RCItemType CPP_11(: Int)
-{
- ITEM_BUDDY,
- ITEM_REQUEST,
- ITEM_NONBUDDY,
- ITEM_NONE,
-};
-
-class GameSpyRCMenuData
-{
-public:
- AsciiString m_nick;
- GPProfile m_id;
- RCItemType m_itemType;
-};
-
-class BuddyInfo
-{
-public:
- GPProfile m_id;
- AsciiString m_name;
- AsciiString m_email;
- AsciiString m_countryCode;
- GPEnum m_status;
- UnicodeString m_statusString;
- UnicodeString m_locationString;
-};
-typedef std::map BuddyInfoMap;
-
-class BuddyMessage
-{
-public:
- UnsignedInt m_timestamp;
- GPProfile m_senderID;
- AsciiString m_senderNick;
- GPProfile m_recipientID;
- AsciiString m_recipientNick;
- UnicodeString m_message;
-};
-typedef std::list BuddyMessageList;
-
-class GameSpyGroupRoom
-{
-public:
- GameSpyGroupRoom() { m_name = AsciiString::TheEmptyString; m_translatedName = UnicodeString::TheEmptyString; m_groupID = m_numWaiting = m_maxWaiting = m_numGames = m_numPlaying = 0; }
- AsciiString m_name;
- UnicodeString m_translatedName;
- Int m_groupID;
- Int m_numWaiting;
- Int m_maxWaiting;
- Int m_numGames;
- Int m_numPlaying;
-};
-typedef std::map GroupRoomMap;
-
-class Transport;
-class NAT;
-
-typedef std::map StagingRoomMap;
-
-class PlayerInfo
-{
-public:
- PlayerInfo() { m_name = m_locale = AsciiString::TheEmptyString; m_wins = m_losses = m_rankPoints = m_side = m_preorder = m_profileID = m_flags = 0; }
- AsciiString m_name;
- AsciiString m_locale;
- Int m_wins;
- Int m_losses;
- Int m_profileID;
- Int m_flags;
- Int m_rankPoints;
- Int m_side;
- Int m_preorder;
- Bool isIgnored( void );
-};
-struct AsciiComparator
-{
- bool operator()(AsciiString s1, AsciiString s2) const;
-};
-
-
-typedef std::map PlayerInfoMap;
-
-enum GameSpyColors CPP_11(: Int) {
- GSCOLOR_DEFAULT = 0,
- GSCOLOR_CURRENTROOM,
- GSCOLOR_ROOM,
- GSCOLOR_GAME,
- GSCOLOR_GAME_FULL,
- GSCOLOR_GAME_CRCMISMATCH,
- GSCOLOR_PLAYER_NORMAL,
- GSCOLOR_PLAYER_OWNER,
- GSCOLOR_PLAYER_BUDDY,
- GSCOLOR_PLAYER_SELF,
- GSCOLOR_PLAYER_IGNORED,
- GSCOLOR_CHAT_NORMAL,
- GSCOLOR_CHAT_EMOTE,
- GSCOLOR_CHAT_OWNER,
- GSCOLOR_CHAT_OWNER_EMOTE,
- GSCOLOR_CHAT_PRIVATE,
- GSCOLOR_CHAT_PRIVATE_EMOTE,
- GSCOLOR_CHAT_PRIVATE_OWNER,
- GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE,
- GSCOLOR_CHAT_BUDDY,
- GSCOLOR_CHAT_SELF,
- GSCOLOR_ACCEPT_TRUE,
- GSCOLOR_ACCEPT_FALSE,
- GSCOLOR_MAP_SELECTED,
- GSCOLOR_MAP_UNSELECTED,
- GSCOLOR_MOTD,
- GSCOLOR_MOTD_HEADING,
- GSCOLOR_MAX
-};
-
-extern Color GameSpyColor[GSCOLOR_MAX];
-
-enum GameSpyBuddyStatus CPP_11(: Int) {
- BUDDY_OFFLINE,
- BUDDY_ONLINE,
- BUDDY_LOBBY,
- BUDDY_STAGING,
- BUDDY_LOADING,
- BUDDY_PLAYING,
- BUDDY_MATCHING,
-};
-
-// ---------------------------------------------------
-// this class holds info used in the main thread
-class GameSpyInfoInterface
-{
-public:
- virtual ~GameSpyInfoInterface() {};
- virtual void reset( void ) {};
- virtual void clearGroupRoomList( void ) = 0;
- virtual GroupRoomMap* getGroupRoomList( void ) = 0;
- virtual void addGroupRoom( GameSpyGroupRoom room ) = 0;
- virtual Bool gotGroupRoomList( void ) = 0;
- virtual void joinGroupRoom( Int groupID ) = 0;
- virtual void leaveGroupRoom( void ) = 0;
- virtual void joinBestGroupRoom( void ) = 0;
- virtual void setCurrentGroupRoom( Int groupID ) = 0;
- virtual Int getCurrentGroupRoom( void ) = 0;
- virtual void updatePlayerInfo( PlayerInfo pi, AsciiString oldNick = AsciiString::TheEmptyString ) = 0;
- virtual void playerLeftGroupRoom( AsciiString nick ) = 0;
- virtual PlayerInfoMap* getPlayerInfoMap( void ) = 0;
-
- virtual BuddyInfoMap* getBuddyMap( void ) = 0;
- virtual BuddyInfoMap* getBuddyRequestMap( void ) = 0;
- virtual BuddyMessageList* getBuddyMessages( void ) = 0;
- virtual Bool isBuddy( Int id ) = 0;
-
- virtual void setLocalName( AsciiString name ) = 0;
- virtual AsciiString getLocalName( void ) = 0;
- virtual void setLocalProfileID( Int profileID ) = 0;
- virtual Int getLocalProfileID( void ) = 0;
- virtual AsciiString getLocalEmail( void ) = 0;
- virtual void setLocalEmail( AsciiString email ) = 0;
- virtual AsciiString getLocalPassword( void ) = 0;
- virtual void setLocalPassword( AsciiString passwd ) = 0;
- virtual void setLocalBaseName( AsciiString name ) = 0;
- virtual AsciiString getLocalBaseName( void ) = 0;
-
- virtual void setCachedLocalPlayerStats( PSPlayerStats stats ) = 0;
- virtual PSPlayerStats getCachedLocalPlayerStats( void ) = 0;
-
- virtual void clearStagingRoomList( void ) = 0;
- virtual StagingRoomMap* getStagingRoomList( void ) = 0;
- virtual GameSpyStagingRoom* findStagingRoomByID( Int id ) = 0;
- virtual void addStagingRoom( GameSpyStagingRoom room ) = 0;
- virtual void updateStagingRoom( GameSpyStagingRoom room ) = 0;
- virtual void removeStagingRoom( GameSpyStagingRoom room ) = 0;
- virtual Bool hasStagingRoomListChanged( void ) = 0;
- virtual void leaveStagingRoom( void ) = 0;
- virtual void markAsStagingRoomHost( void ) = 0;
- virtual void markAsStagingRoomJoiner( Int game ) = 0;
- virtual void sawFullGameList( void ) = 0;
-
- virtual Bool amIHost( void ) = 0;
- virtual GameSpyStagingRoom* getCurrentStagingRoom( void ) = 0;
- virtual void setGameOptions( void ) = 0;
- virtual Int getCurrentStagingRoomID( void ) = 0;
-
- virtual void setDisallowAsianText( Bool val ) = 0;
- virtual void setDisallowNonAsianText( Bool val ) = 0;
- virtual Bool getDisallowAsianText( void ) = 0;
- virtual Bool getDisallowNonAsianText(void ) = 0;
-
- // chat
- virtual void registerTextWindow( GameWindow *win ) = 0;
- virtual void unregisterTextWindow( GameWindow *win ) = 0;
- virtual Int addText( UnicodeString message, Color c, GameWindow *win ) = 0;
- virtual void addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) = 0;
- virtual void addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win ) = 0;
- virtual Bool sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox ) = 0;
-
- virtual void setMOTD( const AsciiString& motd ) = 0;
- virtual const AsciiString& getMOTD( void ) = 0;
-
- virtual void setConfig( const AsciiString& config ) = 0;
- virtual const AsciiString& getConfig( void ) = 0;
-
- virtual void setPingString( const AsciiString& ping ) = 0;
- virtual const AsciiString& getPingString( void ) = 0;
- virtual Int getPingValue( const AsciiString& otherPing ) = 0;
-
- static GameSpyInfoInterface* createNewGameSpyInfoInterface( void );
-
- virtual void addToSavedIgnoreList( Int profileID, AsciiString nick ) = 0;
- virtual void removeFromSavedIgnoreList( Int profileID ) = 0;
- virtual Bool isSavedIgnored( Int profileID ) = 0;
- virtual SavedIgnoreMap returnSavedIgnoreList( void ) = 0;
- virtual void loadSavedIgnoreList( void ) = 0;
-
- virtual IgnoreList returnIgnoreList( void ) = 0;
- virtual void addToIgnoreList( AsciiString nick ) = 0;
- virtual void removeFromIgnoreList( AsciiString nick ) = 0;
- virtual Bool isIgnored( AsciiString nick ) = 0;
-
- virtual void setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP) = 0;
- virtual UnsignedInt getInternalIP(void) = 0;
- virtual UnsignedInt getExternalIP(void) = 0;
-
- virtual Bool isDisconnectedAfterGameStart(Int *reason) const = 0;
- virtual void markAsDisconnectedAfterGameStart(Int reason) = 0;
-
- virtual Bool didPlayerPreorder( Int profileID ) const = 0;
- virtual void markPlayerAsPreorder( Int profileID ) = 0;
-
- virtual void setMaxMessagesPerUpdate( Int num ) = 0;
- virtual Int getMaxMessagesPerUpdate( void ) = 0;
-
- virtual Int getAdditionalDisconnects( void ) = 0;
- virtual void clearAdditionalDisconnects( void ) = 0;
- virtual void readAdditionalDisconnects( void ) = 0;
- virtual void updateAdditionalGameSpyDisconnections(Int count) = 0;
-};
-
-extern GameSpyInfoInterface *TheGameSpyInfo;
-
-void WOLDisplayGameOptions( void );
-void WOLDisplaySlotList( void );
-Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP);
-void SetLobbyAttemptHostJoin(Bool start);
-void SendStatsToOtherPlayers(const GameInfo *game);
-
-class PSPlayerStats;
-void GetAdditionalDisconnectsFromUserFile(PSPlayerStats *stats);
-extern Int GetAdditionalDisconnectsFromUserFile(Int playerID);
-
-//-------------------------------------------------------------------------
-// These functions set up the globals and threads neccessary for our GameSpy impl.
-
-void SetUpGameSpy( const char *motdBuffer, const char *configBuffer );
-void TearDownGameSpy( void );
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h
deleted file mode 100644
index 05a61af37dc..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerDefsImplementation.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PeerDefsImplementation.h //////////////////////////////////////////////////////
-// Generals GameSpy Peer (chat) implementation definitions
-// Author: Matthew D. Campbell, Sept 2002
-
-#pragma once
-
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-
-
-class GameSpyInfo : public GameSpyInfoInterface
-{
-public:
- GameSpyInfo();
- virtual ~GameSpyInfo();
- virtual void reset( void );
- virtual void clearGroupRoomList( void ) { m_groupRooms.clear(); m_gotGroupRoomList = false; }
- virtual GroupRoomMap* getGroupRoomList( void ) { return &m_groupRooms; }
- virtual void addGroupRoom( GameSpyGroupRoom room );
- virtual Bool gotGroupRoomList( void ) { return m_gotGroupRoomList; }
- virtual void joinGroupRoom( Int groupID );
- virtual void leaveGroupRoom( void );
- virtual void joinBestGroupRoom( void );
- virtual void setCurrentGroupRoom( Int groupID ) { m_currentGroupRoomID = groupID; m_playerInfoMap.clear(); }
- virtual Int getCurrentGroupRoom( void ) { return m_currentGroupRoomID; }
- virtual void updatePlayerInfo( PlayerInfo pi, AsciiString oldNick = AsciiString::TheEmptyString );
- virtual void playerLeftGroupRoom( AsciiString nick );
- virtual PlayerInfoMap* getPlayerInfoMap( void ) { return &m_playerInfoMap; }
-
- virtual void setLocalName( AsciiString name ) { m_localName = name; }
- virtual AsciiString getLocalName( void ) { return m_localName; }
- virtual void setLocalProfileID( Int profileID ) { m_localProfileID = profileID; }
- virtual Int getLocalProfileID( void ) { return m_localProfileID; }
- virtual AsciiString getLocalEmail( void ) { return m_localEmail; }
- virtual void setLocalEmail( AsciiString email ) { m_localEmail = email; }
- virtual AsciiString getLocalPassword( void ){ return m_localPasswd; }
- virtual void setLocalPassword( AsciiString passwd ) { m_localPasswd = passwd; }
- virtual void setLocalBaseName( AsciiString name ) { m_localBaseName = name; }
- virtual AsciiString getLocalBaseName( void ){ return m_localBaseName; }
- virtual void setCachedLocalPlayerStats( PSPlayerStats stats ) {m_cachedLocalPlayerStats = stats; }
- virtual PSPlayerStats getCachedLocalPlayerStats( void ){ return m_cachedLocalPlayerStats; }
-
- virtual BuddyInfoMap* getBuddyMap( void ) { return &m_buddyMap; }
- virtual BuddyInfoMap* getBuddyRequestMap( void ) { return &m_buddyRequestMap; }
- virtual BuddyMessageList* getBuddyMessages( void ) { return &m_buddyMessages; }
- virtual Bool isBuddy( Int id );
-
- virtual void clearStagingRoomList( void );
- virtual StagingRoomMap* getStagingRoomList( void ) { return &m_stagingRooms; }
- virtual GameSpyStagingRoom* findStagingRoomByID( Int id );
- virtual void addStagingRoom( GameSpyStagingRoom room );
- virtual void updateStagingRoom( GameSpyStagingRoom room );
- virtual void removeStagingRoom( GameSpyStagingRoom room );
- virtual Bool hasStagingRoomListChanged( void );
- virtual void leaveStagingRoom( void );
- virtual void markAsStagingRoomHost( void );
- virtual void markAsStagingRoomJoiner( Int game );
- virtual Int getCurrentStagingRoomID( void ) { return m_localStagingRoomID; }
-
- virtual void sawFullGameList( void ) { m_sawFullGameList = TRUE; }
-
- virtual void setDisallowAsianText( Bool val );
- virtual void setDisallowNonAsianText( Bool val );
- virtual Bool getDisallowAsianText( void );
- virtual Bool getDisallowNonAsianText(void );
- // chat
- virtual void registerTextWindow( GameWindow *win );
- virtual void unregisterTextWindow( GameWindow *win );
- virtual Int addText( UnicodeString message, Color c, GameWindow *win );
- virtual void addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win );
- virtual void addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win );
- virtual Bool sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox );
-
- virtual void setMOTD( const AsciiString& motd );
- virtual const AsciiString& getMOTD( void );
- virtual void setConfig( const AsciiString& config );
- virtual const AsciiString& getConfig( void );
-
- virtual void setPingString( const AsciiString& ping ) { m_pingString = ping; }
- virtual const AsciiString& getPingString( void ) { return m_pingString; }
- virtual Int getPingValue( const AsciiString& otherPing );
-
- virtual Bool amIHost( void );
- virtual GameSpyStagingRoom* getCurrentStagingRoom( void );
- virtual void setGameOptions( void );
-
- virtual void addToIgnoreList( AsciiString nick );
- virtual void removeFromIgnoreList( AsciiString nick );
- virtual Bool isIgnored( AsciiString nick );
- virtual IgnoreList returnIgnoreList( void );
-
- virtual void loadSavedIgnoreList( void );
- virtual SavedIgnoreMap returnSavedIgnoreList( void );
- virtual void addToSavedIgnoreList( Int profileID, AsciiString nick);
- virtual void removeFromSavedIgnoreList( Int profileID );
- virtual Bool isSavedIgnored( Int profileID );
- virtual void setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP);
- virtual UnsignedInt getInternalIP(void) { return m_internalIP; }
- virtual UnsignedInt getExternalIP(void) { return m_externalIP; }
-
- virtual Bool isDisconnectedAfterGameStart(Int *reason) const { if (reason) *reason = m_disconReason; return m_isDisconAfterGameStart; }
- virtual void markAsDisconnectedAfterGameStart(Int reason) { m_isDisconAfterGameStart = TRUE; m_disconReason = reason; }
-
- virtual Bool didPlayerPreorder( Int profileID ) const;
- virtual void markPlayerAsPreorder( Int profileID );
-
- virtual void setMaxMessagesPerUpdate( Int num );
- virtual Int getMaxMessagesPerUpdate( void );
-
- virtual Int getAdditionalDisconnects( void );
- virtual void clearAdditionalDisconnects( void );
- virtual void readAdditionalDisconnects( void );
- virtual void updateAdditionalGameSpyDisconnections(Int count);
-private:
- Bool m_sawFullGameList;
- Bool m_isDisconAfterGameStart;
- Int m_disconReason;
- AsciiString m_rawMotd;
- AsciiString m_rawConfig;
- AsciiString m_pingString;
- GroupRoomMap m_groupRooms;
- StagingRoomMap m_stagingRooms;
- Bool m_stagingRoomsDirty;
- BuddyInfoMap m_buddyMap;
- BuddyInfoMap m_buddyRequestMap;
- PlayerInfoMap m_playerInfoMap;
- BuddyMessageList m_buddyMessages;
- Int m_currentGroupRoomID;
- Bool m_gotGroupRoomList;
- AsciiString m_localName;
- Int m_localProfileID;
- AsciiString m_localPasswd;
- AsciiString m_localEmail;
- AsciiString m_localBaseName;
- PSPlayerStats m_cachedLocalPlayerStats;
- Bool m_disallowAsainText;
- Bool m_disallowNonAsianText;
- UnsignedInt m_internalIP, m_externalIP;
- Int m_maxMessagesPerUpdate;
-
- Int m_joinedStagingRoom; // if we join a staging room, this holds its ID (0 otherwise)
- Bool m_isHosting; // if we host, this is true, and
- GameSpyStagingRoom m_localStagingRoom; // this holds the GameInfo for it.
- Int m_localStagingRoomID;
-
- IgnoreList m_ignoreList;
- SavedIgnoreMap m_savedIgnoreMap;
-
- std::set m_textWindows;
-
- std::set m_preorderPlayers;
- Int m_additionalDisconnects;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h
deleted file mode 100644
index d2df592081b..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PeerThread.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PeerThread.h //////////////////////////////////////////////////////
-// Generals GameSpy Peer-to-peer chat thread class interface
-// Author: Matthew D. Campbell, June 2002
-
-#pragma once
-
-#include "gamespy/peer/peer.h"
-#include "GameNetwork/NetworkDefs.h"
-
-enum SerialAuthResult CPP_11(: Int)
-{
- SERIAL_NONEXISTENT,
- SERIAL_AUTHFAILED,
- SERIAL_BANNED,
- SERIAL_OK
-};
-
-// this class encapsulates a request for the peer thread
-class PeerRequest
-{
-public:
- enum
- {
- PEERREQUEST_LOGIN, // attempt to login
- PEERREQUEST_LOGOUT, // log out if connected
- PEERREQUEST_MESSAGEPLAYER,
- PEERREQUEST_MESSAGEROOM,
- PEERREQUEST_JOINGROUPROOM,
- PEERREQUEST_LEAVEGROUPROOM,
- PEERREQUEST_STARTGAMELIST,
- PEERREQUEST_STOPGAMELIST,
- PEERREQUEST_CREATESTAGINGROOM,
- PEERREQUEST_SETGAMEOPTIONS,
- PEERREQUEST_JOINSTAGINGROOM,
- PEERREQUEST_LEAVESTAGINGROOM,
- PEERREQUEST_UTMPLAYER,
- PEERREQUEST_UTMROOM,
- PEERREQUEST_STARTGAME,
- PEERREQUEST_STARTQUICKMATCH,
- PEERREQUEST_WIDENQUICKMATCHSEARCH,
- PEERREQUEST_STOPQUICKMATCH,
- PEERREQUEST_PUSHSTATS,
- PEERREQUEST_GETEXTENDEDSTAGINGROOMINFO,
- PEERREQUEST_MAX
- } peerRequestType;
-
- std::string nick; // only used by login, but must be outside the union b/c of copy constructor
- std::wstring text; // can't be in a union
- std::string password;
- std::string email;
- std::string id;
-
- // gameopts
- std::string options; // full string for UTMs
- std::string ladderIP;
- std::string hostPingStr;
- std::string gameOptsMapName;
- std::string gameOptsPlayerNames[MAX_SLOTS];
-
- std::vector qmMaps;
-
- union
- {
- struct
- {
- Int profileID;
- } login;
-
- struct
- {
- Int id;
- } groupRoom;
-
- struct
- {
- Bool restrictGameList;
- } gameList;
-
- struct
- {
- Bool isAction;
- } message;
-
- struct
- {
- Int id;
- } stagingRoom;
-
- struct
- {
- UnsignedInt exeCRC;
- UnsignedInt iniCRC;
- UnsignedInt gameVersion;
- Bool allowObservers;
- Bool useStats;
- UnsignedShort ladPort;
- UnsignedInt ladPassCRC;
- Bool restrictGameList;
- } stagingRoomCreation;
-
- struct
- {
- Int wins[MAX_SLOTS];
- Int losses[MAX_SLOTS];
- Int profileID[MAX_SLOTS];
- Int faction[MAX_SLOTS];
- Int color[MAX_SLOTS];
- Int numPlayers;
- Int maxPlayers;
- Int numObservers;
- } gameOptions;
-
- struct
- {
- Bool isStagingRoom;
- } UTM;
-
- struct
- {
- Int minPointPercentage, maxPointPercentage, points;
- Int widenTime;
- Int ladderID;
- UnsignedInt ladderPassCRC;
- Int maxPing;
- Int maxDiscons, discons;
- char pings[17]; // 8 servers (0-ff), 1 NULL
- Int numPlayers;
- Int botID;
- Int roomID;
- Int side;
- Int color;
- Int NAT;
- UnsignedInt exeCRC;
- UnsignedInt iniCRC;
- } QM;
-
- struct
- {
- Int locale;
- Int wins;
- Int losses;
- Int rankPoints;
- Int side;
- Bool preorder;
- } statsToPush;
-
- };
-};
-
-//-------------------------------------------------------------------------
-
-enum DisconnectReason CPP_11(: Int)
-{
- DISCONNECT_NICKTAKEN = 1,
- DISCONNECT_BADNICK,
- DISCONNECT_LOSTCON,
- DISCONNECT_COULDNOTCONNECT,
- DISCONNECT_GP_LOGIN_TIMEOUT,
- DISCONNECT_GP_LOGIN_BAD_NICK,
- DISCONNECT_GP_LOGIN_BAD_EMAIL,
- DISCONNECT_GP_LOGIN_BAD_PASSWORD,
- DISCONNECT_GP_LOGIN_BAD_PROFILE,
- DISCONNECT_GP_LOGIN_PROFILE_DELETED,
- DISCONNECT_GP_LOGIN_CONNECTION_FAILED,
- DISCONNECT_GP_LOGIN_SERVER_AUTH_FAILED,
- DISCONNECT_SERIAL_INVALID,
- DISCONNECT_SERIAL_NOT_PRESENT,
- DISCONNECT_SERIAL_BANNED,
- DISCONNECT_GP_NEWUSER_BAD_NICK,
- DISCONNECT_GP_NEWUSER_BAD_PASSWORD,
- DISCONNECT_GP_NEWPROFILE_BAD_NICK,
- DISCONNECT_GP_NEWPROFILE_BAD_OLD_NICK,
-};
-
-enum QMStatus CPP_11(: Int)
-{
- QM_IDLE,
- QM_JOININGQMCHANNEL,
- QM_LOOKINGFORBOT,
- QM_SENTINFO,
- QM_WORKING,
- QM_POOLSIZE,
- QM_WIDENINGSEARCH,
- QM_MATCHED,
- QM_INCHANNEL,
- QM_NEGOTIATINGFIREWALLS,
- QM_STARTINGGAME,
- QM_COULDNOTFINDBOT,
- QM_COULDNOTFINDCHANNEL,
- QM_COULDNOTNEGOTIATEFIREWALLS,
- QM_STOPPED,
-};
-
-// this class encapsulates an action the peer thread wants from the UI
-class PeerResponse
-{
-public:
- enum
- {
- PEERRESPONSE_LOGIN,
- PEERRESPONSE_DISCONNECT,
- PEERRESPONSE_MESSAGE,
- PEERRESPONSE_GROUPROOM,
- PEERRESPONSE_STAGINGROOM,
- PEERRESPONSE_STAGINGROOMLISTCOMPLETE,
- PEERRESPONSE_STAGINGROOMPLAYERINFO,
- PEERRESPONSE_JOINGROUPROOM,
- PEERRESPONSE_CREATESTAGINGROOM,
- PEERRESPONSE_JOINSTAGINGROOM,
- PEERRESPONSE_PLAYERJOIN,
- PEERRESPONSE_PLAYERLEFT,
- PEERRESPONSE_PLAYERCHANGEDNICK,
- PEERRESPONSE_PLAYERINFO,
- PEERRESPONSE_PLAYERCHANGEDFLAGS,
- PEERRESPONSE_ROOMUTM,
- PEERRESPONSE_PLAYERUTM,
- PEERRESPONSE_QUICKMATCHSTATUS,
- PEERRESPONSE_GAMESTART,
- PEERRESPONSE_FAILEDTOHOST,
- PEERRESPONSE_MAX
- } peerResponseType;
-
- std::string groupRoomName; // can't be in union
-
- std::string nick; // can't be in a union
- std::string oldNick; // can't be in a union
- std::wstring text; // can't be in a union
- std::string locale; // can't be in a union
-
- std::string stagingServerGameOptions; // full string from UTMs
-
- // game opts sent with PEERRESPONSE_STAGINGROOM
- std::wstring stagingServerName;
- std::string stagingServerPingString;
- std::string stagingServerLadderIP;
- std::string stagingRoomMapName;
-
- // game opts sent with PEERRESPONSE_STAGINGROOMPLAYERINFO
- std::string stagingRoomPlayerNames[MAX_SLOTS];
-
- std::string command;
- std::string commandOptions;
-
- union
- {
- struct
- {
- DisconnectReason reason;
- } discon;
-
- struct
- {
- Int id;
- Int numWaiting;
- Int maxWaiting;
- Int numGames;
- Int numPlaying;
- } groupRoom;
-
- struct
- {
- Int id;
- Bool ok;
- } joinGroupRoom;
-
- struct
- {
- Int result;
- } createStagingRoom;
-
- struct
- {
- Int id;
- Bool ok;
- Bool isHostPresent;
- Int result; // for failures
- } joinStagingRoom;
-
- struct
- {
- Bool isPrivate;
- Bool isAction;
- Int profileID;
- } message;
-
- struct
- {
- Int profileID;
- Int wins;
- Int losses;
- RoomType roomType;
- Int flags;
- UnsignedInt IP;
- Int rankPoints;
- Int side;
- Int preorder;
- UnsignedInt internalIP; // for us, on connection
- UnsignedInt externalIP; // for us, on connection
- } player;
-
- struct
- {
- Int id;
- Int action;
- Bool isStaging;
- Bool requiresPassword;
- Bool allowObservers;
- Bool useStats;
- UnsignedInt version;
- UnsignedInt exeCRC;
- UnsignedInt iniCRC;
- UnsignedShort ladderPort;
- Int wins[MAX_SLOTS];
- Int losses[MAX_SLOTS];
- Int profileID[MAX_SLOTS];
- Int faction[MAX_SLOTS];
- Int color[MAX_SLOTS];
- Int numPlayers;
- Int numObservers;
- Int maxPlayers;
- Int percentComplete;
- } stagingRoom;
-
- struct
- {
- QMStatus status;
- Int poolSize;
- Int mapIdx; // when matched
- Int seed; // when matched
- UnsignedInt IP[MAX_SLOTS]; // when matched
- Int side[MAX_SLOTS]; // when matched
- Int color[MAX_SLOTS]; // when matched
- Int nat[MAX_SLOTS];
- } qmStatus;
- };
-};
-
-//-------------------------------------------------------------------------
-
-// this is the actual message queue used to pass messages between threads
-class GameSpyPeerMessageQueueInterface
-{
-public:
- virtual ~GameSpyPeerMessageQueueInterface() {}
- virtual void startThread( void ) = 0;
- virtual void endThread( void ) = 0;
- virtual Bool isThreadRunning( void ) = 0;
- virtual Bool isConnected( void ) = 0;
- virtual Bool isConnecting( void ) = 0;
-
- virtual void addRequest( const PeerRequest& req ) = 0;
- virtual Bool getRequest( PeerRequest& req ) = 0;
-
- virtual void addResponse( const PeerResponse& resp ) = 0;
- virtual Bool getResponse( PeerResponse& resp ) = 0;
-
- virtual SerialAuthResult getSerialAuthResult( void ) = 0;
-
- static GameSpyPeerMessageQueueInterface* createNewMessageQueue( void );
-};
-
-extern GameSpyPeerMessageQueueInterface *TheGameSpyPeerMessageQueue;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h
deleted file mode 100644
index 62d84b887a9..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageDefs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PersistentStorageDefs.h //////////////////////////////////////////////////////
-// Generals GameSpy Persistent Storage definitions
-// Author: Matthew D. Campbell, July 2002
-
-#pragma once
-
-enum LocaleType CPP_11(: Int)
-{
- LOC_UNKNOWN = 0,
- LOC_MIN = 1,
- LOC_MAX = 37
-};
-
-void HandlePersistentStorageResponses(void);
-void UpdateLocalPlayerStats(void);
-
-void SetLookAtPlayer( Int id, AsciiString nick );
-void PopulatePlayerInfoWindows( AsciiString parentWindowName );
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h
deleted file mode 100644
index 7832c036f84..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PersistentStorageThread.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PersistentStorageThread.h //////////////////////////////////////////////////////
-// Generals GameSpy Persistent Storage thread class interface
-// Author: Matthew D. Campbell, July 2002
-
-#pragma once
-
-#include "gamespy/gstats/gpersist.h"
-
-#define MAX_BUDDY_CHAT_LEN 128
-
-typedef std::map PerGeneralMap;
-// this structure holds all info on a player that is stored online
-class PSPlayerStats
-{
-public:
- PSPlayerStats( void );
- PSPlayerStats( const PSPlayerStats& other );
- void reset(void);
-
- Int id;
- PerGeneralMap wins;
- PerGeneralMap losses;
- PerGeneralMap games; //first: playerTemplate #, second: #games played (see also gamesAsRandom)
- PerGeneralMap duration;
- PerGeneralMap unitsKilled;
- PerGeneralMap unitsLost;
- PerGeneralMap unitsBuilt;
- PerGeneralMap buildingsKilled;
- PerGeneralMap buildingsLost;
- PerGeneralMap buildingsBuilt;
- PerGeneralMap earnings;
- PerGeneralMap techCaptured;
- PerGeneralMap discons;
- PerGeneralMap desyncs;
- PerGeneralMap surrenders;
- PerGeneralMap gamesOf2p;
- PerGeneralMap gamesOf3p;
- PerGeneralMap gamesOf4p;
- PerGeneralMap gamesOf5p;
- PerGeneralMap gamesOf6p;
- PerGeneralMap gamesOf7p;
- PerGeneralMap gamesOf8p;
- PerGeneralMap customGames;
- PerGeneralMap QMGames;
- Int locale;
- Int gamesAsRandom;
- std::string options;
- std::string systemSpec;
- Real lastFPS;
- Int lastGeneral;
- Int gamesInRowWithLastGeneral;
- Int challengeMedals;
- Int battleHonors;
- Int QMwinsInARow;
- Int maxQMwinsInARow;
-
- Int winsInARow;
- Int maxWinsInARow;
- Int lossesInARow;
- Int maxLossesInARow;
- Int disconsInARow;
- Int maxDisconsInARow;
- Int desyncsInARow;
- Int maxDesyncsInARow;
-
- Int builtParticleCannon;
- Int builtNuke;
- Int builtSCUD;
-
- Int lastLadderPort;
- std::string lastLadderHost;
-
- void incorporate( const PSPlayerStats& other );
-};
-
-// this class encapsulates a request for the thread
-class PSRequest
-{
-public:
- PSRequest();
- enum
- {
- PSREQUEST_READPLAYERSTATS, // read stats for a player
- PSREQUEST_UPDATEPLAYERSTATS, // update stats on the server
- PSREQUEST_UPDATEPLAYERLOCALE, // update locale on the server
- PSREQUEST_READCDKEYSTATS, // read stats for a cdkey
- PSREQUEST_SENDGAMERESTOGAMESPY, // report game results to GameSpy
- PSREQUEST_MAX
- } requestType;
-
- // player stats for the *PLAYERSTATS
- PSPlayerStats player;
-
- // cdkey for READCDKEYSTATS;
- std::string cdkey;
-
- // our info for UPDATEPLAYERSTATS
- std::string nick;
- std::string password;
- std::string email;
- Bool addDiscon;
- Bool addDesync;
- Int lastHouse;
-
- // for GameRes
- std::string results;
-};
-
-//-------------------------------------------------------------------------
-
-// this class encapsulates a response from the thread
-class PSResponse
-{
-public:
- enum
- {
- PSRESPONSE_PLAYERSTATS,
- PSRESPONSE_COULDNOTCONNECT,
- PSRESPONSE_PREORDER,
- PSRESPONSE_MAX
- } responseType;
-
- // player stats for the *PLAYERSTATS
- PSPlayerStats player;
-
- // preorder flag
- Bool preorder;
-};
-
-//-------------------------------------------------------------------------
-
-// this is the actual message queue used to pass messages between threads
-class GameSpyPSMessageQueueInterface
-{
-public:
- virtual ~GameSpyPSMessageQueueInterface() {}
- virtual void startThread( void ) = 0;
- virtual void endThread( void ) = 0;
- virtual Bool isThreadRunning( void ) = 0;
-
- virtual void addRequest( const PSRequest& req ) = 0;
- virtual Bool getRequest( PSRequest& req ) = 0;
-
- virtual void addResponse( const PSResponse& resp ) = 0;
- virtual Bool getResponse( PSResponse& resp ) = 0;
-
- // called from the main thread
- virtual void trackPlayerStats( PSPlayerStats stats ) = 0;
- virtual PSPlayerStats findPlayerStatsByID( Int id ) = 0;
-
- static GameSpyPSMessageQueueInterface* createNewMessageQueue( void );
-
- static std::string formatPlayerKVPairs( PSPlayerStats stats );
- static PSPlayerStats parsePlayerKVPairs( std::string kvPairs );
-};
-
-extern GameSpyPSMessageQueueInterface *TheGameSpyPSMessageQueue;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h
deleted file mode 100644
index aab2e51609e..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/PingThread.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PingThread.h //////////////////////////////////////////////////////
-// Generals ping thread class interface
-// Author: Matthew D. Campbell, August 2002
-// Note: adapted from WOLAPI
-
-#pragma once
-
-// this class encapsulates a request for the thread
-class PingRequest
-{
-public:
- std::string hostname;
- Int repetitions;
- Int timeout;
-};
-
-//-------------------------------------------------------------------------
-
-// this class encapsulates a response from the thread
-class PingResponse
-{
-public:
- std::string hostname;
- Int avgPing;
- Int repetitions;
-};
-
-//-------------------------------------------------------------------------
-
-// this is the actual message queue used to pass messages between threads
-class PingerInterface
-{
-public:
- virtual ~PingerInterface() {}
- virtual void startThreads( void ) = 0;
- virtual void endThreads( void ) = 0;
- virtual Bool areThreadsRunning( void ) = 0;
-
- virtual void addRequest( const PingRequest& req ) = 0;
- virtual Bool getRequest( PingRequest& resp ) = 0;
-
- virtual void addResponse( const PingResponse& resp ) = 0;
- virtual Bool getResponse( PingResponse& resp ) = 0;
-
- static PingerInterface* createNewPingerInterface( void );
-
- virtual Bool arePingsInProgress( void ) = 0;
- virtual Int getPing( AsciiString hostname ) = 0;
- virtual void clearPingMap( void ) = 0;
- virtual AsciiString getPingString( Int timeout ) = 0;
-};
-
-extern PingerInterface *ThePinger;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
deleted file mode 100644
index 5f7572a343d..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/StagingRoomGameInfo.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: StagingRoomGameInfo.h //////////////////////////////////////////////////////
-// Generals GameSpy GameInfo
-// Author: Matthew D. Campbell, Sept 2002
-
-#pragma once
-
-#include "GameNetwork/GameInfo.h"
-#include "GameNetwork/Transport.h"
-
-class GameSpyGameSlot : public GameSlot
-{
-public:
- GameSpyGameSlot();
- Int getProfileID( void ) const { return m_profileID; }
- void setProfileID( Int id ) { m_profileID = id; }
- AsciiString getLoginName( void ) const { return m_gameSpyLogin; }
- void setLoginName( AsciiString name ) { m_gameSpyLogin = name; }
- AsciiString getLocale( void ) const { return m_gameSpyLocale; }
- void setLocale( AsciiString name ) { m_gameSpyLocale = name; }
- Int getWins( void ) const { return m_wins; }
- Int getLosses( void ) const { return m_losses; }
- void setWins( Int wins ) { m_wins = wins; }
- void setLosses( Int losses ) { m_losses = losses; }
-
- Int getSlotRankPoints( void ) const { return m_rankPoints; }
- Int getFavoriteSide( void ) const { return m_favoriteSide; }
- void setSlotRankPoints( Int val ) { m_rankPoints = val; }
- void setFavoriteSide( Int val ) { m_favoriteSide = val; }
-
- void setPingString( AsciiString pingStr );
- inline AsciiString getPingString( void ) const { return m_pingStr; }
- inline Int getPingAsInt( void ) const { return m_pingInt; }
-
-protected:
- Int m_profileID;
- AsciiString m_gameSpyLogin;
- AsciiString m_gameSpyLocale;
-
- AsciiString m_pingStr;
- Int m_pingInt;
- Int m_wins, m_losses;
- Int m_rankPoints, m_favoriteSide;
-};
-
-/**
- * GameSpyStagingRoom class - maintains information about the GameSpy game and
- * the contents of its slot list throughout the game.
- */
-class GameSpyStagingRoom : public GameInfo
-{
-private:
- GameSpyGameSlot m_GameSpySlot[MAX_SLOTS]; ///< The GameSpy Games Slot List
- UnicodeString m_gameName;
- Int m_id;
- Transport *m_transport;
- AsciiString m_localName;
- Bool m_requiresPassword;
- Bool m_allowObservers;
- UnsignedInt m_version;
- UnsignedInt m_exeCRC;
- UnsignedInt m_iniCRC;
- Bool m_isQM;
-
- AsciiString m_ladderIP;
- AsciiString m_pingStr;
- Int m_pingInt;
- UnsignedShort m_ladderPort;
-
- Int m_reportedNumPlayers;
- Int m_reportedMaxPlayers;
- Int m_reportedNumObservers;
-
-public:
- GameSpyStagingRoom();
- virtual void reset( void );
-
- void cleanUpSlotPointers(void);
- inline void setID(Int id) { m_id = id; }
- inline Int getID( void ) const { return m_id; }
-
- inline void setHasPassword(Bool val) { m_requiresPassword = val; }
- inline Bool getHasPassword(void) const { return m_requiresPassword; }
- inline void setAllowObservers(Bool val) { m_allowObservers = val; }
- inline Bool getAllowObservers(void) const { return m_allowObservers; }
-
- inline void setVersion(UnsignedInt val) { m_version = val; }
- inline UnsignedInt getVersion(void) const { return m_version; }
- inline void setExeCRC(UnsignedInt val) { m_exeCRC = val; }
- inline UnsignedInt getExeCRC(void) const { return m_exeCRC; }
- inline void setIniCRC(UnsignedInt val) { m_iniCRC = val; }
- inline UnsignedInt getIniCRC(void) const { return m_iniCRC; }
-
- inline void setReportedNumPlayers(Int val) { m_reportedNumPlayers = val; }
- inline Int getReportedNumPlayers(void) const { return m_reportedNumPlayers; }
-
- inline void setReportedMaxPlayers(Int val) { m_reportedMaxPlayers = val; }
- inline Int getReportedMaxPlayers(void) const { return m_reportedMaxPlayers; }
-
- inline void setReportedNumObservers(Int val) { m_reportedNumObservers = val; }
- inline Int getReportedNumObservers(void) const { return m_reportedNumObservers; }
-
- inline void setLadderIP( AsciiString ladderIP ) { m_ladderIP = ladderIP; }
- inline AsciiString getLadderIP( void ) const { return m_ladderIP; }
- inline void setLadderPort( UnsignedShort ladderPort ) { m_ladderPort = ladderPort; }
- inline UnsignedShort getLadderPort( void ) const { return m_ladderPort; }
- void setPingString( AsciiString pingStr );
- inline AsciiString getPingString( void ) const { return m_pingStr; }
- inline Int getPingAsInt( void ) const { return m_pingInt; }
-
- virtual Bool amIHost( void ) const; ///< Convenience function - is the local player the game host?
-
- GameSpyGameSlot *getGameSpySlot( Int index );
-
- AsciiString generateGameSpyGameResultsPacket( void );
- AsciiString generateLadderGameResultsPacket( void );
- void markGameAsQM( void ) { m_isQM = TRUE; }
- Bool isQMGame( void ) { return m_isQM; }
-
- virtual void init(void);
- virtual void resetAccepted(void); ///< Reset the accepted flag on all players
-
- virtual void startGame(Int gameID); ///< Mark our game as started and record the game ID.
- void launchGame( void ); ///< NAT negotiation has finished - really start
- virtual Int getLocalSlotNum( void ) const; ///< Get the local slot number, or -1 if we're not present
-
- inline void setGameName( UnicodeString name ) { m_gameName = name; }
- inline UnicodeString getGameName( void ) const { return m_gameName; }
-
- inline void setLocalName( AsciiString name ) { m_localName = name; }
-};
-
-extern GameSpyStagingRoom *TheGameSpyGame;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h
deleted file mode 100644
index ace441eaf02..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpy/ThreadUtils.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: ThreadUtils.h //////////////////////////////////////////////////////
-// Generals GameSpy thread utils
-// Author: Matthew D. Campbell, July 2002
-
-#pragma once
-
-std::wstring MultiByteToWideCharSingleLine( const char *orig );
-std::string WideCharStringToMultiByte( const WideChar *orig );
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h
deleted file mode 100644
index e56f238c1ce..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyOverlay.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GamespyOverlay.h //////////////////////////////////////////////////////
-// Generals GameSpy overlay screens
-// Author: Matthew D. Campbell, March 2002
-
-#pragma once
-
-#include "Common/NameKeyGenerator.h"
-#include "GameClient/WindowLayout.h"
-#include "GameClient/Gadget.h"
-#include "GameClient/Shell.h"
-#include "GameClient/KeyDefs.h"
-#include "GameClient/GameWindowManager.h"
-
-void ClearGSMessageBoxes( void ); ///< Tear down any GS message boxes (e.g. in case we have a new one to put up)
-void GSMessageBoxOk(UnicodeString titleString,UnicodeString bodyString, GameWinMsgBoxFunc okFunc = NULL); ///< Display a Message box with Ok button and track it
-void GSMessageBoxOkCancel(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc okFunc, GameWinMsgBoxFunc cancelFunc); ///< Display a Message box with Ok/Cancel buttons and track it
-void GSMessageBoxYesNo(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc yesFunc, GameWinMsgBoxFunc noFunc); ///< Display a Message box with Yes/No buttons and track it
-void RaiseGSMessageBox( void ); ///< Bring GS message box to the foreground (if we transition screens while a message box is up)
-
-enum GSOverlayType CPP_11(: Int)
-{
- GSOVERLAY_PLAYERINFO,
- GSOVERLAY_MAPSELECT,
- GSOVERLAY_BUDDY,
- GSOVERLAY_PAGE,
- GSOVERLAY_GAMEOPTIONS,
- GSOVERLAY_GAMEPASSWORD,
- GSOVERLAY_LADDERSELECT,
- GSOVERLAY_LOCALESELECT,
- GSOVERLAY_OPTIONS,
- GSOVERLAY_MAX
-};
-
-void GameSpyOpenOverlay( GSOverlayType );
-void GameSpyCloseOverlay( GSOverlayType );
-void GameSpyCloseAllOverlays( void );
-Bool GameSpyIsOverlayOpen( GSOverlayType );
-void GameSpyToggleOverlay( GSOverlayType );
-void GameSpyUpdateOverlays( void );
-void ReOpenPlayerInfo( void );
-void CheckReOpenPlayerInfo(void );
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyThread.h b/Generals/Code/GameEngine/Include/GameNetwork/GameSpyThread.h
deleted file mode 100644
index 03046f692ae..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/GameSpyThread.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameSpyThread.h //////////////////////////////////////////////////////
-// Generals GameSpy thread class
-// Author: Matthew D. Campbell, March 2002
-
-#pragma once
-
-#include "mutex.h"
-#include "thread.h"
-
-class GameSpyThreadClass : public ThreadClass
-{
-
-public:
- GameSpyThreadClass::GameSpyThreadClass() : ThreadClass() { m_doLogin = false; m_readStats = false; m_updateWins = false; m_updateLosses = false; m_updateLocale = false; m_showLocaleSelect = false; m_nextShellScreen.clear(); }
- void queueLogin(AsciiString nick, AsciiString pass, AsciiString email) { m_nick = nick; m_pass = pass; m_email = email; m_doLogin = true; }
- void queueReadPersistentStatsFromServer( void ) { m_readStats = true; }
- void queueUpdateLocale( AsciiString locale ) { m_locale = locale; m_updateLocale = true; }
- void queueUpdateWins ( AsciiString wins ) { m_wins = wins; m_updateWins = true; }
- void queueUpdateLosses( AsciiString losses ) { m_losses = losses; m_updateLosses = true; }
-
- void Thread_Function();
-
- AsciiString getNextShellScreen( void );
- Bool showLocaleSelect( void );
-
- void setNextShellScreen( AsciiString nextShellScreen );
- void setShowLocaleSelect( Bool val );
-
-private:
- AsciiString m_nick, m_pass, m_email;
- Bool m_doLogin, m_readStats, m_updateWins, m_updateLosses, m_updateLocale;
- AsciiString m_locale, m_wins, m_losses;
- AsciiString m_nextShellScreen;
- Bool m_showLocaleSelect;
-};
-
-extern GameSpyThreadClass *TheGameSpyThread;
-extern MutexClass TheGameSpyMutex;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/IPEnumeration.h b/Generals/Code/GameEngine/Include/GameNetwork/IPEnumeration.h
deleted file mode 100644
index cef08e33aac..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/IPEnumeration.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// IPEnumeration.h ///////////////////////////////////////////////////////////////
-// Class for enumerating IP addresses
-// Author: Matthew D. Campbell, October 2001
-
-#pragma once
-
-#include "GameNetwork/Transport.h"
-
-/**
- * IP wrapper class.
- */
-class EnumeratedIP : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(EnumeratedIP, "EnumeratedIP")
-public:
- EnumeratedIP() { m_IPstring = ""; m_next = NULL; m_IP = 0; }
-
- // Access functions
- inline AsciiString getIPstring( void ) { return m_IPstring; }
- inline void setIPstring( AsciiString name ) { m_IPstring = name; }
- inline UnsignedInt getIP( void ) { return m_IP; }
- inline void setIP( UnsignedInt IP ) { m_IP = IP; }
- inline EnumeratedIP *getNext( void ) { return m_next; }
- inline void setNext( EnumeratedIP *next ) { m_next = next; }
-
-protected:
- AsciiString m_IPstring;
- UnsignedInt m_IP;
- EnumeratedIP *m_next;
-};
-EMPTY_DTOR(EnumeratedIP)
-
-
-/**
- * The IPEnumeration class is used to obtain a list of IP addresses on the
- * local machine.
- */
-class IPEnumeration
-{
-public:
-
- IPEnumeration();
- ~IPEnumeration();
-
- EnumeratedIP * getAddresses( void ); ///< Return a linked list of local IP addresses
- AsciiString getMachineName( void ); ///< Return the Network Neighborhood machine name
-
-protected:
- void addNewIP( UnsignedByte a, UnsignedByte b, UnsignedByte c, UnsignedByte d );
-
- EnumeratedIP *m_IPlist;
- Bool m_isWinsockInitialized;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/LANAPI.h b/Generals/Code/GameEngine/Include/GameNetwork/LANAPI.h
deleted file mode 100644
index 48d04a2991a..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/LANAPI.h
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// LANAPI.h ///////////////////////////////////////////////////////////////
-// LANAPI singleton class - defines interface to LAN broadcast communications
-// Author: Matthew D. Campbell, October 2001
-
-#pragma once
-
-#include "GameNetwork/Transport.h"
-#include "GameNetwork/NetworkInterface.h"
-#include "GameNetwork/NetworkDefs.h"
-#include "GameNetwork/LANPlayer.h"
-#include "GameNetwork/LANGameInfo.h"
-
-//static const Int g_lanPlayerNameLength = 20;
-static const Int g_lanPlayerNameLength = 12; // reduced length because of game option length
-//static const Int g_lanLoginNameLength = 16;
-//static const Int g_lanHostNameLength = 16;
-static const Int g_lanLoginNameLength = 1;
-static const Int g_lanHostNameLength = 1;
-//static const Int g_lanGameNameLength = 32;
-static const Int g_lanGameNameLength = 16; // reduced length because of game option length
-static const Int g_lanGameNameReservedLength = 16; // save N wchars for ID info
-static const Int g_lanMaxChatLength = 100;
-static const Int m_lanMaxOptionsLength = MAX_PACKET_SIZE - ( 8 + (g_lanGameNameLength+1)*2 + 4 + (g_lanPlayerNameLength+1)*2
- + (g_lanLoginNameLength+1) + (g_lanHostNameLength+1) );
-static const Int g_maxSerialLength = 23; // including the trailing '\0'
-
-struct LANMessage;
-
-/**
- * The LANAPI class is used to instantiate a singleton which
- * implements the interface to all LAN broadcast communications.
- */
-class LANAPIInterface : public SubsystemInterface
-{
-public:
-
- virtual ~LANAPIInterface() { };
-
- virtual void init( void ) = 0; ///< Initialize or re-initialize the instance
- virtual void reset( void ) = 0; ///< reset the logic system
- virtual void update( void ) = 0; ///< update the world
-
- virtual void setIsActive(Bool isActive ) = 0; ///< Tell TheLAN whether or not the app is active.
-
- // Possible types of chat messages
- enum ChatType
- {
- LANCHAT_NORMAL = 0,
- LANCHAT_EMOTE,
- LANCHAT_SYSTEM,
- };
-
- // Request functions generate network traffic
- virtual void RequestLocations( void ) = 0; ///< Request everybody to respond with where they are
- virtual void RequestGameJoin( LANGameInfo *game, UnsignedInt ip = 0 ) = 0; ///< Request to join a game
- virtual void RequestGameJoinDirectConnect( UnsignedInt ipaddress ) = 0; ///< Request to join a game at an IP address
- virtual void RequestGameLeave( void ) = 0; ///< Tell everyone we're leaving
- virtual void RequestAccept( void ) = 0; ///< Indicate we're OK with the game options
- virtual void RequestHasMap( void ) = 0; ///< Send our map status
- virtual void RequestChat( UnicodeString message, ChatType format ) = 0; ///< Send a chat message
- virtual void RequestGameStart( void ) = 0; ///< Tell everyone the game is starting
- virtual void RequestGameStartTimer( Int seconds ) = 0;
- virtual void RequestGameOptions( AsciiString gameOptions, Bool isPublic, UnsignedInt ip = 0 ) = 0; ///< Change the game options
- virtual void RequestGameCreate( UnicodeString gameName, Bool isDirectConnect ) = 0; ///< Try to host a game
- virtual void RequestGameAnnounce( void ) = 0; ///< Sound out current game info if host
-// virtual void RequestSlotList( void ) = 0; ///< Pump out the Slot info.
- virtual void RequestSetName( UnicodeString newName ) = 0; ///< Pick a new name
- virtual void RequestLobbyLeave( Bool forced ) = 0; ///< Announce that we're leaving the lobby
- virtual void ResetGameStartTimer( void ) = 0;
-
- // Possible result codes passed to On functions
- enum ReturnType
- {
- RET_OK, // Any function
- RET_TIMEOUT, // OnGameJoin/Leave/Start, etc
- RET_GAME_FULL, // OnGameJoin
- RET_DUPLICATE_NAME, // OnGameJoin
- RET_CRC_MISMATCH, // OnGameJoin
- RET_SERIAL_DUPE, // OnGameJoin
- RET_GAME_STARTED, // OnGameJoin
- RET_GAME_EXISTS, // OnGameCreate
- RET_GAME_GONE, // OnGameJoin
- RET_BUSY, // OnGameCreate/Join/etc if another action is in progress
- RET_UNKNOWN, // Default message for oddity
- };
- UnicodeString getErrorStringFromReturnType( ReturnType ret );
-
- // On functions are (generally) the result of network traffic
- virtual void OnGameList( LANGameInfo *gameList ) = 0; ///< List of games
- virtual void OnPlayerList( LANPlayer *playerList ) = 0; ///< List of players in the Lobby
- virtual void OnGameJoin( ReturnType ret, LANGameInfo *theGame ) = 0; ///< Did we get in the game?
- virtual void OnPlayerJoin( Int slot, UnicodeString playerName ) = 0; ///< Someone else joined our game (host only; joiners get a slotlist)
- virtual void OnHostLeave( void ) = 0; ///< Host left the game
- virtual void OnPlayerLeave( UnicodeString player ) = 0; ///< Someone left the game
- virtual void OnAccept( UnsignedInt playerIP, Bool status ) = 0; ///< Someone's accept status changed
- virtual void OnHasMap( UnsignedInt playerIP, Bool status ) = 0; ///< Someone's map status changed
- virtual void OnChat( UnicodeString player, UnsignedInt ip,
- UnicodeString message, ChatType format ) = 0; ///< Chat message from someone
- virtual void OnGameStart( void ) = 0; ///< The game is starting
- virtual void OnGameStartTimer( Int seconds ) = 0;
- virtual void OnGameOptions( UnsignedInt playerIP, Int playerSlot, AsciiString options ) = 0; ///< Someone sent game options
- virtual void OnGameCreate( ReturnType ret ) = 0; ///< Your game is created
-// virtual void OnSlotList( ReturnType ret, LANGameInfo *theGame ) = 0; ///< Slotlist for a game in setup
- virtual void OnNameChange( UnsignedInt IP, UnicodeString newName ) = 0; ///< Someone has morphed
-
- // Misc utility functions
- virtual LANGameInfo * LookupGame( UnicodeString gameName ) = 0; ///< return a pointer to a game we know about
- virtual LANGameInfo * LookupGameByListOffset( Int offset ) = 0; ///< return a pointer to a game we know about
- virtual Bool SetLocalIP( UnsignedInt localIP ) = 0; ///< For multiple NIC machines
- virtual void SetLocalIP( AsciiString localIP ) = 0; ///< For multiple NIC machines
- virtual Bool AmIHost( void ) = 0; ///< Am I hosting a game?
- virtual inline UnicodeString GetMyName( void ) = 0; ///< What's my name?
- virtual inline LANGameInfo *GetMyGame( void ) = 0; ///< What's my Game?
- virtual void fillInLANMessage( LANMessage *msg ) = 0; ///< Fill in default params
- virtual void checkMOTD( void ) = 0;
-};
-
-
-/**
- * The LANAPI class is used to instantiate a singleton which
- * implements the interface to all LAN broadcast communications.
- */
-class LANAPI : public LANAPIInterface
-{
-public:
-
- LANAPI();
- virtual ~LANAPI();
-
- virtual void init( void ); ///< Initialize or re-initialize the instance
- virtual void reset( void ); ///< reset the logic system
- virtual void update( void ); ///< update the world
-
- virtual void setIsActive(Bool isActive); ///< tell TheLAN whether or not
-
- // Request functions generate network traffic
- virtual void RequestLocations( void ); ///< Request everybody to respond with where they are
- virtual void RequestGameJoin( LANGameInfo *game, UnsignedInt ip = 0 ); ///< Request to join a game
- virtual void RequestGameJoinDirectConnect( UnsignedInt ipaddress ); ///< Request to join a game at an IP address
- virtual void RequestGameLeave( void ); ///< Tell everyone we're leaving
- virtual void RequestAccept( void ); ///< Indicate we're OK with the game options
- virtual void RequestHasMap( void ); ///< Send our map status
- virtual void RequestChat( UnicodeString message, ChatType format ); ///< Send a chat message
- virtual void RequestGameStart( void ); ///< Tell everyone the game is starting
- virtual void RequestGameStartTimer( Int seconds );
- virtual void RequestGameOptions( AsciiString gameOptions, Bool isPublic, UnsignedInt ip = 0 ); ///< Change the game options
- virtual void RequestGameCreate( UnicodeString gameName, Bool isDirectConnect ); ///< Try to host a game
- virtual void RequestGameAnnounce( void ); ///< Send out game info if host
- virtual void RequestSetName( UnicodeString newName ); ///< Pick a new name
-// virtual void RequestSlotList( void ); ///< Pump out the Slot info.
- virtual void RequestLobbyLeave( Bool forced ); ///< Announce that we're leaving the lobby
- virtual void ResetGameStartTimer( void );
-
- // On functions are (generally) the result of network traffic
- virtual void OnGameList( LANGameInfo *gameList ); ///< List of games
- virtual void OnPlayerList( LANPlayer *playerList ); ///< List of players in the Lobby
- virtual void OnGameJoin( ReturnType ret, LANGameInfo *theGame ); ///< Did we get in the game?
- virtual void OnPlayerJoin( Int slot, UnicodeString playerName ); ///< Someone else joined our game (host only; joiners get a slotlist)
- virtual void OnHostLeave( void ); ///< Host left the game
- virtual void OnPlayerLeave( UnicodeString player ); ///< Someone left the game
- virtual void OnAccept( UnsignedInt playerIP, Bool status ); ///< Someone's accept status changed
- virtual void OnHasMap( UnsignedInt playerIP, Bool status ); ///< Someone's map status changed
- virtual void OnChat( UnicodeString player, UnsignedInt ip,
- UnicodeString message, ChatType format ); ///< Chat message from someone
- virtual void OnGameStart( void ); ///< The game is starting
- virtual void OnGameStartTimer( Int seconds );
- virtual void OnGameOptions( UnsignedInt playerIP, Int playerSlot, AsciiString options ); ///< Someone sent game options
- virtual void OnGameCreate( ReturnType ret ); ///< Your game is created
- //virtual void OnSlotList( ReturnType ret, LANGameInfo *theGame ); ///< Slotlist for a game in setup
- virtual void OnNameChange( UnsignedInt IP, UnicodeString newName ); ///< Someone has morphed
- virtual void OnInActive( UnsignedInt IP ); ///< Someone has alt-tabbed out.
-
-
- // Misc utility functions
- virtual LANGameInfo * LookupGame( UnicodeString gameName ); ///< return a pointer to a game we know about
- virtual LANGameInfo * LookupGameByListOffset( Int offset ); ///< return a pointer to a game we know about
- virtual LANPlayer * LookupPlayer( UnsignedInt playerIP ); ///< return a pointer to a player we know about
- virtual Bool SetLocalIP( UnsignedInt localIP ); ///< For multiple NIC machines
- virtual void SetLocalIP( AsciiString localIP ); ///< For multiple NIC machines
- virtual Bool AmIHost( void ); ///< Am I hosting a game?
- virtual inline UnicodeString GetMyName( void ) { return m_name; } ///< What's my name?
- virtual inline LANGameInfo* GetMyGame( void ) { return m_currentGame; } ///< What's my Game?
- virtual inline UnsignedInt GetLocalIP( void ) { return m_localIP; } ///< What's my IP?
- virtual void fillInLANMessage( LANMessage *msg ); ///< Fill in default params
- virtual void checkMOTD( void );
-protected:
-
- enum PendingActionType
- {
- ACT_NONE = 0,
- ACT_JOIN,
- ACT_JOINDIRECTCONNECT,
- ACT_LEAVE,
- };
-
- static const UnsignedInt s_resendDelta; // in ms
-
-protected:
- LANPlayer * m_lobbyPlayers; ///< List of players in the lobby
- LANGameInfo * m_games; ///< List of games
- UnicodeString m_name; ///< Who do we think we are?
- AsciiString m_userName; ///< login name
- AsciiString m_hostName; ///< machine name
- UnsignedInt m_gameStartTime;
- Int m_gameStartSeconds;
-
- PendingActionType m_pendingAction; ///< What action are we performing?
- UnsignedInt m_expiration; ///< When should we give up on our action?
- UnsignedInt m_actionTimeout;
- UnsignedInt m_directConnectRemoteIP;///< The IP address of the game we are direct connecting to.
-
- // Resend timer ---------------------------------------------------------------------------
- UnsignedInt m_lastResendTime; // in ms
-
- Bool m_isInLANMenu; ///< true while we are in a LAN menu (lobby, game options, direct connect)
- Bool m_inLobby; ///< Are we in the lobby (not in a game)?
- LANGameInfo * m_currentGame; ///< Pointer to game (setup screen) we are currently in (NULL for lobby)
- //LANGameInfo *m_currentGameInfo; ///< Pointer to game setup info we are currently in.
-
- UnsignedInt m_localIP;
- Transport* m_transport;
-
- UnsignedInt m_broadcastAddr;
-
- UnsignedInt m_lastUpdate;
- AsciiString m_lastGameopt; /// @todo: hack for demo - remove this
-
- Bool m_isActive; ///< is the game currently active?
-
-protected:
- void sendMessage(LANMessage *msg, UnsignedInt ip = 0); // Convenience function
- void removePlayer(LANPlayer *player);
- void removeGame(LANGameInfo *game);
- void addPlayer(LANPlayer *player);
- void addGame(LANGameInfo *game);
- AsciiString createSlotString( void );
-
- // Functions to handle incoming messages -----------------------------------
- void handleRequestLocations( LANMessage *msg, UnsignedInt senderIP );
- void handleGameAnnounce( LANMessage *msg, UnsignedInt senderIP );
- void handleLobbyAnnounce( LANMessage *msg, UnsignedInt senderIP );
- void handleRequestGameInfo( LANMessage *msg, UnsignedInt senderIP );
- void handleRequestJoin( LANMessage *msg, UnsignedInt senderIP );
- void handleJoinAccept( LANMessage *msg, UnsignedInt senderIP );
- void handleJoinDeny( LANMessage *msg, UnsignedInt senderIP );
- void handleRequestGameLeave( LANMessage *msg, UnsignedInt senderIP );
- void handleRequestLobbyLeave( LANMessage *msg, UnsignedInt senderIP );
- void handleSetAccept( LANMessage *msg, UnsignedInt senderIP );
- void handleHasMap( LANMessage *msg, UnsignedInt senderIP );
- void handleChat( LANMessage *msg, UnsignedInt senderIP );
- void handleGameStart( LANMessage *msg, UnsignedInt senderIP );
- void handleGameStartTimer( LANMessage *msg, UnsignedInt senderIP );
- void handleGameOptions( LANMessage *msg, UnsignedInt senderIP );
- void handleInActive( LANMessage *msg, UnsignedInt senderIP );
-
-};
-
-
-
-/**
- * LAN message class
- */
-#pragma pack(push, 1)
-struct LANMessage
-{
- enum Type ///< What kind of message are we?
- {
- // Locating everybody
- MSG_REQUEST_LOCATIONS, ///< Hey, where is everybody?
- MSG_GAME_ANNOUNCE, ///< Here I am, and here's my game info!
- MSG_LOBBY_ANNOUNCE, ///< Hey, I'm in the lobby!
-
- // Joining games
- MSG_REQUEST_JOIN, ///< Let me in! Let me in!
- MSG_JOIN_ACCEPT, ///< Okay, you can join.
- MSG_JOIN_DENY, ///< Go away! We don't want any!
-
- // Leaving games
- MSG_REQUEST_GAME_LEAVE, ///< I want to leave the game
- MSG_REQUEST_LOBBY_LEAVE,///< I'm leaving the lobby
-
- // Game options, chat, etc
- MSG_SET_ACCEPT, ///< I'm cool with everything as is.
- MSG_MAP_AVAILABILITY, ///< I do (not) have the map.
- MSG_CHAT, ///< Just spouting my mouth off.
- MSG_GAME_START, ///< Hold on; we're starting!
- MSG_GAME_START_TIMER, ///< The game will start in N seconds
- MSG_GAME_OPTIONS, ///< Here's some info about the game.
- MSG_INACTIVE, ///< I've alt-tabbed out. Unaccept me cause I'm a poo-flinging monkey.
-
- MSG_REQUEST_GAME_INFO, ///< For direct connect, get the game info from a specific IP Address
- } messageType;
-
- WideChar name[g_lanPlayerNameLength+1]; ///< My name, for convenience
- char userName[g_lanLoginNameLength+1]; ///< login name, for convenience
- char hostName[g_lanHostNameLength+1]; ///< machine name, for convenience
-
- // No additional data is required for REQUEST_LOCATIONS, LOBBY_ANNOUNCE,
- // REQUEST_LOBBY_LEAVE, GAME_START.
- union
- {
- // StartTimer is sent with GAME_START_TIMER
- struct
- {
- Int seconds;
- } StartTimer;
-
- // GameJoined is sent with REQUEST_GAME_LEAVE
- struct
- {
- WideChar gameName[g_lanGameNameLength+1];
- } GameToLeave;
-
- // GameInfo if sent with GAME_ANNOUNCE
- struct
- {
- WideChar gameName[g_lanGameNameLength+1];
- Bool inProgress;
- char options[m_lanMaxOptionsLength+1];
- Bool isDirectConnect;
- } GameInfo;
-
- // PlayerInfo is sent with REQUEST_GAME_INFO for direct connect games.
- struct
- {
- UnsignedInt ip;
- WideChar playerName[g_lanPlayerNameLength+1];
- } PlayerInfo;
-
- // GameToJoin is sent with REQUEST_JOIN
- struct
- {
- UnsignedInt gameIP;
- UnsignedInt exeCRC;
- UnsignedInt iniCRC;
- char serial[g_maxSerialLength];
- } GameToJoin;
-
- // GameJoined is sent with JOIN_ACCEPT
- struct
- {
- WideChar gameName[g_lanGameNameLength+1];
- UnsignedInt gameIP;
- UnsignedInt playerIP;
- Int slotPosition;
- } GameJoined;
-
- // GameNotJoined is sent with JOIN_DENY
- struct
- {
- WideChar gameName[g_lanGameNameLength+1];
- UnsignedInt gameIP;
- UnsignedInt playerIP;
- LANAPIInterface::ReturnType reason;
- } GameNotJoined;
-
- // Accept is sent with SET_ACCEPT
- struct
- {
- WideChar gameName[g_lanGameNameLength+1];
- Bool isAccepted;
- } Accept;
-
- // Accept is sent with MAP_AVAILABILITY
- struct
- {
- WideChar gameName[g_lanGameNameLength+1];
- UnsignedInt mapCRC; // to make sure we're talking about the same map
- Bool hasMap;
- } MapStatus;
-
- // Chat is sent with CHAT
- struct
- {
- WideChar gameName[g_lanGameNameLength+1];
- LANAPIInterface::ChatType chatType;
- WideChar message[g_lanMaxChatLength+1];
- } Chat;
-
- // GameOptions is sent with GAME_OPTIONS
- struct
- {
- char options[m_lanMaxOptionsLength+1];
- } GameOptions;
-
- };
-};
-#pragma pack(pop)
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/LANAPICallbacks.h b/Generals/Code/GameEngine/Include/GameNetwork/LANAPICallbacks.h
deleted file mode 100644
index 48d5ee28a89..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/LANAPICallbacks.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: LANAPICallbacks.h
-// Author: Chris Huybregts, October 2001
-// Description: LAN API Callbacks header
-///////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/NameKeyGenerator.h"
-#include "GameClient/Shell.h"
-#include "GameClient/GadgetListBox.h"
-#include "GameClient/GadgetTextEntry.h"
-#include "GameNetwork/LANAPI.h"
-
-
-// LAN API Singleton ----------------------------------------------------------------------
-extern LANAPI *TheLAN;
-
-//external declarations of the Gadgets the callbacks can use
-// LanLobby
-extern NameKeyType listboxChatWindowID;
-extern GameWindow *listboxChatWindow;
-extern GameWindow *listboxPlayers;
-extern NameKeyType listboxGamesID;
-extern GameWindow *listboxGames;
-//LanGame Options screen
-extern NameKeyType listboxChatWindowLanGameID;
-extern GameWindow *listboxChatWindowLanGame;
-extern WindowLayout *mapSelectLayout;
-// ScoreScreen
-extern NameKeyType listboxChatWindowScoreScreenID;
-extern GameWindow *listboxChatWindowScoreScreen;
-
-
-//Colors used for the chat dialogs
-extern const Color playerColor;
-extern const Color gameColor;
-extern const Color gameInProgressColor;
-extern const Color chatNormalColor;
-extern const Color chatActionColor;
-extern const Color chatLocalNormalColor;
-extern const Color chatLocalActionColor;
-extern const Color chatSystemColor;
-extern const Color chatSystemColor;
-extern const Color acceptTrueColor;
-extern const Color acceptFalseColor;
-
-
-void lanUpdateSlotList( void );
-void updateGameOptions( void );
-void setLANPlayerTooltip(LANPlayer* player);
-
-//Enum is used for the utility function so other windows do not need
-//to know about controls on LanGameOptions window.
-enum PostToLanGameType CPP_11(: Int){ SEND_GAME_OPTS = 0,
- MAP_BACK,
- POST_TO_LAN_GAME_TYPE_COUNT };
-//the utility function mentioned above
-void PostToLanGameOptions(PostToLanGameType post);
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/LANGameInfo.h b/Generals/Code/GameEngine/Include/GameNetwork/LANGameInfo.h
deleted file mode 100644
index 69504d50bb0..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/LANGameInfo.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: LANGameInfo.h //////////////////////////////////////////////////////
-// Generals LAN game setup information
-// Author: Matthew D. Campbell, December 2001
-
-#pragma once
-
-#include "GameNetwork/GameInfo.h"
-#include "GameNetwork/LANPlayer.h"
-
-class GameWindow;
-
-/**
- * LANGameSlot class - maintains information about the contents of a
- * game slot. This persists throughout the game.
- */
-class LANGameSlot : public GameSlot
-{
-public:
- LANGameSlot();
-
- LANPlayer *getUser( void ); ///< Get the User structure associated with the slot (NULL for non-humans)
-
- // Various tests
- Bool isUser( LANPlayer *user ); ///< Does this slot contain the given user? Based off user->name
- Bool isUser( UnicodeString userName ); ///< Does this slot contain the given user?
- Bool isLocalPlayer( void ) const; ///< Is this slot me?
- inline void setLogin( UnicodeString name ) { m_user.setLogin(name); }
- inline void setLogin( AsciiString name ) { m_user.setLogin(name); }
- inline void setHost( UnicodeString name ) { m_user.setHost(name); }
- inline void setHost( AsciiString name ) { m_user.setHost(name); }
- inline void setSerial( AsciiString serial ) { m_serial = serial; }
- inline AsciiString getSerial( void ) { return m_serial; }
-
- inline void setLastHeard( UnsignedInt t ) { m_lastHeard = t; }
- inline UnsignedInt getLastHeard( void ) { return m_lastHeard; }
-
- //LANGameSlot& operator=(const LANGameSlot& src);
-
-private:
-
- LANPlayer m_user; ///< filled in for each getUser() call
- AsciiString m_serial;
-
- UnsignedInt m_lastHeard;
-};
-
-/**
- * LANGameInfo class - maintains information about the LAN game and
- * the contents of its slot list hroughout the game.
- */
-class LANGameInfo : public GameInfo
-{
-private:
- LANGameSlot m_LANSlot[MAX_SLOTS]; ///< The Lan Games Slot List
-
-public:
- LANGameInfo();
- void setSlot( Int slotNum, LANGameSlot slotInfo ); ///< Set the slot state (human, open, AI, etc)
- LANGameSlot* getLANSlot( Int slotNum ); ///< Get the slot
- const LANGameSlot* getConstLANSlot( Int slotNum ) const; ///< Get the slot
- virtual Int getLocalSlotNum( void ) const; ///< Get the local slot number, or -1 if we're not present
- Int getSlotNum( UnicodeString userName ); ///< Get the slot number corresponding to a specific user, or -1 if he's not present
-
- inline UnsignedInt getLastHeard( void ) { return m_lastHeard; }
- inline void setLastHeard( UnsignedInt lastHeard ) { m_lastHeard = lastHeard; }
- inline LANGameInfo *getNext( void ) { return m_next; }
- inline void setNext( LANGameInfo *next ) { m_next = next; }
-
- // Game options
- void setMap( AsciiString mapName ); ///< Set the map to play on
- void setSeed( Int seed ); ///< Set the random seed for the game
-
- inline void setName( UnicodeString name ) { m_gameName = name; } ///< Set the Name of the Game
- inline UnicodeString getName( void ) { return m_gameName; } ///< Get the Name of the Game
-
- // Convinience functions that interface with the LANPlayer held in the slot list
- virtual void resetAccepted(void); ///< Reset the accepted flag on all players
- Bool amIHost( void ); ///< Convenience function - is the local player the game host?
-
- /// Get the IP of selected player or return 0
- inline UnsignedInt getIP( int who )
- {
- return m_LANSlot[who].getIP();
- }
-
- /// Set the IP of the Selected Player
- inline void setIP( int who, UnsignedInt IP )
- {
- m_LANSlot[who].setIP(IP);
- }
-
- /// set whether or not this is a direct connect game or not.
- inline void setIsDirectConnect(Bool isDirectConnect)
- {
- m_isDirectConnect = isDirectConnect;
- }
-
- /// returns whether or not this is a direct connect game or not.
- inline Bool getIsDirectConnect()
- {
- return m_isDirectConnect;
- }
-
- /// Set the Player Name
- inline void setPlayerName( int who, UnicodeString name )
- {
- m_LANSlot[who].setName(name);
- }
-
- /// Return the Player name or TheEmptyString
- inline UnicodeString getPlayerName(int who)
- {
- return m_LANSlot[who].getName();
- }
-
- /// Return the time the player was heard from last, or 0
- inline UnsignedInt getPlayerLastHeard( int who )
- {
- if (m_LANSlot[who].isHuman())
- return m_LANSlot[who].getLastHeard();
- return 0;
- }
-
- /// Set the last time we heard from the player
- inline void setPlayerLastHeard( int who, UnsignedInt lastHeard )
- {
- DEBUG_LOG(("LANGameInfo::setPlayerLastHeard - changing player %d last heard from %d to %d", who, getPlayerLastHeard(who), lastHeard));
- if (m_LANSlot[who].isHuman())
- m_LANSlot[who].setLastHeard(lastHeard);
- }
-
- /// Return the hosts IP or 0
- UnsignedInt getHostIP(void)
- {
- if (m_LANSlot[0].isHuman())
- return m_LANSlot[0].getIP();
- return 0;
- }
-
-
-private:
- LANGameInfo *m_next; ///< Pointer for linked list
- UnsignedInt m_lastHeard; ///< The last time we heard from this game (for timeout purposes)
- UnicodeString m_gameName; ///< Game name. @todo: are game names based off of host player names?
- Bool m_isDirectConnect; ///< Is this game a direct connect game, or a LAN game?
-};
-
-void LANDisplayGameList( GameWindow *gameListbox, LANGameInfo *gameList ); ///< Displays the list of games in a listbox, preserving selections
-void LANEnableStartButton(Bool enabled);
-
-void LANDisplaySlotList( void ); ///< Displays the slot list according to TheLANGameInfo
-void LANDisplayGameOptions( void ); ///< Displays the game options according to TheLANGameInfo
-
-AsciiString GenerateGameOptionsString( void );
-Bool ParseGameOptionsString(LANGameInfo *game, AsciiString options);
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/LANPlayer.h b/Generals/Code/GameEngine/Include/GameNetwork/LANPlayer.h
deleted file mode 100644
index e87f3880b68..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/LANPlayer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// LANPlayer.h ///////////////////////////////////////////////////////////////
-// LAN Player Class used for both the LANAPI and LANGameInfo
-// Author: Matthew D. Campbell, October 2001 (Pulled out of LANAPI.h by CLH on 12/21/01
-
-#pragma once
-
-/**
- * LAN player class. This is for players sitting in the lobby. Players are
- * uniquely identified by their IP addresses.
- */
-class LANPlayer
-{
-public:
- LANPlayer() { m_name = m_login = m_host = L""; m_lastHeard = 0; m_next = NULL; m_IP = 0; }
-
- // Access functions
- inline UnicodeString getName( void ) { return m_name; }
- inline void setName( UnicodeString name ) { m_name = name; }
- inline UnicodeString getLogin( void ) { return m_login; }
- inline void setLogin( UnicodeString name ) { m_login = name; }
- inline void setLogin( AsciiString name ) { m_login.translate(name); }
- inline UnicodeString getHost( void ) { return m_host; }
- inline void setHost( UnicodeString name ) { m_host = name; }
- inline void setHost( AsciiString name ) { m_host.translate(name); }
- inline UnsignedInt getLastHeard( void ) { return m_lastHeard; }
- inline void setLastHeard( UnsignedInt lastHeard ) { m_lastHeard = lastHeard; }
- inline LANPlayer *getNext( void ) { return m_next; }
- inline void setNext( LANPlayer *next ) { m_next = next; }
- inline UnsignedInt getIP( void ) { return m_IP; }
- inline void setIP( UnsignedInt IP ) { m_IP = IP; }
-
-protected:
- UnicodeString m_name; ///< Player name
- UnicodeString m_login; ///< login name
- UnicodeString m_host; ///< machine name
- UnsignedInt m_lastHeard; ///< The last time we heard from this player (for timeout purposes)
- LANPlayer *m_next; ///< Linked list pointer
- UnsignedInt m_IP; ///< Player's IP
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NAT.h b/Generals/Code/GameEngine/Include/GameNetwork/NAT.h
deleted file mode 100644
index 499b84d6ff6..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NAT.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: NAT.h /////////////////////////////////////////////////////////////////////////////////
-// Author: Bryan Cleveland April 2002
-// Desc: Resolves NAT'd IPs and port numbers for the other players in a game.
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Lib/BaseType.h"
-#include "GameNetwork/NetworkInterface.h"
-#include "GameNetwork/FirewallHelper.h"
-
-class Transport;
-class GameSlot;
-
-enum NATStateType CPP_11(: Int) {
- NATSTATE_IDLE,
- NATSTATE_DOCONNECTIONPATHS,
- NATSTATE_WAITFORSTATS,
- NATSTATE_DONE,
- NATSTATE_FAILED
-};
-
-enum NATConnectionState CPP_11(: Int) {
- NATCONNECTIONSTATE_NOSTATE,
- NATCONNECTIONSTATE_WAITINGTOBEGIN,
-// NATCONNECTIONSTATE_NETGEARDELAY,
- NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE,
- NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT,
- NATCONNECTIONSTATE_WAITINGFORRESPONSE,
- NATCONNECTIONSTATE_DONE,
- NATCONNECTIONSTATE_FAILED
-};
-
-struct ConnectionNodeType {
- FirewallHelperClass::tFirewallBehaviorType m_behavior; ///< the NAT/Firewall behavior of this node.
- UnsignedInt m_slotIndex; ///< the player list index of this node.
-};
-
-class NAT {
-public:
- NAT();
- virtual ~NAT();
-
- NATStateType update();
-
- void attachSlotList(GameSlot **slotList, Int localSlot, UnsignedInt localIP);
- void establishConnectionPaths();
-
- Int getSlotPort(Int slot);
- Transport * getTransport(); ///< return the newly created Transport layer that has all the connections and whatnot.
-
- // Notification messages from GameSpy
- void processGlobalMessage(Int slotNum, const char *options);
-
-protected:
- NATConnectionState connectionUpdate(); ///< the update function for the connections.
- void sendMangledSourcePort(); ///< starts the process to get the next mangled source port.
- void processManglerResponse(UnsignedShort mangledPort);
-
- Bool allConnectionsDoneThisRound();
- Bool allConnectionsDone();
-
- void generatePortNumbers(GameSlot **slotList, Int localSlot); ///< generate all of the slots' port numbers to be used.
-
- void doThisConnectionRound(); ///< compute who will connect with who for this round.
- void setConnectionState(Int nodeNumber, NATConnectionState state); ///< central point for changing a connection's state.
- void sendAProbe(UnsignedInt ip, UnsignedShort port, Int fromNode); ///< send a "PROBE" packet to this IP and port.
- void notifyTargetOfProbe(GameSlot *targetSlot);
- void notifyUsersOfConnectionDone(Int nodeIndex);
- void notifyUsersOfConnectionFailed(Int nodeIndex);
- void sendMangledPortNumberToTarget(UnsignedShort mangledPort, GameSlot *targetSlot);
-
- void probed(Int nodeNumber);
- void gotMangledPort(Int nodeNumber, UnsignedShort mangledPort);
- void gotInternalAddress(Int nodeNumber, UnsignedInt address);
- void connectionComplete(Int slotIndex);
- void connectionFailed(Int slotIndex);
-
- Transport *m_transport;
- GameSlot **m_slotList;
- NATStateType m_NATState;
- Int m_localNodeNumber; ///< The node number of the local player.
- Int m_targetNodeNumber; ///< The node number of the player we are connecting to this round.
- UnsignedInt m_localIP; ///< The IP of the local computer.
- UnsignedInt m_numNodes; ///< The number of players we have to connect together.
- UnsignedInt m_connectionRound; ///< The "round" of connections we are currently on.
-
- Int m_numRetries;
- Int m_maxNumRetriesAllowed;
-
- UnsignedShort m_packetID;
- UnsignedShort m_spareSocketPort;
- time_t m_manglerRetryTime;
- Int m_manglerRetries;
- UnsignedShort m_previousSourcePort;
-
- Bool m_beenProbed; ///< have I been notified that I've been probed this round?
-
- UnsignedInt m_manglerAddress;
-
- time_t m_timeTillNextSend; ///< The number of milliseconds till we send to the other guy's port again.
- NATConnectionState m_connectionStates[MAX_SLOTS]; ///< connection states for this round for all the nodes.
-
- ConnectionNodeType m_connectionNodes[MAX_SLOTS]; ///< info regarding the nodes that are being connected.
-
- UnsignedShort m_sourcePorts[MAX_SLOTS]; ///< the source ports that the other players communicate to us on.
-
- Bool m_myConnections[MAX_SLOTS]; ///< keeps track of all the nodes I've connected to. For keepalive.
- time_t m_nextKeepaliveTime; ///< the next time we will send out our keepalive packets.
-
- static Int m_connectionPairs[MAX_SLOTS-1][MAX_SLOTS-1][MAX_SLOTS];
- Int m_connectionPairIndex;
-
- UnsignedShort m_startingPortNumber; ///< the starting port number for this game. The slots all get port numbers with their port numbers based on this number.
- ///< this is done so that games that are played right after each other with the same players in the same
- ///< slot order will not use the old source port allocation scheme in case their NAT
- ///< hasn't timed out that connection.
-
- time_t m_nextPortSendTime; ///< Last time we sent our mangled port number to our target this round.
-
- time_t m_timeoutTime; ///< the time at which we will time out waiting for the other player's port number.
- time_t m_roundTimeout; ///< the time at which we will time out this connection round.
-
- static Int m_timeBetweenRetries; // 1 second between retries sounds good to me.
- static time_t m_manglerRetryTimeInterval; // sounds good to me.
- static Int m_maxAllowedManglerRetries; // works for me.
- static time_t m_keepaliveInterval; // 15 seconds between keepalive packets seems good.
- static time_t m_timeToWaitForPort; // wait for ten seconds for the other player's port number.
- static time_t m_timeForRoundTimeout; // wait for at most ten seconds for each connection round to finish.
-
-};
-
-extern NAT *TheNAT;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandList.h b/Generals/Code/GameEngine/Include/GameNetwork/NetCommandList.h
deleted file mode 100644
index 2497f904fd6..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandList.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/GameMemory.h"
-#include "GameNetwork/NetCommandRef.h"
-
-/**
- * The NetCommandList is a ordered linked list of NetCommandRef objects.
- * The list is ordered based on the command id, player id, and command type.
- * It is ordered in this way to aid in constructing the packets efficiently.
- * The list keeps track of the last message inserted in order to accommodate
- * adding commands in order more efficiently since that is whats going to be
- * done most of the time. If the new message doesn't go after the last message
- * inserted, then the list will be traversed linearly until the proper spot is
- * found. We can get away with this inefficient method since these occurances
- * will be rare. Also, the list is not expected to ever have more than 30 or so
- * commands on it at a time. Five commands would probably be a normal amount.
- */
-
-class NetCommandList : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetCommandList, "NetCommandList")
-public:
- NetCommandList();
- //virtual ~NetCommandList();
-
- void init(); ///< Initialize the list
- void reset(); ///< Reset the list to the initial state.
- NetCommandRef * addMessage(NetCommandMsg *cmdMsg); ///< Add message to the list in its properly ordered place.
- Bool isEqualCommandMsg(NetCommandMsg *msg1, NetCommandMsg *msg2);
- NetCommandRef * getFirstMessage(); ///< Get the first message on the list.
- NetCommandRef * findMessage(NetCommandMsg *msg); ///< Find and return a reference to the given message if one exists.
- NetCommandRef * findMessage(UnsignedShort commandID, UnsignedByte playerID); ///< Find and return a reference to the
- ///< message given the player id and the command id.
- ///< This will only check against messages of types that require
- ///< a command id.
- void removeMessage(NetCommandRef *msg); ///< Remove the given message from the list.
- void appendList(NetCommandList *list); ///< Append the given list to the end of this list.
- Int length(); ///< Returns the number of nodes in this list. This is inefficient and is meant to be a debug tool.
-
-protected:
- NetCommandRef *m_first; ///< Head of the list.
- NetCommandRef *m_last; ///< Tail of the list.
- NetCommandRef *m_lastMessageInserted; ///< The last message that was inserted to this list.
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandMsg.h b/Generals/Code/GameEngine/Include/GameNetwork/NetCommandMsg.h
deleted file mode 100644
index 4c585bb3555..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandMsg.h
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-//------------------------------------------------------------------------------------
-// The CommandMsg class is a linked-list wrapper around GameMessage objects that
-// are queued up to execute at a later time
-
-#pragma once
-
-#include "Lib/BaseType.h"
-#include "GameNetwork/NetworkDefs.h"
-#include "Common/UnicodeString.h"
-
-//-----------------------------------------------------------------------------
-class NetCommandMsg : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetCommandMsg, "NetCommandMsg")
-public:
- NetCommandMsg();
- //virtual ~NetCommandMsg();
- inline UnsignedInt GetTimestamp() { return m_timestamp; }
- inline void SetTimestamp(UnsignedInt timestamp) { m_timestamp = timestamp; }
- inline void setExecutionFrame(UnsignedInt frame) { m_executionFrame = frame; }
- inline void setPlayerID(UnsignedInt playerID) { m_playerID = playerID; }
- inline void setID(UnsignedShort id) { m_id = id; }
- inline UnsignedInt getExecutionFrame() { return m_executionFrame; }
- inline UnsignedInt getPlayerID() { return m_playerID; }
- inline UnsignedShort getID() { return m_id; }
- inline void setNetCommandType(NetCommandType type) { m_commandType = type; }
- inline NetCommandType getNetCommandType() { return m_commandType; }
- virtual Int getSortNumber();
- void attach();
- void detach();
-
-protected:
- UnsignedInt m_timestamp;
- UnsignedInt m_executionFrame;
- UnsignedInt m_playerID;
- UnsignedShort m_id;
-
- NetCommandType m_commandType;
- Int m_referenceCount;
-};
-
-
-//-----------------------------------------------------------------------------
-/**
- * The NetGameCommandMsg is the NetCommandMsg representation of a GameMessage
- */
-class NetGameCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetGameCommandMsg, "NetGameCommandMsg")
-public:
- NetGameCommandMsg();
- NetGameCommandMsg(GameMessage *msg);
- //virtual ~NetGameCommandMsg();
-
- GameMessage *constructGameMessage();
- void addArgument(const GameMessageArgumentDataType type, GameMessageArgumentType arg);
- void setGameMessageType(GameMessage::Type type);
-
-protected:
- Int m_numArgs;
- Int m_argSize;
- GameMessage::Type m_type;
- GameMessageArgument *m_argList, *m_argTail;
-};
-
-//-----------------------------------------------------------------------------
-/**
- * The NetAckBothCommandMsg is the NetCommandMsg representation of the combination of a
- * stage 1 ack and a stage 2 ack.
- */
-class NetAckBothCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetAckBothCommandMsg, "NetAckBothCommandMsg")
-public:
- NetAckBothCommandMsg(NetCommandMsg *msg);
- NetAckBothCommandMsg();
- //virtual ~NetAckBothCommandMsg();
-
- UnsignedShort getCommandID();
- void setCommandID(UnsignedShort commandID);
- UnsignedByte getOriginalPlayerID();
- void setOriginalPlayerID(UnsignedByte originalPlayerID);
- virtual Int getSortNumber();
-
-protected:
- UnsignedShort m_commandID;
- UnsignedByte m_originalPlayerID;
-};
-
-//-----------------------------------------------------------------------------
-/**
- * The NetAckStage1CommandMsg is the NetCommandMsg representation of an ack message for the initial
- * recipient.
- */
-class NetAckStage1CommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetAckStage1CommandMsg, "NetAckStage1CommandMsg")
-public:
- NetAckStage1CommandMsg(NetCommandMsg *msg);
- NetAckStage1CommandMsg();
- //virtual ~NetAckStage1CommandMsg();
-
- UnsignedShort getCommandID();
- void setCommandID(UnsignedShort commandID);
- UnsignedByte getOriginalPlayerID();
- void setOriginalPlayerID(UnsignedByte originalPlayerID);
- virtual Int getSortNumber();
-
-protected:
- UnsignedShort m_commandID;
- UnsignedByte m_originalPlayerID;
-};
-
-//-----------------------------------------------------------------------------
-/**
- * The NetAckStage2CommandMsg is the NetCommandMsg representation of an ack message for all eventual
- * recipients. (when this is returned, all the players in the relay mask have received the packet)
- */
-class NetAckStage2CommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetAckStage2CommandMsg, "NetAckStage2CommandMsg")
-public:
- NetAckStage2CommandMsg(NetCommandMsg *msg);
- NetAckStage2CommandMsg();
- //virtual ~NetAckStage2CommandMsg();
-
- UnsignedShort getCommandID();
- void setCommandID(UnsignedShort commandID);
- UnsignedByte getOriginalPlayerID();
- void setOriginalPlayerID(UnsignedByte originalPlayerID);
- virtual Int getSortNumber();
-
-protected:
- UnsignedShort m_commandID;
- UnsignedByte m_originalPlayerID;
-};
-
-//-----------------------------------------------------------------------------
-class NetFrameCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetFrameCommandMsg, "NetFrameCommandMsg")
-public:
- NetFrameCommandMsg();
- //virtual ~NetFrameCommandMsg();
-
- void setCommandCount(UnsignedShort commandCount);
- UnsignedShort getCommandCount();
-
-protected:
- UnsignedShort m_commandCount;
-};
-
-//-----------------------------------------------------------------------------
-class NetPlayerLeaveCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetPlayerLeaveCommandMsg, "NetPlayerLeaveCommandMsg")
-public:
- NetPlayerLeaveCommandMsg();
- //virtual ~NetPlayerLeaveCommandMsg();
-
- UnsignedByte getLeavingPlayerID();
- void setLeavingPlayerID(UnsignedByte id);
-
-protected:
- UnsignedByte m_leavingPlayerID;
-};
-
-//-----------------------------------------------------------------------------
-class NetRunAheadMetricsCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetRunAheadMetricsCommandMsg, "NetRunAheadMetricsCommandMsg")
-public:
- NetRunAheadMetricsCommandMsg();
- //virtual ~NetRunAheadMetricsCommandMsg();
-
- Real getAverageLatency();
- void setAverageLatency(Real avgLat);
- Int getAverageFps();
- void setAverageFps(Int fps);
-
-protected:
- Real m_averageLatency;
- Int m_averageFps;
-};
-
-//-----------------------------------------------------------------------------
-class NetRunAheadCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetRunAheadCommandMsg, "NetRunAheadCommandMsg")
-public:
- NetRunAheadCommandMsg();
- //virtual ~NetRunAheadCommandMsg();
-
- UnsignedShort getRunAhead();
- void setRunAhead(UnsignedShort runAhead);
-
- UnsignedByte getFrameRate();
- void setFrameRate(UnsignedByte frameRate);
-
-protected:
- UnsignedShort m_runAhead;
- UnsignedByte m_frameRate;
-};
-
-//-----------------------------------------------------------------------------
-class NetDestroyPlayerCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetDestroyPlayerCommandMsg, "NetDestroyPlayerCommandMsg")
-public:
- NetDestroyPlayerCommandMsg();
- //virtual ~NetDestroyPlayerCommandMsg();
-
- UnsignedInt getPlayerIndex();
- void setPlayerIndex(UnsignedInt playerIndex);
-
-protected:
- UnsignedInt m_playerIndex;
-};
-
-//-----------------------------------------------------------------------------
-class NetKeepAliveCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetKeepAliveCommandMsg, "NetKeepAliveCommandMsg")
-public:
- NetKeepAliveCommandMsg();
- //virtual ~NetKeepAliveCommandMsg();
-};
-
-//-----------------------------------------------------------------------------
-class NetDisconnectKeepAliveCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetDisconnectKeepAliveCommandMsg, "NetDisconnectKeepAliveCommandMsg")
-public:
- NetDisconnectKeepAliveCommandMsg();
- //virtual ~NetDisconnectKeepAliveCommandMsg();
-};
-
-//-----------------------------------------------------------------------------
-class NetDisconnectPlayerCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetDisconnectPlayerCommandMsg, "NetDisconnectPlayerCommandMsg")
-public:
- NetDisconnectPlayerCommandMsg();
- //virtual ~NetDisconnectPlayerCommandMsg();
-
- UnsignedByte getDisconnectSlot();
- void setDisconnectSlot(UnsignedByte slot);
-
- UnsignedInt getDisconnectFrame();
- void setDisconnectFrame(UnsignedInt frame);
-
-protected:
- UnsignedByte m_disconnectSlot;
- UnsignedInt m_disconnectFrame;
-};
-
-//-----------------------------------------------------------------------------
-class NetPacketRouterQueryCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetPacketRouterQueryCommandMsg, "NetPacketRouterQueryCommandMsg")
-public:
- NetPacketRouterQueryCommandMsg();
- //virtual ~NetPacketRouterQueryCommandMsg();
-};
-
-//-----------------------------------------------------------------------------
-class NetPacketRouterAckCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetPacketRouterAckCommandMsg, "NetPacketRouterAckCommandMsg")
-public:
- NetPacketRouterAckCommandMsg();
- //virtual ~NetPacketRouterAckCommandMsg();
-};
-
-//-----------------------------------------------------------------------------
-class NetDisconnectChatCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetDisconnectChatCommandMsg, "NetDisconnectChatCommandMsg")
-public:
- NetDisconnectChatCommandMsg();
- //virtual ~NetDisconnectChatCommandMsg();
-
- UnicodeString getText();
- void setText(UnicodeString text);
-
-protected:
- UnicodeString m_text;
-};
-
-//-----------------------------------------------------------------------------
-class NetChatCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetChatCommandMsg, "NetChatCommandMsg")
-public:
- NetChatCommandMsg();
- //virtual ~NetChatCommandMsg();
-
- UnicodeString getText();
- void setText(UnicodeString text);
-
- Int getPlayerMask( void );
- void setPlayerMask( Int playerMask );
-
-protected:
- UnicodeString m_text;
- Int m_playerMask;
-};
-
-//-----------------------------------------------------------------------------
-class NetDisconnectVoteCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetDisconnectVoteCommandMsg, "NetDisconnectVoteCommandMsg")
-public:
- NetDisconnectVoteCommandMsg();
- //virtual ~NetDisconnectVoteCommandMsg();
-
- UnsignedByte getSlot();
- void setSlot(UnsignedByte slot);
-
- UnsignedInt getVoteFrame();
- void setVoteFrame(UnsignedInt voteFrame);
-
-protected:
- UnsignedByte m_slot;
- UnsignedInt m_voteFrame;
-};
-
-//-----------------------------------------------------------------------------
-class NetProgressCommandMsg: public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetProgressCommandMsg, "NetProgressCommandMsg")
-public:
- NetProgressCommandMsg( void );
- //virtual ~NetProgressCommandMsg( void );
-
- UnsignedByte getPercentage();
- void setPercentage( UnsignedByte percent );
-protected:
- UnsignedByte m_percent;
-};
-
-//-----------------------------------------------------------------------------
-class NetWrapperCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetWrapperCommandMsg, "NetWrapperCommandMsg")
-public:
- NetWrapperCommandMsg( void );
- //virtual ~NetWrapperCommandMsg();
-
- UnsignedByte * getData();
- void setData(UnsignedByte *data, UnsignedInt dataLength);
-
- UnsignedInt getChunkNumber();
- void setChunkNumber(UnsignedInt chunkNumber);
-
- UnsignedInt getNumChunks();
- void setNumChunks(UnsignedInt numChunks);
-
- UnsignedInt getDataLength();
-
- UnsignedInt getTotalDataLength();
- void setTotalDataLength(UnsignedInt totalDataLength);
-
- UnsignedInt getDataOffset();
- void setDataOffset(UnsignedInt offset);
-
- UnsignedShort getWrappedCommandID();
- void setWrappedCommandID(UnsignedShort wrappedCommandID);
-
-private:
- UnsignedByte *m_data;
- // using UnsignedInt's so we can send around files of effectively unlimited size easily
- UnsignedInt m_dataLength;
- UnsignedInt m_dataOffset;
- UnsignedInt m_totalDataLength;
- UnsignedInt m_chunkNumber;
- UnsignedInt m_numChunks;
- UnsignedShort m_wrappedCommandID;
-};
-
-//-----------------------------------------------------------------------------
-class NetFileCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetFileCommandMsg, "NetFileCommandMsg")
-public:
- NetFileCommandMsg();
- //virtual ~NetFileCommandMsg();
-
- AsciiString getRealFilename();
- void setRealFilename(AsciiString filename);
-
- AsciiString getPortableFilename() { return m_portableFilename; }
- void setPortableFilename(AsciiString filename) { m_portableFilename = filename; }
-
- UnsignedInt getFileLength();
-
- UnsignedByte * getFileData();
- void setFileData(UnsignedByte *data, UnsignedInt dataLength);
-
-protected:
- AsciiString m_portableFilename;
-
- UnsignedByte *m_data;
- UnsignedInt m_dataLength;
-};
-
-//-----------------------------------------------------------------------------
-class NetFileAnnounceCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetFileAnnounceCommandMsg, "NetFileAnnounceCommandMsg")
-public:
- NetFileAnnounceCommandMsg();
- //virtual ~NetFileAnnounceCommandMsg();
-
- AsciiString getRealFilename();
- void setRealFilename(AsciiString filename);
-
- AsciiString getPortableFilename() { return m_portableFilename; }
- void setPortableFilename(AsciiString filename) { m_portableFilename = filename; }
-
- UnsignedShort getFileID();
- void setFileID(UnsignedShort fileID);
-
- UnsignedByte getPlayerMask(void);
- void setPlayerMask(UnsignedByte playerMask);
-
-protected:
- AsciiString m_portableFilename;
- UnsignedShort m_fileID;
- UnsignedByte m_playerMask;
-};
-
-//-----------------------------------------------------------------------------
-class NetFileProgressCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetFileProgressCommandMsg, "NetFileProgressCommandMsg")
-public:
- NetFileProgressCommandMsg();
- //virtual ~NetFileProgressCommandMsg();
-
- UnsignedShort getFileID();
- void setFileID(UnsignedShort val);
-
- Int getProgress();
- void setProgress(Int val);
-
-protected:
- UnsignedShort m_fileID;
- Int m_progress;
-};
-
-//-----------------------------------------------------------------------------
-class NetDisconnectFrameCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetDisconnectFrameCommandMsg, "NetDisconnectFrameCommandMsg")
-public:
- NetDisconnectFrameCommandMsg();
-
- UnsignedInt getDisconnectFrame();
- void setDisconnectFrame(UnsignedInt disconnectFrame);
-
-protected:
- UnsignedInt m_disconnectFrame;
-};
-
-//-----------------------------------------------------------------------------
-class NetDisconnectScreenOffCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetDisconnectScreenOffCommandMsg, "NetDisconnectScreenOffCommandMsg")
-public:
- NetDisconnectScreenOffCommandMsg();
-
- UnsignedInt getNewFrame();
- void setNewFrame(UnsignedInt newFrame);
-
-protected:
- UnsignedInt m_newFrame;
-};
-
-//-----------------------------------------------------------------------------
-class NetFrameResendRequestCommandMsg : public NetCommandMsg
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetFrameResendRequestCommandMsg, "NetFrameResendRequestCommandMsg")
-public:
- NetFrameResendRequestCommandMsg();
-
- UnsignedInt getFrameToResend();
- void setFrameToResend(UnsignedInt frame);
-
-protected:
- UnsignedInt m_frameToResend;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandRef.h b/Generals/Code/GameEngine/Include/GameNetwork/NetCommandRef.h
deleted file mode 100644
index a5321e4df2e..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandRef.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "GameNetwork/NetCommandMsg.h"
-#include "Common/GameMemory.h"
-
-#if defined(RTS_DEBUG)
-// #define DEBUG_NETCOMMANDREF
-#endif
-
-#ifdef DEBUG_NETCOMMANDREF
-#define NEW_NETCOMMANDREF(msg) newInstance(NetCommandRef)(msg, __FILE__, __LINE__)
-#else
-#define NEW_NETCOMMANDREF(msg) newInstance(NetCommandRef)(msg)
-#endif
-
-
-class NetCommandRef : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetCommandRef, "NetCommandRef")
-public:
-#ifdef DEBUG_NETCOMMANDREF
- NetCommandRef(NetCommandMsg *msg, char *filename, int line);
-#else
- NetCommandRef(NetCommandMsg *msg);
-#endif
- //~NetCommandRef();
-
- NetCommandMsg *getCommand();
- NetCommandRef *getNext();
- NetCommandRef *getPrev();
- void setNext(NetCommandRef *next);
- void setPrev(NetCommandRef *prev);
-
- void setRelay(UnsignedByte relay);
- UnsignedByte getRelay() const;
-
- time_t getTimeLastSent() const;
- void setTimeLastSent(time_t timeLastSent);
-
-protected:
- NetCommandMsg *m_msg;
- NetCommandRef *m_next;
- NetCommandRef *m_prev;
- UnsignedByte m_relay; ///< Need this in the command reference since the relay value will be different depending on where this particular reference is being sent.
- time_t m_timeLastSent;
-
-#ifdef DEBUG_NETCOMMANDREF
- UnsignedInt m_id;
-#endif
-};
-
-/**
- * Return the command message.
- */
-inline NetCommandMsg * NetCommandRef::getCommand()
-{
- return m_msg;
-}
-
-/**
- * Return the next command ref in the list.
- */
-inline NetCommandRef * NetCommandRef::getNext()
-{
- return m_next;
-}
-
-/**
- * Return the previous command ref in the list.
- */
-inline NetCommandRef * NetCommandRef::getPrev()
-{
- return m_prev;
-}
-
-/**
- * Set the next command ref in the list.
- */
-inline void NetCommandRef::setNext(NetCommandRef *next)
-{
- m_next = next;
-}
-
-/**
- * Set the previous command ref in the list.
- */
-inline void NetCommandRef::setPrev(NetCommandRef *prev)
-{
- m_prev = prev;
-}
-
-/**
- * Return the time for the last time this command was sent from this reference.
- */
-inline time_t NetCommandRef::getTimeLastSent() const
-{
- return m_timeLastSent;
-}
-
-/**
- * Set the time for the last time this command was sent from this reference.
- */
-inline void NetCommandRef::setTimeLastSent(time_t timeLastSent)
-{
- m_timeLastSent = timeLastSent;
-}
-
-/**
- * Set the send relay for this reference of the command.
- */
-inline void NetCommandRef::setRelay(UnsignedByte relay)
-{
- m_relay = relay;
-}
-
-/**
- * Return the send relay for this refreence of the command.
- */
-inline UnsignedByte NetCommandRef::getRelay() const
-{
- return m_relay;
-}
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandWrapperList.h b/Generals/Code/GameEngine/Include/GameNetwork/NetCommandWrapperList.h
deleted file mode 100644
index e61f43d7e14..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NetCommandWrapperList.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-////// NetCommandWrapperList.h ////////////////////////////////
-// Bryan Cleveland
-
-#pragma once
-
-#include "GameNetwork/NetCommandList.h"
-
-class NetCommandWrapperListNode : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetCommandWrapperListNode, "NetCommandWrapperListNode")
-public:
- NetCommandWrapperListNode(NetWrapperCommandMsg *msg);
- //virtual ~NetCommandWrapperListNode();
-
- Bool isComplete();
- UnsignedShort getCommandID();
- UnsignedInt getRawDataLength();
- void copyChunkData(NetWrapperCommandMsg *msg);
- UnsignedByte * getRawData();
-
- Int getPercentComplete(void);
-
- NetCommandWrapperListNode *m_next;
-
-protected:
- UnsignedShort m_commandID;
- UnsignedByte *m_data;
- UnsignedInt m_dataLength;
- Bool *m_chunksPresent;
- UnsignedInt m_numChunks;
- UnsignedInt m_numChunksPresent;
-
-};
-
-class NetCommandWrapperList : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetCommandWrapperList, "NetCommandWrapperList")
-public:
- NetCommandWrapperList();
- //virtual ~NetCommandWrapperList();
-
- void init();
- void reset();
-
- void processWrapper(NetCommandRef *ref);
- NetCommandList * getReadyCommands();
-
- Int getPercentComplete(UnsignedShort wrappedCommandID);
-
-protected:
- void removeFromList(NetCommandWrapperListNode *node);
-
- NetCommandWrapperListNode *m_list;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NetPacket.h b/Generals/Code/GameEngine/Include/GameNetwork/NetPacket.h
deleted file mode 100644
index bf657ae5c06..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NetPacket.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-/*
-Ok, how this should have been done is to make each of the command types
-have a bitmask telling which command message header information
-each command type required. That would make finding out the size of
-a particular command easier to find, without so much repetitious code.
-We would still need to have a separate function for each command type
-for the data, but at least that wouldn't be repeating code, that would
-be specialized code.
-*/
-
-#pragma once
-
-#include "NetworkDefs.h"
-
-#include "GameNetwork/NetCommandList.h"
-#include "Common/MessageStream.h"
-#include "Common/GameMemory.h"
-
-class NetPacket;
-
-typedef std::list NetPacketList;
-typedef std::list::iterator NetPacketListIter;
-
-class NetPacket : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(NetPacket, "NetPacket")
-public:
- NetPacket();
- NetPacket(TransportMessage *msg);
- //virtual ~NetPacket();
-
- void init();
- void reset();
- void setAddress(Int addr, Int port);
- Bool addCommand(NetCommandRef *msg);
- Int getNumCommands();
-
- NetCommandList *getCommandList();
-
- static NetCommandRef * ConstructNetCommandMsgFromRawData(UnsignedByte *data, UnsignedShort dataLength);
- static NetPacketList ConstructBigCommandPacketList(NetCommandRef *ref);
-
- UnsignedByte *getData();
- Int getLength();
- UnsignedInt getAddr();
- UnsignedShort getPort();
-
-protected:
- static UnsignedInt GetBufferSizeNeededForCommand(NetCommandMsg *msg);
- static void FillBufferWithCommand(UnsignedByte *buffer, NetCommandRef *msg);
-
- // These functions return the size of the command without any compression, repetition, etc.
- // i.e. All of the required fields are taken into account when returning the size.
- static UnsignedInt GetGameCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetAckCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetFrameCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetPlayerLeaveCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetRunAheadMetricsCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetRunAheadCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetDestroyPlayerCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetKeepAliveCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetDisconnectKeepAliveCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetDisconnectPlayerCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetPacketRouterQueryCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetPacketRouterAckCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetDisconnectChatCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetDisconnectVoteCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetChatCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetProgressMessageSize(NetCommandMsg *msg);
- static UnsignedInt GetLoadCompleteMessageSize(NetCommandMsg *msg);
- static UnsignedInt GetTimeOutGameStartMessageSize(NetCommandMsg *msg);
- static UnsignedInt GetWrapperCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetFileCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetFileAnnounceCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetFileProgressCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetDisconnectFrameCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetDisconnectScreenOffCommandSize(NetCommandMsg *msg);
- static UnsignedInt GetFrameResendRequestCommandSize(NetCommandMsg *msg);
-
- static void FillBufferWithGameCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithAckCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithFrameCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithPlayerLeaveCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithRunAheadMetricsCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithRunAheadCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithDestroyPlayerCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithKeepAliveCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithDisconnectKeepAliveCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithDisconnectPlayerCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithPacketRouterQueryCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithPacketRouterAckCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithDisconnectChatCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithDisconnectVoteCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithChatCommand(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithProgressMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithLoadCompleteMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithTimeOutGameStartMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithFileMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithFileProgressMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithFileAnnounceMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithDisconnectFrameMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithDisconnectScreenOffMessage(UnsignedByte *buffer, NetCommandRef *msg);
- static void FillBufferWithFrameResendRequestMessage(UnsignedByte *buffer, NetCommandRef *msg);
-
- Bool addFrameCommand(NetCommandRef *msg);
- Bool isRoomForFrameMessage(NetCommandRef *msg);
- Bool addAckCommand(NetCommandRef *msg, UnsignedShort commandID, UnsignedByte originalPlayerID);
- Bool addAckStage1Command(NetCommandRef *msg);
- Bool addAckStage2Command(NetCommandRef *msg);
- Bool addAckBothCommand(NetCommandRef *msg);
- Bool isRoomForAckMessage(NetCommandRef *msg);
- Bool addGameCommand(NetCommandRef *msg);
- Bool isRoomForGameMessage(NetCommandRef *msg, GameMessage *gmsg);
- Bool addPlayerLeaveCommand(NetCommandRef *msg);
- Bool isRoomForPlayerLeaveMessage(NetCommandRef *msg);
- Bool addRunAheadMetricsCommand(NetCommandRef *msg);
- Bool isRoomForRunAheadMetricsMessage(NetCommandRef *msg);
- Bool addRunAheadCommand(NetCommandRef *msg);
- Bool isRoomForRunAheadMessage(NetCommandRef *msg);
- Bool addDestroyPlayerCommand(NetCommandRef *msg);
- Bool isRoomForDestroyPlayerMessage(NetCommandRef *msg);
- Bool addKeepAliveCommand(NetCommandRef *msg);
- Bool isRoomForKeepAliveMessage(NetCommandRef *msg);
- Bool addDisconnectKeepAliveCommand(NetCommandRef *msg);
- Bool isRoomForDisconnectKeepAliveMessage(NetCommandRef *msg);
- Bool addDisconnectPlayerCommand(NetCommandRef *msg);
- Bool isRoomForDisconnectPlayerMessage(NetCommandRef *msg);
- Bool addPacketRouterQueryCommand(NetCommandRef *msg);
- Bool isRoomForPacketRouterQueryMessage(NetCommandRef *msg);
- Bool addPacketRouterAckCommand(NetCommandRef *msg);
- Bool isRoomForPacketRouterAckMessage(NetCommandRef *msg);
- Bool addDisconnectChatCommand(NetCommandRef *msg);
- Bool isRoomForDisconnectChatMessage(NetCommandRef *msg);
- Bool addChatCommand(NetCommandRef *msg);
- Bool isRoomForChatMessage(NetCommandRef *msg);
- Bool addDisconnectVoteCommand(NetCommandRef *msg);
- Bool isRoomForDisconnectVoteMessage(NetCommandRef *msg);
- Bool addProgressMessage( NetCommandRef *msg );
- Bool isRoomForProgressMessage( NetCommandRef *msg );
- Bool addLoadCompleteMessage( NetCommandRef *msg );
- Bool isRoomForLoadCompleteMessage( NetCommandRef *msg );
- Bool addTimeOutGameStartMessage( NetCommandRef *msg );
- Bool isRoomForTimeOutGameStartMessage( NetCommandRef *msg );
- Bool addWrapperCommand(NetCommandRef *msg);
- Bool isRoomForWrapperMessage(NetCommandRef *msg);
- Bool addFileCommand(NetCommandRef *msg);
- Bool isRoomForFileMessage(NetCommandRef *msg);
- Bool addFileAnnounceCommand(NetCommandRef *msg);
- Bool isRoomForFileAnnounceMessage(NetCommandRef *msg);
- Bool addFileProgressCommand(NetCommandRef *msg);
- Bool isRoomForFileProgressMessage(NetCommandRef *msg);
- Bool addDisconnectFrameCommand(NetCommandRef *msg);
- Bool isRoomForDisconnectFrameMessage(NetCommandRef *msg);
- Bool addDisconnectScreenOffCommand(NetCommandRef *msg);
- Bool isRoomForDisconnectScreenOffMessage(NetCommandRef *msg);
- Bool addFrameResendRequestCommand(NetCommandRef *msg);
- Bool isRoomForFrameResendRequestMessage(NetCommandRef *msg);
-
- Bool isAckRepeat(NetCommandRef *msg);
- Bool isAckBothRepeat(NetCommandRef *msg);
- Bool isAckStage1Repeat(NetCommandRef *msg);
- Bool isAckStage2Repeat(NetCommandRef *msg);
- Bool isFrameRepeat(NetCommandRef *msg);
-
- static NetCommandMsg * readGameMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readAckBothMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readAckStage1Message(UnsignedByte *data, Int &i);
- static NetCommandMsg * readAckStage2Message(UnsignedByte *data, Int &i);
- static NetCommandMsg * readFrameMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readPlayerLeaveMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readRunAheadMetricsMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readRunAheadMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readDestroyPlayerMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readKeepAliveMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readDisconnectKeepAliveMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readDisconnectPlayerMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readPacketRouterQueryMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readPacketRouterAckMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readDisconnectChatMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readDisconnectVoteMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readChatMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readProgressMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readLoadCompleteMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readTimeOutGameStartMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readWrapperMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readFileMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readFileAnnounceMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readFileProgressMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readDisconnectFrameMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readDisconnectScreenOffMessage(UnsignedByte *data, Int &i);
- static NetCommandMsg * readFrameResendRequestMessage(UnsignedByte *data, Int &i);
-
- void writeGameMessageArgumentToPacket(GameMessageArgumentDataType type, GameMessageArgumentType arg);
- static void readGameMessageArgumentFromPacket(GameMessageArgumentDataType type, NetGameCommandMsg *msg, UnsignedByte *data, Int &i);
-
- void dumpPacketToLog();
-
-protected:
- UnsignedByte m_packet[MAX_PACKET_SIZE];
- Int m_packetLen;
- UnsignedInt m_addr;
- Int m_numCommands;
- NetCommandRef* m_lastCommand;
- UnsignedInt m_lastFrame;
- UnsignedShort m_port;
- UnsignedShort m_lastCommandID;
- UnsignedByte m_lastPlayerID;
- UnsignedByte m_lastCommandType;
- UnsignedByte m_lastRelay;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NetworkDefs.h b/Generals/Code/GameEngine/Include/GameNetwork/NetworkDefs.h
deleted file mode 100644
index 138aaeb9dbb..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NetworkDefs.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Lib/BaseType.h"
-#include "Common/MessageStream.h"
-
-static const Int WOL_NAME_LEN = 64;
-
-/// Max number of commands per frame
-static const Int MAX_COMMANDS = 256;
-
-extern Int MIN_LOGIC_FRAMES;
-extern Int MAX_FRAMES_AHEAD;
-extern Int MIN_RUNAHEAD;
-
-// FRAME_DATA_LENGTH needs to be MAX_FRAMES_AHEAD+1 because a player on a different
-// computer can send commands for a frame that is one beyond twice the max runahead.
-extern Int FRAME_DATA_LENGTH;
-extern Int FRAMES_TO_KEEP;
-
-// This is the connection numbering: 1-8 are for players, 9 is a broadcast con.
-enum ConnectionNumbers CPP_11(: Int)
-{
- MAX_PLAYER = 7, // The index of the highest possible player number. This is 0 based, so the most players allowed in a game is MAX_PLAYER+1.
- NUM_CONNECTIONS
-};
-
-static const Int MAX_SLOTS = MAX_PLAYER+1;
-
-// UDP (8 bytes) + IP header (28 bytes) = 36 bytes total. We want a total packet size of 512, so 512 - 36 = 476
-static const Int MAX_PACKET_SIZE = 476;
-
-/**
- * Command packet - contains frame #, total # of commands, and each command. This is what gets sent
- * to each player every frame
- */
-#define MAX_MESSAGE_LEN 1024
-#define MAX_MESSAGES 128
-static const Int numCommandsPerCommandPacket = (MAX_MESSAGE_LEN - sizeof(UnsignedInt) - sizeof(UnsignedShort))/sizeof(GameMessage);
-#pragma pack(push, 1)
-struct CommandPacket
-{
- UnsignedInt m_frame;
- UnsignedShort m_numCommands;
- unsigned char m_commands[numCommandsPerCommandPacket * sizeof(GameMessage)];
-};
-#pragma pack(pop)
-
-#define MAX_TRANSPORT_STATISTICS_SECONDS 30
-
-#pragma pack(push, 1)
-struct TransportMessageHeader
-{
- UnsignedInt crc; ///< packet-level CRC (must be first in packet)
- UnsignedShort magic; ///< Magic number identifying Generals packets
-// Int id;
-// NetMessageFlags flags;
-};
-#pragma pack(pop)
-
-/**
- * Transport message - encapsulating info kept by the transport layer about each
- * packet. These structs make up the in/out buffers at the transport layer.
- */
-#pragma pack(push, 1)
-struct TransportMessage
-{
- TransportMessageHeader header;
- UnsignedByte data[MAX_MESSAGE_LEN];
- Int length;
- UnsignedInt addr;
- UnsignedShort port;
-};
-#pragma pack(pop)
-
-#if defined(RTS_DEBUG)
-#pragma pack(push, 1)
-struct DelayedTransportMessage
-{
- UnsignedInt deliveryTime;
- TransportMessage message;
-};
-#pragma pack(pop)
-#endif
-
-/**
- * Message types
- */
-enum NetMessageFlag CPP_11(: Int) {
- MSG_ACK = 1,
- MSG_NEEDACK = 2,
- MSG_SEQUENCED = 4,
- MSG_SUPERCEDING = 8
-};
-typedef UnsignedByte NetMessageFlags;
-
-enum NetCommandType CPP_11(: Int) {
- NETCOMMANDTYPE_UNKNOWN = -1,
- NETCOMMANDTYPE_ACKBOTH = 0,
- NETCOMMANDTYPE_ACKSTAGE1,
- NETCOMMANDTYPE_ACKSTAGE2,
- NETCOMMANDTYPE_FRAMEINFO,
- NETCOMMANDTYPE_GAMECOMMAND,
- NETCOMMANDTYPE_PLAYERLEAVE,
- NETCOMMANDTYPE_RUNAHEADMETRICS,
- NETCOMMANDTYPE_RUNAHEAD,
- NETCOMMANDTYPE_DESTROYPLAYER,
- NETCOMMANDTYPE_KEEPALIVE,
- NETCOMMANDTYPE_DISCONNECTCHAT,
- NETCOMMANDTYPE_CHAT,
- NETCOMMANDTYPE_MANGLERQUERY,
- NETCOMMANDTYPE_MANGLERRESPONSE,
- NETCOMMANDTYPE_PROGRESS,
- NETCOMMANDTYPE_LOADCOMPLETE,
- NETCOMMANDTYPE_TIMEOUTSTART,
- NETCOMMANDTYPE_WRAPPER, // A wrapper command that holds a command thats too big to fit in a single packet.
- NETCOMMANDTYPE_FILE,
- NETCOMMANDTYPE_FILEANNOUNCE,
- NETCOMMANDTYPE_FILEPROGRESS,
- NETCOMMANDTYPE_FRAMERESENDREQUEST,
-
- // Disconnect menu command section.
- NETCOMMANDTYPE_DISCONNECTSTART,
- NETCOMMANDTYPE_DISCONNECTKEEPALIVE,
- NETCOMMANDTYPE_DISCONNECTPLAYER,
- NETCOMMANDTYPE_PACKETROUTERQUERY,
- NETCOMMANDTYPE_PACKETROUTERACK,
- NETCOMMANDTYPE_DISCONNECTVOTE,
- NETCOMMANDTYPE_DISCONNECTFRAME,
- NETCOMMANDTYPE_DISCONNECTSCREENOFF,
- NETCOMMANDTYPE_DISCONNECTEND,
-};
-
-enum NetLocalStatus CPP_11(: Int) {
- NETLOCALSTATUS_PREGAME = 0,
- NETLOCALSTATUS_INGAME,
- NETLOCALSTATUS_LEAVING,
- NETLOCALSTATUS_LEFT,
- NETLOCALSTATUS_POSTGAME
-};
-
-enum PlayerLeaveCode CPP_11(: Int) {
- PLAYERLEAVECODE_CLIENT = 0,
- PLAYERLEAVECODE_LOCAL,
- PLAYERLEAVECODE_PACKETROUTER,
- PLAYERLEAVECODE_UNKNOWN
-};
-
-// Magic number for identifying a Generals packet.
-static const UnsignedShort GENERALS_MAGIC_NUMBER = 0xF00D;
-
-// The number of fps history entries.
-//static const Int NETWORK_FPS_HISTORY_LENGTH = 30;
-
-// The number of ping history entries.
-//static const Int NETWORK_LATENCY_HISTORY_LENGTH = 200;
-
-// The number of miliseconds between run ahead metrics things
-//static const Int NETWORK_RUN_AHEAD_METRICS_TIME = 5000;
-
-// The number of cushion values to keep.
-//static const Int NETWORK_CUSHION_HISTORY_LENGTH = 10;
-
-// The amount of slack in the run ahead value. This is the percentage of the calculated run ahead that is added.
-//static const Int NETWORK_RUN_AHEAD_SLACK = 20;
-
-// The number of seconds between when the connections to each player send a keep-alive packet.
-// This should be less than 30 just to keep firewall ports open.
-//static const Int NETWORK_KEEPALIVE_DELAY = 20;
-
-// The number of milliseconds between when the game gets stuck on a frame for a network stall and
-// and when the disconnect dialog comes up.
-//static const Int NETWORK_DISCONNECT_TIME = 5000;
-
-// The number of miliseconds between when a player's last disconnect keep alive command
-// was recieved and when they are considered disconnected from the game.
-//static const Int NETWORK_PLAYER_TIMEOUT_TIME = 60000;
-
-// The base port number used for the transport socket. A players slot number is added to this
-// value to get their actual port number.
-static const Int NETWORK_BASE_PORT_NUMBER = 8088;
-
-// the singleton
-class NetworkInterface;
-extern NetworkInterface *TheNetwork;
-
-#define PRINTF_IP_AS_4_INTS(ip) ((ip) >> 24) & 0xff, ((ip) >> 16) & 0xff, ((ip) >> 8 ) & 0xff, (ip) & 0xff
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/NetworkInterface.h b/Generals/Code/GameEngine/Include/GameNetwork/NetworkInterface.h
deleted file mode 100644
index 74e3942cedd..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/NetworkInterface.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// NetworkInterface.h ///////////////////////////////////////////////////////////////
-// Network singleton class - defines interface to Network methods
-// Author: Matthew D. Campbell, July 2001
-
-#pragma once
-
-#include "Common/MessageStream.h"
-#include "GameNetwork/ConnectionManager.h"
-#include "GameNetwork/User.h"
-#include "GameNetwork/NetworkDefs.h"
-
-// forward declarations
-
-struct CommandPacket;
-class GameMessage;
-class GameInfo;
-
-void ClearCommandPacket(UnsignedInt frame); ///< ClearCommandPacket clears the command packet at the start of the frame.
-CommandPacket *GetCommandPacket(void); ///< TheNetwork calls GetCommandPacket to get commands to send.
-
-
-
-/**
- * Interface definition for the Network.
- */
-class NetworkInterface : public SubsystemInterface
-{
-protected:
-
-public:
- virtual ~NetworkInterface() { };
-
- static NetworkInterface * createNetwork( void );
-
- //---------------------------------------------------------------------------------------
- // SubsystemInterface functions
- virtual void init( void ) = 0; ///< Initialize the network
- virtual void reset( void ) = 0; ///< Re-initialize the network
- virtual void update( void ) = 0; ///< Updates the network
- virtual void liteupdate( void ) = 0; ///< does a lightweight update for passing messages around.
-
- virtual void setLocalAddress(UnsignedInt ip, UnsignedInt port) = 0; ///< Tell the network what local ip and port to bind to.
- virtual Bool isFrameDataReady( void ) = 0; ///< Are the commands for the next frame available?
- virtual Bool isStalling() = 0;
- virtual void parseUserList( const GameInfo *game ) = 0; ///< Parse a userlist, creating connections
- virtual void startGame(void) = 0; ///< Sets the network game frame counter to -1
- virtual UnsignedInt getRunAhead(void) = 0; ///< Get the current RunAhead value
- virtual UnsignedInt getFrameRate(void) = 0; ///< Get the current allowed frame rate.
- virtual UnsignedInt getPacketArrivalCushion(void) = 0; ///< Get the smallest packet arrival cushion since this was last called.
-
- // Chat functions
- virtual void sendChat(UnicodeString text, Int playerMask) = 0; ///< Send a chat line using the normal system.
- virtual void sendDisconnectChat(UnicodeString text) = 0; ///< Send a chat line using the disconnect manager.
-
- virtual void sendFile(AsciiString path, UnsignedByte playerMask, UnsignedShort commandID) = 0;
- virtual UnsignedShort sendFileAnnounce(AsciiString path, UnsignedByte playerMask) = 0;
- virtual Int getFileTransferProgress(Int playerID, AsciiString path) = 0;
- virtual Bool areAllQueuesEmpty(void) = 0;
-
- virtual void quitGame() = 0; ///< Quit the game right now.
-
- virtual void selfDestructPlayer(Int index) = 0;
-
- virtual void voteForPlayerDisconnect(Int slot) = 0; ///< register a vote towards this player's disconnect.
- virtual Bool isPacketRouter( void ) = 0;
-
- // Bandwidth metrics
- virtual Real getIncomingBytesPerSecond( void ) = 0;
- virtual Real getIncomingPacketsPerSecond( void ) = 0;
- virtual Real getOutgoingBytesPerSecond( void ) = 0;
- virtual Real getOutgoingPacketsPerSecond( void ) = 0;
- virtual Real getUnknownBytesPerSecond( void ) = 0;
- virtual Real getUnknownPacketsPerSecond( void ) = 0;
-
- virtual void updateLoadProgress( Int percent ) = 0;
- virtual void loadProgressComplete( void ) = 0;
- virtual void sendTimeOutGameStart( void ) = 0;
- virtual UnsignedInt getLocalPlayerID()= 0;
- virtual UnicodeString getPlayerName(Int playerNum)= 0;
- virtual Int getNumPlayers() = 0;
-
- virtual Int getAverageFPS() = 0;
- virtual Int getSlotAverageFPS(Int slot) = 0;
-
- virtual void attachTransport(Transport *transport) = 0;
- virtual void initTransport() = 0;
- virtual Bool sawCRCMismatch() = 0;
- virtual void setSawCRCMismatch() = 0;
-
- virtual Bool isPlayerConnected(Int playerID) = 0;
-
- virtual void notifyOthersOfCurrentFrame() = 0; ///< Tells all the other players what frame we are on.
- virtual void notifyOthersOfNewFrame(UnsignedInt frame) = 0; ///< Tells all the other players that we are on a new frame.
-
- virtual Int getExecutionFrame() = 0; ///< Returns the next valid frame for simultaneous command execution.
-
-#if defined(RTS_DEBUG)
- virtual void toggleNetworkOn( void ) = 0; ///< toggle whether or not to send network traffic.
-#endif
-
- // For disconnect blame assignment
- virtual UnsignedInt getPingFrame() = 0;
- virtual Int getPingsSent() = 0;
- virtual Int getPingsRecieved() = 0;
-};
-
-
-/**
- * ResolveIP turns a string ("games2.westwood.com", or "192.168.0.1") into
- * a 32-bit unsigned integer.
- */
-UnsignedInt ResolveIP(AsciiString host);
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/RankPointValue.h b/Generals/Code/GameEngine/Include/GameNetwork/RankPointValue.h
deleted file mode 100644
index 973eaedf5c9..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/RankPointValue.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: RankPointValue.h /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Sep 2002
-//
-// Filename: RankPointValue.h
-//
-// author: Chris Huybregts
-//
-// purpose:
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-class Image;
-class PSPlayerStats;
-//-----------------------------------------------------------------------------
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-enum
-{
- RANK_PRIVATE = 0,
- RANK_CORPORAL,
- RANK_SERGEANT,
- RANK_LIEUTENANT,
- RANK_CAPTAIN,
- RANK_MAJOR,
- RANK_COLONEL,
- RANK_BRIGADIER_GENERAL,
- RANK_GENERAL,
- RANK_COMMANDER_IN_CHIEF,
-
- MAX_RANKS
-};
-
-struct RankPoints
-{
-RankPoints(void );
- Int m_ranks[MAX_RANKS];
- Real m_winMultiplier;
- Real m_lostMultiplier;
- Real m_hourSpentOnlineMultiplier;
- Real m_completedSoloCampaigns;
- Real m_disconnectMultiplier;
-};
-//-----------------------------------------------------------------------------
-// INLINING ///////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// EXTERNALS //////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-Int CalculateRank( const PSPlayerStats& stats );
-Int GetFavoriteSide( const PSPlayerStats& stats );
-const Image* LookupSmallRankImage(Int side, Int rankPoints);
-extern RankPoints *TheRankPointValues;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/Transport.h b/Generals/Code/GameEngine/Include/GameNetwork/Transport.h
deleted file mode 100644
index 8701cddd6cf..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/Transport.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// Transport.h ///////////////////////////////////////////////////////////////
-// Transport layer - a thin layer around a UDP socket, with queues.
-// Author: Matthew D. Campbell, July 2001
-
-#pragma once
-
-#include "GameNetwork/udp.h"
-#include "GameNetwork/NetworkDefs.h"
-
-/**
- * The transport layer handles the UDP socket for the game, and will packetize and
- * de-packetize multiple ACK/CommandPacket/etc packets into larger aggregates.
- */
-// we only ever allocate one of there, and it is quite large, so we really DON'T want
-// it to be a MemoryPoolObject (srj)
-class Transport //: public MemoryPoolObject
-{
- //MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Transport, "Transport")
-public:
-
- Transport();
- ~Transport();
-
- Bool init( AsciiString ip, UnsignedShort port );
- Bool init( UnsignedInt ip, UnsignedShort port );
- void reset( void );
- Bool update( void ); ///< Call this once a GameEngine tick, regardless of whether the frame advances.
-
- Bool doRecv( void ); ///< call this to service the receive packets
- Bool doSend( void ); ///< call this to service the send queue.
-
- Bool queueSend(UnsignedInt addr, UnsignedShort port, const UnsignedByte *buf, Int len /*,
- NetMessageFlags flags, Int id */); ///< Queue a packet for sending to the specified address and port. This will be sent on the next update() call.
-
- inline Bool allowBroadcasts(Bool val) { if (!m_udpsock) return false; return (m_udpsock->AllowBroadcasts(val))?true:false; }
-
- // Latency insertion and packet loss
- void setLatency( Bool val ) { m_useLatency = val; }
- void setPacketLoss( Bool val ) { m_usePacketLoss = val; }
-
- // Bandwidth metrics
- Real getIncomingBytesPerSecond( void );
- Real getIncomingPacketsPerSecond( void );
- Real getOutgoingBytesPerSecond( void );
- Real getOutgoingPacketsPerSecond( void );
- Real getUnknownBytesPerSecond( void );
- Real getUnknownPacketsPerSecond( void );
-
- TransportMessage m_outBuffer[MAX_MESSAGES];
- TransportMessage m_inBuffer[MAX_MESSAGES];
-
-#if defined(RTS_DEBUG)
- DelayedTransportMessage m_delayedInBuffer[MAX_MESSAGES];
-#endif
-
- UnsignedShort m_port;
-private:
- Bool m_winsockInit;
- UDP *m_udpsock;
-
- // Latency insertion and packet loss
- Bool m_useLatency;
- Bool m_usePacketLoss;
-
- // Bandwidth metrics
- UnsignedInt m_incomingBytes[MAX_TRANSPORT_STATISTICS_SECONDS];
- UnsignedInt m_unknownBytes[MAX_TRANSPORT_STATISTICS_SECONDS];
- UnsignedInt m_outgoingBytes[MAX_TRANSPORT_STATISTICS_SECONDS];
- UnsignedInt m_incomingPackets[MAX_TRANSPORT_STATISTICS_SECONDS];
- UnsignedInt m_unknownPackets[MAX_TRANSPORT_STATISTICS_SECONDS];
- UnsignedInt m_outgoingPackets[MAX_TRANSPORT_STATISTICS_SECONDS];
- Int m_statisticsSlot;
- UnsignedInt m_lastSecond;
-
- Bool isGeneralsPacket( TransportMessage *msg );
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/User.h b/Generals/Code/GameEngine/Include/GameNetwork/User.h
deleted file mode 100644
index 959137cc0c8..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/User.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * User class used by the network.
- */
-
-#pragma once
-
-#include "GameNetwork/NetworkDefs.h"
-#include "Common/UnicodeString.h"
-
-class User : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(User, "User")
-public:
- User() {}
- User(UnicodeString name, UnsignedInt addr, UnsignedInt port);
- User &operator= (const User *other);
- Bool operator== (const User *other);
- Bool operator!= (const User *other);
-
- inline UnicodeString GetName() { return m_name; }
- void setName(UnicodeString name);
- inline UnsignedShort GetPort() { return m_port; }
- inline UnsignedInt GetIPAddr() { return m_ipaddr; }
- inline void SetPort(UnsignedShort port) { m_port = port; }
- inline void SetIPAddr(UnsignedInt ipaddr) { m_ipaddr = ipaddr; }
-
-
-private:
- UnicodeString m_name;
- UnsignedShort m_port;
- UnsignedInt m_ipaddr;
-};
-EMPTY_DTOR(User)
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/WOLBrowser/FEBDispatch.h b/Generals/Code/GameEngine/Include/GameNetwork/WOLBrowser/FEBDispatch.h
deleted file mode 100644
index e2a0207616a..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/WOLBrowser/FEBDispatch.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-//
-// FEBDispatch class is a template class which, when inherited from, can implement the
-// IDispatch for a COM object with a type library.
-//
-
-#pragma once
-
-#include
-extern CComModule _Module;
-#include
-#include // For _bstr_t.
-
-#include "oleauto.h"
-
-template
-class FEBDispatch :
-public CComObjectRootEx,
-public CComCoClass,
-public C
-{
-public:
-
- BEGIN_COM_MAP(T)
- COM_INTERFACE_ENTRY(C)
- COM_INTERFACE_ENTRY_AGGREGATE(IID_IDispatch, m_dispatch)
- END_COM_MAP()
-
- FEBDispatch()
- {
- m_ptinfo = NULL;
- m_dispatch = NULL;
-
- ITypeLib *ptlib;
- HRESULT hr;
- HRESULT TypeLibraryLoadResult;
- char filename[256];
-
- GetModuleFileName(NULL, filename, sizeof(filename));
- _bstr_t bstr(filename);
-
- TypeLibraryLoadResult = LoadTypeLib(bstr, &ptlib);
-
- DEBUG_ASSERTCRASH(TypeLibraryLoadResult == 0, ("Can't load type library for Embedded Browser"));
-
- if (TypeLibraryLoadResult == S_OK)
- {
- hr = ptlib->GetTypeInfoOfGuid(*I, &m_ptinfo);
- ptlib->Release();
-
- if (hr == S_OK)
- {
- hr = CreateStdDispatch(static_cast(this), static_cast(this), m_ptinfo, &m_dispatch);
-
- m_dispatch->AddRef();
- // Don't release the IUnknown from CreateStdDispatch without calling AddRef.
- // It looks like CreateStdDispatch doesn't call AddRef on the IUnknown it returns.
- }
- }
-
- if ( m_dispatch == NULL )
- {
- DEBUG_LOG(("Error creating Dispatch for Web interface"));
- }
- }
-
- virtual ~FEBDispatch()
- {
- if (m_ptinfo)
- m_ptinfo->Release();
-
- if (m_dispatch)
- m_dispatch->Release();
- }
-
- IUnknown *m_dispatch;
-
-private:
- ITypeInfo *m_ptinfo;
-};
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/WOLBrowser/WebBrowser.h b/Generals/Code/GameEngine/Include/GameNetwork/WOLBrowser/WebBrowser.h
deleted file mode 100644
index 8122da61aec..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/WOLBrowser/WebBrowser.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-/******************************************************************************
-*
-* NAME
-* $Archive: $
-*
-* DESCRIPTION
-* Web Browser
-*
-* PROGRAMMER
-* Bryan Cleveland
-* $Author: $
-*
-* VERSION INFO
-* $Revision: $
-* $Modtime: $
-*
-******************************************************************************/
-
-#pragma once
-
-#include "Common/SubsystemInterface.h"
-#include
-#include
-#include
-#include "EABrowserDispatch/BrowserDispatch.h"
-#include "FEBDispatch.h"
-#include
-
-class GameWindow;
-
-class WebBrowserURL : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( WebBrowserURL, "WebBrowserURL" )
-
-public:
-
- WebBrowserURL();
- // virtual destructor prototype defined by memory pool object
-
- const FieldParse *getFieldParse( void ) const { return m_URLFieldParseTable; }
-
- AsciiString m_tag;
- AsciiString m_url;
-
- WebBrowserURL *m_next;
-
- static const FieldParse m_URLFieldParseTable[]; ///< the parse table for INI definition
-
-};
-
-
-
-class WebBrowser :
- public FEBDispatch,
- public SubsystemInterface
- {
- public:
- void init( void );
- void reset( void );
- void update( void );
-
- // Create an instance of the embedded browser for Dune Emperor.
- virtual Bool createBrowserWindow(const char *tag, GameWindow *win) = 0;
- virtual void closeBrowserWindow(GameWindow *win) = 0;
-
- WebBrowserURL *makeNewURL(AsciiString tag);
- WebBrowserURL *findURL(AsciiString tag);
-
- protected:
- // Protected to prevent direct construction via new, use CreateInstance() instead.
- WebBrowser();
- virtual ~WebBrowser();
-
- // Protected to prevent copy and assignment
- WebBrowser(const WebBrowser&);
- const WebBrowser& operator=(const WebBrowser&);
-
-// Bool RetrievePageURL(const char* page, char* url, int size);
-// Bool RetrieveHTMLPath(char* path, int size);
-
- protected:
- ULONG mRefCount;
- WebBrowserURL *m_urlList;
-
- //---------------------------------------------------------------------------
- // IUnknown methods
- //---------------------------------------------------------------------------
- protected:
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) IUNKNOWN_NOEXCEPT;
- ULONG STDMETHODCALLTYPE AddRef(void) IUNKNOWN_NOEXCEPT;
- ULONG STDMETHODCALLTYPE Release(void) IUNKNOWN_NOEXCEPT;
-
- //---------------------------------------------------------------------------
- // IBrowserDispatch methods
- //---------------------------------------------------------------------------
- public:
- STDMETHOD(TestMethod)(Int num1);
- };
-
-extern CComObject *TheWebBrowser;
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/networkutil.h b/Generals/Code/GameEngine/Include/GameNetwork/networkutil.h
deleted file mode 100644
index de7dc46c706..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/networkutil.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "GameNetwork/NetworkDefs.h"
-#include "GameNetwork/NetworkInterface.h"
-
-UnsignedInt AssembleIp(UnsignedByte a, UnsignedByte b, UnsignedByte c, UnsignedByte d);
-UnsignedInt ResolveIP(AsciiString host);
-UnsignedShort GenerateNextCommandID();
-Bool DoesCommandRequireACommandID(NetCommandType type);
-Bool CommandRequiresAck(NetCommandMsg *msg);
-Bool CommandRequiresDirectSend(NetCommandMsg *msg);
-Bool IsCommandSynchronized(NetCommandType type);
-const char* GetNetCommandTypeAsString(NetCommandType type);
-
-#ifdef DEBUG_LOGGING
-extern "C" {
-void dumpBufferToLog(const void *vBuf, Int len, const char *fname, Int line);
-};
-#define LOGBUFFER(buf, len) dumpBufferToLog(buf, len, __FILE__, __LINE__)
-#else
-#define LOGBUFFER(buf, len) {}
-#endif // DEBUG_LOGGING
-
-inline UnsignedInt AssembleIp(UnsignedByte a, UnsignedByte b, UnsignedByte c, UnsignedByte d)
-{
- return ((UnsignedInt)(a) << 24) |
- ((UnsignedInt)(b) << 16) |
- ((UnsignedInt)(c) << 8) |
- ((UnsignedInt)(d));
-}
diff --git a/Generals/Code/GameEngine/Include/GameNetwork/udp.h b/Generals/Code/GameEngine/Include/GameNetwork/udp.h
deleted file mode 100644
index f7dedc7ca03..00000000000
--- a/Generals/Code/GameEngine/Include/GameNetwork/udp.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#ifdef _UNIX
-#include
-#endif
-
-#ifdef _WINDOWS
-#include
-#include
-//#define close _close
-//#define read _read
-//#define write _write
-
-#else //UNIX
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#endif
-
-#ifdef AIX
-#include
-#endif
-
-#include "Lib/BaseType.h"
-
-#define DEFAULT_PROTOCOL 0
-
-//#include "wlib/wstypes.h"
-//#include "wlib/wtime.h"
-
-class UDP
-{
- // DATA
- private:
- Int fd;
- UnsignedInt myIP;
- UnsignedShort myPort;
- struct sockaddr_in addr;
-
- public:
- // These defines specify a system independent way to
- // get error codes for socket services.
- enum sockStat CPP_11(: Int)
- {
- OK = 0, // Everything's cool
- UNKNOWN = -1, // There was an error of unknown type
- ISCONN = -2, // The socket is already connected
- INPROGRESS = -3, // The socket is non-blocking and the operation
- // isn't done yet
- ALREADY = -4, // The socket is already attempting a connection
- // but isn't done yet
- AGAIN = -5, // Try again.
- ADDRINUSE = -6, // Address already in use
- ADDRNOTAVAIL = -7, // That address is not available on the remote host
- BADF = -8, // Not a valid FD
- CONNREFUSED = -9, // Connection was refused
- INTR =-10, // Operation was interrupted
- NOTSOCK =-11, // FD wasn't a socket
- PIPE =-12, // That operation just made a SIGPIPE
- WOULDBLOCK =-13, // That operation would block
- INVAL =-14, // Invalid
- TIMEDOUT =-15 // Timeout
- };
-
-// CODE
- private:
- Int SetBlocking(Int block);
-
- Int m_lastError;
-
- public:
- UDP();
- ~UDP();
- Int Bind(UnsignedInt IP,UnsignedShort port);
- Int Bind(const char *Host,UnsignedShort port);
- Int Write(const unsigned char *msg,UnsignedInt len,UnsignedInt IP,UnsignedShort port);
- Int Read(unsigned char *msg,UnsignedInt len,sockaddr_in *from);
- sockStat GetStatus(void);
- void ClearStatus(void);
- //int Wait(Int sec,Int usec,fd_set &returnSet);
- //int Wait(Int sec,Int usec,fd_set &givenSet,fd_set &returnSet);
-
- Int getLocalAddr(UnsignedInt &ip, UnsignedShort &port);
- Int getFD(void) { return(fd); }
-
- Int SetInputBuffer(UnsignedInt bytes);
- Int SetOutputBuffer(UnsignedInt bytes);
- int GetInputBuffer(void);
- int GetOutputBuffer(void);
- Int AllowBroadcasts(Bool status);
-};
-
-#ifdef DEBUG_LOGGING
-AsciiString GetWSAErrorString( Int error );
-#endif
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/Connection.cpp b/Generals/Code/GameEngine/Source/GameNetwork/Connection.cpp
deleted file mode 100644
index 691b88aef6e..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/Connection.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/Connection.h"
-#include "GameNetwork/networkutil.h"
-#include "GameLogic/GameLogic.h"
-
-enum { MaxQuitFlushTime = 30000 }; // wait this many milliseconds at most to retry things before quitting
-
-/**
- * The constructor.
- */
-Connection::Connection() {
- m_transport = NULL;
- m_user = NULL;
- m_netCommandList = NULL;
- m_retryTime = 2000; // set retry time to 2 seconds.
- m_lastTimeSent = 0;
- m_frameGrouping = 1;
- m_isQuitting = false;
- m_quitTime = 0;
- // Added By Sadullah Nader
- // clearing out the latency tracker
- m_averageLatency = 0.0f;
- Int i;
- for(i = 0; i < CONNECTION_LATENCY_HISTORY_LENGTH; i++)
- {
- m_latencies[i] = 0.0f;
- }
- // End Add
-}
-
-/**
- * The destructor.
- */
-Connection::~Connection() {
- deleteInstance(m_user);
- m_user = NULL;
-
- deleteInstance(m_netCommandList);
- m_netCommandList = NULL;
-}
-
-/**
- * Initialize the connection and any subsystems.
- */
-void Connection::init() {
- m_transport = NULL;
-
- deleteInstance(m_user);
- m_user = NULL;
-
- if (m_netCommandList == NULL) {
- m_netCommandList = newInstance(NetCommandList);
- m_netCommandList->init();
- }
- m_netCommandList->reset();
-
- m_lastTimeSent = 0;
- m_frameGrouping = 1;
- m_numRetries = 0;
- m_retryMetricsTime = 0;
-
- for (Int i = 0; i < CONNECTION_LATENCY_HISTORY_LENGTH; ++i) {
- m_latencies[i] = 0;
- }
- m_averageLatency = 0;
- m_isQuitting = FALSE;
- m_quitTime = 0;
-}
-
-/**
- * Take the connection back to the initial state.
- */
-void Connection::reset() {
- init();
-}
-
-/**
- * Doesn't really do anything.
- */
-void Connection::update() {
-}
-
-/**
- * Attach the transport object that this connection should use.
- */
-void Connection::attachTransport(Transport *transport) {
- m_transport = transport;
-}
-
-/**
- * Assign this connection a user. This is the user to whome we send all our packetized goodies.
- */
-void Connection::setUser(User *user) {
- deleteInstance(m_user);
- m_user = user;
-}
-
-/**
- * Return the user object.
- */
-User * Connection::getUser() {
- return m_user;
-}
-
-/**
- * Add this network command to the send queue for this connection.
- * The relay is the mask specifying the people the person we are sending to should send to.
- * The relay mostly has to do with the packet router.
- */
-void Connection::sendNetCommandMsg(NetCommandMsg *msg, UnsignedByte relay) {
- static NetPacket *packet = NULL;
-
- // this is done so we don't have to allocate and delete a packet every time we send a message.
- if (packet == NULL) {
- packet = newInstance(NetPacket);
- }
-
-
- if (m_isQuitting)
- return;
-
- if (m_netCommandList != NULL) {
- // check to see if this command will fit in a packet. If not, we need to split it up.
- // we are splitting up the command here so that the retry logic will not try to
- // resend the ENTIRE command (i.e. multiple packets work of data) and only do the retry
- // one wrapper command at a time.
- packet->reset();
-
- NetCommandRef *tempref = NEW_NETCOMMANDREF(msg);
-
- Bool msgFits = packet->addCommand(tempref);
- deleteInstance(tempref); // delete the temporary reference.
- tempref = NULL;
-
- if (!msgFits) {
- NetCommandRef *origref = NEW_NETCOMMANDREF(msg);
- origref->setRelay(relay);
- // the message doesn't fit in a single packet, need to split it up.
- NetPacketList packetList = NetPacket::ConstructBigCommandPacketList(origref);
- NetPacketListIter tempPacketPtr = packetList.begin();
-
- while (tempPacketPtr != packetList.end()) {
- NetPacket *tempPacket = (*tempPacketPtr);
-
- NetCommandList *list = tempPacket->getCommandList();
- NetCommandRef *ref1 = list->getFirstMessage();
- while (ref1 != NULL) {
- NetCommandRef *ref2 = m_netCommandList->addMessage(ref1->getCommand());
- ref2->setRelay(relay);
-
- ref1 = ref1->getNext();
- }
-
- deleteInstance(tempPacket);
- tempPacket = NULL;
- ++tempPacketPtr;
-
- deleteInstance(list);
- list = NULL;
- }
-
- deleteInstance(origref);
- origref = NULL;
-
- return;
- }
-
- // the message fits in a packet, add to the command list normally.
- NetCommandRef *ref = m_netCommandList->addMessage(msg);
-
- if (ref != NULL) {
-
-/*
-#if defined(RTS_DEBUG)
- if (msg->getNetCommandType() == NETCOMMANDTYPE_GAMECOMMAND) {
- DEBUG_LOG(("Connection::sendNetCommandMsg - added game command %d to net command list for frame %d.",
- msg->getID(), msg->getExecutionFrame()));
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_FRAMEINFO) {
- DEBUG_LOG(("Connection::sendNetCommandMsg - added frame info for frame %d", msg->getExecutionFrame()));
- }
-#endif // RTS_DEBUG
-*/
-
- ref->setRelay(relay);
- }
- }
-}
-
-void Connection::clearCommandsExceptFrom( Int playerIndex )
-{
- NetCommandRef *tmp = m_netCommandList->getFirstMessage();
- while (tmp)
- {
- NetCommandRef *next = tmp->getNext();
- NetCommandMsg *msg = tmp->getCommand();
-
- if (msg->getPlayerID() != playerIndex)
- {
- DEBUG_LOG(("Connection::clearCommandsExceptFrom(%d) - clearing a command from player %d for frame %d",
- playerIndex, tmp->getCommand()->getPlayerID(), tmp->getCommand()->getExecutionFrame()));
-
- m_netCommandList->removeMessage(tmp);
- deleteInstance(tmp);
- }
-
- tmp = next;
- }
-}
-
-Bool Connection::isQueueEmpty() {
- if (m_netCommandList->getFirstMessage() == NULL) {
- return TRUE;
- }
- return FALSE;
-}
-
-void Connection::setQuitting( void )
-{
- m_isQuitting = TRUE;
- m_quitTime = timeGetTime();
- DEBUG_LOG(("Connection::setQuitting() at time %d", m_quitTime));
-}
-
-/**
- * This is the good part. We take all the network commands queued up for this connection,
- * packetize them and put them on the transport's send queue for actual sending.
- */
-UnsignedInt Connection::doSend() {
- Int numpackets = 0;
- time_t curtime = timeGetTime();
- Bool couldQueue = TRUE;
-
- // Do this check first, since it's an important fail-safe
- if (m_isQuitting && curtime > m_quitTime + MaxQuitFlushTime)
- {
- DEBUG_LOG(("Timed out a quitting connection. Deleting all %d messages", m_netCommandList->length()));
- m_netCommandList->reset();
- return 0;
- }
-
- if ((curtime - m_lastTimeSent) < m_frameGrouping) {
-// DEBUG_LOG(("not sending packet, time = %d, m_lastFrameSent = %d, m_frameGrouping = %d", curtime, m_lastTimeSent, m_frameGrouping));
- return 0;
- }
-
- // iterate through all the messages and put them into a packet(s).
- NetCommandRef *msg = m_netCommandList->getFirstMessage();
-
- while ((msg != NULL) && couldQueue) {
- NetPacket *packet = newInstance(NetPacket);
- packet->init();
- packet->setAddress(m_user->GetIPAddr(), m_user->GetPort());
-
- Bool notDone = TRUE;
-
- // add the command messages until either we run out of messages or the packet is full.
- while ((msg != NULL) && notDone) {
- NetCommandRef *next = msg->getNext(); // Need this since msg could be deleted
-
- time_t timeLastSent = msg->getTimeLastSent();
-
- if (((curtime - timeLastSent) > m_retryTime) || (timeLastSent == -1)) {
- notDone = packet->addCommand(msg);
- if (notDone) {
- // the msg command was added to the packet.
- if (CommandRequiresAck(msg->getCommand())) {
- if (timeLastSent != -1) {
- ++m_numRetries;
- }
- doRetryMetrics();
- msg->setTimeLastSent(curtime);
- } else {
- m_netCommandList->removeMessage(msg);
- deleteInstance(msg);
- }
- }
- }
- msg = next;
- }
-
- if (msg != NULL) {
- DEBUG_LOG(("didn't finish sending all commands in connection"));
- }
-
- ++numpackets;
-
- /// @todo Make the act of giving the transport object a packet to send more efficient. Make the transport take a NetPacket object rather than the raw data, thus avoiding an extra memcpy.
- if (packet->getNumCommands() > 0) {
- // If the packet actually has any information to give, give it to the transport object
- // for transmission.
- couldQueue = m_transport->queueSend(packet->getAddr(), packet->getPort(), packet->getData(), packet->getLength());
- m_lastTimeSent = curtime;
- }
-
- deleteInstance(packet); // delete the packet now that we're done with it.
- }
-
- return numpackets;
-}
-
-NetCommandRef * Connection::processAck(NetAckStage1CommandMsg *msg) {
- return processAck(msg->getCommandID(), msg->getOriginalPlayerID());
-}
-
-NetCommandRef * Connection::processAck(NetAckBothCommandMsg *msg) {
- return processAck(msg->getCommandID(), msg->getOriginalPlayerID());
-}
-
-NetCommandRef * Connection::processAck(NetCommandMsg *msg) {
- if (msg->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE1) {
- NetAckStage1CommandMsg *ackmsg = (NetAckStage1CommandMsg *)msg;
- return processAck(ackmsg);
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_ACKBOTH) {
- NetAckBothCommandMsg *ackmsg = (NetAckBothCommandMsg *)msg;
- return processAck(ackmsg);
- }
-
- return NULL;
-}
-
-/**
- * The person we are sending to has ack'd one of the messages we sent him.
- * Take that message off the list of commands to send.
- */
-NetCommandRef * Connection::processAck(UnsignedShort commandID, UnsignedByte originalPlayerID) {
- NetCommandRef *temp = m_netCommandList->getFirstMessage();
- while ((temp != NULL) && ((temp->getCommand()->getID() != commandID) || (temp->getCommand()->getPlayerID() != originalPlayerID))) {
-
- // cycle through the commands till we find the one we need to remove.
- // Need to check for both the command ID and the player ID.
- temp = temp->getNext();
- }
- if (temp == NULL) {
- return NULL;
- }
-
-#if defined(RTS_DEBUG)
- Bool doDebug = FALSE;
- if (temp->getCommand()->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) {
- doDebug = TRUE;
- }
-#endif
-
- Int index = temp->getCommand()->getID() % CONNECTION_LATENCY_HISTORY_LENGTH;
- m_averageLatency -= ((Real)(m_latencies[index])) / CONNECTION_LATENCY_HISTORY_LENGTH;
- Real lat = timeGetTime() - temp->getTimeLastSent();
- m_averageLatency += lat / CONNECTION_LATENCY_HISTORY_LENGTH;
- m_latencies[index] = lat;
-
-#if defined(RTS_DEBUG)
- if (doDebug == TRUE) {
- DEBUG_LOG(("Connection::processAck - disconnect frame command %d found, removing from command list.", commandID));
- }
-#endif
- m_netCommandList->removeMessage(temp);
- return temp;
-}
-
-void Connection::setFrameGrouping(time_t frameGrouping) {
- m_frameGrouping = frameGrouping;
-// m_retryTime = frameGrouping * 4;
-}
-
-void Connection::doRetryMetrics() {
- static Int numSeconds = 0;
- time_t curTime = timeGetTime();
-
- if ((curTime - m_retryMetricsTime) > 10000) {
- m_retryMetricsTime = curTime;
- ++numSeconds;
-// DEBUG_LOG(("Retries in the last 10 seconds = %d, average latency = %fms", m_numRetries, m_averageLatency));
- m_numRetries = 0;
-// m_retryTime = m_averageLatency * 1.5;
- }
-}
-
-#if defined(RTS_DEBUG)
-void Connection::debugPrintCommands() {
- NetCommandRef *ref = m_netCommandList->getFirstMessage();
- while (ref != NULL) {
- DEBUG_LOG(("Connection::debugPrintCommands - ID: %d\tType: %s\tRelay: 0x%X for frame %d",
- ref->getCommand()->getID(), GetNetCommandTypeAsString(ref->getCommand()->getNetCommandType()),
- ref->getRelay(), ref->getCommand()->getExecutionFrame()));
- ref = ref->getNext();
- }
-}
-#endif
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/ConnectionManager.cpp b/Generals/Code/GameEngine/Source/GameNetwork/ConnectionManager.cpp
deleted file mode 100644
index 924e462b8f8..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/ConnectionManager.cpp
+++ /dev/null
@@ -1,2416 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Compression.h"
-#include "strtok_r.h"
-#include "Common/AudioEventRTS.h"
-#include "Common/CRCDebug.h"
-#include "Common/Debug.h"
-#include "Common/file.h"
-#include "Common/GameAudio.h"
-#include "Common/LocalFileSystem.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "Common/RandomValue.h"
-#include "Common/Recorder.h"
-
-#include "GameClient/Diplomacy.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MessageBox.h"
-#include "GameNetwork/ConnectionManager.h"
-#include "GameNetwork/LANAPICallbacks.h"
-#include "GameNetwork/NAT.h"
-#include "GameNetwork/NetCommandWrapperList.h"
-#include "GameNetwork/networkutil.h"
-#include "GameLogic/GameLogic.h"
-#include "GameLogic/ScriptActions.h"
-#include "GameLogic/ScriptEngine.h"
-#include "GameLogic/VictoryConditions.h"
-#include "GameClient/DisconnectMenu.h"
-#include "GameClient/InGameUI.h"
-
-
-/**
- * Le destructor.
- */
-ConnectionManager::~ConnectionManager(void)
-{
- deleteInstance(m_localUser);
- m_localUser = NULL;
-
- // Network will delete transports; we just forget them
- delete m_transport;
- m_transport = NULL;
-
- Int i = 0;
- for (; i < MAX_SLOTS; ++i) {
- deleteInstance(m_frameData[i]);
- m_frameData[i] = NULL;
- }
-
- for (i = 0; i < NUM_CONNECTIONS; ++i) {
- deleteInstance(m_connections[i]);
- m_connections[i] = NULL;
- }
-
- // This is done here since TheDisconnectMenu should only be there if we are in a network game.
- delete TheDisconnectMenu;
- TheDisconnectMenu = NULL;
-
- delete m_disconnectManager;
- m_disconnectManager = NULL;
-
- deleteInstance(m_pendingCommands);
- m_pendingCommands = NULL;
-
- deleteInstance(m_relayedCommands);
- m_relayedCommands = NULL;
-
- deleteInstance(m_netCommandWrapperList);
- m_netCommandWrapperList = NULL;
-
- s_fileCommandMap.clear();
- s_fileRecipientMaskMap.clear();
- for (i = 0; i < MAX_SLOTS; ++i) {
- s_fileProgressMap[i].clear();
- }
-}
-
-/**
- * Le constructor
- */
-ConnectionManager::ConnectionManager(void)
-{
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- m_frameData[i] = NULL;
- }
- m_transport = NULL;
- m_disconnectManager = NULL;
- m_pendingCommands = NULL;
- m_relayedCommands = NULL;
- m_localAddr = 0;
- m_localPort = 0;
- m_netCommandWrapperList = NULL;
- m_localUser = NULL;
- m_localUser = newInstance(User);
-}
-
-/**
- * Initialize the connection manager and any subsystems.
- */
-void ConnectionManager::init()
-{
-// if (m_transport == NULL) {
-// m_transport = new Transport;
-// }
-// m_transport->reset();
-
- UnsignedInt i = 0;
- for (; i < NUM_CONNECTIONS; ++i) {
- m_connections[i] = NULL;
- }
-
- if (m_pendingCommands == NULL) {
- m_pendingCommands = newInstance(NetCommandList);
- m_pendingCommands->init();
- }
- m_pendingCommands->reset();
-
- if (m_relayedCommands == NULL) {
- m_relayedCommands = newInstance(NetCommandList);
- m_relayedCommands->init();
- }
- m_relayedCommands->reset();
-
- m_localSlot = -1;
-#ifdef MEMORYPOOL_DEBUG
- TheMemoryPoolFactory->debugSetInitFillerIndex(m_localSlot);
-#endif
- m_packetRouterSlot = 0; /// @todo The LAN/WOL interface should be telling us who the packet router is based on machine specs passed around through game options.
- for (i = 0; i < MAX_SLOTS; ++i) {
- m_packetRouterFallback[i] = -1;
- }
-
- for (i = 0; i < MAX_SLOTS; ++i) {
- deleteInstance(m_frameData[i]);
- m_frameData[i] = NULL;
- }
-
-// m_averageFps = 30; // since 30 fps is the desired rate, we'll start off at that.
-// m_averageLatency = (Real)0.2; // 200ms seems like a good starting point.
-
- for (i = 0; i < MAX_SLOTS; ++i) {
- m_fpsAverages[i] = -1;
- }
- for (i = 0; i < MAX_SLOTS; ++i) {
- m_latencyAverages[i] = 0.0; // using zero since all floating point standards should be able to specify 0.0 accurately.
- }
- m_smallestPacketArrivalCushion = -1;
-
- m_frameMetrics.init();
-
- TheDisconnectMenu = NEW DisconnectMenu;
- TheDisconnectMenu->init();
-
- m_disconnectManager = NEW DisconnectManager;
- m_disconnectManager->init();
-
- TheDisconnectMenu->attachDisconnectManager(m_disconnectManager);
- TheDisconnectMenu->hideScreen();
-
- m_netCommandWrapperList = newInstance(NetCommandWrapperList);
- m_netCommandWrapperList->init();
-
- s_fileCommandMap.clear();
- s_fileRecipientMaskMap.clear();
- for (i = 0; i < MAX_SLOTS; ++i) {
- s_fileProgressMap[i].clear();
- }
-}
-
-/**
- * Reset the connection manager and any subsystems.
- */
-void ConnectionManager::reset()
-{
-// if (m_transport == NULL) {
-// m_transport = new Transport;
-// }
-// m_transport->reset();
-
- delete m_transport;
- m_transport = NULL;
-
- UnsignedInt i = 0;
- for (; i < (UnsignedInt)NUM_CONNECTIONS; ++i) {
- deleteInstance(m_connections[i]);
- m_connections[i] = NULL;
- }
-
- for (i=0; i<(UnsignedInt)MAX_SLOTS; ++i)
- {
- deleteInstance(m_frameData[i]);
- m_frameData[i] = NULL;
- }
-
- if (m_pendingCommands == NULL) {
- m_pendingCommands = newInstance(NetCommandList);
- m_pendingCommands->init();
- }
- m_pendingCommands->reset();
-
- if (m_relayedCommands == NULL) {
- m_relayedCommands = newInstance(NetCommandList);
- m_relayedCommands->init();
- }
- m_relayedCommands->reset();
-
- if (m_netCommandWrapperList == NULL) {
- m_netCommandWrapperList = newInstance(NetCommandWrapperList);
- m_netCommandWrapperList->init();
- }
- m_netCommandWrapperList->reset();
-
- m_localSlot = -1;
-#ifdef MEMORYPOOL_DEBUG
- TheMemoryPoolFactory->debugSetInitFillerIndex(m_localSlot);
-#endif
- m_packetRouterSlot = -1;
-
- for (i = 0; i < TheGlobalData->m_networkFPSHistoryLength; ++i) {
- m_fpsAverages[i] = -1;
- }
- for (i = 0; i < TheGlobalData->m_networkLatencyHistoryLength; ++i) {
- m_latencyAverages[i] = 0.0;
- }
-
- for (i = 0; i < (UnsignedInt)MAX_SLOTS; ++i) {
- m_packetRouterFallback[i] = -1;
- }
-
- m_frameMetrics.reset();
-}
-
-UnsignedInt ConnectionManager::getPingFrame()
-{
- return (m_disconnectManager)?m_disconnectManager->getPingFrame():0;
-}
-
-Int ConnectionManager::getPingsSent()
-{
- return (m_disconnectManager)?m_disconnectManager->getPingsSent():0;
-}
-
-Int ConnectionManager::getPingsRecieved()
-{
- return (m_disconnectManager)?m_disconnectManager->getPingsRecieved():0;
-}
-
-Bool ConnectionManager::isPlayerConnected( Int playerID )
-{
- return ( playerID == m_localSlot || (m_connections[playerID] && !m_connections[playerID]->isQuitting()) );
-}
-
-void ConnectionManager::attachTransport(Transport *transport) {
- delete m_transport;
- m_transport = transport;
-}
-
-/**
- * zero out the command counts for the given frames. Presently this is used for
- * the start of a game since there won't be any commands for the first few frames due to runahead.
- */
-void ConnectionManager::zeroFrames(UnsignedInt startingFrame, UnsignedInt numFrames) {
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_frameData[i] != NULL) {
-// DEBUG_LOG(("Calling zeroFrames on player %d, starting frame %d, numFrames %d", i, startingFrame, numFrames));
- m_frameData[i]->zeroFrames(startingFrame, numFrames);
- }
- }
-}
-
-/**
- * Destroy any game messages that are left over due to the run ahead.
- */
-void ConnectionManager::destroyGameMessages() {
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- // Need to destroy these game messages because when the game ends, there are
- // still some game messages left over because of the run ahead aspect of
- // network play.
- if (m_frameData[i] != NULL) {
- m_frameData[i]->destroyGameMessages();
- }
- }
-}
-
-/**
- * ConnectionManager::doRelay()
- * Queries the transport for commands that need to be relayed to another client.
- * Get those commands and relay them to the appropriate Connection(s). We make the
- * assumption that a command will only be relayed once.
- */
-void ConnectionManager::doRelay() {
- static Int numPackets = 0;
- static Int numCommands = 0;
-
- NetPacket *packet = NULL;
-
- for (Int i = 0; i < MAX_MESSAGES; ++i) {
- if (m_transport->m_inBuffer[i].length != 0) {
- // This transport buffer has yet to be processed.
-
- // make a NetPacket out of this data so it can be broken up into individual commands.
- packet = newInstance(NetPacket)(&(m_transport->m_inBuffer[i]));
-
- //DEBUG_LOG(("ConnectionManager::doRelay() - got a packet with %d commands", packet->getNumCommands()));
- //LOGBUFFER( packet->getData(), packet->getLength() );
-
- // Get the command list from the packet.
- NetCommandList *cmdList = packet->getCommandList();
- NetCommandRef *cmd = cmdList->getFirstMessage();
-
- // Iterate through the commands in this packet and send them to the proper connections.
- while (cmd != NULL) {
- //DEBUG_LOG(("ConnectionManager::doRelay() - Looking at a command of type %s",
- //GetNetCommandTypeAsString(cmd->getCommand()->getNetCommandType())));
- if (CommandRequiresAck(cmd->getCommand())) {
- ackCommand(cmd, m_localSlot);
- }
- if (!processNetCommand(cmd)) {
- sendRemoteCommand(cmd);
- }
- cmd = cmd->getNext();
-
- ++numCommands;
- }
- ++numPackets;
-
- // Delete this packet since we won't be needing it anymore.
- deleteInstance(packet);
- packet = NULL;
-
- deleteInstance(cmdList);
- cmdList = NULL;
-
- // signal that this has been processed.
- m_transport->m_inBuffer[i].length = 0;
- }
- }
-
- NetCommandList *cmdList = m_netCommandWrapperList->getReadyCommands();
- NetCommandRef *cmd = cmdList->getFirstMessage();
- while (cmd != NULL) {
- if (CommandRequiresAck(cmd->getCommand())) {
- ackCommand(cmd, m_localSlot);
- }
- if (!processNetCommand(cmd)) {
- sendRemoteCommand(cmd);
- }
- cmd = cmd->getNext();
-
- ++numCommands;
- }
- ++numPackets;
-
- // Delete this packet since we won't be needing it anymore.
- deleteInstance(packet);
- packet = NULL;
-
- deleteInstance(cmdList);
- cmdList = NULL;
-}
-
-/**
- * This is where the non-synchronized network commands should be processed.
- * Return TRUE if the command should not be relayed. Return FALSE if it should be relayed.
- */
-Bool ConnectionManager::processNetCommand(NetCommandRef *ref) {
- NetCommandMsg *msg = ref->getCommand();
-
- if ((msg->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE1) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE2) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_ACKBOTH)) {
-
- processAck(msg);
- return FALSE;
- }
-
- if ((m_connections[msg->getPlayerID()] == NULL) && (msg->getPlayerID() != m_localSlot)) {
- // if this is from a player that is no longer in the game, then ignore them.
- return TRUE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_WRAPPER) {
- processWrapper(ref); // need to send the NetCommandRef since we have to construct the relay for the wrapped command.
- return FALSE;
- }
-
- if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS) && (msg->getPlayerID() != m_localSlot)) {
- if (m_connections[msg->getPlayerID()] == NULL) {
- return TRUE;
- }
- }
-
- // Don't allow an out of date command to be sent through.
- // Its unnecessary traffic and it could cause problems.
- //
- // This was a fix for a command count bug where a command would be
- // executed, then a command for that old frame would be added to the
- // FrameData for that frame + 256, and would screw up the command count.
-
- if (IsCommandSynchronized(msg->getNetCommandType())) {
- if (ref->getCommand()->getExecutionFrame() < TheGameLogic->getFrame()) {
- return TRUE;
- }
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_FRAMEINFO) {
- processFrameInfo((NetFrameCommandMsg *)msg);
-
- // need to set the relay so we don't send it to ourselves.
- UnsignedByte relay = ref->getRelay();
- relay = relay & (0xff ^ (1 << m_localSlot));
- ref->setRelay(relay);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_PROGRESS)
- {
- //DEBUG_LOG(("ConnectionManager::processNetCommand - got a progress net command from player %d", msg->getPlayerID()));
- processProgress((NetProgressCommandMsg *) msg);
-
- // need to set the relay so we don't send it to ourselves.
- UnsignedByte relay = ref->getRelay();
- relay = relay & (0xff ^ (1 << m_localSlot));
- ref->setRelay(relay);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_TIMEOUTSTART)
- {
- DEBUG_LOG(("ConnectionManager::processNetCommand - got a TimeOut GameStart net command from player %d", msg->getPlayerID()));
- processTimeOutGameStart(msg);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_RUNAHEADMETRICS) {
- processRunAheadMetrics((NetRunAheadMetricsCommandMsg *)msg);
- return TRUE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_KEEPALIVE) {
- return TRUE;
- }
-
- if ((msg->getNetCommandType() > NETCOMMANDTYPE_DISCONNECTSTART) && (msg->getNetCommandType() < NETCOMMANDTYPE_DISCONNECTEND)) {
- m_disconnectManager->processDisconnectCommand(ref, this);
- return TRUE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTCHAT) {
- processDisconnectChat((NetDisconnectChatCommandMsg *)msg);
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_LOADCOMPLETE)
- {
- DEBUG_LOG(("ConnectionManager::processNetCommand - got a Load Complete net command from player %d", msg->getPlayerID()));
- processLoadComplete(msg);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_CHAT) {
- processChat((NetChatCommandMsg *)msg);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_FILE) {
- processFile((NetFileCommandMsg *)msg);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_FILEANNOUNCE) {
- processFileAnnounce((NetFileAnnounceCommandMsg *)msg);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_FILEPROGRESS) {
- processFileProgress((NetFileProgressCommandMsg *)msg);
- return FALSE;
- }
-
- if (msg->getNetCommandType() == NETCOMMANDTYPE_FRAMERESENDREQUEST) {
- processFrameResendRequest((NetFrameResendRequestCommandMsg *)msg);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void ConnectionManager::processFrameResendRequest(NetFrameResendRequestCommandMsg *msg) {
- // first make sure this is a valid slot
- Int playerID = msg->getPlayerID();
- if ((playerID < 0) || (playerID >= MAX_SLOTS)) {
- return;
- }
-
- // make sure this player is still in our game.
- if ((m_connections[playerID] == NULL) || (m_connections[playerID]->isQuitting() == TRUE)) {
- return;
- }
-
- sendFrameDataToPlayer(playerID, msg->getFrameToResend());
-}
-
-/**
- * We have received a wrapper for a command too big to fit in a packet.
- */
-void ConnectionManager::processWrapper(NetCommandRef *ref)
-{
- NetWrapperCommandMsg *wrapperMsg = (NetWrapperCommandMsg *)(ref->getCommand());
- UnsignedShort commandID = wrapperMsg->getWrappedCommandID();
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::processWrapper() - wrapped commandID is %d, commandID is %d",
- commandID, wrapperMsg->getID()));
- Int origProgress = 0;
- FileCommandMap::iterator fcIt = s_fileCommandMap.find(commandID);
- if (fcIt != s_fileCommandMap.end())
- {
- origProgress = s_fileProgressMap[m_localSlot][commandID];
- }
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::processWrapper() - origProgress[%d] == %d for command %d",
- m_localSlot, origProgress, commandID));
-
- m_netCommandWrapperList->processWrapper(ref);
-
- if (fcIt != s_fileCommandMap.end())
- {
- Int newProgress = m_netCommandWrapperList->getPercentComplete(commandID);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::processWrapper() - newProgress[%d] == %d for command %d",
- m_localSlot, newProgress, commandID));
- if (newProgress > origProgress && newProgress < 100)
- {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::processWrapper() - sending a NetFileProgressCommandMsg"));
- s_fileProgressMap[m_localSlot][commandID] = newProgress;
-
- Int progressMask = 0xff ^ (1 << m_localSlot);
- NetFileProgressCommandMsg *msg = newInstance(NetFileProgressCommandMsg);
- msg->setPlayerID(m_localSlot);
- msg->setID(0);
- if (DoesCommandRequireACommandID(msg->getNetCommandType()))
- {
- msg->setID(GenerateNextCommandID());
- }
- msg->setFileID(commandID);
- msg->setProgress(newProgress);
- sendLocalCommand(msg, progressMask);
- processFileProgress(msg);
- msg->detach();
- }
- }
-}
-
-/**
- * A client has sent us their run ahead metrics, lets store them away for future calculations.
- */
-void ConnectionManager::processRunAheadMetrics(NetRunAheadMetricsCommandMsg *msg)
-{
- UnsignedInt player = msg->getPlayerID();
- if ((player >= 0) && (player < MAX_SLOTS) && (isPlayerConnected(player))) {
- m_latencyAverages[player] = msg->getAverageLatency();
- m_fpsAverages[player] = msg->getAverageFps();
- //DEBUG_LOG(("ConnectionManager::processRunAheadMetrics - player %d, fps = %d, latency = %f", player, msg->getAverageFps(), msg->getAverageLatency()));
- if (m_fpsAverages[player] > 100) {
- // limit the reported frame rate average to 100. This is done because if a
- // user alt-tab's out of the game their frame rate climbs to in the neighborhood of
- // 300, that was deemed "ugly" by the powers that be.
- m_fpsAverages[player] = 100;
- }
- }
-}
-
-void ConnectionManager::processDisconnectChat(NetDisconnectChatCommandMsg *msg)
-{
- UnicodeString unitext;
- UnicodeString name;
- UnsignedByte playerID = msg->getPlayerID();
- if (playerID == m_localSlot) {
- name = m_localUser->GetName();
- } else if (isPlayerConnected(playerID)) {
- name = m_connections[playerID]->getUser()->GetName();
- }
- unitext.format(L"[%ls] %ls", name.str(), msg->getText().str());
-// DEBUG_LOG(("ConnectionManager::processDisconnectChat - got message from player %d, message is %ls", playerID, unitext.str()));
- TheDisconnectMenu->showChat(unitext); // <-- need to implement this
-}
-
-void ConnectionManager::processChat(NetChatCommandMsg *msg)
-{
- UnicodeString unitext;
- UnicodeString name;
- UnsignedByte playerID = msg->getPlayerID();
- //DEBUG_LOG(("processChat(): playerID = %d", playerID));
- if (playerID == m_localSlot) {
- name = m_localUser->GetName();
- //DEBUG_LOG(("connection is NULL, using %ls", name.str()));
- } else if (((m_connections[playerID] != NULL) && (m_connections[playerID]->isQuitting() == FALSE))) {
- name = m_connections[playerID]->getUser()->GetName();
- //DEBUG_LOG(("connection is non-NULL, using %ls", name.str()));
- }
- unitext.format(L"[%ls] %ls", name.str(), msg->getText().str());
-// DEBUG_LOG(("ConnectionManager::processChat - got message from player %d (mask %8.8X), message is %ls", playerID, msg->getPlayerMask(), unitext.str()));
-
- AsciiString playerName;
- playerName.format("player%d", msg->getPlayerID());
- const Player *player = ThePlayerList->findPlayerWithNameKey( TheNameKeyGenerator->nameToKey( playerName ) );
- if (!player)
- {
- TheInGameUI->message(UnicodeString(L"%ls"), unitext.str());
- return;
- }
-
- Bool fromObserver = !player->isPlayerActive();
- Bool amIObserver = !ThePlayerList->getLocalPlayer()->isPlayerActive();
- Bool canSeeChat = (amIObserver || !fromObserver) && !TheGameInfo->getConstSlot(playerID)->isMuted();
-
- if ( ((1<getPlayerMask() ) && canSeeChat )
- {
- RGBColor rgb;
- rgb.setFromInt(player->getPlayerColor());
- TheInGameUI->messageColor(&rgb, UnicodeString(L"%ls"), unitext.str());
-
- // feedback for received chat messages in-game
- AudioEventRTS audioEvent("GUICommunicatorIncoming");
- TheAudio->addAudioEvent(&audioEvent);
- }
-}
-
-void ConnectionManager::processFile(NetFileCommandMsg *msg)
-{
-#ifdef DEBUG_LOGGING
- UnicodeString log;
- log.format(L"Saw file transfer: '%hs' of %d bytes from %d", msg->getPortableFilename().str(), msg->getFileLength(), msg->getPlayerID());
- DEBUG_LOG(("%ls", log.str()));
-#endif
-
- AsciiString realFileName = msg->getRealFilename();
- if (realFileName.isEmpty())
- {
- // TheSuperHackers @security slurmlord 18/06/2025 As the file name/path from the NetFileCommandMsg failed to normalize,
- // in other words is bogus and points outside of the approved target directory, avoid an arbitrary file overwrite vulnerability
- // by simply returning and let the transfer time out.
- DEBUG_LOG(("Got a file name transferred that failed to normalize: '%s'!", msg->getPortableFilename().str()));
- return;
- }
-
- if (TheFileSystem->doesFileExist(realFileName.str()))
- {
- DEBUG_LOG(("File exists already!"));
- //return;
- }
-
- UnsignedByte *buf = msg->getFileData();
- Int len = msg->getFileLength();
-
- // uncompress Targas
-#ifdef COMPRESS_TARGAS
- Bool deleteBuf = FALSE;
- if (msg->getFilename().endsWith(".tga") && CompressionManager::isDataCompressed(buf, len))
- {
- Int uncompLen = CompressionManager::getUncompressedSize(buf, len);
- UnsignedByte *uncompBuffer = NEW UnsignedByte[uncompLen];
- Int actualLen = CompressionManager::decompressData(buf, len, uncompBuffer, uncompLen);
- if (actualLen == uncompLen)
- {
- DEBUG_LOG(("Uncompressed Targa after map transfer"));
- deleteBuf = TRUE;
- buf = uncompBuffer;
- len = uncompLen;
- }
- else
- {
- DEBUG_LOG(("Failed to uncompress Targa after map transfer"));
- delete[] uncompBuffer; // failed to decompress, so just use the source
- }
- }
-#endif // COMPRESS_TARGAS
-
- File *fp = TheFileSystem->openFile(realFileName.str(), File::CREATE | File::BINARY | File::WRITE);
- if (fp)
- {
- fp->write(buf, len);
- fp->close();
- fp = NULL;
- DEBUG_LOG(("Wrote %d bytes to file %s!", len, realFileName.str()));
-
- }
- else
- {
- DEBUG_LOG(("Cannot open file!"));
- }
-
- DEBUG_LOG(("ConnectionManager::processFile() - sending a NetFileProgressCommandMsg"));
-
- Int commandID = msg->getID();
- Int newProgress = 100;
-
- s_fileProgressMap[m_localSlot][commandID] = newProgress;
-
- Int progressMask = 0xff ^ (1 << m_localSlot);
- NetFileProgressCommandMsg *progressMsg = newInstance(NetFileProgressCommandMsg);
- progressMsg->setPlayerID(m_localSlot);
- progressMsg->setID(0);
- if (DoesCommandRequireACommandID(progressMsg->getNetCommandType()))
- {
- progressMsg->setID(GenerateNextCommandID());
- }
- progressMsg->setFileID(commandID);
- progressMsg->setProgress(newProgress);
- sendLocalCommand(progressMsg, progressMask);
- processFileProgress(progressMsg);
- progressMsg->detach();
-
-#ifdef COMPRESS_TARGAS
- if (deleteBuf)
- {
- delete[] buf;
- buf = NULL;
- }
-#endif // COMPRESS_TARGAS
-}
-
-void ConnectionManager::processFileAnnounce(NetFileAnnounceCommandMsg *msg)
-{
- DEBUG_LOG(("ConnectionManager::processFileAnnounce() - expecting '%s' (%s) in command %d", msg->getPortableFilename().str(), msg->getRealFilename().str(), msg->getFileID()));
- s_fileCommandMap[msg->getFileID()] = msg->getRealFilename();
- s_fileRecipientMaskMap[msg->getFileID()] = msg->getPlayerMask();
- for (Int i=0; igetPlayerMask() )
- {
- s_fileProgressMap[i][msg->getFileID()] = 0;
- }
- else
- {
- s_fileProgressMap[i][msg->getFileID()] = 100; // they don't need to get it, so they're already done.
- }
- }
-}
-
-void ConnectionManager::processFileProgress(NetFileProgressCommandMsg *msg)
-{
- DEBUG_LOG(("ConnectionManager::processFileProgress() - command %d is at %d%%",
- msg->getFileID(), msg->getProgress()));
- Int oldProgress = s_fileProgressMap[msg->getPlayerID()][msg->getFileID()];
-
- s_fileProgressMap[msg->getPlayerID()][msg->getFileID()] = max(oldProgress, msg->getProgress());
-}
-
-void ConnectionManager::processProgress( NetProgressCommandMsg *msg )
-{
- TheGameLogic->processProgress(msg->getPlayerID(), msg->getPercentage());
-}
-
-void ConnectionManager::processLoadComplete( NetCommandMsg *msg )
-{
- TheGameLogic->processProgressComplete(msg->getPlayerID());
-}
-
-void ConnectionManager::processTimeOutGameStart( NetCommandMsg *msg )
-{
- TheGameLogic->timeOutGameStart();
-}
-
-/**
- * Another client has sent us the command count for a new frame.
- */
-void ConnectionManager::processFrameInfo(NetFrameCommandMsg *msg) {
- //stupid frame info, why don't you process yourself?
-
- UnsignedInt playerID = msg->getPlayerID();
-
- if ((playerID >= 0) && (playerID < MAX_SLOTS)) {
- if (m_frameData[playerID] != NULL) {
-// DEBUG_LOG(("ConnectionManager::processFrameInfo - player %d, frame %d, command count %d, received on frame %d", playerID, msg->getExecutionFrame(), msg->getCommandCount(), TheGameLogic->getFrame()));
- m_frameData[playerID]->setFrameCommandCount(msg->getExecutionFrame(), msg->getCommandCount());
- }
- }
-}
-
-/**
- * We just got a stage 1 ack from someone. So we should remove it from the connection that sent it so
- * it doesn't keep resending it.
- */
-void ConnectionManager::processAckStage1(NetCommandMsg *msg) {
-#if defined(RTS_DEBUG)
- Bool doDebug = (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) ? TRUE : FALSE;
-#endif
-
- UnsignedByte playerID = msg->getPlayerID();
- NetCommandRef *ref = NULL;
-
-#if defined(RTS_DEBUG)
- if (doDebug == TRUE) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::processAck - processing ack for command %d from player %d", ((NetAckStage1CommandMsg *)msg)->getCommandID(), playerID));
- }
-#endif
-
- if ((playerID >= 0) && (playerID < NUM_CONNECTIONS)) {
- if (m_connections[playerID] != NULL) {
- ref = m_connections[playerID]->processAck(msg);
- }
- } else {
- DEBUG_ASSERTCRASH((playerID >= 0) && (playerID < NUM_CONNECTIONS), ("ConnectionManager::processAck - %d is an invalid player number", playerID));
- }
-
- if (ref != NULL) {
- if (ref->getCommand()->getNetCommandType() == NETCOMMANDTYPE_FRAMEINFO) {
- m_frameMetrics.processLatencyResponse(((NetFrameCommandMsg *)(ref->getCommand()))->getExecutionFrame());
- }
-
- deleteInstance(ref);
- ref = NULL;
- }
-}
-
-/**
- * We just got a stage 2 ack from someone. So remove it from the pending commands list so it doesn't
- * get sent in the case of a new packet router.
- */
-void ConnectionManager::processAckStage2(NetCommandMsg *msg) {
- UnsignedShort commandID = 0;
- UnsignedByte playerID = 0;
- if (msg->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE2) {
- commandID = ((NetAckStage2CommandMsg *)msg)->getCommandID();
- playerID = ((NetAckStage2CommandMsg *)msg)->getOriginalPlayerID();
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_ACKBOTH) {
- commandID = ((NetAckBothCommandMsg *)msg)->getCommandID();
- playerID = ((NetAckBothCommandMsg *)msg)->getOriginalPlayerID();
- } else {
- return;
- }
-
- NetCommandRef *ref = m_pendingCommands->findMessage(commandID, playerID);
- if (ref != NULL) {
- //DEBUG_LOG(("ConnectionManager::processAckStage2 - removing command %d from the pending commands list.", commandID));
- DEBUG_ASSERTCRASH((m_localSlot == playerID), ("Found a command in the pending commands list that wasn't originated by the local player"));
- m_pendingCommands->removeMessage(ref);
- deleteInstance(ref);
- ref = NULL;
- } else {
- //DEBUG_LOG(("ConnectionManager::processAckStage2 - Couldn't find command %d from player %d in the pending commands list.", commandID, playerID));
- }
-
- ref = m_relayedCommands->findMessage(commandID, playerID);
- if (ref != NULL) {
- //DEBUG_LOG(("ConnectionManager::processAckStage2 - found command ID %d from player %d in the relayed commands list.", commandID, playerID));
- UnsignedByte prevRelay = ref->getRelay();
- UnsignedByte relay = prevRelay & ~(1 << msg->getPlayerID());
- //DEBUG_LOG(("ConnectionManager::processAckStage2 - relay was %d and is now %d", relay, prevRelay));
- if (relay == 0) {
- //DEBUG_LOG(("ConnectionManager::processAckStage2 - relay is 0, removing command from the relayed commands list."));
- m_relayedCommands->removeMessage(ref);
- NetAckStage2CommandMsg *ackmsg = newInstance(NetAckStage2CommandMsg)(ref->getCommand());
- sendLocalCommand(ackmsg, 1 << ackmsg->getOriginalPlayerID());
- deleteInstance(ref);
- ref = NULL;
-
- ackmsg->detach();
- ackmsg = NULL;
- } else {
- ref->setRelay(relay);
- }
- }
-}
-
-/**
- * We just got a "both" ack from someone. So process it as both a stage 1 and stage 2 ack.
- */
-void ConnectionManager::processAck(NetCommandMsg *msg) {
- if ((msg->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE1) || (msg->getNetCommandType() == NETCOMMANDTYPE_ACKBOTH)) {
- processAckStage1(msg);
- }
- if ((msg->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE2) || (msg->getNetCommandType() == NETCOMMANDTYPE_ACKBOTH)) {
- processAckStage2(msg);
- }
-}
-
-/**
- * A player has just left our game. Delete their connection and frame data manager.
- * return codes are:
- * PLAYERLEAVECODE_UNKNOWN - player didn't have a valid slot number.
- * PLAYERLEAVECODE_CLIENT - someone in the game that wasn't us or the packet router.
- * PLAYERLEAVECODE_LOCAL - We are leaving the game, we could also be the packet router.
- * PLAYERLEAVECODE_PACKETROUTER - The packet router left the game.
- *
- * If we are leaving and are also the packet router, it will return the PLAYERLEAVECODE_LOCAL return code.
- */
-PlayerLeaveCode ConnectionManager::processPlayerLeave(NetPlayerLeaveCommandMsg *msg) {
- UnsignedByte playerID = msg->getLeavingPlayerID();
- if ((playerID != m_localSlot) && (m_connections[playerID] != NULL)) {
- DEBUG_LOG(("ConnectionManager::processPlayerLeave() - setQuitting() on player %d on frame %d", playerID, TheGameLogic->getFrame()));
- m_connections[playerID]->setQuitting();
- }
- DEBUG_ASSERTCRASH(m_frameData[playerID]->getIsQuitting() == FALSE, ("Player %d is already quitting", playerID));
- if ((playerID != m_localSlot) && (m_frameData[playerID] != NULL) && (m_frameData[playerID]->getIsQuitting() == FALSE)) {
- DEBUG_LOG(("ConnectionManager::processPlayerLeave - setQuitFrame on player %d for frame %d", playerID, TheGameLogic->getFrame()+1));
- m_frameData[playerID]->setQuitFrame(TheGameLogic->getFrame() + FRAMES_TO_KEEP + 1);
- }
-
- if (playerID == m_localSlot)
- {
- // we're leaving, so mark our connections and frame datas to go away.
- for (Int i=0; iclearCommandsExceptFrom(m_localSlot);
- m_connections[i]->setQuitting();
- }
- }
- }
-
- PlayerLeaveCode code = disconnectPlayer(playerID);
- DEBUG_LOG(("ConnectionManager::processPlayerLeave() - just disconnected player %d with ret code %d", playerID, code));
- if (code == PLAYERLEAVECODE_PACKETROUTER)
- resendPendingCommands();
-
- PopulateInGameDiplomacyPopup();
- return code;
-}
-
-UnsignedInt ConnectionManager::getPacketRouterFallbackSlot(Int packetRouterNumber) {
- if ((packetRouterNumber >= 0) && (packetRouterNumber < MAX_SLOTS)) {
- return m_packetRouterFallback[packetRouterNumber];
- }
- return MAX_SLOTS;
-}
-
-UnsignedInt ConnectionManager::getPacketRouterSlot() {
- return m_packetRouterSlot;
-}
-
-Bool ConnectionManager::areAllQueuesEmpty(void) {
- Bool retval = TRUE;
- for (Int i = 0; (i < MAX_SLOTS) && retval; ++i) {
- if (m_connections[i] != NULL) {
- if (m_connections[i]->isQueueEmpty() == FALSE) {
- //DEBUG_LOG(("ConnectionManager::areAllQueuesEmpty() - m_connections[%d] is not empty", i));
- //m_connections[i]->debugPrintCommands();
- retval = FALSE;
- }
- }
- }
-
- return retval;
-}
-
-Bool ConnectionManager::canILeave() {
- return areAllQueuesEmpty();
-}
-
-/**
- * The local player is leaving. Tell the local player as well as the other players
- * to remove this player at the specified frame.
- */
-void ConnectionManager::handleLocalPlayerLeaving(UnsignedInt frame) {
- NetPlayerLeaveCommandMsg *msg = newInstance(NetPlayerLeaveCommandMsg);
-
- msg->setLeavingPlayerID(m_localSlot);
- msg->setExecutionFrame(frame);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
- msg->setPlayerID(m_localSlot);
-
- DEBUG_LOG(("ConnectionManager::handleLocalPlayerLeaving - Local player leaving on frame %d", frame));
- DEBUG_ASSERTCRASH(m_packetRouterSlot >= 0, ("ConnectionManager::handleLocalPlayerLeaving, packet router is %d, illegal value.", m_packetRouterSlot));
-
- sendLocalCommand(msg);
-
- msg->detach();
-}
-
-/**
- * We just got a message that needs to be ack'd, so ack it!
- */
-void ConnectionManager::ackCommand(NetCommandRef *ref, UnsignedInt localSlot) {
- NetCommandMsg *msg = ref->getCommand();
- NetCommandMsg *ackmsg;
- UnsignedShort commandID;
- UnsignedByte originalPlayerID;
- UnsignedByte sendRelay = 0;
-
- // Make send relay a bitmask for the connections that the relay will actually be sent to. This is
- // necessary to determine whether or not we have to wait to send a stage 2 ack.
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (((m_connections[i] != NULL) && (m_connections[i]->isQuitting() == FALSE))) {
- sendRelay = sendRelay | (1 << i);
- }
- }
-
-#if defined(RTS_DEBUG)
- Bool doDebug = (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) ? TRUE : FALSE;
-#endif
-
- sendRelay = sendRelay & ref->getRelay();
- if (sendRelay == 0) {
- NetAckBothCommandMsg *bothmsg = newInstance(NetAckBothCommandMsg)(ref->getCommand());
- ackmsg = bothmsg;
- commandID = bothmsg->getCommandID();
- originalPlayerID = bothmsg->getOriginalPlayerID();
-#if defined(RTS_DEBUG)
- if (doDebug) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::ackCommand - doing ack both for command %d from player %d", bothmsg->getCommandID(), bothmsg->getOriginalPlayerID()));
- }
-#endif
- } else {
- NetAckStage1CommandMsg *stage1msg = newInstance(NetAckStage1CommandMsg)(ref->getCommand());
- ackmsg = stage1msg;
- commandID = stage1msg->getCommandID();
- originalPlayerID = stage1msg->getOriginalPlayerID();
-#if defined(RTS_DEBUG)
- if (doDebug) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::ackCommand - doing ack stage 1 for command %d from player %d", stage1msg->getCommandID(), stage1msg->getOriginalPlayerID()));
- }
-#endif
- }
-
- ackmsg->setPlayerID(localSlot); // Tell the player who this ack is coming from.
-
- if (CommandRequiresDirectSend(msg) && CommandRequiresAck(msg)) {
- // Send this ack directly back to the sending player, don't go through the packet router.
- if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) {
- if (m_connections[msg->getPlayerID()] != NULL) {
- m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID());
- }
- }
- } else {
- // The local connection may be the packet router, in that case, the connection would be NULL. So do something about it!
- if ((m_packetRouterSlot >= 0) && (m_packetRouterSlot < MAX_SLOTS)) {
- if (m_connections[m_packetRouterSlot] != NULL) {
-// DEBUG_LOG(("ConnectionManager::ackCommand - acking command %d from player %d to packet router.", commandID, m_packetRouterSlot));
- m_connections[m_packetRouterSlot]->sendNetCommandMsg(ackmsg, 1 << m_packetRouterSlot);
- } else if (m_localSlot == m_packetRouterSlot) {
- // we are the packet router, send the ack to the player that sent the command.
- if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) {
- if (m_connections[msg->getPlayerID()] != NULL) {
-// DEBUG_LOG(("ConnectionManager::ackCommand - acking command %d from player %d directly to player.", commandID, msg->getPlayerID()));
- m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID());
- } else {
- // DEBUG_ASSERTCRASH(m_connections[msg->getPlayerID()] != NULL, ("Connection to player is NULL"));
- }
- } else {
- DEBUG_ASSERTCRASH((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS), ("Command sent by an invalid player ID."));
- }
- } else {
- DEBUG_ASSERTCRASH(m_connections[m_packetRouterSlot] != NULL, ("Connection to packet router is NULL"));
- }
- } else {
- DEBUG_ASSERTCRASH((m_packetRouterSlot >= 0) && (m_packetRouterSlot < MAX_SLOTS), ("I don't know who the packet router is."));
- }
- }
-
- ackmsg->detach();
-}
-
-/**
- * This is where we relay a command from one client to others (including ourselves).
- * This should only be done by the current packet router.
- */
-void ConnectionManager::sendRemoteCommand(NetCommandRef *msg) {
- UnsignedByte actualRelay = 0;
- if (msg->getCommand() == NULL) {
- return;
- }
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - sending net command %d of type %s from player %d, relay is 0x%x",
- msg->getCommand()->getID(), GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getRelay()));
-
- UnsignedByte relay = msg->getRelay();
- if ((relay & (1 << m_localSlot)) && (m_frameData[msg->getCommand()->getPlayerID()] != NULL)) {
- if (IsCommandSynchronized(msg->getCommand()->getNetCommandType())) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - adding net command of type %s to player %d for frame %d", GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getCommand()->getExecutionFrame()));
- m_frameData[msg->getCommand()->getPlayerID()]->addNetCommandMsg(msg->getCommand());
- }
- }
-
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if ((relay & (1 << i)) && ((m_connections[i] != NULL) && (m_connections[i]->isQuitting() == FALSE))) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - relaying command %d to player %d", msg->getCommand()->getID(), i));
- m_connections[i]->sendNetCommandMsg(msg->getCommand(), 1 << i);
- actualRelay = actualRelay | (1 << i);
- }
- }
-
- if ((actualRelay != 0) && (CommandRequiresAck(msg->getCommand()) == TRUE)) {
- NetCommandRef *ref = m_relayedCommands->addMessage(msg->getCommand());
- if (ref != NULL) {
- ref->setRelay(actualRelay);
- //DEBUG_LOG(("ConnectionManager::sendRemoteCommand - command %d added to relayed commands with relay %d", msg->getCommand()->getID(), ref->getRelay()));
- }
- }
-
- // Do some metrics to find the minimum packet arrival cushion.
- if (IsCommandSynchronized(msg->getCommand()->getNetCommandType())) {
-// DEBUG_LOG(("ConnectionManager::sendRemoteCommand - about to call allCommandsReady"));
- if (allCommandsReady(msg->getCommand()->getExecutionFrame(), TRUE)) {
- UnsignedInt cushion = msg->getCommand()->getExecutionFrame() - TheGameLogic->getFrame();
- if ((cushion < m_smallestPacketArrivalCushion) || (m_smallestPacketArrivalCushion == -1)) {
- m_smallestPacketArrivalCushion = cushion;
- }
- m_frameMetrics.addCushion(cushion);
-// DEBUG_LOG(("Adding %d to cushion for frame %d", cushion, msg->getCommand()->getExecutionFrame()));
- }
- }
-}
-
-/**
- * ConnectionManager::update
- * Update the connections. Tell them to do the receive and send. Also relay
- * commands to their final destinations as necessary.
- */
-void ConnectionManager::update(Bool isInGame) {
-//
-// 1. do this
-// 2. do that
-// 3. do something else
-// 4. blow something up
-// 5. bust some cap
-//
-
- if ((m_localAddr == 0) || (m_localPort == 0)) {
- // we don't have a local address or port yet, this is bad.
- DEBUG_ASSERTCRASH((m_localAddr != 0) && (m_localPort != 0), ("ConnectionManager doesn't have a local address."));
- return;
- }
-
- m_transport->doRecv();
-
- if (isInGame) {
- m_disconnectManager->update(this);
- }
-
- // take the packets from the transport, break them up into commands, and give them to the appropriate connections.
- doRelay();
-
- // send any necessary keep-alive packets.
- doKeepAlive();
-
- for (Int i = 0; i < NUM_CONNECTIONS; ++i) {
- if (m_connections[i] != NULL) {
- /*
- if (m_connections[i]->isQueueEmpty() == FALSE) {
-// DEBUG_LOG(("ConnectionManager::update - calling doSend on connection %d", i));
- }
- */
-
- m_connections[i]->doSend();
-
- if (m_connections[i]->isQuitting() && m_connections[i]->isQueueEmpty())
- {
- DEBUG_LOG(("ConnectionManager::update - deleting connection for slot %d", i));
- deleteInstance(m_connections[i]);
- m_connections[i] = NULL;
- }
- }
-
- if ((m_frameData[i] != NULL) && (m_frameData[i]->getIsQuitting() == TRUE)) {
- if (m_frameData[i]->getQuitFrame() == TheGameLogic->getFrame()) {
- DEBUG_LOG(("ConnectionManager::update - deleting frame data for slot %d on quitting frame %d", i, m_frameData[i]->getQuitFrame()));
- deleteInstance(m_frameData[i]);
- m_frameData[i] = NULL;
- }
- }
- }
-
- m_transport->doSend();
-}
-
-void ConnectionManager::updateRunAhead(Int oldRunAhead, Int frameRate, Bool didSelfSlug, Int nextExecutionFrame) {
- static time_t lasttimesent = 0;
- time_t curTime = timeGetTime();
-
- if ((lasttimesent == 0) || ((curTime - lasttimesent) > TheGlobalData->m_networkRunAheadMetricsTime)) {
- if (m_localSlot == m_packetRouterSlot) {
- // We are the packet router, time to compute a new run ahead for this game.
- m_latencyAverages[m_localSlot] = m_frameMetrics.getAverageLatency();
-
- // since we are now using the display frame rate rather than the logic frame rate to get our average FPS,
- // it doesn't make sense to send the desired logic frame rate if we "slugged" ourself.
-// if (didSelfSlug) {
-// m_fpsAverages[m_localSlot] = frameRate;
-// } else {
- m_fpsAverages[m_localSlot] = m_frameMetrics.getAverageFPS();
-// }
- if (didSelfSlug) {
- //DEBUG_LOG(("ConnectionManager::updateRunAhead - local player run ahead metrics, fps = %d, actual fps = %d, latency = %f, didSelfSlug = true", m_fpsAverages[m_localSlot], m_frameMetrics.getAverageFPS(), m_latencyAverages[m_localSlot]));
- } else {
- //DEBUG_LOG(("ConnectionManager::updateRunAhead - local player run ahead metrics, fps = %d, latency = %f, didSelfSlug = false", m_fpsAverages[m_localSlot], m_latencyAverages[m_localSlot]));
- }
- Int minFps;
- Int minFpsPlayer;
- getMinimumFps(minFps, minFpsPlayer);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::updateRunAhead - max latency = %f, min fps = %d, min fps player = %d old FPS = %d", getMaximumLatency(), minFps, minFpsPlayer, frameRate));
- if ((minFps >= ((frameRate * 9) / 10)) && (minFps < frameRate)) {
- // if the minimum fps is within 10% of the desired framerate, then keep the current minimum fps.
- minFps = frameRate;
- }
-
- // TheSuperHackers @info this clamps the logic time scale fps in network games
- minFps = clamp(MIN_LOGIC_FRAMES, minFps, TheGlobalData->m_framesPerSecondLimit);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::updateRunAhead - minFps after adjustment is %d", minFps));
-
- // TheSuperHackers @bugfix Mauller 21/08/2025 calculate the runahead so it always follows the latency
- // The runahead should always be rounded up to the next integer value to prevent variations in latency from causing stutter
- // The network slack pushes the runahead up to the next value when the latency is within the slack percentage of the current runahead
- const Real runAheadSlackScale = 1.0f + ( (Real)TheGlobalData->m_networkRunAheadSlack / 100.0f );
- Int newRunAhead = ceilf( getMaximumLatency() * runAheadSlackScale * (Real)minFps );
-
- // TheSuperHackers @info if the runahead goes below 3 logic frames it can start to introduce stutter
- // We also limit the upper range of the runahead to prevent it getting out of hand
- newRunAhead = clamp(MIN_RUNAHEAD, newRunAhead, MAX_FRAMES_AHEAD / 2);
-
- NetRunAheadCommandMsg *msg = newInstance(NetRunAheadCommandMsg);
- msg->setPlayerID(m_localSlot);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
-
- // needs to be set to the greater of getExecutionFrame and TheGameLogic->getFrame() + oldRunAhead
- // This prevents the case of...
- // run ahead starts at 30
- // run ahead changes to 10 at frame 31 (the command was created on frame 1)
- // run ahead changes to 10 at frame 56 (the command was created on frame 46)
- // notice that 56 is within the previous run ahead of 30 which has triggered
- // the frame command count being set for frames 1 through 60 since run ahead
- // didn't change for the first time till frame 31. This creates an extra command
- // for frame 56 that isn't accounted for in the frame command count that is sent
- // out in the NetFrameCommandMsg. sheesh.
- if (nextExecutionFrame > (TheGameLogic->getFrame() + oldRunAhead)) {
- msg->setExecutionFrame(nextExecutionFrame);
- } else {
- msg->setExecutionFrame(TheGameLogic->getFrame() + oldRunAhead);
- }
-
- msg->setRunAhead(newRunAhead);
- msg->setFrameRate(minFps);
- //DEBUG_LOG(("ConnectionManager::updateRunAhead - new run ahead = %d, new frame rate = %d, execution frame %d", newRunAhead, minFps, msg->getExecutionFrame()));
- sendLocalCommand(msg, 0xff ^ (1 << minFpsPlayer)); // Send the packet to everyone but the lowest FPS player.
-
- NetRunAheadCommandMsg *msg2 = newInstance(NetRunAheadCommandMsg);
- msg2->setPlayerID(m_localSlot);
- if (DoesCommandRequireACommandID(msg2->getNetCommandType())) {
- /*
- * Ok there needs to be a big friggin comment about this change...
- * What happens is that the two run ahead commands get sent to different players
- * using different command ID's. So player 1 has the run ahead command as command x
- * and player 2 has the command as command x+1. This is all good except when it comes
- * to players being disconnected. With the new disconnect scheme player 1 could potentially
- * send his run ahead command to player 2 (or the other way around) to let player 2 catch
- * up to him. So if player 2 has his run ahead command as x+1 and now he gets player 1's
- * command list with the run ahead command listed as command x, he won't see them as being
- * the same command and will now think he has two different run ahead commands for that frame
- * and thus his command list will have an extra command and he will never be able to recover.
- * So to fix this we have to use the same command ID for both run ahead commands. That way
- * when the commands are copied places for the disconnect screen they will be seen as the
- * same command, and all will be good.
- */
-// msg2->setID(GenerateNextCommandID());
- msg2->setID(msg->getID());
- }
- if (nextExecutionFrame > (TheGameLogic->getFrame() + oldRunAhead)) {
- msg2->setExecutionFrame(nextExecutionFrame);
- } else {
- msg2->setExecutionFrame(TheGameLogic->getFrame() + oldRunAhead);
- }
-
- // Let the player with the slowest FPS run a little faster than the other computers...
- // just in case they are able to. Then we might be able to run the game faster which would be good.
- Int newMinFps = (minFps * 11) / 10;
- if (newMinFps == minFps) {
- newMinFps = minFps + 1;
- }
- if (newMinFps > 30) {
- newMinFps = 30; // Cap FPS to 30.
- }
- msg2->setRunAhead(newRunAhead);
- msg2->setFrameRate(newMinFps);
-
- sendLocalCommand(msg2, 1 << minFpsPlayer);
-
- msg->detach();
- msg2->detach();
- } else {
- // We are not the packet router, send our metrics info to the packet router.
- NetRunAheadMetricsCommandMsg *msg = newInstance(NetRunAheadMetricsCommandMsg);
- msg->setPlayerID(m_localSlot);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
- msg->setAverageLatency(m_frameMetrics.getAverageLatency());
-
- // see above for explanation.
-// if (didSelfSlug) {
-// msg->setAverageFps(frameRate);
-// } else {
- msg->setAverageFps(m_frameMetrics.getAverageFPS());
-// }
- if (didSelfSlug) {
- //DEBUG_LOG(("ConnectionManager::updateRunAhead - average latency = %f, average fps = %d, actual fps = %d, didSelfSlug = true", m_frameMetrics.getAverageLatency(), m_frameMetrics.getAverageFPS(), m_frameMetrics.getAverageFPS()));
- } else {
- //DEBUG_LOG(("ConnectionManager::updateRunAhead - average latency = %f, average fps = %d, didSelfSlug = false", m_frameMetrics.getAverageLatency(), m_frameMetrics.getAverageFPS()));
- }
- m_connections[m_packetRouterSlot]->sendNetCommandMsg(msg, 1 << m_packetRouterSlot);
- msg->detach();
- }
- lasttimesent = curTime;
- }
-}
-
-Real ConnectionManager::getMaximumLatency() {
- Real maxLatency = 0.0f;
-
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (isPlayerConnected(i) && m_latencyAverages[i] > maxLatency) {
- maxLatency = m_latencyAverages[i];
- }
- }
-
- return maxLatency;
-}
-
-void ConnectionManager::getMinimumFps(Int &minFps, Int &minFpsPlayer) {
- minFps = -1;
- minFpsPlayer = -1;
-// DEBUG_LOG_RAW(("ConnectionManager::getMinimumFps -"));
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if ((m_connections[i] != NULL) || (i == m_localSlot)) {
-// DEBUG_LOG_RAW((" %d: %d,", i, m_fpsAverages[i]));
- if (m_fpsAverages[i] != -1) {
- if ((minFps == -1) || (m_fpsAverages[i] < minFps)) {
- minFps = m_fpsAverages[i];
- minFpsPlayer = i;
- }
- }
- }
- }
-// DEBUG_LOG_RAW(("\n"));
-}
-
-UnsignedInt ConnectionManager::getMinimumCushion() {
- return m_frameMetrics.getMinimumCushion();
-}
-
-/**
- * The commands for the given frame are all ready, time to send out our command count for that frame.
- */
-void ConnectionManager::processFrameTick(UnsignedInt frame) {
- if ((m_frameData[m_localSlot] == NULL) || (m_frameData[m_localSlot]->getIsQuitting() == TRUE)) {
- // if the local frame data stuff is NULL, we must be leaving the game.
- return;
- }
- UnsignedShort commandCount = m_frameData[m_localSlot]->getCommandCount(frame);
- NetFrameCommandMsg *msg = newInstance(NetFrameCommandMsg);
- msg->setExecutionFrame(frame);
- msg->setCommandCount(commandCount);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
- msg->setPlayerID(m_localSlot);
-
- m_frameMetrics.doPerFrameMetrics(frame);
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::processFrameTick - sending frame info for frame %d, ID %d, command count %d", frame, msg->getID(), commandCount));
-
- sendLocalCommand(msg, 0xff & ~(1 << m_localSlot));
-
- msg->detach();
-}
-
-/**
- * Set the local address.
- */
-void ConnectionManager::setLocalAddress(UnsignedInt ip, UnsignedInt port) {
- DEBUG_LOG(("ConnectionManager::setLocalAddress() - local address is %X:%d", ip, port));
- m_localAddr = ip;
- m_localPort = port;
-}
-
-/**
- * Initialize the transport object
- */
-void ConnectionManager::initTransport() {
- DEBUG_ASSERTCRASH((m_transport == NULL), ("m_transport already exists when trying to init it."));
- DEBUG_LOG(("ConnectionManager::initTransport - Initializing Transport"));
-
- delete m_transport;
- m_transport = new Transport;
- m_transport->reset();
- m_transport->init(m_localAddr, m_localPort);
-}
-
-/**
- * This is where the commands from the local client are sent to the other clients in
- * the game. This is also where the local commands are put into the frame data for
- * future execution.
- */
-void ConnectionManager::sendLocalGameMessage(GameMessage *msg, UnsignedInt frame) {
- UnsignedShort currentID = 0;
- if (DoesCommandRequireACommandID(NETCOMMANDTYPE_GAMECOMMAND)) {
- currentID = GenerateNextCommandID();
- }
-
- NetCommandMsg *netmsg = newInstance(NetGameCommandMsg)(msg);
- netmsg->setExecutionFrame(frame);
- netmsg->setPlayerID(m_localSlot);
- netmsg->setID(currentID);
-
- sendLocalCommand(netmsg);
-
- netmsg->detach();
-}
-
-/**
- * This is a NetCommandMsg that originated on the local computer. Send this to everyone specified
- * in the relay field. Commands sent in this way go through the packet router.
- */
-void ConnectionManager::sendLocalCommand(NetCommandMsg *msg, UnsignedByte relay /* = 0xff by default*/) {
- if (CommandRequiresDirectSend(msg) || (m_packetRouterSlot < 0) || (m_packetRouterSlot >= MAX_SLOTS) || (m_connections[m_packetRouterSlot] == NULL)) {
- sendLocalCommandDirect(msg, relay);
- return;
- }
- msg->attach();
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendLocalCommand - sending net command %d of type %s", msg->getID(),
- GetNetCommandTypeAsString(msg->getNetCommandType())));
-
- if (relay & (1 << m_localSlot)) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendLocalCommand - adding net command of type %s to player %d for frame %d", GetNetCommandTypeAsString(msg->getNetCommandType()), msg->getPlayerID(), msg->getExecutionFrame()));
- m_frameData[m_localSlot]->addNetCommandMsg(msg);
- }
-
- // Send the packet to everyone else
- if (m_localSlot == m_packetRouterSlot) {
- // I am the packet router, I need to send this packet to everyone individually.
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- // Send it to all open connections.
- if (((m_connections[i] != NULL) && (m_connections[i]->isQuitting() == FALSE)) && (relay & (1 << i))) {
- // Set the relay mask to only go to this player so he knows not to relay it to anyone else.
- UnsignedByte temprelay = 1 << i;
- m_connections[i]->sendNetCommandMsg(msg, temprelay); // This will create a new copy of netmsg for this connection.
- }
- }
- } else {
- // Send the command to everyone else via the packet router.
- UnsignedByte temprelay = relay & ~(1 << m_localSlot); // Tell the packet router to relay the message to everyone but myself.
- // Hopefully the packet router is smart enough to not send it
- // to slots that are not in the game.
-
- m_connections[m_packetRouterSlot]->sendNetCommandMsg(msg, temprelay); // This will create a new copy of netmsg for this connection.
-
- if (CommandRequiresAck(msg)) {
- NetCommandRef *ref = m_pendingCommands->addMessage(msg);
- //DEBUG_LOG(("ConnectionManager::sendLocalCommand - added command %d to pending commands list.", msg->getID()));
- if (ref != NULL) {
- ref->setRelay(temprelay);
- }
- }
- }
-
- msg->detach(); // detach from the command msg.
-}
-
-/**
- * This is a NetCommandMsg that originated on the local computer. Send this to everyone specified
- * in the relay field. Commands sent in this way do not go through the packet router.
- */
-void ConnectionManager::sendLocalCommandDirect(NetCommandMsg *msg, UnsignedByte relay) {
- msg->attach();
-
- if (((relay & (1 << m_localSlot)) != 0) && (m_frameData[m_localSlot] != NULL)) {
- if (IsCommandSynchronized(msg->getNetCommandType()) == TRUE) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendLocalCommandDirect - adding net command of type %s to player %d for frame %d", GetNetCommandTypeAsString(msg->getNetCommandType()), msg->getPlayerID(), msg->getExecutionFrame()));
- m_frameData[m_localSlot]->addNetCommandMsg(msg);
- }
- }
-
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if ((relay & (1 << i)) != 0) {
- if ((m_connections[i] != NULL) && (m_connections[i]->isQuitting() == FALSE)) {
- UnsignedByte temprelay = 1 << i;
- m_connections[i]->sendNetCommandMsg(msg, temprelay);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendLocalCommandDirect - Sending direct command %d of type %s to player %d", msg->getID(), GetNetCommandTypeAsString(msg->getNetCommandType()), i));
- }
- }
- }
-
- msg->detach();
-}
-
-Int commandsReadyDebugSpewage = 0;
-
-/**
- * Returns true if all the commands for the given frame are ready to be executed.
- */
-Bool ConnectionManager::allCommandsReady(UnsignedInt frame, Bool justTesting /* = FALSE */) {
- Bool retval = TRUE;
- FrameDataReturnType frameRetVal = FRAMEDATA_NOTREADY;
-// retval = FALSE; // ****for testing purposes only!!!!!!****
- Int i = 0;
- for (; (i < MAX_SLOTS) && retval; ++i) {
- if ((m_frameData[i] != NULL) && (m_frameData[i]->getIsQuitting() == FALSE)) {
-/*
- if (!(m_frameData[i]->allCommandsReady(frame, (frame != commandsReadyDebugSpewage) && (justTesting == FALSE)))) {
- if ((frame != commandsReadyDebugSpewage) && (justTesting == FALSE)) {
- DEBUG_LOG(("ConnectionManager::allCommandsReady, frame %d player %d not ready.", frame, i));
- commandsReadyDebugSpewage = frame;
- }
- retval = FALSE;
- } else {
-// DEBUG_LOG(("ConnectionManager::allCommandsReady, frame %d player %d is ready.", frame, i));
- }
-*/
-
- frameRetVal = m_frameData[i]->allCommandsReady(frame, (frame != commandsReadyDebugSpewage) && (justTesting == FALSE));
- if (frameRetVal == FRAMEDATA_NOTREADY) {
- retval = FALSE;
- } else if (frameRetVal == FRAMEDATA_RESEND) {
- requestFrameDataResend(i, frame);
- retval = FALSE;
- }
- }
- }
-
- if (frameRetVal == FRAMEDATA_RESEND) {
- // this frame's data is really screwed up, we need to clean it out so it can be resent to us.
- for (i = 0; i < MAX_SLOTS; ++i) {
- if ((m_frameData[i] != NULL) && (i != m_localSlot)) {
- m_frameData[i]->resetFrame(frame, FALSE);
- }
- }
- }
-
- if ((retval == TRUE) && (justTesting == FALSE)) {
- m_disconnectManager->allCommandsReady(TheGameLogic->getFrame(), this);
- retval = m_disconnectManager->allowedToContinue(); // allow the disconnect manager to keep us on this frame
- // in case we are waiting for a new packet router or something.
- }
-
- return retval;
-}
-
-void ConnectionManager::handleAllCommandsReady(void)
-{
- m_disconnectManager->allCommandsReady(TheGameLogic->getFrame(), this, FALSE);
-}
-
-
-/**
- * Only call this after making sure that all the commands are there for this frame.
- * After calling this the commands for this frame will be removed from the connection.
- *
- * BGC - To account for the case where the host disconnects without sending the
- * same commands to all players, we now have to keep around the last 'run ahead'
- * frames so we can potentially send those commands to the other players in the
- * game so they can catch up.
- */
-NetCommandList *ConnectionManager::getFrameCommandList(UnsignedInt frame)
-{
- NetCommandList *retlist = newInstance(NetCommandList);
- retlist->init();
-
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_frameData[i] != NULL) {
- retlist->appendList(m_frameData[i]->getFrameCommandList(frame));
- if (frame > FRAMES_TO_KEEP) {
- m_frameData[i]->resetFrame(frame - FRAMES_TO_KEEP); // After getting the commands for that frame from this
- // FrameDataManager object, we need to tell it that we're
- // done with the messages for that frame.
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("getFrameCommandList - called reset frame on player %d for frame %d", i, frame - FRAMES_TO_KEEP));
- }
- }
- }
-
- return retlist; // retlist deallocated by calling function.
-}
-
-void ConnectionManager::setFrameGrouping(time_t frameGrouping) {
- // Since we are the packet router, we should send more packets per second since we
- // may become the latency bottleneck for sending packets from one player to the next.
- // This is probably ok since the packet router should have the fastest connection of all
- // the players in the game.
- if (m_localSlot == m_packetRouterSlot) {
- frameGrouping = frameGrouping / 2;
- }
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_connections[i] != NULL) {
- m_connections[i]->setFrameGrouping(frameGrouping);
- }
- }
-}
-
-/*
-void ConnectionManager::determineRouterFallbackPlan() {
- memset(m_packetRouterFallback, 0, sizeof(m_packetRouterFallback));
- Int curnum = 1;
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_connections[i] != NULL) {
- m_packetRouterFallback[i] = curnum;
- if (curnum == 1) {
- m_packetRouterSlot = i;
- }
- ++curnum;
- }
- }
-}
-*/
-
-void ConnectionManager::doKeepAlive() {
- static Int nextIndex = 0;
- static time_t startTime = 0;
-
- time_t curTime = timeGetTime();
-
- if (startTime == 0) {
- startTime = curTime;
- return;
- }
-
- time_t numSeconds = (curTime - startTime) / 1000;
-
- while ((nextIndex <= numSeconds) && (nextIndex < MAX_SLOTS)) {
-// DEBUG_LOG(("ConnectionManager::doKeepAlive - trying to send keep alive message to player %d", nextIndex));
- if (m_connections[nextIndex] != NULL) {
- NetKeepAliveCommandMsg *msg = newInstance(NetKeepAliveCommandMsg);
- msg->setPlayerID(m_localSlot);
- if (DoesCommandRequireACommandID(msg->getNetCommandType()) == TRUE) {
- msg->setID(GenerateNextCommandID());
- }
-// DEBUG_LOG(("ConnectionManager::doKeepAlive - sending keep alive message to player %d", nextIndex));
- sendLocalCommandDirect(msg, 1 << nextIndex);
- msg->detach();
- }
- ++nextIndex;
- }
- if (nextIndex == MAX_SLOTS) {
- nextIndex = 0;
- startTime = curTime;
- }
-}
-
-PlayerLeaveCode ConnectionManager::disconnectPlayer(Int slot) {
- // Need to do the deletion of the slot's connection and frame data here.
- PlayerLeaveCode retval = PLAYERLEAVECODE_CLIENT;
- DEBUG_LOG(("ConnectionManager::disconnectPlayer - disconnecting slot %d on frame %d", slot, TheGameLogic->getFrame()));
-
- if ((slot < 0) || (slot >= MAX_SLOTS)) {
- return PLAYERLEAVECODE_UNKNOWN;
- }
-
- if (TheGameInfo)
- {
- GameSlot *gSlot = TheGameInfo->getSlot( slot );
- if (gSlot && !gSlot->lastFrameInGame())
- {
- DEBUG_LOG(("ConnectionManager::disconnectPlayer(%d) - slot is last in the game on frame %d",
- slot, TheGameLogic->getFrame()));
- gSlot->setLastFrameInGame(TheGameLogic->getFrame());
- }
- }
-
- UnicodeString unicodeName;
- unicodeName = getPlayerName(slot);
- if (unicodeName.getLength() > 0 && m_connections[slot]) {
- TheInGameUI->message("Network:PlayerLeftGame", unicodeName.str());
-
- // People are boneheads. Also play a sound
- static AudioEventRTS leftGameSound("GUIMessageReceived");
- TheAudio->addAudioEvent(&leftGameSound);
- }
-
- if ((m_frameData[slot] != NULL) && (m_frameData[slot]->getIsQuitting() == FALSE)) {
- DEBUG_LOG(("ConnectionManager::disconnectPlayer - deleting player %d frame data", slot));
- deleteInstance(m_frameData[slot]);
- m_frameData[slot] = NULL;
- }
-
- if (m_connections[slot] != NULL && !m_connections[slot]->isQuitting()) {
- DEBUG_LOG(("ConnectionManager::disconnectPlayer - deleting player %d connection", slot));
- deleteInstance(m_connections[slot]);
- m_connections[slot] = NULL;
- }
-
-// if (playerID == m_localSlot) {
-// TheMessageStream->appendMessage(GameMessage::MSG_CLEAR_GAME_DATA);
-// }
-
- if (slot == m_packetRouterSlot) {
- Int index = 0;
- while ((index < (MAX_SLOTS-1)) && (m_packetRouterFallback[index] != m_packetRouterSlot)) {
- ++index;
- }
- ++index;
- m_packetRouterSlot = m_packetRouterFallback[index];
- DEBUG_LOG(("Packet router left. New packet router is slot %d", m_packetRouterSlot));
- retval = PLAYERLEAVECODE_PACKETROUTER;
- }
- if (m_localSlot == slot) {
- DEBUG_LOG(("Disconnecting self"));
- retval = PLAYERLEAVECODE_LOCAL;
- }
-
- // Take the player out of the fallback plan
- Int fallbackindex = 0;
- while ((fallbackindex < MAX_SLOTS) && (m_packetRouterFallback[fallbackindex] != slot)) {
- ++fallbackindex;
- }
-
- for (Int i = fallbackindex; i < MAX_SLOTS-1; ++i) {
- m_packetRouterFallback[i] = m_packetRouterFallback[i+1];
- }
- m_packetRouterFallback[MAX_SLOTS-1] = -1;
-
- return retval;
-}
-
-void ConnectionManager::quitGame() {
- // Need to do the NetDisconnectPlayerCommandMsg creation and sending here.
- NetDisconnectPlayerCommandMsg *disconnectMsg = newInstance(NetDisconnectPlayerCommandMsg);
- disconnectMsg->setDisconnectSlot(m_localSlot);
- disconnectMsg->setPlayerID(m_localSlot);
- if (DoesCommandRequireACommandID(disconnectMsg->getNetCommandType())) {
- disconnectMsg->setID(GenerateNextCommandID());
- }
- //DEBUG_LOG(("ConnectionManager::disconnectLocalPlayer - about to send disconnect command"));
- sendLocalCommandDirect(disconnectMsg, 0xff ^ (1 << m_localSlot));
-
- //DEBUG_LOG(("ConnectionManager::disconnectLocalPlayer - about to flush connections"));
- flushConnections(); // need to do this so our packet actually gets sent before the connections are deleted.
- //DEBUG_LOG(("ConnectionManager::disconnectLocalPlayer - done flushing connections"));
-
- disconnectMsg->detach();
-
-#if RTS_GENERALS
- // if we get here, we hit Quit on the disconnect screen. Mark everyone as having disconnected from us
- // so the online stats can give us appropriate feedback.
- if (TheGameInfo)
- {
- for (Int i = 0; i < MAX_SLOTS; ++i)
- {
- GameSlot *gSlot = TheGameInfo->getSlot( i );
- if (gSlot && !gSlot->lastFrameInGame())
- {
- gSlot->markAsDisconnected();
- }
- }
- }
-#endif
-
- disconnectLocalPlayer();
-}
-
-void ConnectionManager::disconnectLocalPlayer() {
- // kill the frame data and the connections for all the other players.
- DEBUG_LOG(("ConnectionManager::disconnectLocalPlayer()"));
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (i != m_localSlot) {
- disconnectPlayer(i);
- }
- }
-}
-
-/**
- * Takes all the commands that are ready to send and sends them right now.
- */
-void ConnectionManager::flushConnections() {
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_connections[i] != NULL) {
-// DEBUG_LOG(("ConnectionManager::flushConnections - flushing connection to player %d", i));
- /*
- if (m_connections[i]->isQueueEmpty()) {
-// DEBUG_LOG(("ConnectionManager::flushConnections - connection queue empty"));
- }
- */
- m_connections[i]->doSend();
- }
- }
-
- if (m_transport != NULL) {
- m_transport->doSend();
- }
-}
-
-void ConnectionManager::resendPendingCommands() {
- //DEBUG_LOG(("ConnectionManager::resendPendingCommands()"));
- if (m_pendingCommands == NULL) {
- return;
- }
-
- NetCommandRef *ref = m_pendingCommands->getFirstMessage();
- while (ref != NULL) {
- //DEBUG_LOG(("ConnectionManager::resendPendingCommands - resending command %d", ref->getCommand()->getID()));
- sendLocalCommand(ref->getCommand(), ref->getRelay());
- ref = ref->getNext();
- }
-}
-
-UnsignedInt ConnectionManager::getLocalPlayerID() {
- return m_localSlot;
-}
-
-UnicodeString ConnectionManager::getPlayerName(Int playerNum) {
- UnicodeString retval;
- if( playerNum == m_localSlot ) {
- retval = m_localUser->GetName();
- } else if (((m_connections[playerNum] != NULL) && (m_connections[playerNum]->isQuitting() == FALSE))) {
- retval = m_connections[playerNum]->getUser()->GetName();
- }
- return retval;
-}
-
-/**
- * Take a user list and make connections and frame data manager objects for each of the players.
- * For now, this is also how we'll determine the packet router fallback plan.
- */
-void ConnectionManager::parseUserList(const GameInfo *game)
-{
- if (!game)
- return;
-
- Int i;
- Int numUsers = 0;
- m_localSlot = -1;
- DEBUG_LOG(("Local slot is %d", game->getLocalSlotNum()));
- for (i=0; igetConstSlot(i); // badness, but since we cast right back to const, we should be ok
- if (slot->isHuman())
- {
- if (game->getLocalSlotNum() == i)
- {
- m_localSlot = i;
- m_localUser->setName(slot->getName());
- }
-
- if (m_localSlot != i)
- {
- m_connections[i] = newInstance(Connection)();
- m_connections[i]->init();
- m_connections[i]->attachTransport(m_transport);
-// UnsignedShort port = (TheNAT)?TheNAT->getSlotPort(i):8088;
- UnsignedShort port = slot->getPort();
- m_connections[i]->setUser(newInstance(User)(slot->getName(), slot->getIP(), port));
- m_frameData[i] = newInstance(FrameDataManager)(FALSE);
- DEBUG_LOG(("Remote user is at %X:%d", slot->getIP(), slot->getPort()));
- }
- else
- {
- DEBUG_LOG(("Local user is %d (%X:%d)", m_localSlot, slot->getIP(), slot->getPort()));
- m_frameData[i] = newInstance(FrameDataManager)(TRUE);
- }
- m_frameData[i]->init();
- m_frameData[i]->reset();
-
- m_packetRouterFallback[numUsers] = i;
-
- ++numUsers;
-
- }
- }
-#ifdef MEMORYPOOL_DEBUG
- TheMemoryPoolFactory->debugSetInitFillerIndex(m_localSlot);
-#endif
-
- /*
- if ( numUsers < 2 || m_localSlot == -1 )
- {
- DEBUG_CRASH(("FAILED parseUserList - network game won't work as expected"));
- return;
- }
-
- char * list = strdup(buf);
- char *listPtr = list;
- if (!list)
- return;
-
- User users[MAX_SLOTS];
- int localUser = -1;
- int i;
-
- for (i=0; i= MAX_SLOTS)
- {
- DEBUG_LOG(("ConnectionManager::parseUserList - (numUsers = %d) FAILED parseUserList with list [%s]", numUsers, buf));
- return;
- }
-
- addrAsciiStr = addrStr;
- UnsignedInt addr = ResolveIP(addrAsciiStr);
- UnsignedInt port = atoi(portStr);
-
-// if ((m_localAddr != addr) || (m_localPort != port)) {
- if (loginName.compare(nameStr) != 0) {
- m_connections[numUsers] = newInstance(Connection)();
- m_connections[numUsers]->init();
- m_connections[numUsers]->attachTransport(m_transport);
- m_connections[numUsers]->setUser(newInstance(User)(nameStr, addr, port));
-
- m_frameData[numUsers] = newInstance(FrameDataManager)(FALSE);
-
- DEBUG_LOG(("ConnectionManager::parseUserList - User %d is %s", numUsers, nameStr));
- } else {
- m_localSlot = numUsers;
- m_localUser.setName(nameStr);
-
- DEBUG_LOG(("ConnectionManager::parseUserList - User %d is %s", numUsers, nameStr));
- DEBUG_LOG(("Local user is %d", m_localSlot));
-
- m_frameData[numUsers] = newInstance(FrameDataManager)(TRUE);
- }
- m_frameData[numUsers]->init();
- m_frameData[numUsers]->reset();
-
- m_packetRouterFallback[numUsers] = numUsers;
-
- numUsers++;
- }
-
- if (numUsers < 2 || m_localSlot == -1)
- {
- DEBUG_LOG(("ConnectionManager::parseUserList - FAILED (local user = %d, num players = %d) with list [%s]", m_localSlot, numUsers, buf));
- return;
- }
-
- free(list); // from the strdup above.
- list = NULL;
- */
-}
-
-/**
- * Return the number of incoming bytes per second averaged over 30 sec.
- */
-Real ConnectionManager::getIncomingBytesPerSecond( void )
-{
- if (m_transport)
- return m_transport->getIncomingBytesPerSecond();
- else
- return 0.0;
-}
-
-/**
- * Return the number of incoming packets per second averaged over the last 30 sec.
- */
-Real ConnectionManager::getIncomingPacketsPerSecond( void )
-{
- if (m_transport)
- return m_transport->getIncomingPacketsPerSecond();
- else
- return 0.0;
-}
-
-/**
- * Return the number of outgoing bytes per second averaged over the last 30 sec.
- */
-Real ConnectionManager::getOutgoingBytesPerSecond( void )
-{
- if (m_transport)
- return m_transport->getOutgoingBytesPerSecond();
- else
- return 0.0;
-}
-
-/**
- * Return the number of outgoing packets per second averaged over the last 30 sec.
- */
-Real ConnectionManager::getOutgoingPacketsPerSecond( void )
-{
- if (m_transport) {
- return m_transport->getOutgoingPacketsPerSecond();
- } else {
- return 0.0;
- }
-}
-
-/**
- * Return the number of bytes not from generals clients received per second averaged over the last 30 sec.
- */
-Real ConnectionManager::getUnknownBytesPerSecond( void )
-{
- if (m_transport)
- return m_transport->getUnknownBytesPerSecond();
- else
- return 0.0;
-}
-
-/**
- * Return the number ov packets not from generals clients received per second averaged over the last 30 sec.
- */
-Real ConnectionManager::getUnknownPacketsPerSecond( void )
-{
- if (m_transport)
- return m_transport->getUnknownPacketsPerSecond();
- else
- return 0.0;
-}
-
-/**
- * Return the smallest packet arrival cushion since this was last called.
- */
-UnsignedInt ConnectionManager::getPacketArrivalCushion() {
- UnsignedInt retval = m_smallestPacketArrivalCushion;
- m_smallestPacketArrivalCushion = -1;
- return retval;
-}
-
-void ConnectionManager::sendChat(UnicodeString text, Int playerMask, UnsignedInt executionFrame)
-{
- NetChatCommandMsg *msg = newInstance(NetChatCommandMsg);
- msg->setText(text);
- msg->setPlayerMask(playerMask);
- msg->setPlayerID(m_localSlot);
- msg->setID(0);
- msg->setExecutionFrame(executionFrame);
- if (DoesCommandRequireACommandID(msg->getNetCommandType()))
- {
- msg->setID(GenerateNextCommandID());
- }
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Chat message has ID of %d, mask of %8.8X, text of %ls", msg->getID(), msg->getPlayerMask(), msg->getText().str()));
-
- sendLocalCommand(msg, 0xff ^ (1 << m_localSlot));
- processChat(msg);
-
- msg->detach();
-}
-
-void ConnectionManager::sendDisconnectChat(UnicodeString text) {
- NetDisconnectChatCommandMsg *msg = newInstance(NetDisconnectChatCommandMsg);
- msg->setPlayerID(m_localSlot);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
- msg->setText(text);
-
- sendLocalCommandDirect(msg, 0xff ^ (1 << m_localSlot));
- processDisconnectChat(msg);
-}
-
-UnsignedShort ConnectionManager::sendFileAnnounce(AsciiString path, UnsignedByte playerMask)
-{
- File *theFile = TheLocalFileSystem->openFile(path.str());
- if (!theFile || !theFile->size())
- {
- UnicodeString log;
- log.format(L"Not sending file '%hs' to %X", path.str(), playerMask);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("%ls", log.str()));
- if (TheLAN)
- TheLAN->OnChat(UnicodeString(L"sendFile"), 0, log, LANAPI::LANCHAT_SYSTEM);
- return 0;
- }
-
- theFile->close();
-
- Int announceMask = 0xff ^ (1 << m_localSlot);
- NetFileAnnounceCommandMsg *announceMsg = newInstance(NetFileAnnounceCommandMsg);
- announceMsg->setPlayerID(m_localSlot);
- if (DoesCommandRequireACommandID(announceMsg->getNetCommandType()) == TRUE) {
- announceMsg->setID(GenerateNextCommandID());
- }
- announceMsg->setRealFilename(path);
- announceMsg->setPlayerMask(playerMask);
- UnsignedShort fileID = GenerateNextCommandID();
- announceMsg->setFileID(fileID);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFileAnnounce() - creating announce message with ID of %d from %d to mask %X for '%s' going to %X as command %d",
- announceMsg->getID(), announceMsg->getPlayerID(), announceMask, announceMsg->getRealFilename().str(),
- announceMsg->getPlayerMask(), announceMsg->getFileID()));
-
- processFileAnnounce(announceMsg); // set up things for the host
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Sending file announce to %X", announceMask));
- sendLocalCommand(announceMsg, announceMask);
- announceMsg->detach();
-
- return fileID;
-}
-
-void ConnectionManager::sendFile(AsciiString path, UnsignedByte playerMask, UnsignedShort commandID)
-{
- File *theFile = TheLocalFileSystem->openFile(path.str());
- if (!theFile || !theFile->size())
- {
- UnicodeString log;
- log.format(L"Not sending file '%hs' to %X", path.str(), playerMask);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("%ls", log.str()));
- if (TheLAN)
- TheLAN->OnChat(UnicodeString(L"sendFile"), 0, log, LANAPI::LANCHAT_SYSTEM);
- return;
- }
-
- Int len = theFile->size();
- char *buf = theFile->readEntireAndClose();
-
- // compress Targas
-#ifdef COMPRESS_TARGAS
- char *compressedBuf = NULL;
- Int compressedLen = path.endsWith(".tga")?CompressionManager::getMaxCompressedSize(len, CompressionManager::getPreferredCompression()):0;
- Int compressedSize = 0;
- if (compressedLen)
- compressedSize = CompressionManager::compressData(CompressionManager::getPreferredCompression(),
- buf, len, compressedBuf, compressedLen);
-
- if (!compressedSize)
- {
- delete[] compressedBuf;
- compressedBuf = NULL;
- }
-#endif // COMPRESS_TARGAS
-
- NetFileCommandMsg *fileMsg = newInstance(NetFileCommandMsg);
- fileMsg->setPlayerID(m_localSlot);
- fileMsg->setID(commandID);
- fileMsg->setRealFilename(path);
-#ifdef COMPRESS_TARGAS
- if (compressedBuf)
- {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Compressed '%s' from %d to %d (%g%%) before transfer", path.str(), len, compressedSize,
- (Real)compressedSize/(Real)len*100.0f));
- fileMsg->setFileData((unsigned char *)compressedBuf, compressedSize);
- }
- else
-#endif // COMPRESS_TARGAS
- {
- fileMsg->setFileData((unsigned char *)buf, len);
- }
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFile() - creating file message with ID of %d for '%s' going to %X from %d, size of %d",
- fileMsg->getID(), fileMsg->getRealFilename().str(), playerMask, fileMsg->getPlayerID(), fileMsg->getFileLength()));
-
- delete[] buf;
- buf = NULL;
-#ifdef COMPRESS_TARGAS
- delete[] compressedBuf;
- compressedBuf = NULL;
-#endif // COMPRESS_TARGAS
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Sending file: '%s', len %d, to %X", path.str(), len, playerMask));
-
- sendLocalCommand(fileMsg, playerMask);
-
- fileMsg->detach();
-}
-
-Int ConnectionManager::getFileTransferProgress(Int playerID, AsciiString path)
-{
- FileCommandMap::iterator commandIt = s_fileCommandMap.begin();
- while (commandIt != s_fileCommandMap.end())
- {
- //DEBUG_LOG(("ConnectionManager::getFileTransferProgress(%s): looking at existing transfer of '%s'",
- // path.str(), commandIt->second.str()));
- if (commandIt->second == path)
- {
- return s_fileProgressMap[playerID][commandIt->first];
- }
- ++commandIt;
- }
- //DEBUG_LOG(("Falling back to 0, since we couldn't find the map"));
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::getFileTransferProgress: path %s not found",path.str()));
- return 0;
-}
-
-
-void ConnectionManager::voteForPlayerDisconnect(Int slot) {
- if (m_disconnectManager != NULL) {
- m_disconnectManager->voteForPlayerDisconnect(slot, this);
- }
-}
-
-Int ConnectionManager::getNumPlayers()
-{
- Int retval = 0;
- for (Int i = 0; i < MAX_SLOTS; ++i)
- {
- if (isPlayerConnected(i)) {
- ++retval;
- }
- }
-
- return retval;
-}
-
-void ConnectionManager::updateLoadProgress( Int progress )
-{
- NetProgressCommandMsg *msg = newInstance(NetProgressCommandMsg);
- msg->setPercentage( progress );
- msg->setPlayerID( m_localSlot );
- if (DoesCommandRequireACommandID(msg->getNetCommandType()) == TRUE) {
- msg->setID(GenerateNextCommandID());
- }
- processProgress(msg);
- sendLocalCommand(msg, 0xff ^ (1 << m_localSlot));
-
- msg->detach();
-}
-
-void ConnectionManager::loadProgressComplete()
-{
- NetCommandMsg *msg = newInstance(NetCommandMsg);
- msg->setPlayerID( m_localSlot );
- if (DoesCommandRequireACommandID(msg->getNetCommandType()) == TRUE) {
- msg->setID(GenerateNextCommandID());
- }
- msg->setNetCommandType(NETCOMMANDTYPE_LOADCOMPLETE);
- processLoadComplete(msg);
- sendLocalCommand(msg, 0xff ^ (1 << m_localSlot));
-
- msg->detach();
-}
-
-void ConnectionManager::sendTimeOutGameStart()
-{
- NetCommandMsg *msg = newInstance(NetCommandMsg);
- msg->setPlayerID( m_localSlot );
- msg->setNetCommandType(NETCOMMANDTYPE_TIMEOUTSTART);
- if (DoesCommandRequireACommandID(msg->getNetCommandType()) == TRUE) {
- msg->setID(GenerateNextCommandID());
- }
- processTimeOutGameStart(msg);
- sendLocalCommand(msg, 0xff ^ (1 << m_localSlot));
-
- msg->detach();
-}
-
-Bool ConnectionManager::isPacketRouter( void )
-{
- return m_localSlot == m_packetRouterSlot;
-}
-
-Int ConnectionManager::getAverageFPS( void )
-{
- return m_frameMetrics.getAverageFPS();
-}
-
-Int ConnectionManager::getSlotAverageFPS(Int slot) {
- if ((slot < 0) || (slot >= MAX_SLOTS)) {
- return -1;
- }
- if ((m_packetRouterSlot != m_localSlot) && (slot == m_localSlot)) {
- // our framerate data isn't valid for other players unless we are the
- // packet router, so don't fake someone out.
- return -1;
- }
- return m_fpsAverages[slot];
-}
-
-#if defined(RTS_DEBUG)
-void ConnectionManager::debugPrintConnectionCommands() {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::debugPrintConnectionCommands - begin commands"));
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_connections[i] != NULL) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::debugPrintConnectionCommands - commands for connection %d", i));
- m_connections[i]->debugPrintCommands();
- }
- }
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::debugPrintConnectionCommands - end commands"));
-}
-#endif
-
-void ConnectionManager::notifyOthersOfCurrentFrame(Int frame) {
- NetDisconnectFrameCommandMsg *msg = newInstance(NetDisconnectFrameCommandMsg);
-
- msg->setPlayerID(m_localSlot);
- msg->setDisconnectFrame(frame);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::notifyOthersOfCurrentFrame - sending disconnect frame of %d, command ID = %d", frame, msg->getID()));
- sendLocalCommandDirect(msg, 0xff ^ (1 << m_localSlot));
- NetCommandRef *ref = NEW_NETCOMMANDREF(msg);
- ref->setRelay(1 << m_localSlot);
- m_disconnectManager->processDisconnectCommand(ref, this);
- deleteInstance(ref);
-
- msg->detach();
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::notifyOthersOfCurrentFrame - start screen on debug stuff"));
-#if defined(RTS_DEBUG)
- debugPrintConnectionCommands();
-#endif
-}
-
-void ConnectionManager::notifyOthersOfNewFrame(UnsignedInt frame) {
- NetDisconnectScreenOffCommandMsg *msg = newInstance(NetDisconnectScreenOffCommandMsg);
-
- msg->setPlayerID(m_localSlot);
- msg->setNewFrame(frame);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
-
- sendLocalCommandDirect(msg, 0xff ^ (1 << m_localSlot));
- NetCommandRef *ref = NEW_NETCOMMANDREF(msg);
- ref->setRelay(1 << m_localSlot);
- m_disconnectManager->processDisconnectCommand(ref, this);
- deleteInstance(ref);
-
- msg->detach();
-}
-
-void ConnectionManager::sendFrameDataToPlayer(UnsignedInt playerID, UnsignedInt startingFrame) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFrameDataToPlayer - sending frame data to player %d starting with frame %d", playerID, startingFrame));
- for (UnsignedInt frame = startingFrame; frame < TheGameLogic->getFrame(); ++frame) {
- sendSingleFrameToPlayer(playerID, frame);
- }
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFrameDataToPlayer - done sending commands to player %d", playerID));
-}
-
-void ConnectionManager::sendSingleFrameToPlayer(UnsignedInt playerID, UnsignedInt frame) {
- if ((TheGameLogic->getFrame() - FRAMES_TO_KEEP) > frame) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendSingleFrameToPlayer - player %d requested frame %d when we are on frame %d, this is too far in the past.", playerID, frame, TheGameLogic->getFrame()));
- return;
- }
-
- UnsignedByte relay = 1 << playerID;
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFrameDataToPlayer - sending data for frame %d", frame));
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if ((m_frameData[i] != NULL) && (i != playerID)) { // no need to send his own commands to him.
- NetCommandList *list = m_frameData[i]->getFrameCommandList(frame);
- if (list != NULL) {
- NetCommandRef *ref = list->getFirstMessage();
- while (ref != NULL) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFrameDataToPlayer - sending command %d from player %d to player %d using relay 0x%x", ref->getCommand()->getID(), i, playerID, relay));
- sendLocalCommandDirect(ref->getCommand(), relay);
- ref = ref->getNext();
- }
- }
- UnsignedInt frameCommandCount = m_frameData[i]->getFrameCommandCount(frame);
- NetFrameCommandMsg *msg = newInstance(NetFrameCommandMsg);
- msg->setExecutionFrame(frame);
- msg->setCommandCount(frameCommandCount);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
- msg->setPlayerID(i);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendFrameDataToPlayer - sending frame info from player %d to player %d for frame %d with command count %d and ID %d and relay %d", i, playerID, msg->getExecutionFrame(), msg->getCommandCount(), msg->getID(), relay));
- sendLocalCommandDirect(msg, relay);
- msg->detach();
- }
- }
-}
-
-UnsignedInt ConnectionManager::getNextPacketRouterSlot(UnsignedInt playerID) {
- Int index = 0;
- while ((index < (MAX_SLOTS-1)) && (m_packetRouterFallback[index] != playerID)) {
- ++index;
- }
- ++index;
- return m_packetRouterFallback[index];
-}
-
-void ConnectionManager::requestFrameDataResend(Int playerID, UnsignedInt frame) {
- NetFrameResendRequestCommandMsg *msg = newInstance(NetFrameResendRequestCommandMsg);
- msg->setPlayerID(m_localSlot);
- msg->setFrameToResend(frame);
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
-
- if (isPlayerConnected(playerID) == FALSE) {
- playerID = 0;
- while ((playerID < MAX_SLOTS) && (isPlayerConnected(playerID) == FALSE)) {
- ++playerID;
- }
- }
-
- if (playerID < MAX_SLOTS) {
- sendLocalCommandDirect(msg, 1 << playerID);
- }
-
- msg->detach();
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/DisconnectManager.cpp b/Generals/Code/GameEngine/Source/GameNetwork/DisconnectManager.cpp
deleted file mode 100644
index d7c1add1c9d..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/DisconnectManager.cpp
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/Recorder.h"
-#include "GameClient/DisconnectMenu.h"
-#include "GameClient/InGameUI.h"
-#include "GameLogic/GameLogic.h"
-#include "GameNetwork/DisconnectManager.h"
-#include "GameNetwork/NetworkInterface.h"
-#include "GameNetwork/networkutil.h"
-#include "GameNetwork/GameSpy/PingThread.h"
-#include "GameNetwork/GameSpy/GSConfig.h"
-
-
-DisconnectManager::DisconnectManager()
-{
- // Added By Sadullah Nader
- // Initializations missing and needed
- Int i;
- m_currentPacketRouterIndex = 0;
- m_lastFrame = 0;
- m_lastFrameTime = 0;
- m_lastKeepAliveSendTime = 0;
- m_haveNotifiedOtherPlayersOfCurrentFrame = FALSE;
- m_timeOfDisconnectScreenOn = 0;
-
- for( i = 0; i < MAX_SLOTS; ++i) {
- m_packetRouterFallback[i] = 0;
- }
-
- m_packetRouterTimeout = 0;
- for( i = 0; i < MAX_SLOTS -1; ++i) {
- m_playerTimeouts[i] = 0;
- }
-
- for( i = 0; i < MAX_SLOTS; ++i) {
- for (Int j = 0; j < MAX_SLOTS; ++j) {
- m_playerVotes[i][j].vote = FALSE;
- m_playerVotes[i][j].frame = 0;
- }
- }
-}
-
-DisconnectManager::~DisconnectManager() {
-}
-
-void DisconnectManager::init() {
- TheDisconnectMenu->hideScreen(); // make sure the screen starts out hidden.
- m_lastFrame = 0;
- m_lastFrameTime = -1;
- m_lastKeepAliveSendTime = -1;
- m_disconnectState = DISCONNECTSTATETYPE_SCREENOFF;
- m_currentPacketRouterIndex = 0;
- m_timeOfDisconnectScreenOn = 0;
-
- Int i = 0;
- for (; i < MAX_SLOTS; ++i) {
- for (Int j = 0; j < MAX_SLOTS; ++j) {
- m_playerVotes[i][j].vote = FALSE;
- m_playerVotes[i][j].frame = 0;
- }
- }
-
- for (i = 0; i < MAX_SLOTS; ++i) {
- m_disconnectFrames[i] = 0;
- m_disconnectFramesReceived[i] = FALSE;
- }
-
- m_pingFrame = 0;
- m_pingsSent = 0;
- m_pingsRecieved = 0;
-}
-
-void DisconnectManager::update(ConnectionManager *conMgr) {
- if (m_lastFrameTime == -1) {
- m_lastFrameTime = timeGetTime();
- }
-
- // The game logic stalls on the frame we are currently waiting for commands on,
- // so we have to check for the current logic frame being one higher than
- // the last one we had the commands ready for.
- if (TheGameLogic->getFrame() == m_lastFrame) {
- time_t curTime = timeGetTime();
- if ((curTime - m_lastFrameTime) > TheGlobalData->m_networkDisconnectTime) {
- if (m_disconnectState == DISCONNECTSTATETYPE_SCREENOFF) {
- turnOnScreen(conMgr);
- }
- sendKeepAlive(conMgr);
- }
- } else {
- nextFrame(TheGameLogic->getFrame(), conMgr);
- }
-
- if (m_disconnectState != DISCONNECTSTATETYPE_SCREENOFF) {
- updateDisconnectStatus(conMgr);
-
- // check to see if we need to send pings
- if (m_pingFrame < TheGameLogic->getFrame())
- {
- time_t curTime = timeGetTime();
- if ((curTime - m_lastFrameTime) > 10000) /// @todo: plug in some better measure here
- {
- m_pingFrame = TheGameLogic->getFrame();
- m_pingsSent = 0;
- m_pingsRecieved = 0;
-
- // Send the pings
- if (ThePinger)
- {
- //use next ping server
- static size_t serverIndex = 0;
- serverIndex++;
-
- AsciiStringList pingServers = TheGameSpyConfig->getPingServers();
-
- if( serverIndex >= pingServers.size() )
- serverIndex = 0; //wrap back to first ping server
-
- std::list::iterator it = pingServers.begin();
- for( size_t i = 0; i < serverIndex; i++ )
- it++;
-
- PingRequest req;
- req.hostname = it->str();
- req.repetitions = 5;
- req.timeout = 2000;
- m_pingsSent = req.repetitions;
- ThePinger->addRequest(req);
- DEBUG_LOG(("DisconnectManager::update() - requesting %d pings of %d from %s",
- req.repetitions, req.timeout, req.hostname.c_str()));
- }
- }
- }
-
- // update the ping thread, tracking pings if we are on the same frame
- if (ThePinger)
- {
- PingResponse resp;
- while (ThePinger->getResponse(resp))
- {
- if (m_pingFrame != TheGameLogic->getFrame())
- {
- // wrong frame - we're not pinging yet
- DEBUG_LOG(("DisconnectManager::update() - discarding ping of %d from %s (%d reps)",
- resp.avgPing, resp.hostname.c_str(), resp.repetitions));
- }
- else
- {
- // right frame
- DEBUG_LOG(("DisconnectManager::update() - keeping ping of %d from %s (%d reps)",
- resp.avgPing, resp.hostname.c_str(), resp.repetitions));
- if (resp.avgPing < 2000)
- {
- m_pingsRecieved += resp.repetitions;
- }
- }
- }
- }
- }
-}
-
-UnsignedInt DisconnectManager::getPingFrame()
-{
- return m_pingFrame;
-}
-
-Int DisconnectManager::getPingsSent()
-{
- return m_pingsSent;
-}
-
-Int DisconnectManager::getPingsRecieved()
-{
- return m_pingsRecieved;
-}
-
-
-void DisconnectManager::updateDisconnectStatus(ConnectionManager *conMgr) {
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (conMgr->isPlayerConnected(i)) {
- Int slot = translatedSlotPosition(i, conMgr->getLocalPlayerID());
- if (slot != -1) {
- time_t curTime = timeGetTime();
- time_t newTime = TheGlobalData->m_networkPlayerTimeoutTime - (curTime - m_playerTimeouts[slot]);
-
-// if someone is more than 2/3 timed out, lets get our frame numbers sync'd up. Also if someone is voted out
-// lets do the same thing.
-
- if (m_haveNotifiedOtherPlayersOfCurrentFrame == FALSE) {
- if ((newTime < TheGlobalData->m_networkPlayerTimeoutTime / 3) || (isPlayerVotedOut(slot, conMgr) == TRUE)) {
- TheNetwork->notifyOthersOfCurrentFrame();
- m_haveNotifiedOtherPlayersOfCurrentFrame = TRUE;
- }
-
- DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - curTime = %d, m_timeOfDisconnectScreenOn = %d, curTime - m_timeOfDisconnectScreenOn = %d", curTime, m_timeOfDisconnectScreenOn, curTime - m_timeOfDisconnectScreenOn));
-
- if (m_timeOfDisconnectScreenOn != 0) {
- if ((curTime - m_timeOfDisconnectScreenOn) > TheGlobalData->m_networkDisconnectScreenNotifyTime) {
- TheNetwork->notifyOthersOfCurrentFrame();
- m_haveNotifiedOtherPlayersOfCurrentFrame = TRUE;
- }
- }
- }
-
- if ((newTime < 0) || (isPlayerVotedOut(slot, conMgr) == TRUE)) {
- newTime = 0;
- DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - player %d(translated slot %d) has been voted out or timed out", i, slot));
- if (allOnSameFrame(conMgr) == TRUE) {
- DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - all on same frame"));
- if (isLocalPlayerNextPacketRouter(conMgr) == TRUE) {
- DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - local player is next packet router"));
- DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - about to do the disconnect procedure for player %d", i));
- sendDisconnectCommand(i, conMgr);
- disconnectPlayer(i, conMgr);
- sendPlayerDestruct(i, conMgr);
- } else {
- DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - local player is not the next packet router"));
- }
- } else {
- DEBUG_LOG(("DisconnectManager::updateDisconnectStatus - not all on same frame"));
- }
- }
- TheDisconnectMenu->setPlayerTimeoutTime(slot, newTime);
- }
- }
- }
-}
-
-void DisconnectManager::updateWaitForPacketRouter(ConnectionManager *conMgr) {
-/*
- time_t curTime = timeGetTime();
- time_t newTime = TheGlobalData->m_networkPlayerTimeoutTime - (curTime - m_packetRouterTimeout);
- if (newTime < 0) {
- newTime = 0;
-
- // The guy that we were hoping would be the new packet router isn't. We're screwed, get out of the game.
-
- DEBUG_LOG(("DisconnectManager::updateWaitForPacketRouter - timed out waiting for new packet router, quitting game"));
- TheNetwork->quitGame();
- }
- TheDisconnectMenu->setPacketRouterTimeoutTime(newTime);
-*/
-}
-
-void DisconnectManager::processDisconnectCommand(NetCommandRef *ref, ConnectionManager *conMgr) {
- NetCommandMsg *msg = ref->getCommand();
- if (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTKEEPALIVE) {
- processDisconnectKeepAlive(msg, conMgr);
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTPLAYER) {
- processDisconnectPlayer(msg, conMgr);
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_PACKETROUTERQUERY) {
- processPacketRouterQuery(msg, conMgr);
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_PACKETROUTERACK) {
- processPacketRouterAck(msg, conMgr);
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTVOTE) {
- processDisconnectVote(msg, conMgr);
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) {
- processDisconnectFrame(msg, conMgr);
- } else if (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTSCREENOFF) {
- processDisconnectScreenOff(msg, conMgr);
- }
-}
-
-void DisconnectManager::processDisconnectKeepAlive(NetCommandMsg *msg, ConnectionManager *conMgr) {
- NetDisconnectKeepAliveCommandMsg *cmdMsg = (NetDisconnectKeepAliveCommandMsg *)msg;
- Int slot = translatedSlotPosition(cmdMsg->getPlayerID(), conMgr->getLocalPlayerID());
- if (slot != -1) {
- resetPlayerTimeout(slot);
- }
-}
-
-void DisconnectManager::processDisconnectPlayer(NetCommandMsg *msg, ConnectionManager *conMgr) {
- NetDisconnectPlayerCommandMsg *cmdMsg = (NetDisconnectPlayerCommandMsg *)msg;
- DEBUG_LOG(("DisconnectManager::processDisconnectPlayer - Got disconnect player command from player %d. Disconnecting player %d on frame %d", msg->getPlayerID(), cmdMsg->getDisconnectSlot(), cmdMsg->getDisconnectFrame()));
- DEBUG_ASSERTCRASH(TheGameLogic->getFrame() == cmdMsg->getDisconnectFrame(), ("disconnecting player on the wrong frame!!!"));
- disconnectPlayer(cmdMsg->getDisconnectSlot(), conMgr);
-}
-
-void DisconnectManager::processPacketRouterQuery(NetCommandMsg *msg, ConnectionManager *conMgr) {
- NetPacketRouterQueryCommandMsg *cmdMsg = (NetPacketRouterQueryCommandMsg *)msg;
- DEBUG_LOG(("DisconnectManager::processPacketRouterQuery - got a packet router query command from player %d", msg->getPlayerID()));
-
- if (conMgr->getPacketRouterSlot() == conMgr->getLocalPlayerID()) {
- NetPacketRouterAckCommandMsg *ackmsg = newInstance(NetPacketRouterAckCommandMsg);
- ackmsg->setPlayerID(conMgr->getLocalPlayerID());
- if (DoesCommandRequireACommandID(ackmsg->getNetCommandType()) == TRUE) {
- ackmsg->setID(GenerateNextCommandID());
- }
- DEBUG_LOG(("DisconnectManager::processPacketRouterQuery - We are the new packet router, responding with an packet router ack. Local player is %d", ackmsg->getPlayerID()));
- conMgr->sendLocalCommandDirect(ackmsg, 1 << cmdMsg->getPlayerID());
- ackmsg->detach();
- } else {
- DEBUG_LOG(("DisconnectManager::processPacketRouterQuery - We are NOT the new packet router, these are not the droids you're looking for."));
- }
-}
-
-void DisconnectManager::processPacketRouterAck(NetCommandMsg *msg, ConnectionManager *conMgr) {
- NetPacketRouterAckCommandMsg *cmdMsg = (NetPacketRouterAckCommandMsg *)msg;
- DEBUG_LOG(("DisconnectManager::processPacketRouterAck - got packet router ack command from player %d", msg->getPlayerID()));
-
- if (conMgr->getPacketRouterSlot() == cmdMsg->getPlayerID()) {
- DEBUG_LOG(("DisconnectManager::processPacketRouterAck - packet router command is from who it should be."));
- resetPacketRouterTimeout();
- Int currentPacketRouterSlot = conMgr->getPacketRouterSlot();
- Int currentPacketRouterIndex = 0;
- while ((currentPacketRouterSlot != conMgr->getPacketRouterFallbackSlot(currentPacketRouterIndex)) && (currentPacketRouterIndex < MAX_SLOTS)) {
- ++currentPacketRouterIndex;
- }
- DEBUG_ASSERTCRASH((currentPacketRouterIndex < MAX_SLOTS), ("Invalid packet router index"));
-
- DEBUG_LOG(("DisconnectManager::processPacketRouterAck - New packet router confirmed, resending pending commands"));
- conMgr->resendPendingCommands();
- m_currentPacketRouterIndex = currentPacketRouterIndex;
- DEBUG_LOG(("DisconnectManager::processPacketRouterAck - Setting disconnect state to screen on."));
- m_disconnectState = DISCONNECTSTATETYPE_SCREENON; ///< set it to screen on so that the next call to AllCommandsReady can set up everything for the next frame properly.
- }
-}
-
-void DisconnectManager::processDisconnectVote(NetCommandMsg *msg, ConnectionManager *conMgr) {
- NetDisconnectVoteCommandMsg *cmdMsg = (NetDisconnectVoteCommandMsg *)msg;
- DEBUG_LOG(("DisconnectManager::processDisconnectVote - Got a disconnect vote for player %d command from player %d", cmdMsg->getSlot(), cmdMsg->getPlayerID()));
- Int transSlot = translatedSlotPosition(msg->getPlayerID(), conMgr->getLocalPlayerID());
-
- if (isPlayerInGame(transSlot, conMgr) == FALSE) {
- // if they've been timed out, voted out, disconnected, don't count their vote.
- return;
- }
-
- applyDisconnectVote(cmdMsg->getSlot(), cmdMsg->getVoteFrame(), cmdMsg->getPlayerID(), conMgr);
-}
-
-void DisconnectManager::processDisconnectFrame(NetCommandMsg *msg, ConnectionManager *conMgr) {
- NetDisconnectFrameCommandMsg *cmdMsg = (NetDisconnectFrameCommandMsg *)msg;
- UnsignedInt playerID = cmdMsg->getPlayerID();
- if (m_disconnectFrames[playerID] >= cmdMsg->getDisconnectFrame()) {
- // this message isn't valid, we have a disconnect frame that is later than this already.
- return;
- }
-
- if (m_disconnectFramesReceived[playerID] == TRUE) {
- DEBUG_LOG(("DisconnectManager::processDisconnectFrame - Got two disconnect frames without an intervening disconnect screen off command from player %d. Frames are %d and %d", playerID, m_disconnectFrames[playerID], cmdMsg->getDisconnectFrame()));
- }
-
- DEBUG_LOG(("DisconnectManager::processDisconnectFrame - about to call resetPlayersVotes for player %d", playerID));
- resetPlayersVotes(playerID, cmdMsg->getDisconnectFrame()-1, conMgr);
-
- m_disconnectFrames[playerID] = cmdMsg->getDisconnectFrame();
- m_disconnectFramesReceived[playerID] = TRUE;
- DEBUG_LOG(("DisconnectManager::processDisconnectFrame - Got a disconnect frame for player %d, frame = %d, local player is %d, local disconnect frame = %d, command id = %d", cmdMsg->getPlayerID(), cmdMsg->getDisconnectFrame(), conMgr->getLocalPlayerID(), m_disconnectFrames[conMgr->getLocalPlayerID()], cmdMsg->getID()));
-
- if (playerID == conMgr->getLocalPlayerID()) {
- DEBUG_LOG(("DisconnectManager::processDisconnectFrame - player %d is the local player", playerID));
- // we just got the message from the local player, check to see if we need to send
- // commands to anyone we already have heard from.
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (i != playerID) {
- Int transSlot = translatedSlotPosition(i, conMgr->getLocalPlayerID());
- if (isPlayerInGame(transSlot, conMgr) == TRUE) {
- if ((m_disconnectFrames[i] < m_disconnectFrames[playerID]) && (m_disconnectFramesReceived[i] == TRUE)) {
- DEBUG_LOG(("DisconnectManager::processDisconnectFrame - I have more frames than player %d, my frame = %d, their frame = %d", i, m_disconnectFrames[conMgr->getLocalPlayerID()], m_disconnectFrames[i]));
- conMgr->sendFrameDataToPlayer(i, m_disconnectFrames[i]);
- }
- }
- }
- }
- } else if ((m_disconnectFrames[playerID] < m_disconnectFrames[conMgr->getLocalPlayerID()]) && (m_disconnectFramesReceived[playerID] == TRUE)) {
- DEBUG_LOG(("DisconnectManager::processDisconnectFrame - I have more frames than player %d, my frame = %d, their frame = %d", playerID, m_disconnectFrames[conMgr->getLocalPlayerID()], m_disconnectFrames[playerID]));
- conMgr->sendFrameDataToPlayer(playerID, m_disconnectFrames[playerID]);
- }
-}
-
-void DisconnectManager::processDisconnectScreenOff(NetCommandMsg *msg, ConnectionManager *conMgr) {
- NetDisconnectScreenOffCommandMsg *cmdMsg = (NetDisconnectScreenOffCommandMsg *)msg;
- UnsignedInt playerID = cmdMsg->getPlayerID();
-
- DEBUG_LOG(("DisconnectManager::processDisconnectScreenOff - got a screen off command from player %d for frame %d", cmdMsg->getPlayerID(), cmdMsg->getNewFrame()));
-
- if ((playerID < 0) || (playerID >= MAX_SLOTS)) {
- return;
- }
-
- UnsignedInt newFrame = cmdMsg->getNewFrame();
- if (newFrame >= m_disconnectFrames[playerID]) {
- DEBUG_LOG(("DisconnectManager::processDisconnectScreenOff - resetting the disconnect screen status for player %d", playerID));
- m_disconnectFramesReceived[playerID] = FALSE;
- m_disconnectFrames[playerID] = newFrame; // just in case we get packets out of order and the disconnect screen off message gets here before the disconnect frame message.
-
- DEBUG_LOG(("DisconnectManager::processDisconnectScreenOff - about to call resetPlayersVotes for player %d", playerID));
- resetPlayersVotes(playerID, cmdMsg->getNewFrame(), conMgr);
- }
-}
-
-void DisconnectManager::applyDisconnectVote(Int slot, UnsignedInt frame, Int fromSlot, ConnectionManager *conMgr) {
- m_playerVotes[slot][fromSlot].vote = TRUE;
- m_playerVotes[slot][fromSlot].frame = frame;
- Int numVotes = countVotesForPlayer(slot);
- DEBUG_LOG(("DisconnectManager::applyDisconnectVote - added a vote to disconnect slot %d, from slot %d, for frame %d, current votes are %d", slot, fromSlot, frame, numVotes));
- Int transSlot = translatedSlotPosition(slot, conMgr->getLocalPlayerID());
- if (transSlot != -1) {
- TheDisconnectMenu->updateVotes(transSlot, numVotes);
- }
-}
-
-void DisconnectManager::nextFrame(UnsignedInt frame, ConnectionManager *conMgr) {
- m_lastFrame = frame;
- m_lastFrameTime = timeGetTime();
- resetPlayerTimeouts(conMgr);
-}
-
-void DisconnectManager::allCommandsReady(UnsignedInt frame, ConnectionManager *conMgr, Bool waitForPacketRouter) {
- if (m_disconnectState != DISCONNECTSTATETYPE_SCREENOFF) {
- DEBUG_LOG(("DisconnectManager::allCommandsReady - setting screen state to off."));
-
- TheDisconnectMenu->hideScreen();
- m_disconnectState = DISCONNECTSTATETYPE_SCREENOFF;
- TheNetwork->notifyOthersOfNewFrame(frame);
-
- // reset the votes since we're moving to a new frame.
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- m_playerVotes[i][conMgr->getLocalPlayerID()].vote = FALSE;
- }
-
- DEBUG_LOG(("DisconnectManager::allCommandsReady - resetting m_timeOfDisconnectScreenOn"));
- m_timeOfDisconnectScreenOn = 0;
- }
-}
-
-Bool DisconnectManager::allowedToContinue() {
- if (m_disconnectState != DISCONNECTSTATETYPE_SCREENOFF) {
- return FALSE;
- }
- return TRUE;
-}
-
-void DisconnectManager::sendKeepAlive(ConnectionManager *conMgr) {
- time_t curTime = timeGetTime();
-
- if (((curTime - m_lastKeepAliveSendTime) > 500) || (m_lastKeepAliveSendTime == -1)) {
- NetDisconnectKeepAliveCommandMsg *msg = newInstance(NetDisconnectKeepAliveCommandMsg);
- msg->setPlayerID(conMgr->getLocalPlayerID());
- if (DoesCommandRequireACommandID(msg->getNetCommandType()) == TRUE) {
- msg->setID(GenerateNextCommandID());
- }
- conMgr->sendLocalCommandDirect(msg, 0xff ^ (1 << msg->getPlayerID()));
- msg->detach();
-
- m_lastKeepAliveSendTime = curTime;
- }
-}
-
-void DisconnectManager::populateDisconnectScreen(ConnectionManager *conMgr) {
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- UnicodeString name = conMgr->getPlayerName(i);
- Int slot = translatedSlotPosition(i, conMgr->getLocalPlayerID());
- if (slot != -1) {
- TheDisconnectMenu->setPlayerName(slot, name);
-
- Int numVotes = countVotesForPlayer(i);
- TheDisconnectMenu->updateVotes(slot, numVotes);
- }
- }
-}
-
-Int DisconnectManager::translatedSlotPosition(Int slot, Int localSlot) {
- if (slot < localSlot) {
- return slot;
- }
-
- if (slot == localSlot) {
- return -1;
- }
-
- return (slot - 1);
-}
-
-Int DisconnectManager::untranslatedSlotPosition(Int slot, Int localSlot) {
- if (slot == -1) {
- return localSlot;
- }
-
- if (slot < localSlot) {
- return slot;
- }
-
- return (slot + 1);
-}
-
-void DisconnectManager::resetPlayerTimeouts(ConnectionManager *conMgr) {
- // reset the player timeouts.
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- Int slot = translatedSlotPosition(i, conMgr->getLocalPlayerID());
- if (slot != -1) {
- resetPlayerTimeout(slot);
- }
- }
-}
-
-void DisconnectManager::resetPlayerTimeout(Int slot) {
- m_playerTimeouts[slot] = timeGetTime();
-}
-
-void DisconnectManager::resetPacketRouterTimeout() {
- m_packetRouterTimeout = timeGetTime();
-}
-
-void DisconnectManager::turnOnScreen(ConnectionManager *conMgr) {
- TheDisconnectMenu->showScreen();
- DEBUG_LOG(("DisconnectManager::turnOnScreen - turning on screen on frame %d", TheGameLogic->getFrame()));
- m_disconnectState = DISCONNECTSTATETYPE_SCREENON;
- m_lastKeepAliveSendTime = -1;
- populateDisconnectScreen(conMgr);
- resetPlayerTimeouts(conMgr);
- TheDisconnectMenu->hidePacketRouterTimeout();
-
- m_haveNotifiedOtherPlayersOfCurrentFrame = FALSE;
-
- m_timeOfDisconnectScreenOn = timeGetTime();
- DEBUG_LOG(("DisconnectManager::turnOnScreen - turned on screen at time %d", m_timeOfDisconnectScreenOn));
-}
-
-void DisconnectManager::disconnectPlayer(Int slot, ConnectionManager *conMgr) {
- DEBUG_LOG(("DisconnectManager::disconnectPlayer - Disconnecting slot number %d on frame %d", slot, TheGameLogic->getFrame()));
- DEBUG_ASSERTCRASH((slot >= 0) && (slot < MAX_SLOTS), ("Attempting to disconnect an invalid slot number"));
- if ((slot < 0) || (slot >= (MAX_SLOTS))) {
- return;
- }
-
- if (TheGameInfo)
- {
- GameSlot *gSlot = TheGameInfo->getSlot( slot );
- if (gSlot)
- {
- gSlot->markAsDisconnected();
- }
- }
-
- Int transSlot = translatedSlotPosition(slot, conMgr->getLocalPlayerID());
-
- if (transSlot != -1) {
- // Ignore any disconnect commands that tell us to disconnect ourselves.
-
- // Get the disconnecting player off the disconnect window.
- UnicodeString uname = conMgr->getPlayerName(slot);
- TheRecorder->logPlayerDisconnect(uname, slot);
- TheDisconnectMenu->removePlayer(transSlot, uname);
-
- PlayerLeaveCode retcode = conMgr->disconnectPlayer(slot);
- DEBUG_ASSERTCRASH((retcode != PLAYERLEAVECODE_UNKNOWN), ("Invalid player leave code"));
-
- if (retcode == PLAYERLEAVECODE_PACKETROUTER) {
- DEBUG_LOG(("DisconnectManager::disconnectPlayer - disconnecting player was packet router."));
-
- conMgr->resendPendingCommands();
- }
- }
-}
-
-void DisconnectManager::sendDisconnectCommand(Int slot, ConnectionManager *conMgr) {
- DEBUG_LOG(("DisconnectManager::sendDisconnectCommand - Sending disconnect command for slot number %d", slot));
- DEBUG_ASSERTCRASH((slot >= 0) && (slot < MAX_SLOTS), ("Attempting to send a disconnect command for an invalid slot number"));
- if ((slot < 0) || (slot >= (MAX_SLOTS))) {
- return;
- }
-
- UnsignedInt disconnectFrame = getMaxDisconnectFrame();
-
- // Need to do the NetDisconnectPlayerCommandMsg creation and sending here.
- NetDisconnectPlayerCommandMsg *msg = newInstance(NetDisconnectPlayerCommandMsg);
- msg->setDisconnectSlot(slot);
- msg->setDisconnectFrame(disconnectFrame);
- msg->setPlayerID(conMgr->getLocalPlayerID());
- if (DoesCommandRequireACommandID(msg->getNetCommandType())) {
- msg->setID(GenerateNextCommandID());
- }
-
- conMgr->sendLocalCommand(msg);
-
- DEBUG_LOG(("DisconnectManager::sendDisconnectCommand - Sending disconnect command for slot number %d for frame %d", slot, disconnectFrame));
-
- msg->detach();
-}
-
-void DisconnectManager::sendVoteCommand(Int slot, ConnectionManager *conMgr) {
- NetDisconnectVoteCommandMsg *msg = newInstance(NetDisconnectVoteCommandMsg);
-
- msg->setPlayerID(conMgr->getLocalPlayerID());
- msg->setSlot(slot);
- msg->setVoteFrame(TheGameLogic->getFrame());
- if (DoesCommandRequireACommandID(msg->getNetCommandType()) == TRUE) {
- msg->setID(GenerateNextCommandID());
- }
-
- conMgr->sendLocalCommandDirect(msg, 0xff & ~(1 << conMgr->getLocalPlayerID()));
-
- msg->detach();
-}
-
-void DisconnectManager::voteForPlayerDisconnect(Int slot, ConnectionManager *conMgr) {
- Int transSlot = untranslatedSlotPosition(slot, conMgr->getLocalPlayerID());
-
- if (m_playerVotes[transSlot][conMgr->getLocalPlayerID()].vote == FALSE) {
- m_playerVotes[transSlot][conMgr->getLocalPlayerID()].vote = TRUE;
-
- sendVoteCommand(transSlot, conMgr);
-
- // we use the game logic frame cause we might not have sent out our own disconnect frame yet.
- applyDisconnectVote(transSlot, TheGameLogic->getFrame(), conMgr->getLocalPlayerID(), conMgr);
- }
-}
-
-void DisconnectManager::recalculatePacketRouterIndex(ConnectionManager *conMgr) {
- Int currentPacketRouterSlot = conMgr->getPacketRouterSlot();
- m_currentPacketRouterIndex = 0;
- while ((currentPacketRouterSlot != conMgr->getPacketRouterFallbackSlot(m_currentPacketRouterIndex)) && (m_currentPacketRouterIndex < MAX_SLOTS)) {
- ++m_currentPacketRouterIndex;
- }
- DEBUG_ASSERTCRASH((m_currentPacketRouterIndex < MAX_SLOTS), ("Invalid packet router index"));
-}
-
-Bool DisconnectManager::allOnSameFrame(ConnectionManager *conMgr) {
- Bool retval = TRUE;
- for (Int i = 0; (i < MAX_SLOTS) && (retval == TRUE); ++i) {
- Int transSlot = translatedSlotPosition(i, conMgr->getLocalPlayerID());
- if (transSlot == -1) {
- continue;
- }
- if ((conMgr->isPlayerConnected(i) == TRUE) && (isPlayerInGame(transSlot, conMgr) == TRUE)) {
- // ok, i is someone who is in the game and hasn't timed out yet or been voted out.
- if (m_disconnectFramesReceived[i] == FALSE) {
- // we don't know what frame they are on yet.
- retval = FALSE;
- }
- if ((m_disconnectFramesReceived[i] == TRUE) && (m_disconnectFrames[conMgr->getLocalPlayerID()] != m_disconnectFrames[i])) {
- // We know their frame, but they aren't on the same frame as us.
- retval = FALSE;
- }
- }
- }
- return retval;
-}
-
-Bool DisconnectManager::isLocalPlayerNextPacketRouter(ConnectionManager *conMgr) {
- UnsignedInt localSlot = conMgr->getLocalPlayerID();
- UnsignedInt packetRouterSlot = conMgr->getPacketRouterSlot();
- Int transSlot = translatedSlotPosition(packetRouterSlot, localSlot);
-
- // stop when we have found a packet router that is connected
- while ((transSlot != -1) && (isPlayerInGame(transSlot, conMgr) == FALSE)) {
- packetRouterSlot = conMgr->getNextPacketRouterSlot(packetRouterSlot);
- if ((packetRouterSlot >= MAX_SLOTS) || (packetRouterSlot < 0)) {
- // don't know who the next packet router is going to be,
- // so this game is not going to go anywhere anymore.
- DEBUG_CRASH(("no more players left to be the packet router, this shouldn't happen."));
- return FALSE;
- }
- transSlot = translatedSlotPosition(packetRouterSlot, localSlot);
- }
-
- if (packetRouterSlot == localSlot) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-Bool DisconnectManager::hasPlayerTimedOut(Int slot) {
- if (slot == -1) {
- return FALSE;
- }
-
- time_t newTime = TheGlobalData->m_networkPlayerTimeoutTime - (timeGetTime() - m_playerTimeouts[slot]);
- if (newTime <= 0) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-// this function assumes that we are the packet router. (or at least that
-// we will be after everyone is getting disconnected)
-void DisconnectManager::sendPlayerDestruct(Int slot, ConnectionManager *conMgr) {
- UnsignedShort currentID = 0;
- if (DoesCommandRequireACommandID(NETCOMMANDTYPE_DESTROYPLAYER))
- {
- currentID = GenerateNextCommandID();
- }
-
- DEBUG_LOG(("Queueing DestroyPlayer %d for frame %d on frame %d as command %d",
- slot, TheNetwork->getExecutionFrame()+1, TheGameLogic->getFrame(), currentID));
-
- NetDestroyPlayerCommandMsg *netmsg = newInstance(NetDestroyPlayerCommandMsg);
- netmsg->setExecutionFrame(TheNetwork->getExecutionFrame()+1);
- netmsg->setPlayerID(conMgr->getLocalPlayerID());
- netmsg->setID(currentID);
- netmsg->setPlayerIndex(slot);
- conMgr->sendLocalCommand(netmsg);
- netmsg->detach();
-}
-
-// the 'slot' variable is supposed to be a translated slot position. (translated slot meaning
-// that it is the player's position in the disconnect menu)
-Bool DisconnectManager::isPlayerVotedOut(Int slot, ConnectionManager *conMgr) {
- if (slot == -1) {
- // we can't vote out ourselves.
- return FALSE;
- }
- Int transSlot = untranslatedSlotPosition(slot, conMgr->getLocalPlayerID());
- Int numVotes = countVotesForPlayer(transSlot);
- if (numVotes >= (conMgr->getNumPlayers() - 1)) {
- return TRUE;
- }
- return FALSE;
-}
-
-UnsignedInt DisconnectManager::getMaxDisconnectFrame() {
- UnsignedInt retval = 0;
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_disconnectFrames[i] > retval) {
- retval = m_disconnectFrames[i];
- }
- }
- return retval;
-}
-
-Bool DisconnectManager::isPlayerInGame(Int slot, ConnectionManager *conMgr) {
- Int transSlot = untranslatedSlotPosition(slot, conMgr->getLocalPlayerID());
- DEBUG_ASSERTCRASH((transSlot >= 0) && (transSlot < MAX_SLOTS), ("invalid slot number"));
- if (((transSlot < 0) || (transSlot >= MAX_SLOTS)) || conMgr->isPlayerConnected(transSlot) == FALSE) {
- return FALSE;
- }
-
- if (isPlayerVotedOut(slot, conMgr) == TRUE) {
- return FALSE;
- }
-
- if (hasPlayerTimedOut(slot) == TRUE) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-void DisconnectManager::playerHasAdvancedAFrame(Int slot, UnsignedInt frame) {
- // if they have advanced beyond the frame they had been previously disconnecting on.
- if (frame >= m_disconnectFrames[slot]) {
- m_disconnectFrames[slot] = frame; // just in case we get a disconnect frame command after this is called.
- m_disconnectFramesReceived[slot] = FALSE;
- }
-}
-
-Int DisconnectManager::countVotesForPlayer(Int slot) {
- if ((slot < 0) || (slot >= MAX_SLOTS)) {
- return 0;
- }
-
- Int retval = 0;
- for (Int i = 0; i < MAX_SLOTS; ++i) {
- // using TheGameLogic->getFrame() cause we might not have sent our disconnect frame yet.
- if ((m_playerVotes[slot][i].vote == TRUE) && (m_playerVotes[slot][i].frame == TheGameLogic->getFrame())) {
- ++retval;
- }
- }
-
- return retval;
-}
-
-void DisconnectManager::resetPlayersVotes(Int playerID, UnsignedInt frame, ConnectionManager *conMgr) {
- DEBUG_LOG(("DisconnectManager::resetPlayersVotes - resetting player %d's votes on frame %d", playerID, frame));
-
- // we need to reset this player's votes that happened before or on the given frame.
- for(Int i = 0; i < MAX_SLOTS; ++i) {
- if (m_playerVotes[i][playerID].frame <= frame) {
- DEBUG_LOG(("DisconnectManager::resetPlayersVotes - resetting player %d's vote for player %d from frame %d on frame %d", playerID, i, m_playerVotes[i][playerID].frame, frame));
- m_playerVotes[i][playerID].vote = FALSE;
- }
- }
-
- Int numVotes = countVotesForPlayer(playerID);
- DEBUG_LOG(("DisconnectManager::resetPlayersVotes - after adjusting votes, player %d has %d votes", playerID, numVotes));
- Int transSlot = translatedSlotPosition(playerID, conMgr->getLocalPlayerID());
- if (transSlot != -1) {
- TheDisconnectMenu->updateVotes(transSlot, numVotes);
- }
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/DownloadManager.cpp b/Generals/Code/GameEngine/Source/GameNetwork/DownloadManager.cpp
deleted file mode 100644
index 221ed56f95d..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/DownloadManager.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: DownloadManager.cpp //////////////////////////////////////////////////////
-// Generals download manager code
-// Author: Matthew D. Campbell, July 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/GameText.h"
-#include "GameNetwork/DownloadManager.h"
-
-DownloadManager *TheDownloadManager;
-
-DownloadManager::DownloadManager()
-{
- m_download = NEW CDownload(this);
- m_wasError = m_sawEnd = false;
-
- //Added By Sadullah Nader
- //Initializations missing and needed
-
- m_queuedDownloads.clear();
-
- //
-
- m_statusString = TheGameText->fetch("FTP:StatusIdle");
-
- // ----- Initialize Winsock -----
- m_winsockInit = true;
- WORD verReq = MAKEWORD(2, 2);
- WSADATA wsadata;
-
- int err = WSAStartup(verReq, &wsadata);
- if (err != 0)
- {
- m_winsockInit = false;
- }
- else
- {
- if ((LOBYTE(wsadata.wVersion) != 2) || (HIBYTE(wsadata.wVersion) !=2))
- {
- WSACleanup();
- m_winsockInit = false;
- }
- }
-
-}
-
-DownloadManager::~DownloadManager()
-{
- delete m_download;
- if (m_winsockInit)
- {
- WSACleanup();
- m_winsockInit = false;
- }
-}
-
-void DownloadManager::init( void )
-{
-}
-
-void DownloadManager::reset( void )
-{
-}
-
-HRESULT DownloadManager::update( void )
-{
- return m_download->PumpMessages();
-}
-
-HRESULT DownloadManager::downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume )
-{
- return m_download->DownloadFile( server.str(), username.str(), password.str(), file.str(), localfile.str(), regkey.str(), tryResume );
-}
-
-void DownloadManager::queueFileForDownload( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume )
-{
- QueuedDownload q;
- q.file = file;
- q.localFile = localfile;
- q.password = password;
- q.regKey = regkey;
- q.server = server;
- q.tryResume = tryResume;
- q.userName = username;
-
- m_queuedDownloads.push_back(q);
-}
-
-HRESULT DownloadManager::downloadNextQueuedFile( void )
-{
- QueuedDownload q;
- std::list::iterator it = m_queuedDownloads.begin();
- if (it != m_queuedDownloads.end())
- {
- q = *it;
- m_queuedDownloads.pop_front();
- m_wasError = m_sawEnd = false;
- return downloadFile( q.server, q.userName, q.password, q.file, q.localFile, q.regKey, q.tryResume );
- }
- else
- {
- DEBUG_CRASH(("Starting non-existent download!"));
- return S_OK;
- }
-}
-
-AsciiString DownloadManager::getLastLocalFile( void )
-{
- char buf[256] = "";
- m_download->GetLastLocalFile(buf, 256);
- return buf;
-}
-
-HRESULT DownloadManager::OnError( Int error )
-{
- m_wasError = true;
- AsciiString s = "FTP:UnknownError";
- switch (error)
- {
- case DOWNLOADEVENT_NOSUCHSERVER:
- s = "FTP:NoSuchServer";
- break;
- case DOWNLOADEVENT_COULDNOTCONNECT:
- s = "FTP:CouldNotConnect";
- break;
- case DOWNLOADEVENT_LOGINFAILED:
- s = "FTP:LoginFailed";
- break;
- case DOWNLOADEVENT_NOSUCHFILE:
- s = "FTP:NoSuchFile";
- break;
- case DOWNLOADEVENT_LOCALFILEOPENFAILED:
- s = "FTP:LocalFileOpenFailed";
- break;
- case DOWNLOADEVENT_TCPERROR:
- s = "FTP:TCPError";
- break;
- case DOWNLOADEVENT_DISCONNECTERROR:
- s = "FTP:DisconnectError";
- break;
- }
- m_errorString = TheGameText->fetch(s);
- DEBUG_LOG(("DownloadManager::OnError(): %s(%d)", s.str(), error));
- return S_OK;
-}
-
-HRESULT DownloadManager::OnEnd()
-{
- m_sawEnd = true;
- DEBUG_LOG(("DownloadManager::OnEnd()"));
- return S_OK;
-}
-
-HRESULT DownloadManager::OnQueryResume()
-{
- DEBUG_LOG(("DownloadManager::OnQueryResume()"));
- //return DOWNLOADEVENT_DONOTRESUME;
- return DOWNLOADEVENT_RESUME;
-}
-
-HRESULT DownloadManager::OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft )
-{
- DEBUG_LOG(("DownloadManager::OnProgressUpdate(): %d/%d %d/%d", bytesread, totalsize, timetaken, timeleft));
- return S_OK;
-}
-
-HRESULT DownloadManager::OnStatusUpdate( Int status )
-{
- AsciiString s = "FTP:StatusNone";
- switch (status)
- {
- case DOWNLOADSTATUS_CONNECTING:
- s = "FTP:StatusConnecting";
- break;
- case DOWNLOADSTATUS_LOGGINGIN:
- s = "FTP:StatusLoggingIn";
- break;
- case DOWNLOADSTATUS_FINDINGFILE:
- s = "FTP:StatusFindingFile";
- break;
- case DOWNLOADSTATUS_QUERYINGRESUME:
- s = "FTP:StatusQueryingResume";
- break;
- case DOWNLOADSTATUS_DOWNLOADING:
- s = "FTP:StatusDownloading";
- break;
- case DOWNLOADSTATUS_DISCONNECTING:
- s = "FTP:StatusDisconnecting";
- break;
- case DOWNLOADSTATUS_FINISHING:
- s = "FTP:StatusFinishing";
- break;
- case DOWNLOADSTATUS_DONE:
- s = "FTP:StatusDone";
- break;
- }
- m_statusString = TheGameText->fetch(s);
- DEBUG_LOG(("DownloadManager::OnStatusUpdate(): %s(%d)", s.str(), status));
- return S_OK;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/FileTransfer.cpp b/Generals/Code/GameEngine/Source/GameNetwork/FileTransfer.cpp
deleted file mode 100644
index e30a4ed52fe..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/FileTransfer.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: FileTransfer.cpp
-// Author: Matthew D. Campbell, December 2002
-// Description: File Transfer wrapper using TheNetwork
-///////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/LoadScreen.h"
-#include "GameClient/Shell.h"
-#include "GameNetwork/FileTransfer.h"
-#include "GameNetwork/networkutil.h"
-
-//-------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------
-
-static Bool doFileTransfer( AsciiString filename, MapTransferLoadScreen *ls, Int mask )
-{
- Bool fileTransferDone = FALSE;
- Int fileTransferPercent = 0;
- Int i;
-
- if (mask)
- {
- ls->setCurrentFilename(filename);
- UnsignedInt startTime = timeGetTime();
- const Int timeoutPeriod = 2*60*1000;
- ls->processTimeout(timeoutPeriod/1000);
-
- ls->update(0);
- fileTransferDone = FALSE;
- fileTransferPercent = 0;
-
- UnsignedShort fileCommandID = 0;
- Bool sentFile = FALSE;
- if (TheGameInfo->amIHost())
- {
- Sleep(500);
- fileCommandID = TheNetwork->sendFileAnnounce(filename, mask);
- }
- else
- {
- sentFile = TRUE;
- }
-
- DEBUG_LOG(("Starting file transfer loop"));
-
- while (!fileTransferDone)
- {
- if (!sentFile && TheNetwork->areAllQueuesEmpty())
- {
- TheNetwork->sendFile(filename, mask, fileCommandID);
- sentFile = TRUE;
- }
-
- // get the progress for each player, and take the min for our overall progress
- fileTransferDone = TRUE;
- fileTransferPercent = 100;
- for (i=1; igetConstSlot(i)->isHuman() && !TheGameInfo->getConstSlot(i)->hasMap())
- {
- Int slotTransferPercent = TheNetwork->getFileTransferProgress(i, filename);
- fileTransferPercent = min(fileTransferPercent, slotTransferPercent);
-
- if (slotTransferPercent == 0)
- ls->processProgress(i, slotTransferPercent, "MapTransfer:Preparing");
- else if (slotTransferPercent < 100)
- ls->processProgress(i, slotTransferPercent, "MapTransfer:Recieving");
- else
- ls->processProgress(i, slotTransferPercent, "MapTransfer:Done");
- }
- }
- if (fileTransferPercent < 100)
- {
- fileTransferDone = FALSE;
- if (fileTransferPercent == 0)
- ls->processProgress(0, fileTransferPercent, "MapTransfer:Preparing");
- else
- ls->processProgress(0, fileTransferPercent, "MapTransfer:Sending");
- }
- else
- {
- DEBUG_LOG(("File transfer is 100%%!"));
- ls->processProgress(0, fileTransferPercent, "MapTransfer:Done");
- }
-
- Int now = timeGetTime();
- if (now > startTime + timeoutPeriod) // bail if we don't finish in a reasonable amount of time
- {
- DEBUG_LOG(("Timing out file transfer"));
- break;
- }
- else
- {
- ls->processTimeout((startTime + timeoutPeriod - now)/1000);
- }
-
- ls->update(fileTransferPercent);
- }
-
- if (!fileTransferDone)
- {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-//-------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------
-
-AsciiString GetBasePathFromPath( AsciiString path )
-{
- const char *s = path.reverseFind('\\');
- if (s)
- {
- Int len = s - path.str();
-
- AsciiString base;
- char *buf = base.getBufferForRead(len + 1);
- memcpy(buf, path.str(), len);
- buf[len] = 0;
- return buf;
- }
- return AsciiString::TheEmptyString;
-}
-
-AsciiString GetFileFromPath( AsciiString path )
-{
- const char *s = path.reverseFind('\\');
- if (s)
- return s+1;
- return path;
-}
-
-AsciiString GetExtensionFromFile( AsciiString fname )
-{
- const char *s = fname.reverseFind('.');
- if (s)
- return s+1;
- return fname;
-}
-
-AsciiString GetBaseFileFromFile( AsciiString fname )
-{
- const char *s = fname.reverseFind('.');
- if (s)
- {
- Int len = s - fname.str();
-
- AsciiString base;
- char *buf = base.getBufferForRead(len + 1);
- memcpy(buf, fname.str(), len);
- buf[len] = 0;
- return buf;
- }
- return AsciiString::TheEmptyString;
-}
-
-AsciiString GetPreviewFromMap( AsciiString path )
-{
- AsciiString fname = GetBaseFileFromFile(GetFileFromPath(path));
- AsciiString base = GetBasePathFromPath(path);
-
- AsciiString out;
- out.format("%s\\%s.tga", base.str(), fname.str());
- return out;
-}
-
-AsciiString GetINIFromMap( AsciiString path )
-{
- AsciiString base = GetBasePathFromPath(path);
-
- AsciiString out;
- out.format("%s\\map.ini", base.str());
- return out;
-}
-
-AsciiString GetStrFileFromMap( AsciiString path )
-{
- AsciiString base = GetBasePathFromPath(path);
-
- AsciiString out;
- out.format("%s\\map.str", base.str());
- return out;
-}
-
-AsciiString GetSoloINIFromMap( AsciiString path )
-{
- AsciiString base = GetBasePathFromPath(path);
-
- AsciiString out;
- out.format("%s\\solo.ini", base.str());
- return out;
-}
-
-AsciiString GetAssetUsageFromMap( AsciiString path )
-{
- AsciiString base = GetBasePathFromPath(path);
-
- AsciiString out;
- out.format("%s\\assetusage.txt", base.str());
- return out;
-}
-
-AsciiString GetReadmeFromMap( AsciiString path )
-{
- AsciiString base = GetBasePathFromPath(path);
-
- AsciiString out;
- out.format("%s\\readme.txt", base.str());
- return out;
-}
-
-//-------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------
-
-Bool DoAnyMapTransfers(GameInfo *game)
-{
- TheGameInfo = game;
- Int mask = 0;
- Int i=0;
- for (i=1; igetConstSlot(i)->isHuman() && !TheGameInfo->getConstSlot(i)->hasMap())
- {
- DEBUG_LOG(("Adding player %d to transfer mask", i));
- mask |= (1<hideShell();
- MapTransferLoadScreen *ls = NEW MapTransferLoadScreen;
- ls->init(TheGameInfo);
- Bool ok = TRUE;
- if (TheGameInfo->getMapContentsMask() & 2)
- ok = doFileTransfer(GetPreviewFromMap(game->getMap()), ls, mask);
- if (ok && TheGameInfo->getMapContentsMask() & 4)
- ok = doFileTransfer(GetINIFromMap(game->getMap()), ls, mask);
- if (ok && TheGameInfo->getMapContentsMask() & 8)
- ok = doFileTransfer(GetStrFileFromMap(game->getMap()), ls, mask);
- if (ok && TheGameInfo->getMapContentsMask() & 16)
- ok = doFileTransfer(GetSoloINIFromMap(game->getMap()), ls, mask);
- if (ok && TheGameInfo->getMapContentsMask() & 32)
- ok = doFileTransfer(GetAssetUsageFromMap(game->getMap()), ls, mask);
- if (ok && TheGameInfo->getMapContentsMask() & 64)
- ok = doFileTransfer(GetReadmeFromMap(game->getMap()), ls, mask);
- if (ok)
- ok = doFileTransfer(game->getMap(), ls, mask);
- delete ls;
- ls = NULL;
- if (!ok)
- TheShell->showShell();
- return ok;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/FirewallHelper.cpp b/Generals/Code/GameEngine/Source/GameNetwork/FirewallHelper.cpp
deleted file mode 100644
index 8a2d7569450..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/FirewallHelper.cpp
+++ /dev/null
@@ -1,1574 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-/***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * $Archive:: /RedAlert2/NAT.cpp $*
- * *
- * $Author:: Steve_t $*
- * *
- * $Modtime:: 3/15/01 12:00PM $*
- * *
- * $Revision:: 1 $*
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/crc.h"
-#include "Common/UserPreferences.h"
-#include "GameNetwork/FirewallHelper.h"
-#include "GameNetwork/NAT.h"
-#include "GameNetwork/udp.h"
-#include "GameNetwork/NetworkDefs.h"
-#include "GameNetwork/GameSpy/GSConfig.h"
-
-
-FirewallHelperClass *TheFirewallHelper = NULL;
-
-FirewallHelperClass * createFirewallHelper()
-{
- return NEW FirewallHelperClass();
-}
-
-
-/***********************************************************************************************
- * FirewallHelperClass::FirewallHelperClass -- Constructor *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 5:03PM ST : Created *
- *=============================================================================================*/
-/* static */ Int FirewallHelperClass::m_sourcePortPool = 4096;
-
-FirewallHelperClass::FirewallHelperClass(void)
-{
- //Added Sadullah Nader
- //Initializations missing and needed
- m_currentTry = 0;
- m_numManglers = 0;
- m_numResponses = 0;
- m_packetID = 0;
- m_timeoutLength = 0;
- m_timeoutStart = 0;
- //
-
- m_behavior = FIREWALL_TYPE_UNKNOWN;
- m_lastBehavior = FIREWALL_TYPE_UNKNOWN;
- m_sourcePortAllocationDelta = 0;
- m_lastSourcePortAllocationDelta = 0;
- Int i = 0;
- for (; i < MAX_SPARE_SOCKETS; ++i) {
- m_spareSockets[i].port = 0;
- m_messages[i].length = 0;
- m_mangledPorts[i] = 0;
- m_sparePorts[i] = 0;
- }
-
- for (i = 0; i < MAX_NUM_MANGLERS; i++)
- {
- m_manglers[i] = 0;
- }
-
- m_currentState = DETECTIONSTATE_IDLE;
-
- m_sourcePortPool = 4096 + ((timeGetTime() / 1000) % 1000); // do this to make sure we don't use the same source
- // port before a previous connection has had a chance
- // to time out.
-}
-
-
-
-/***********************************************************************************************
- * FirewallHelperClass::~FirewallHelperClass -- Destructor *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 4/16/02 BGC : Created *
- *=============================================================================================*/
-FirewallHelperClass::~FirewallHelperClass()
-{
- reset();
-}
-
-/***********************************************************************************************
- * FirewallHelperClass::Reset -- Cleans out the object *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/29/01 1:04AM ST : Created *
- *=============================================================================================*/
-void FirewallHelperClass::reset(void)
-{
- closeAllSpareSockets();
- m_currentState = DETECTIONSTATE_IDLE;
- for (Int i = 0; i < MAX_SPARE_SOCKETS; ++i) {
- m_messages[i].length = 0;
- }
-}
-
-
-
-
-/***********************************************************************************************
- * FirewallHelperClass::Detect_Firewall -- See what our firewall is up to *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 6:47PM ST : Created *
- *=============================================================================================*/
-Bool FirewallHelperClass::detectFirewall(void)
-{
- OptionPreferences pref;
-
- OptionPreferences::const_iterator it = pref.find("FirewallNeedToRefresh");
- if (it != pref.end()) {
- AsciiString str = it->second;
- if (str.compareNoCase("TRUE") == 0) {
- TheWritableGlobalData->m_firewallBehavior = FIREWALL_TYPE_UNKNOWN;
- }
- }
-
- if (TheWritableGlobalData->m_firewallBehavior == FIREWALL_TYPE_UNKNOWN) {
- detectFirewallBehavior();
-
- return FALSE;
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectFirewall - firewall behavior already specified as %d, port allocation delta is %d, skipping detection.", TheWritableGlobalData->m_firewallBehavior, TheWritableGlobalData->m_firewallPortAllocationDelta));
- }
-
- return TRUE;
-}
-
-
-Bool FirewallHelperClass::behaviorDetectionUpdate()
-{
- if (m_currentState == DETECTIONSTATE_IDLE) {
- return FALSE;
- }
-
- if (m_currentState == DETECTIONSTATE_DONE) {
- return TRUE;
- }
-
- if (m_currentState == DETECTIONSTATE_BEGIN) {
- return detectionBeginUpdate();
- }
-
- if (m_currentState == DETECTIONSTATE_TEST1) {
- return detectionTest1Update();
- }
-
- if (m_currentState == DETECTIONSTATE_TEST2) {
- return detectionTest2Update();
- }
-
- if (m_currentState == DETECTIONSTATE_TEST3) {
- return detectionTest3Update();
- }
-
- if (m_currentState == DETECTIONSTATE_TEST3_WAITFORRESPONSES) {
- return detectionTest3WaitForResponsesUpdate();
- }
-
- if (m_currentState == DETECTIONSTATE_TEST4_1) {
- return detectionTest4Stage1Update();
- }
-
- if (m_currentState == DETECTIONSTATE_TEST4_2) {
- return detectionTest4Stage2Update();
- }
-
- if (m_currentState == DETECTIONSTATE_TEST5) {
- return detectionTest5Update();
- }
-
- return TRUE;
-}
-
-/***********************************************************************************************
- * FHC::getNextTemporarySourcePort -- Get a throwaway source port for temporary use *
- * *
- * *
- * *
- * INPUT: number of ports in sequence to skip *
- * *
- * OUTPUT: port number *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:06PM ST : Created *
- *=============================================================================================*/
-UnsignedShort FirewallHelperClass::getNextTemporarySourcePort(Int skip)
-{
- UnsignedShort return_port = (UnsignedShort) m_sourcePortPool;
-
- /*
- ** Try max 256 ports until we find one we can bind to a socket.
- */
- Int tries = 256;
- if (skip == 0) {
- skip = 1;
- }
-
- while (tries--) {
-
- m_sourcePortPool += skip;
- return_port = (UnsignedShort) m_sourcePortPool;
-
- if (m_sourcePortPool > 65535) {
- m_sourcePortPool = 2048;
- }
-
- /*
- ** Validate the port by trying to bind it to a socket.
- */
- Bool result = openSpareSocket(return_port);
-
- if (result) {
- closeSpareSocket(return_port);
- return(return_port);
- } else {
- DEBUG_LOG(("FirewallHelperClass::getNextTemporarySourcePort - failed to open socket on port %d", return_port));
- }
- }
-
- return(return_port);
-
-}
-
-
-
-
-
-/***********************************************************************************************
- * FHC::sendToManglerFromPort -- Send to the mangler from the specified port *
- * *
- * *
- * *
- * INPUT: Address of mangler server *
- * Source port to send *from* *
- * *
- * OUTPUT: True if sent OK *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:47PM ST : Created *
- *=============================================================================================*/
-Bool FirewallHelperClass::sendToManglerFromPort(UnsignedInt address, UnsignedShort port, UnsignedShort packetID, Bool blitzme)
-{
- DEBUG_LOG(("sizeof(ManglerMessage) == %d, sizeof(ManglerData) == %d",
- sizeof(ManglerMessage), sizeof(ManglerData)));
-
- /*
- ** Build the packet to send out.
- */
- ManglerMessage packet;
- memset(&(packet.data),0x44, sizeof(ManglerData));
- packet.data.NetCommandType = 12; // mangler request.
- packet.data.PacketID = packetID;
- if (blitzme) {
- packet.data.BlitzMe = 1;
- } else {
- packet.data.BlitzMe = 0;
- }
- packet.data.magic = GENERALS_MAGIC_NUMBER;
- packet.data.OriginalPortNumber = port;
-/*
- DEBUG_LOG_RAW(("Pre-Adjust Buffer = "));
- for (Int i = 0; i < sizeof(ManglerData); ++i) {
- DEBUG_LOG_RAW(("%02x", *(((unsigned char *)(&(packet.data))) + i)));
- }
- DEBUG_LOG_RAW(("\n"));
-*/
- byteAdjust(&(packet.data));
-/*
- DEBUG_LOG_RAW(("Pre-CRC Buffer = "));
- for (i = 0; i < sizeof(ManglerData); ++i) {
- DEBUG_LOG_RAW(("%02x", *(((unsigned char *)(&(packet.data))) + i)));
- }
- DEBUG_LOG_RAW(("\n"));
-*/
- CRC crc;
- crc.computeCRC((unsigned char *)(&(packet.data.magic)), sizeof(ManglerData) - sizeof(unsigned int));
- packet.data.CRC = htonl(crc.get());
-
- packet.length = sizeof(ManglerData);
-
- DEBUG_LOG(("FirewallHelperClass::sendToManglerFromPort - Sending from port %d to %d.%d.%d.%d:%d", (UnsignedInt)port,
- PRINTF_IP_AS_4_INTS(address), MANGLER_PORT));
-/*
- DEBUG_LOG_RAW(("Buffer = "));
- for (i = 0; i < sizeof(ManglerData); ++i) {
- DEBUG_LOG_RAW(("%02x", *(((unsigned char *)(&(packet.data))) + i)));
- }
- DEBUG_LOG_RAW(("\n"));
-*/
- SpareSocketStruct *spareSocket = findSpareSocketByPort(port);
-// DEBUG_LOG(("PacketID = %u", packetID));
-// DEBUG_LOG(("OriginalPortNumber = %u", port));
-
- if (spareSocket == NULL) {
- DEBUG_ASSERTCRASH(spareSocket != NULL, ("Could not find spare socket for send."));
- DEBUG_LOG(("FirewallHelperClass::sendToManglerFromPort - failed to find the spare socket for port %d", port));
- return FALSE;
- }
-
- spareSocket->udp->Write((UnsignedByte *) &packet, sizeof(ManglerData), address, MANGLER_PORT);
-
- return(TRUE);
-}
-
-
-SpareSocketStruct * FirewallHelperClass::findSpareSocketByPort(UnsignedShort port) {
- DEBUG_LOG(("FirewallHelperClass::findSpareSocketByPort - trying to find spare socket with port %d", port));
- for (Int i = 0; i < MAX_SPARE_SOCKETS; ++i) {
- if (m_spareSockets[i].port == port) {
- DEBUG_LOG(("FirewallHelperClass::findSpareSocketByPort - found it!"));
- return &(m_spareSockets[i]);
- }
- }
-
- DEBUG_LOG(("FirewallHelperClass::findSpareSocketByPort - didn't find it"));
- return NULL;
-}
-
-ManglerMessage * FirewallHelperClass::findEmptyMessage() {
- for (Int i = 0; i < MAX_SPARE_SOCKETS; ++i) {
- if (m_messages[i].length == 0) {
- return &(m_messages[i]);
- }
- }
- return NULL;
-}
-
-void FirewallHelperClass::byteAdjust(ManglerData *data) {
-// for (Int i = 0; i < len/4; ++i) {
-// *buf = htonl(*buf);
-// ++buf;
-// }
- data->CRC = htonl(data->CRC);
- data->magic = htons(data->magic);
- data->MyMangledPortNumber = htons(data->MyMangledPortNumber);
- data->OriginalPortNumber = htons(data->OriginalPortNumber);
- data->PacketID = htons(data->PacketID);
-}
-
-/***********************************************************************************************
- * FHC::Get_Mangler_Response_On_Port -- Get the manglers response to a specific query *
- * *
- * *
- * *
- * INPUT: Packet id of packet we are looking for *
- * *
- * OUTPUT: Port the mangler saw this packet come from. *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:51PM ST : Created *
- *=============================================================================================*/
-UnsignedShort FirewallHelperClass::getManglerResponse(UnsignedShort packetID, Int time)
-{
- ManglerMessage *msg = NULL;
-
-// SpareSocketStruct *spareSocket = NULL;
-
- sockaddr_in addr;
-
- Int i = 0;
- for (; i < MAX_SPARE_SOCKETS; ++i) {
- if (m_spareSockets[i].udp != NULL) {
- ManglerMessage *message = findEmptyMessage();
- if (message == NULL) {
- break;
- }
- Int retval = m_spareSockets[i].udp->Read((unsigned char *)message, sizeof(ManglerData), &addr);
- if (retval > 0) {
- CRC crc;
- crc.computeCRC((unsigned char *)(&(message->data.magic)), sizeof(ManglerData) - sizeof(unsigned int));
- if (crc.get() != htonl(message->data.CRC)) {
- DEBUG_LOG(("FirewallHelperClass::getManglerResponse - Saw message, CRC mismatch. Expected CRC %u, computed CRC %u", message->data.CRC, crc.get()));
- continue;
- }
- byteAdjust(&(message->data));
- message->length = retval;
- DEBUG_LOG(("FirewallHelperClass::getManglerResponse - Saw message of %d bytes from mangler %d on port %u", retval, i, m_spareSockets[i].port));
- DEBUG_LOG(("FirewallHelperClass::getManglerResponse - Message has packet ID %d 0x%08X, looking for packet id %d 0x%08X", message->data.PacketID, message->data.PacketID, packetID, packetID));
- if (message->data.PacketID == packetID) {
- DEBUG_LOG(("FirewallHelperClass::getManglerResponse - packet ID's match, returning message"));
- msg = message;
- message->length = 0;
- }
- if (ntohs(message->data.PacketID) == packetID) {
- DEBUG_LOG(("FirewallHelperClass::getManglerResponse - NETWORK BYTE ORDER packet ID's match, returning message"));
- msg = message;
- message->length = 0;
- }
- }
- }
- }
-
- // See if we have already received it and saved it.
- if (msg == NULL) {
- for (i = 0; i < MAX_SPARE_SOCKETS; ++i) {
- if ((m_messages[i].length != 0) && (m_messages[i].data.PacketID == packetID)) {
- msg = &(m_messages[i]);
- msg->length = 0;
- }
- }
- }
-
- if (msg == NULL) {
- return 0;
- }
-
- UnsignedShort mangled_port = msg->data.MyMangledPortNumber;
- DEBUG_LOG(("Mangler is seeing packets from port %d as coming from port %d", (UnsignedInt)msg->data.OriginalPortNumber, (UnsignedInt)mangled_port));
- return mangled_port;
-}
-
-
-
-
-/***********************************************************************************************
- * FirewallHelperClass::Write_Firewall_Settings -- Save out firewall settings. *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/22/01 10:23PM ST : Created *
- *=============================================================================================*/
-void FirewallHelperClass::writeFirewallBehavior(void)
-{
- OptionPreferences pref;
-
- char num[16];
- num[0] = 0;
- itoa(TheGlobalData->m_firewallBehavior, num, 10);
- AsciiString numstr;
- numstr = num;
- (pref)["FirewallBehavior"] = numstr;
-
- TheWritableGlobalData->m_firewallPortAllocationDelta = TheFirewallHelper->getSourcePortAllocationDelta();
- num[0] = 0;
- itoa(TheGlobalData->m_firewallPortAllocationDelta, num, 10);
- numstr = num;
- (pref)["FirewallPortAllocationDelta"] = numstr;
-
- pref.write();
-}
-
-
-/***********************************************************************************************
- * FirewallHelperClass::flagNeedToRefresh -- Flag that the next time we log in we need to *
- * refresh our firewall settings. *
- * *
- * *
- * *
- * INPUT: flag - whether or not to refresh...munkee *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/19/03 4:30PM BGC : Created *
- *=============================================================================================*/
-void FirewallHelperClass::flagNeedToRefresh(Bool flag)
-{
- OptionPreferences pref;
-
- (pref)["FirewallNeedToRefresh"] = flag ? AsciiString("TRUE") : AsciiString("FALSE");
-
- pref.write();
-}
-
-
-/***********************************************************************************************
- * FirewallHelperClass::Read_Firewall_Behavior -- Read in old firewall settings *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/22/01 10:25PM ST : Created *
- *=============================================================================================*/
-void FirewallHelperClass::readFirewallBehavior(void)
-{
-#if (0)
- m_lastBehavior = (FirewallBehaviorType) ConfigINI.Get_Int("MultiPlayer", "FirewallSettings", FIREWALL_UNKNOWN);
- m_lastSourcePortAllocationDelta = ConfigINI.Get_Int("MultiPlayer", "FirewallDelta", 1);
-#endif //(0)
-}
-
-
-
-/***********************************************************************************************
- * FHC::detectFirewallBehavior -- What is that wacky firewall doing to our packet headers? *
- * *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Firewall behavior *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 12:30PM ST : Created *
- *=============================================================================================*/
-void FirewallHelperClass::detectFirewallBehavior(/*Bool &canRecord*/)
-{
- m_behavior = FIREWALL_TYPE_SIMPLE;
-
- m_currentState = DETECTIONSTATE_BEGIN;
-}
-
-FirewallHelperClass::FirewallBehaviorType FirewallHelperClass::getFirewallBehavior() {
- m_currentState = DETECTIONSTATE_IDLE;
- return m_behavior;
-}
-
-Short FirewallHelperClass::getSourcePortAllocationDelta() {
- return m_sourcePortAllocationDelta;
-}
-
-/* static */ void FirewallHelperClass::getManglerName(Int manglerIndex, Char *nameBuf)
-{
- AsciiString host;
- UnsignedShort port;
- TheGameSpyConfig->getManglerLocation(manglerIndex, host, port);
- strcpy(nameBuf, host.str());
-}
-
-Bool FirewallHelperClass::detectionBeginUpdate() {
-// UnsignedShort mangler_port = MANGLER_PORT;
- m_packetID = 0x7f00;
- //int current_mangler = 0;
-
- /*
- ** Well, we are going to need some manglers.
- */
-
- UnsignedByte mangler_addresses[4][4];
-
-// Int delta = 0;
-
-
- /*
- ** If the user specified a particular port to use then we act as if there is no firewall.
- */
- if (TheWritableGlobalData->m_firewallPortOverride != 0) {
- m_behavior = FIREWALL_TYPE_SIMPLE;
- DEBUG_LOG(("Source port %d specified by user", TheGlobalData->m_firewallPortOverride));
-
- if (TheGlobalData->m_firewallSendDelay) {
- UnsignedInt addbehavior = FIREWALL_TYPE_NETGEAR_BUG;
- addbehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType) addbehavior;
- DEBUG_LOG(("Netgear bug specified by command line or SendDelay flag"));
- }
- m_currentState = DETECTIONSTATE_DONE;
- return TRUE;
- }
-
-
-
- m_timeoutStart = timeGetTime();
- m_timeoutLength = 5000;
- DEBUG_LOG(("About to call gethostbyname for the mangler address"));
- int namenum = 0;
-
- do {
- AsciiString host;
- UnsignedShort port;
- TheGameSpyConfig->getManglerLocation(namenum, host, port);
- const char *mangler_name_ptr = host.str();
- DEBUG_LOG(("Looking at %s:%d", host.str(), port));
-
- /*
- ** Use the wolapi supplied mangler info if available.
- */
-// if (NumManglerServers > namenum) {
-// mangler_name_ptr = &ManglerServerAddress[namenum][0];
-// mangler_port = ManglerServerPort[namenum];
- //current_mangler = CurrentManglerServer;
-// DEBUG_LOG(("Using mangler from servserv"));
-// }
- namenum++;
-
- if (strlen(mangler_name_ptr) == 0) {
- break;
- }
-
- /*
- ** Do the lookup.
- */
- struct hostent *host_info = gethostbyname(mangler_name_ptr);
-
- if (!host_info) {
- DEBUG_LOG(("gethostbyname failed! Error code %d", WSAGetLastError()));
- break;
- }
-
- /*
- ** See if we already have that address in the list.
- */
- Bool found = FALSE;
- for (Int i=0 ; ih_addr_list[0][0], 4) == 0) {
- found = TRUE;
- break;
- }
- }
- /*
- ** Add the address in if we didn't find it.
- */
- if (!found) {
- Int m = m_numManglers++;
- memcpy(&mangler_addresses[m][0], &host_info->h_addr_list[0][0], 4);
- ntohl((UnsignedInt)mangler_addresses[m]);
- DEBUG_LOG(("Found mangler address at %d.%d.%d.%d", mangler_addresses[m][0], mangler_addresses[m][1], mangler_addresses[m][2], mangler_addresses[m][3]));
- }
-
- } while ((m_numManglers < MAX_NUM_MANGLERS) && ((timeGetTime() - m_timeoutStart) < m_timeoutLength));
-
-
- DEBUG_ASSERTCRASH(m_numManglers > 2, ("not enough mangler addresses found."));
- if (m_numManglers < 3) {
- m_currentState = DETECTIONSTATE_DONE;
- return TRUE;
- }
-
- for (Int i=0 ; im_firewallSendDelay) {
- UnsignedInt addbehavior = FIREWALL_TYPE_NETGEAR_BUG;
- addbehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType) addbehavior;
- DEBUG_LOG(("FirewallHelperClass::detectionBeginUpdate - Netgear bug specified by command line or SendDelay flag"));
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionBeginUpdate - Netgear bug not specified"));
- }
-
- /*
- ** OK, we have our manglers.
- **
- ** First test, see if there is any port mangling at all.
- **
- **
- **
- */
-
- DEBUG_LOG(("About to start mangler test 1"));
- /*
- ** Get a spare port number and create a new socket to bind it to.
- */
- m_sparePorts[0] = getNextTemporarySourcePort(0);
- if (!openSpareSocket(m_sparePorts[0])) {
- m_currentState = DETECTIONSTATE_DONE;
- return TRUE;
- }
-
- /*
- ** Send to the mangler from this port until we get a response.
- */
- m_timeoutStart = timeGetTime();
- m_timeoutLength = 6000;
-
- sendToManglerFromPort(m_manglers[0], m_sparePorts[0], m_packetID);
- m_currentState = DETECTIONSTATE_TEST1;
- return FALSE;
-}
-
-
-Bool FirewallHelperClass::detectionTest1Update() {
-
- m_mangledPorts[0] = getManglerResponse(m_packetID);
-
- /*
- ** See if we got no response or a non-mangled response.
- */
- if (m_mangledPorts[0] == 0 || m_mangledPorts[0] == m_sparePorts[0]) {
- if (m_mangledPorts[0] == m_sparePorts[0]) {
- m_sourcePortAllocationDelta = 0;
- DEBUG_LOG(("FirewallHelperClass::detectionTest1Update - Non-mangled response from mangler, quitting test."));
- }
- if ((m_mangledPorts[0] == 0) && ((timeGetTime() - m_timeoutStart) < m_timeoutLength)) {
- // we are still waiting for a response and haven't timed out yet.
- DEBUG_LOG(("FirewallHelperClass::detectionTest1Update - waiting for response from mangler."));
- return FALSE;
- }
- if ((m_mangledPorts[0] == 0) && ((timeGetTime() - m_timeoutStart) >= m_timeoutLength)) {
- // we are still waiting for a response and we timed out.
- DEBUG_LOG(("FirewallHelperClass::detectionTest1Update - timed out waiting for response from mangler."));
- }
- // either we have received a non-mangled response or we timed out waiting for a response.
- closeSpareSocket(m_sparePorts[0]);
-
- m_currentState = DETECTIONSTATE_DONE;
- return TRUE;
- }
-
- DEBUG_LOG(("FirewallHelperClass::detectionTest1Update - test 1 complete"));
- /*
- ** Test one completed, time to start up the second test.
- **
- ** Second test. See if the ports are mangled differently for different destination IPs.
- **
- ** We can use the spare socket from the last test and send to a different mangler.
- **
- */
-
- /*
- ** Send to the mangler from this port until we get a response.
- */
- m_timeoutStart = timeGetTime();
- m_timeoutLength = 6000;
- m_mangledPorts[1] = 0;
- sendToManglerFromPort(m_manglers[1], m_sparePorts[0], m_packetID+1);
-
- m_currentState = DETECTIONSTATE_TEST2;
- return FALSE;
-}
-
-Bool FirewallHelperClass::detectionTest2Update() {
-
- m_mangledPorts[1] = getManglerResponse(m_packetID+1);
-
- if (m_mangledPorts[1] == 0) {
- if ((timeGetTime() - m_timeoutStart) <= m_timeoutLength) {
- return FALSE;
- }
- DEBUG_LOG(("FirewallHelperClass::detectionTest2Update - timed out waiting for mangler response"));
- m_currentState = DETECTIONSTATE_DONE;
- return TRUE;
- }
-
- /*
- ** We are done with this socket/port
- */
- closeSpareSocket(m_sparePorts[0]);
-
- /*
- ** See if we got no response or a non-mangled response.
- */
- if (m_mangledPorts[1] == 0 || m_mangledPorts[1] == m_sparePorts[0]) {
- m_currentState = DETECTIONSTATE_DONE;
- UnsignedInt addBehavior = (UnsignedInt)FIREWALL_TYPE_SIMPLE;
- addBehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType)addBehavior;
-
- if (m_mangledPorts[1] == 0) {
- DEBUG_LOG(("FirewallHelperClass::detectionTest2Update - got no response from mangler"));
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionTest2Update - got a mangler response, no port mangling"));
- }
- DEBUG_LOG(("FirewallHelperClass::detectionTest2Update - Setting behavior to SIMPLE, done testing"));
- return TRUE;
- }
-
- if (m_mangledPorts[0] == m_mangledPorts[1]) {
- DEBUG_LOG(("FirewallHelperClass::detectionTest2Update - port mangling doesn't depend on destination IP, setting to DUMB_MANGLING"));
- UnsignedInt addBehavior = (UnsignedInt)FIREWALL_TYPE_DUMB_MANGLING;
- addBehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType)addBehavior;
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionTest2Update - port mangling depends on destination IP, setting to SMART_MANGLING"));
- UnsignedInt addBehavior = (UnsignedInt)FIREWALL_TYPE_SMART_MANGLING;
- addBehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType)addBehavior;
- }
-
-
-
-
- /*
- ** Third test.
- **
- ** This test tries to detect a pattern in the ports allocated by the NAT.
- ** We use several source ports for this one.
- **
- */
-
- m_currentTry = 0;
- m_packetID = m_packetID + 10;
-
- DEBUG_LOG(("FirewallHelperClass::detectionTest2Update - moving on to 3rd test"));
-
- m_currentState = DETECTIONSTATE_TEST3;
- return FALSE;
-}
-
-Bool FirewallHelperClass::detectionTest3Update() {
- /*
- ** Try this whole thing a max of 3 times.
- */
- if (m_currentTry < 3) {
- memset(m_sparePorts, 0, sizeof(m_sparePorts));
- memset(m_mangledPorts, 0, sizeof(m_mangledPorts));
-
- /*
- ** Open a socket for each source port.
- ** We should use a non-linear set of source ports so we can detect the NAT32 relative offset
- ** case.
- */
- Int i=0;
- for (; i m_timeoutLength) {
- /*
- ** Close down those sockets - we are finished with them.
- */
- for (Int j=0 ; j (int)FIREWALL_TYPE_SIMPLE) {
- /*
- ** If the delta we got last time we played looks good then use that.
- */
- m_sourcePortAllocationDelta = m_lastSourcePortAllocationDelta;
- }
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - didn't get enough responses, using %d as the source port allocation delta, finished test", m_sourcePortAllocationDelta));
- m_currentState = DETECTIONSTATE_DONE;
- return TRUE;
- }
-
-
- Bool relative_delta = FALSE;
- Bool looks_good = FALSE;
- Int delta = getNATPortAllocationScheme(m_numResponses, m_sparePorts, m_mangledPorts, relative_delta, looks_good);
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - getNATPortAllocationScheme returned %d", delta));
-
- if (delta) {
-
- /*
- ** Hey, we got it!
- */
- UnsignedInt addbehavior = 0;
- if (relative_delta) {
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - detected RELATIVE PORT ALLOCATION"));
- addbehavior = (UnsignedInt)FIREWALL_TYPE_RELATIVE_PORT_ALLOCATION;
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - detected SIMPLE PORT ALLOCATION"));
- addbehavior = (UnsignedInt)FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION;
- }
- addbehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType) addbehavior;
-
- m_sourcePortAllocationDelta = delta;
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - setting source port delta to %d", delta));
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - didn't get a delta value"));
- if (m_lastSourcePortAllocationDelta != 0 && (Int)m_lastBehavior > (Int)FIREWALL_TYPE_SIMPLE) {
- /*
- ** If the delta we got last time we played looks good then use that.
- */
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - using the port allocation delta we have from before which is %d", m_lastSourcePortAllocationDelta));
- m_sourcePortAllocationDelta = m_lastSourcePortAllocationDelta;
- }
- ++m_currentTry;
- m_currentState = DETECTIONSTATE_TEST3;
- return FALSE;
- }
-
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForRepsonsesUpdate - starting 4th test"));
- /*
- ** Fourth test.
- **
- ** Test to see if the NAT mangles differently per destination port at the same IP.
- */
- if ((m_behavior & FIREWALL_TYPE_SMART_MANGLING) != 0) {
-
- if ((m_behavior & FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION) != 0) {
-
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForRepsonsesUpdate - simple port allocation, Testing to see if the NAT mangles differently per destination port at the same IP"));
-
- /*
- ** We need 2 source ports for this.
- */
- m_sparePorts[0] = getNextTemporarySourcePort(0);
- if (!openSpareSocket(m_sparePorts[0])) {
- m_currentState = DETECTIONSTATE_DONE;
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForRepsonsesUpdate - Failed to open first spare port, bailing"));
- return TRUE;
- }
-
- m_sparePorts[1] = getNextTemporarySourcePort(0);
- if (!openSpareSocket(m_sparePorts[1])) {
- closeSpareSocket(m_sparePorts[0]);
- m_currentState = DETECTIONSTATE_DONE;
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForRepsonsesUpdate - Failed to open second spare port, bailing"));
- return TRUE;
- }
-
- /*
- ** Get a reference port.
- */
- m_timeoutStart = timeGetTime();
- m_timeoutLength = 4000;
- m_mangledPorts[0] = 0;
- m_packetID += 10;
-
- /*
- ** Wait for a response.
- */
- sendToManglerFromPort(m_manglers[0], m_sparePorts[0], m_packetID);
-
- m_currentState = DETECTIONSTATE_TEST4_1;
- return FALSE;
- } else {
- /*
- ** NAT32 uses different mangled source ports for different destination ports.
- */
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForRepsonsesUpdate - relative port allocation, NAT32 right?"));
- UnsignedInt addbehavior = 0;
- addbehavior = (UnsignedInt)FIREWALL_TYPE_DESTINATION_PORT_DELTA;
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForRepsonsesUpdate - adding DESTINATION PORT DELTA to behavior"));
- addbehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType) addbehavior;
- }
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForResponsesUpdate - We don't have smart mangling, skipping test 4, entering test 5"));
- }
-
- DEBUG_LOG(("FirewallHelperClass::detectionTest3WaitForRepsonsesUpdate - entering test 5"));
-
- m_currentState = DETECTIONSTATE_TEST5;
- return FALSE;
-}
-
-
-
-Bool FirewallHelperClass::detectionTest4Stage1Update() {
- m_mangledPorts[0] = getManglerResponse(m_packetID);
-
- if (m_mangledPorts[0] == 0) {
- if ((timeGetTime() - m_timeoutStart) > m_timeoutLength) {
- closeSpareSocket(m_sparePorts[0]);
- closeSpareSocket(m_sparePorts[1]);
- m_currentState = DETECTIONSTATE_DONE;
- DEBUG_LOG(("FirewallHelperClass::detectionTest4Stage1Update - timed out waiting for mangler response, quitting"));
- return TRUE;
- }
- return FALSE;
- }
-
- /*
- ** Send out to a different port at that IP.
- ** We won't get a response for this.
- */
- UnsignedInt addr = m_manglers[0];
- UnsignedShort port1 = m_sparePorts[0] + 1;
- sendToManglerFromPort(addr, port1, m_packetID);
- sendToManglerFromPort(addr, port1, m_packetID);
- sendToManglerFromPort(addr, port1, m_packetID);
-
- /*
- ** We can't get a response from a different destination port so the only way to detect
- ** this behavior is to check the next mangled port allocation to see if it's double
- ** what we would normally expect.
- */
- m_packetID++;
- m_timeoutStart = timeGetTime();
- m_timeoutLength = 4000;
-
- sendToManglerFromPort(m_manglers[0], m_sparePorts[1], m_packetID);
-
- m_currentState = DETECTIONSTATE_TEST4_2;
- return FALSE;
-}
-
-Bool FirewallHelperClass::detectionTest4Stage2Update() {
- m_mangledPorts[1] = getManglerResponse(m_packetID);
-
- if (m_mangledPorts[1] == 0) {
- if ((timeGetTime() - m_timeoutStart) > m_timeoutLength) {
- closeSpareSocket(m_sparePorts[0]);
- closeSpareSocket(m_sparePorts[1]);
- m_currentState = DETECTIONSTATE_DONE;
- DEBUG_LOG(("FirewallHelperClass::detectionTest4Stage2Update - timed out waiting for the second mangler response, quitting"));
- return TRUE;
- }
- return FALSE;
- }
-
- if (m_mangledPorts[1] != m_mangledPorts[0] + m_sourcePortAllocationDelta) {
- DEBUG_LOG(("FirewallHelperClass::detectionTest4Stage2Update - NAT uses different source ports for different destination ports"));
-
- UnsignedInt addbehavior = 0;
- addbehavior = (UnsignedInt)FIREWALL_TYPE_DESTINATION_PORT_DELTA;
- addbehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType) addbehavior;
- } else {
- DEBUG_ASSERTCRASH(m_mangledPorts[1] == m_mangledPorts[0] + m_sourcePortAllocationDelta, ("Problem getting the source port deltas."));
- if (m_mangledPorts[1] == m_mangledPorts[0] + m_sourcePortAllocationDelta) {
- DEBUG_LOG(("FirewallHelperClass::detectionTest4Stage2Update - NAT uses the same source port for different destination ports"));
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionTest4Stage2Update - Unable to complete destination port mangling test"));
- DEBUG_CRASH(("Unable to complete destination port mangling test"));
- }
- }
-
- m_currentState = DETECTIONSTATE_TEST5;
-
- return detectionTest5Update();
-}
-
-Bool FirewallHelperClass::detectionTest5Update() {
- /*
- ** We have done all the tests we *have* to. There's other info that it would be nice to know though.
- **
- ** Test for the netgear bug behavior.
- */
-#if (0)
-// moved to before test 1. Moved because this flag could be specified for another firewall
-// for testing purposes and never get this far because it has behavior that doesn't require
-// all the tests to be performed.
-// BGC 10/1/02
- DEBUG_LOG(("FirewallHelperClass::detectionTest5Update - Testing for Netgear bug"));
-
- /*
- ** See if the user specified a netgear firewall - that will save us the trouble.
- */
- if (TheGlobalData->m_firewallSendDelay) {
- UnsignedInt addbehavior = FIREWALL_TYPE_NETGEAR_BUG;
- addbehavior |= (UnsignedInt)m_behavior;
- m_behavior = (FirewallBehaviorType) addbehavior;
- DEBUG_LOG(("FirewallHelperClass::detectionTest5Update - Netgear bug specified by command line or SendDelay flag"));
- } else {
- DEBUG_LOG(("FirewallHelperClass::detectionTest5Update - Netgear bug not specified"));
- }
-#endif // #if (0)
-
- DEBUG_LOG_RAW(("FirewallHelperClass::detectionTest5Update - All done, behavior is: "));
-
- if ((m_behavior & FIREWALL_TYPE_SIMPLE) != 0) {
- DEBUG_LOG_RAW((" FIREWALL_TYPE_SIMPLE "));
- }
- if ((m_behavior & FIREWALL_TYPE_DUMB_MANGLING) != 0) {
- DEBUG_LOG_RAW((" FIREWALL_TYPE_DUMB_MANGLING "));
- }
- if ((m_behavior & FIREWALL_TYPE_SMART_MANGLING) != 0) {
- DEBUG_LOG_RAW((" FIREWALL_TYPE_SMART_MANGLING "));
- }
- if ((m_behavior & FIREWALL_TYPE_NETGEAR_BUG) != 0) {
- DEBUG_LOG_RAW((" FIREWALL_TYPE_NETGEAR_BUG "));
- }
- if ((m_behavior & FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION) != 0) {
- DEBUG_LOG_RAW((" FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION "));
- }
- if ((m_behavior & FIREWALL_TYPE_RELATIVE_PORT_ALLOCATION) != 0) {
- DEBUG_LOG_RAW((" FIREWALL_TYPE_RELATIVE_PORT_ALLOCATION "));
- }
- if ((m_behavior & FIREWALL_TYPE_DESTINATION_PORT_DELTA) != 0) {
- DEBUG_LOG_RAW((" FIREWALL_TYPE_DESTINATION_PORT_DELTA "));
- }
-
- DEBUG_LOG_RAW(("\n"));
-
- m_currentState = DETECTIONSTATE_DONE;
- return TRUE;
-}
-
-
-/***********************************************************************************************
- * FHC::Get_NAT_Port_Allocation_Scheme -- Find out how a NAT is allocating ports *
- * *
- * *
- * *
- * INPUT: Number of ports we should analyze *
- * List of original port numbers *
- * List of mangled port numbers *
- * relative_delta (out) Is the delta relative to the original port number? *
- * looks_good (out) Do all the values point to the same delta? *
- * *
- * OUTPUT: Port allocation delta *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 3/15/01 4:45PM ST : Created *
- *=============================================================================================*/
-Int FirewallHelperClass::getNATPortAllocationScheme(Int numPorts, UnsignedShort *originalPorts, UnsignedShort *mangledPorts, Bool &relativeDelta, Bool &looksGood)
-{
- DEBUG_ASSERTCRASH(numPorts > 3, ("numPorts too small"));
-
- DEBUG_LOG(("Looking for port allocation pattern in originalPorts %d, %d, %d, %d", originalPorts[0], originalPorts[1], originalPorts[2], originalPorts[3]));
-
- /*
- ** Sort the mangled ports into order - should be easier to detect patterns.
- ** Stupid bubble sort will do. original_ports may be out of oder after the sort.
- */
- for (Int x=0 ; x mangledPorts[y+1]) {
- Int temp = mangledPorts[y];
- mangledPorts[y] = mangledPorts[y+1];
- mangledPorts[y+1] = temp;
- temp = originalPorts[y];
- originalPorts[y] = originalPorts[y+1];
- originalPorts[y+1] = temp;
- }
- }
- }
-
- /*
- ** Now start looking for patterns in the port numbers. Possible patterns include.
- **
- ** Incremental. Port numbers are allocated incrementally.
- ** Every 'n' ports. NAT adds 'n' port numbers when allocating ports.
- **
- ** Also, schemes may be absolute or relative to the original port number.
- */
-
- /*
- ** 1. Check for absolute sequential allocation.
- */
- if (mangledPorts[1] - mangledPorts[0] == 1) {
- if (mangledPorts[2] - mangledPorts[1] == 1) {
- if (mangledPorts[3] - mangledPorts[2] == 1) {
- DEBUG_LOG(("Incremental port allocation detected"));
- relativeDelta = FALSE;
- looksGood = TRUE;
- return(1);
- }
- }
- }
-
- /*
- ** 2. Check for semi sequential.
- */
- if (mangledPorts[1] - mangledPorts[0] == 2) {
- if (mangledPorts[2] - mangledPorts[1] == 2) {
- if (mangledPorts[3] - mangledPorts[2] == 2) {
- DEBUG_LOG(("Semi-incremental port allocation detected"));
- relativeDelta = FALSE;
- looksGood = TRUE;
- return(2);
- }
- }
- }
-
- Int diff1 = mangledPorts[1] - mangledPorts[0];
- Int diff2 = mangledPorts[2] - mangledPorts[1];
- Int diff3 = mangledPorts[3] - mangledPorts[2];
-
-
- /*
- ** 3. Check for absolute scheme skipping 'n' ports.
- */
- if (diff1 == diff2 && diff2 == diff3) {
- DEBUG_LOG(("Looks good for absolute allocation sequence delta of %d", diff1));
- relativeDelta = FALSE;
- looksGood = TRUE;
- return(diff1);
- }
-
- if (diff1 == diff2) {
- DEBUG_LOG(("Probable absolute allocation sequence delta of %d", diff1));
- relativeDelta = FALSE;
- looksGood = FALSE;
- return(diff1);
- }
-
- if (diff2 == diff3) {
- DEBUG_LOG(("Probable absolute allocation sequence delta of %d", diff2));
- relativeDelta = FALSE;
- looksGood = FALSE;
- return(diff2);
- }
-
-
-
-
- /*
- ** Insert more tests here if we can think of any!!!!!
- */
-
-
-
- /*
- ** 4. Check for relative scheme skipping 'n' ports. NAT32 behaves this way, it skips 100 ports
- ** each time.
- */
- for (Int i=0 ; iBind((UnsignedInt)0, port) != 0) {
- DEBUG_CRASH(("FirewallHelperClass::openSpareSocket - Failed to init spare socket"));
- return FALSE;
- }
-
- m_spareSockets[i].port = port;
- DEBUG_LOG(("FirewallHelperClass::openSpareSocket - port %d is open for send", port));
- return TRUE;
-}
-
-/*
- * closeSpareSocket - closes a socket at a specific port.
- */
-void FirewallHelperClass::closeSpareSocket(UnsignedShort port) {
- for (Int i = 0; i < MAX_SPARE_SOCKETS; ++i) {
- if (m_spareSockets[i].port == port) {
- delete m_spareSockets[i].udp;
- m_spareSockets[i].udp = NULL;
- m_spareSockets[i].port = 0;
- break;
- }
- }
-}
-
-/*
- * closeAllSpareSockets - closes all spare sockets, duh.
- */
-void FirewallHelperClass::closeAllSpareSockets() {
- for (Int i = 0; i < MAX_SPARE_SOCKETS; ++i) {
- delete (m_spareSockets[i].udp);
- m_spareSockets[i].udp = NULL;
- m_spareSockets[i].port = 0;
- }
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/FrameData.cpp b/Generals/Code/GameEngine/Source/GameNetwork/FrameData.cpp
deleted file mode 100644
index 165c6161e81..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/FrameData.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/FrameData.h"
-#include "GameNetwork/networkutil.h"
-
-/**
- * Constructor
- */
-FrameData::FrameData()
-{
- m_frame = 0;
- m_commandList = NULL;
- m_commandCount = 0;
- m_frameCommandCount = -1;
- //Added By Sadullah Nader
- //Initializations missing and needed
- m_lastFailedCC = 0;
- m_lastFailedFrameCC = 0;
- //
-}
-
-/**
- * Destructor
- */
-FrameData::~FrameData()
-{
- deleteInstance(m_commandList);
- m_commandList = NULL;
-}
-
-/**
- * Initialize this thing.
- */
-void FrameData::init()
-{
- m_frame = 0;
- if (m_commandList == NULL) {
- m_commandList = newInstance(NetCommandList);
- m_commandList->init();
- }
- m_commandList->reset();
-
- m_frameCommandCount = -1;
- //DEBUG_LOG(("FrameData::init"));
- m_commandCount = 0;
- m_lastFailedCC = -2;
- m_lastFailedFrameCC = -2;
-}
-
-/**
- * Reset this thing.
- */
-void FrameData::reset() {
- init();
-}
-
-/**
- * update the thing, doesn't do anything at the moment.
- */
-void FrameData::update() {
-}
-
-/**
- * return the frame number this frame data is associated with.
- */
-UnsignedInt FrameData::getFrame() {
- return m_frame;
-}
-
-/**
- * Assign the frame number this frame data is associated with.
- */
-void FrameData::setFrame(UnsignedInt frame) {
- m_frame = frame;
-}
-
-/**
- * Returns true if all the frame command count is equal to the number of commands that have been received.
- */
-FrameDataReturnType FrameData::allCommandsReady(Bool debugSpewage) {
- if (m_frameCommandCount == m_commandCount) {
- m_lastFailedFrameCC = -2;
- m_lastFailedCC = -2;
- return FRAMEDATA_READY;
- }
-
- if (debugSpewage) {
- if ((m_lastFailedFrameCC != m_frameCommandCount) || (m_lastFailedCC != m_commandCount)) {
- DEBUG_LOG(("FrameData::allCommandsReady - failed, frame command count = %d, command count = %d", m_frameCommandCount, m_commandCount));
- m_lastFailedFrameCC = m_frameCommandCount;
- m_lastFailedCC = m_commandCount;
- }
- }
-
- if (m_commandCount > m_frameCommandCount) {
- DEBUG_LOG(("FrameData::allCommandsReady - There are more commands than there should be (%d, should be %d). Commands in command list are...", m_commandCount, m_frameCommandCount));
- NetCommandRef *ref = m_commandList->getFirstMessage();
- while (ref != NULL) {
- DEBUG_LOG(("%s, frame = %d, id = %d", GetNetCommandTypeAsString(ref->getCommand()->getNetCommandType()), ref->getCommand()->getExecutionFrame(), ref->getCommand()->getID()));
- ref = ref->getNext();
- }
- DEBUG_LOG(("FrameData::allCommandsReady - End of command list."));
- DEBUG_LOG(("FrameData::allCommandsReady - about to clear the command list"));
- reset();
- DEBUG_LOG(("FrameData::allCommandsReady - command list cleared. command list length = %d, command count = %d, frame command count = %d", m_commandList->length(), m_commandCount, m_frameCommandCount));
- return FRAMEDATA_RESEND;
- }
- return FRAMEDATA_NOTREADY;
-}
-
-/**
- * Set the command count for this frame
- */
-void FrameData::setFrameCommandCount(UnsignedInt frameCommandCount) {
- //DEBUG_LOG(("setFrameCommandCount to %d for frame %d", frameCommandCount, m_frame));
- m_frameCommandCount = frameCommandCount;
-}
-
-/**
- * Get the command count for this frame.
- */
-UnsignedInt FrameData::getFrameCommandCount() {
- return m_frameCommandCount;
-}
-
-/**
- * return the number of commands received so far.
- */
-UnsignedInt FrameData::getCommandCount() {
- return m_commandCount;
-}
-
-/**
- * Add a command to this frame
- */
-void FrameData::addCommand(NetCommandMsg *msg) {
- // need to add the message in order of command ID
- if (m_commandList == NULL) {
- init();
- }
-
- // We don't need to worry about setting the relay since its not getting sent anywhere.
- if (m_commandList->findMessage(msg) != NULL) {
- // We don't want to add the same command twice.
- return;
- }
- m_commandList->addMessage(msg);
-
- ++m_commandCount;
- //DEBUG_LOG(("added command %d, type = %d(%s), command count = %d, frame command count = %d", msg->getID(), msg->getNetCommandType(), GetNetCommandTypeAsString(msg->getNetCommandType()), m_commandCount, m_frameCommandCount));
-}
-
-/**
- * Return the list of commands for this frame
- */
-NetCommandList * FrameData::getCommandList() {
- return m_commandList;
-}
-
-/**
- * Set both the command count and the frame command count to 0.
- */
-void FrameData::zeroFrame() {
- m_commandCount = 0;
- m_frameCommandCount = 0;
-}
-
-/**
- * destroy all the commands in this frame.
- */
-void FrameData::destroyGameMessages() {
- if (m_commandList == NULL) {
- return;
- }
-
- m_commandList->reset();
- m_commandCount = 0;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/FrameDataManager.cpp b/Generals/Code/GameEngine/Source/GameNetwork/FrameDataManager.cpp
deleted file mode 100644
index c82d1cfd2ea..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/FrameDataManager.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/FrameDataManager.h"
-#include "GameNetwork/networkutil.h"
-
-/**
- * Constructor. isLocal tells it whether its the frame data manager for the local player or not.
- */
-FrameDataManager::FrameDataManager(Bool isLocal) {
- m_isLocal = isLocal;
-
- m_frameData = NEW FrameData[FRAME_DATA_LENGTH];
-
- m_isQuitting = FALSE;
- m_quitFrame = 0;
-}
-
-/**
- * destructor.
- */
-FrameDataManager::~FrameDataManager() {
- for (Int i = 0; i < FRAME_DATA_LENGTH; ++i) {
- m_frameData[i].reset();
- }
- delete[] m_frameData;
- m_frameData = NULL;
-}
-
-/**
- * Initialize all of the frame datas associated with this manager.
- */
-void FrameDataManager::init() {
- for (Int i = 0; i < FRAME_DATA_LENGTH; ++i) {
- m_frameData[i].init();
- if (m_isLocal) {
- // If this is the local connection, adjust the frame command count.
- m_frameData[i].setFrameCommandCount(m_frameData[i].getCommandCount());
- }
- }
-
- m_isQuitting = FALSE;
- m_quitFrame = 0;
-}
-
-/**
- * Reset the state of all the frames.
- */
-void FrameDataManager::reset() {
- init();
-}
-
-/**
- * update function. Does nothing at this time.
- */
-void FrameDataManager::update() {
-}
-
-/**
- * Add a network command to the appropriate frame.
- */
-void FrameDataManager::addNetCommandMsg(NetCommandMsg *msg) {
- UnsignedInt frame = msg->getExecutionFrame();
- UnsignedInt frameindex = frame % FRAME_DATA_LENGTH;
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("FrameDataManager::addNetCommandMsg - about to add a command of type %s for frame %d, frame index %d", GetNetCommandTypeAsString(msg->getNetCommandType()), frame, frameindex));
- m_frameData[frameindex].addCommand(msg);
-
- if (m_isLocal) {
- // If this is the local connection, adjust the frame command count.
- m_frameData[frameindex].setFrameCommandCount(m_frameData[frameindex].getCommandCount());
- }
-}
-
-/**
- * Returns true if all the commands for the given frame are ready.
- */
-FrameDataReturnType FrameDataManager::allCommandsReady(UnsignedInt frame, Bool debugSpewage) {
- UnsignedInt frameindex = frame % FRAME_DATA_LENGTH;
- //DEBUG_ASSERTCRASH(m_frameData[frameindex].getFrame() == frame || frame == 256, ("Looking at old commands!"));
- return m_frameData[frameindex].allCommandsReady(debugSpewage);
-}
-
-/**
- * Returns the command list for the given frame.
- */
-NetCommandList * FrameDataManager::getFrameCommandList(UnsignedInt frame) {
- UnsignedInt frameindex = frame % FRAME_DATA_LENGTH;
- return m_frameData[frameindex].getCommandList();
-}
-
-/**
- * Reset the contents of the given frame.
- */
-void FrameDataManager::resetFrame(UnsignedInt frame, Bool isAdvancing) {
- UnsignedInt frameindex = frame % FRAME_DATA_LENGTH;
-
- m_frameData[frameindex].reset();
-
- if (isAdvancing) {
- m_frameData[frameindex].setFrame(frame + MAX_FRAMES_AHEAD);
- }
-
- if (m_isLocal) {
- m_frameData[frameindex].setFrameCommandCount(m_frameData[frameindex].getCommandCount());
- }
-
- DEBUG_ASSERTCRASH(m_frameData[frameindex].getCommandCount() == 0, ("we just reset the frame data and the command count is not zero, huh?"));
-}
-
-/**
- * Returns the command count for the given frame.
- */
-UnsignedInt FrameDataManager::getCommandCount(UnsignedInt frame) {
- UnsignedInt frameindex = frame % FRAME_DATA_LENGTH;
-
- return m_frameData[frameindex].getCommandCount();
-}
-
-/**
- * Set the frame command count for the given frame.
- */
-void FrameDataManager::setFrameCommandCount(UnsignedInt frame, UnsignedInt commandCount) {
- UnsignedInt frameindex = frame % FRAME_DATA_LENGTH;
-
- m_frameData[frameindex].setFrameCommandCount(commandCount);
-}
-
-/**
- *
- */
-UnsignedInt FrameDataManager::getFrameCommandCount(UnsignedInt frame) {
- UnsignedInt frameindex = frame % FRAME_DATA_LENGTH;
-
- return m_frameData[frameindex].getFrameCommandCount();
-}
-
-/**
- * Set both the command count and the frame command count to 0 for the given frames.
- */
-void FrameDataManager::zeroFrames(UnsignedInt startingFrame, UnsignedInt numFrames) {
- UnsignedInt frameIndex = startingFrame % FRAME_DATA_LENGTH;
- for (UnsignedInt i = 0; i < numFrames; ++i) {
- //DEBUG_LOG(("Calling zeroFrame for frame index %d", frameIndex));
- m_frameData[frameIndex].zeroFrame();
- ++frameIndex;
- frameIndex = frameIndex % FRAME_DATA_LENGTH;
- }
-}
-
-/**
- * Destroy all the commands held by this object.
- */
-void FrameDataManager::destroyGameMessages() {
- for (Int i = 0; i < FRAME_DATA_LENGTH; ++i) {
- m_frameData[i].destroyGameMessages();
- }
-}
-
-/**
- * Sets the quit frame, also sets the isQuitting flag.
- */
-void FrameDataManager::setQuitFrame(UnsignedInt frame) {
- m_isQuitting = TRUE;
- m_quitFrame = frame;
-}
-
-/**
- * returns the quit frame.
- */
-UnsignedInt FrameDataManager::getQuitFrame() {
- return m_quitFrame;
-}
-
-/**
- * returns true if this frame data manager is quitting.
- */
-Bool FrameDataManager::getIsQuitting() {
- return m_isQuitting;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/FrameMetrics.cpp b/Generals/Code/GameEngine/Source/GameNetwork/FrameMetrics.cpp
deleted file mode 100644
index 411daf72787..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/FrameMetrics.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-/** FrameMetrics.cpp */
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/FrameMetrics.h"
-#include "GameClient/Display.h"
-#include "GameNetwork/networkutil.h"
-
-FrameMetrics::FrameMetrics()
-{
- //Added By Sadullah Nader
- //Initializations missing and needed
- m_averageFps = 0.0f;
- m_averageLatency = 0.0f;
- m_cushionIndex = 0;
- m_fpsListIndex = 0;
- m_lastFpsTimeThing = 0;
- m_minimumCushion = 0;
-
- m_pendingLatencies = NEW time_t[MAX_FRAMES_AHEAD];
- for(Int i = 0; i < MAX_FRAMES_AHEAD; i++)
- m_pendingLatencies[i] = 0;
- //
- m_fpsList = NEW Real[TheGlobalData->m_networkFPSHistoryLength];
- m_latencyList = NEW Real[TheGlobalData->m_networkLatencyHistoryLength];
-}
-
-FrameMetrics::~FrameMetrics() {
- delete m_fpsList;
- m_fpsList = NULL;
-
- delete m_latencyList;
- m_latencyList = NULL;
-
- delete[] m_pendingLatencies;
- m_pendingLatencies = NULL;
-}
-
-void FrameMetrics::init() {
- m_averageFps = 30;
- m_averageLatency = (Real)0.2;
- m_minimumCushion = -1;
-
- UnsignedInt i = 0;
- for (; i < TheGlobalData->m_networkFPSHistoryLength; ++i) {
- m_fpsList[i] = 30.0;
- }
- m_fpsListIndex = 0;
- for (i = 0; i < TheGlobalData->m_networkLatencyHistoryLength; ++i) {
- m_latencyList[i] = (Real)0.2;
- }
- m_cushionIndex = 0;
-}
-
-void FrameMetrics::reset() {
- init();
-}
-
-void FrameMetrics::doPerFrameMetrics(UnsignedInt frame) {
- // Do the measurement of the fps.
- time_t curTime = timeGetTime();
- if ((curTime - m_lastFpsTimeThing) >= 1000) {
-// if ((m_fpsListIndex % 16) == 0) {
-// DEBUG_LOG(("FrameMetrics::doPerFrameMetrics - adding %f to fps history. average before: %f ", m_fpsList[m_fpsListIndex], m_averageFps));
-// }
- m_averageFps -= ((m_fpsList[m_fpsListIndex])) / TheGlobalData->m_networkFPSHistoryLength; // subtract out the old value from the average.
- m_fpsList[m_fpsListIndex] = TheDisplay->getAverageFPS();
-// m_fpsList[m_fpsListIndex] = TheGameClient->getFrame() - m_fpsStartingFrame;
- m_averageFps += ((Real)(m_fpsList[m_fpsListIndex])) / TheGlobalData->m_networkFPSHistoryLength; // add the new value to the average.
-// DEBUG_LOG(("average after: %f", m_averageFps));
- ++m_fpsListIndex;
- m_fpsListIndex %= TheGlobalData->m_networkFPSHistoryLength;
- m_lastFpsTimeThing = curTime;
- }
-
- Int pendingLatenciesIndex = frame % MAX_FRAMES_AHEAD;
- m_pendingLatencies[pendingLatenciesIndex] = curTime;
-
-}
-
-void FrameMetrics::processLatencyResponse(UnsignedInt frame) {
- time_t curTime = timeGetTime();
- Int pendingIndex = frame % MAX_FRAMES_AHEAD;
- time_t timeDiff = curTime - m_pendingLatencies[pendingIndex];
-
- Int latencyListIndex = frame % TheGlobalData->m_networkLatencyHistoryLength;
- m_averageLatency -= m_latencyList[latencyListIndex] / TheGlobalData->m_networkLatencyHistoryLength;
- m_latencyList[latencyListIndex] = (Real)timeDiff / (Real)1000; // convert to seconds from milliseconds.
- m_averageLatency += m_latencyList[latencyListIndex] / TheGlobalData->m_networkLatencyHistoryLength;
-
- if (frame % 16 == 0) {
-// DEBUG_LOG(("ConnectionManager::processFrameInfoAck - average latency = %f", m_averageLatency));
- }
-}
-
-void FrameMetrics::addCushion(Int cushion) {
- ++m_cushionIndex;
- m_cushionIndex %= TheGlobalData->m_networkCushionHistoryLength;
- if (m_cushionIndex == 0) {
- m_minimumCushion = -1;
- }
- if ((cushion < m_minimumCushion) || (m_minimumCushion == -1)) {
- m_minimumCushion = cushion;
- }
-}
-
-Int FrameMetrics::getAverageFPS() {
- return (Int)m_averageFps;
-}
-
-Real FrameMetrics::getAverageLatency() {
- return m_averageLatency;
-}
-
-Int FrameMetrics::getMinimumCushion() {
- return m_minimumCushion;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameInfo.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameInfo.cpp
deleted file mode 100644
index 4eda3b00ac2..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameInfo.cpp
+++ /dev/null
@@ -1,1649 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameInfo.cpp //////////////////////////////////////////////////////
-// game setup state info
-// Author: Matthew D. Campbell, December 2001
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/CRCDebug.h"
-#include "Common/file.h"
-#include "Common/FileSystem.h"
-#include "Common/GameState.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MapUtil.h"
-#include "Common/MultiplayerSettings.h"
-#include "Common/PlayerTemplate.h"
-#include "Common/Xfer.h"
-#include "GameNetwork/FileTransfer.h"
-#include "GameNetwork/GameInfo.h"
-#include "GameNetwork/GameSpy/ThreadUtils.h"
-#include "GameNetwork/GameSpy/StagingRoomGameInfo.h"
-#include "GameNetwork/LANAPI.h" // for testing packet size
-#include "GameNetwork/LANAPICallbacks.h" // for testing packet size
-#include "strtok_r.h"
-
-
-
-GameInfo *TheGameInfo = NULL;
-
-// GameSlot ----------------------------------------
-
-GameSlot::GameSlot()
-{
- reset();
-}
-
-void GameSlot::reset()
-{
- m_state = SLOT_CLOSED; // decent default
- m_isAccepted = false;
- m_hasMap = true;
- m_color = -1;
- m_startPos = -1;
- m_playerTemplate = -1;
- m_teamNumber = -1;
- m_NATBehavior = FirewallHelperClass::FIREWALL_TYPE_SIMPLE;
- m_lastFrameInGame = 0;
- m_disconnected = FALSE;
- m_port = 0;
- m_isMuted = FALSE;
- m_origPlayerTemplate = -1;
- m_origStartPos = -1;
- m_origColor = -1;
-}
-
-void GameSlot::saveOffOriginalInfo( void )
-{
- DEBUG_LOG(("GameSlot::saveOffOriginalInfo() - orig was color=%d, pos=%d, house=%d",
- m_origColor, m_origStartPos, m_origPlayerTemplate));
- m_origPlayerTemplate = m_playerTemplate;
- m_origStartPos = m_startPos;
- m_origColor = m_color;
- DEBUG_LOG(("GameSlot::saveOffOriginalInfo() - color=%d, pos=%d, house=%d",
- m_color, m_startPos, m_playerTemplate));
-}
-
-static Int getSlotIndex(const GameSlot *slot)
-{
- for (Int i=0; igetConstSlot(i) == slot)
- return i;
- }
- return -1;
-}
-
-static Bool isSlotLocalAlly(const GameSlot *slot)
-{
- Int slotIndex = getSlotIndex(slot);
- Int localIndex = TheGameInfo->getLocalSlotNum();
- const GameSlot *localSlot = TheGameInfo->getConstSlot(localIndex);
-
- // if either doesn't exist, not an ally
- if (slotIndex < 0 || localIndex < 0)
- return FALSE;
-
- // if slot is us, ally
- if (slotIndex == localIndex)
- return TRUE;
-
- // if slot is same team as us, ally
- if (slot->getTeamNumber() == localSlot->getTeamNumber() && slot->getTeamNumber() >= 0)
- return TRUE;
-
- // if we're an observer, we see all
- if (localSlot->getOriginalPlayerTemplate() == PLAYERTEMPLATE_OBSERVER)
- return TRUE;
-
- // nope
- return FALSE;
-}
-
-UnicodeString GameSlot::getApparentPlayerTemplateDisplayName( void ) const
-{
- if (TheMultiplayerSettings && TheMultiplayerSettings->showRandomPlayerTemplate() &&
- m_origPlayerTemplate == PLAYERTEMPLATE_RANDOM && !isSlotLocalAlly(this))
- {
- return TheGameText->fetch("GUI:Random");
- }
- else if (m_origPlayerTemplate == PLAYERTEMPLATE_OBSERVER)
- {
- return TheGameText->fetch("GUI:Observer");
- }
- DEBUG_LOG(("Fetching player template display name for player template %d (orig is %d)",
- m_playerTemplate, m_origPlayerTemplate));
- if (m_playerTemplate < 0)
- {
- return TheGameText->fetch("GUI:Random");
- }
- return ThePlayerTemplateStore->getNthPlayerTemplate(m_playerTemplate)->getDisplayName();
-}
-
-Int GameSlot::getApparentPlayerTemplate( void ) const
-{
- if (TheMultiplayerSettings && TheMultiplayerSettings->showRandomPlayerTemplate() &&
- !isSlotLocalAlly(this))
- {
- return m_origPlayerTemplate;
- }
- return m_playerTemplate;
-}
-
-Int GameSlot::getApparentColor( void ) const
-{
- if (TheMultiplayerSettings && m_origPlayerTemplate == PLAYERTEMPLATE_OBSERVER)
- return TheMultiplayerSettings->getColor(PLAYERTEMPLATE_OBSERVER)->getColor();
-
- if (TheMultiplayerSettings && TheMultiplayerSettings->showRandomColor() &&
- !isSlotLocalAlly(this))
- {
- return m_origColor;
- }
- return m_color;
-}
-
-Int GameSlot::getApparentStartPos( void ) const
-{
- if (TheMultiplayerSettings && TheMultiplayerSettings->showRandomStartPos() &&
- !isSlotLocalAlly(this))
- {
- return m_origStartPos;
- }
- return m_startPos;
-}
-
-
-void GameSlot::unAccept( void )
-{
- if (isHuman())
- {
- m_isAccepted = false;
- }
-}
-
-void GameSlot::setMapAvailability( Bool hasMap )
-{
- if (isHuman())
- {
- m_hasMap = hasMap;
- }
-}
-
-void GameSlot::setState( SlotState state, UnicodeString name, UnsignedInt IP )
-{
- if (!(isAI() && (state == SLOT_EASY_AI || state == SLOT_MED_AI || state == SLOT_BRUTAL_AI)))
- {
- m_color = -1;
- m_startPos = -1;
- m_playerTemplate = -1;
- m_teamNumber = -1;
-
- if (state == SLOT_OPEN && TheGameSpyGame && TheGameSpyGame->getConstSlot(0) == this)
- {
- DEBUG_CRASH(("Game Is Hosed!"));
- }
- }
- if (state == SLOT_PLAYER)
- {
- reset();
- m_state = state;
- m_name = name;
- }
- else
- {
- m_state = state;
- m_isAccepted = true;
- m_hasMap = true;
- switch(state)
- {
- case SLOT_OPEN:
- m_name = TheGameText->fetch("GUI:Open");
- break;
- case SLOT_EASY_AI:
- m_name = TheGameText->fetch("GUI:EasyAI");
- break;
- case SLOT_MED_AI:
- m_name = TheGameText->fetch("GUI:MediumAI");
- break;
- case SLOT_BRUTAL_AI:
- m_name = TheGameText->fetch("GUI:HardAI");
- break;
- case SLOT_CLOSED:
- default:
- m_name = TheGameText->fetch("GUI:Closed");
- break;
- }
- }
-
- m_IP = IP;
-}
-
-// Various tests
-Bool GameSlot::isHuman( void ) const
-{
- return m_state == SLOT_PLAYER;
-}
-
-Bool GameSlot::isOccupied( void ) const
-{
- return m_state == SLOT_PLAYER || m_state == SLOT_EASY_AI || m_state == SLOT_MED_AI || m_state == SLOT_BRUTAL_AI;
-}
-
-Bool GameSlot::isAI( void ) const
-{
- return m_state == SLOT_EASY_AI || m_state == SLOT_MED_AI || m_state == SLOT_BRUTAL_AI;
-}
-
-Bool GameSlot::isPlayer( AsciiString userName ) const
-{
- UnicodeString uName;
- uName.translate(userName);
- return (m_state == SLOT_PLAYER && !m_name.compareNoCase(uName));
-}
-
-Bool GameSlot::isPlayer( UnicodeString userName ) const
-{
- return (m_state == SLOT_PLAYER && !m_name.compareNoCase(userName));
-}
-
-Bool GameSlot::isPlayer( UnsignedInt ip ) const
-{
- return (m_state == SLOT_PLAYER && m_IP == ip);
-}
-
-Bool GameSlot::isOpen( void ) const
-{
- return m_state == SLOT_OPEN;
-}
-
-// GameInfo ----------------------------------------
-
-GameInfo::GameInfo()
-{
- for (int i=0; im_defaultStartingCash;
-
- //
-
- for (Int i=0; ireset();
- }
-
- m_preorderMask = 0;
-}
-
-Bool GameInfo::isPlayerPreorder(Int index)
-{
- if (index >= 0 && index < MAX_SLOTS)
- return ((m_preorderMask & (1 << index)) != 0);
- return FALSE;
-}
-
-void GameInfo::markPlayerAsPreorder(Int index)
-{
- if (index >= 0 && index < MAX_SLOTS)
- m_preorderMask |= 1 << index;
-}
-
-
-void GameInfo::clearSlotList( void )
-{
- for (int i=0; isetState(SLOT_CLOSED);
- }
-}
-
-Int GameInfo::getNumPlayers( void ) const
-{
- Int numPlayers = 0;
- for (int i=0; iisOccupied())
- numPlayers++;
- }
- return numPlayers;
-}
-
-Int GameInfo::getNumNonObserverPlayers( void ) const
-{
- Int numPlayers = 0;
- for (int i=0; iisOccupied() && m_slot[i]->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER)
- numPlayers++;
- }
- return numPlayers;
-}
-
-Int GameInfo::getMaxPlayers( void ) const
-{
- if (!TheMapCache)
- return -1;
-
- AsciiString lowerMap = m_mapName;
- lowerMap.toLower();
- MapCache::iterator it = TheMapCache->find(lowerMap);
- if (it == TheMapCache->end())
- return -1;
- MapMetaData data = it->second;
- return data.m_numPlayers;
-}
-
-void GameInfo::enterGame( void )
-{
- DEBUG_ASSERTCRASH(!m_inGame && !m_inProgress, ("Entering game at a bad time!"));
- reset();
- m_inGame = true;
- m_inProgress = false;
-}
-
-void GameInfo::leaveGame( void )
-{
- DEBUG_ASSERTCRASH(m_inGame && !m_inProgress, ("Leaving game at a bad time!"));
- reset();
-}
-
-void GameInfo::startGame( Int gameID )
-{
- DEBUG_ASSERTCRASH(m_inGame && !m_inProgress, ("Starting game at a bad time!"));
- m_gameID = gameID;
- closeOpenSlots();
- m_inProgress = true;
-}
-
-void GameInfo::endGame( void )
-{
- DEBUG_ASSERTCRASH(m_inGame && m_inProgress, ("Ending game without playing one!"));
- m_inGame = false;
- m_inProgress = false;
-}
-
-void GameInfo::setSlot( Int slotNum, GameSlot slotInfo )
-{
- DEBUG_ASSERTCRASH( slotNum >= 0 && slotNum < MAX_SLOTS, ("GameInfo::setSlot - Invalid slot number"));
- if (slotNum < 0 || slotNum >= MAX_SLOTS)
- return;
-
- DEBUG_ASSERTCRASH( m_slot[slotNum], ("NULL slot pointer"));
- if (!m_slot[slotNum])
- return;
-
-// Bool isHuman = slotInfo.isHuman();
-// Bool wasHuman = m_slot[slotNum]->isHuman();
-
- if (slotNum == 0)
- {
- slotInfo.setAccept();
- slotInfo.setMapAvailability(true);
- }
- *m_slot[slotNum] = slotInfo;
-
-#ifdef DEBUG_LOGGING
- UnsignedInt ip = slotInfo.getIP();
-#endif
-
- DEBUG_LOG(("GameInfo::setSlot - setting slot %d to be player %ls with IP %d.%d.%d.%d", slotNum, slotInfo.getName().str(),
- PRINTF_IP_AS_4_INTS(ip)));
-}
-
-GameSlot* GameInfo::getSlot( Int slotNum )
-{
- DEBUG_ASSERTCRASH( slotNum >= 0 && slotNum < MAX_SLOTS, ("GameInfo::getSlot - Invalid slot number"));
- if (slotNum < 0 || slotNum >= MAX_SLOTS)
- return NULL;
-
- DEBUG_ASSERTCRASH( m_slot[slotNum], ("NULL slot pointer") );
- return m_slot[slotNum];
-}
-
-const GameSlot* GameInfo::getConstSlot( Int slotNum ) const
-{
- DEBUG_ASSERTCRASH( slotNum >= 0 && slotNum < MAX_SLOTS, ("GameInfo::getSlot - Invalid slot number"));
- if (slotNum < 0 || slotNum >= MAX_SLOTS)
- return NULL;
-
- DEBUG_ASSERTCRASH( m_slot[slotNum], ("NULL slot pointer") );
- return m_slot[slotNum];
-}
-
-Int GameInfo::getLocalSlotNum( void ) const
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for local game slot while not in game"));
- if (!m_inGame)
- return -1;
-
- for (Int i=0; iisPlayer(m_localIP))
- return i;
- }
- return -1;
-}
-
-Int GameInfo::getSlotNum( AsciiString userName ) const
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for game slot while not in game"));
- if (!m_inGame)
- return -1;
-
- UnicodeString uName;
- uName.translate(userName);
- for (Int i=0; iisPlayer( uName ))
- return i;
- }
- return -1;
-}
-
-Bool GameInfo::amIHost( void ) const
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for game slot while not in game"));
- if (!m_inGame)
- return false;
-
- return getConstSlot(0)->isPlayer(m_localIP);
-}
-
-void GameInfo::setMap( AsciiString mapName )
-{
- m_mapName = mapName;
- if (m_inGame && amIHost())
- {
- const MapMetaData *mapData = TheMapCache->findMap( mapName );
- if (mapData)
- {
- m_mapMask = 1;
- AsciiString path = mapName;
- path.truncateBy(3);
- path.concat("tga");
- DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", path.str()));
- File *fp = TheFileSystem->openFile(path.str());
- if (fp)
- {
- m_mapMask |= 2;
- fp->close();
- fp = NULL;
- }
-
- AsciiString newMapName;
- if (mapName.getLength() > 0)
- {
- AsciiString token;
- mapName.nextToken(&token, "\\/");
- // add all the tokens except the last one.
- // that way we don't add the filename, just the
- // directory name, we can do this since the filename
- // is just the directory name with the file extention
- // added onto it.
- while (mapName.find('\\') != NULL)
- {
- if (newMapName.getLength() > 0)
- {
- newMapName.concat('/');
- }
- newMapName.concat(token);
- mapName.nextToken(&token, "\\/");
- }
- }
- newMapName.concat("/map.ini");
- DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", newMapName.str()));
- fp = TheFileSystem->openFile(newMapName.str());
- if (fp)
- {
- m_mapMask |= 4;
- fp->close();
- fp = NULL;
- }
-
- path = GetStrFileFromMap(m_mapName);
- DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", path.str()));
- fp = TheFileSystem->openFile(path.str());
- if (fp)
- {
- m_mapMask |= 8;
- fp->close();
- fp = NULL;
- }
-
- path = GetSoloINIFromMap(m_mapName);
- DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", path.str()));
- fp = TheFileSystem->openFile(path.str());
- if (fp)
- {
- m_mapMask |= 16;
- fp->close();
- fp = NULL;
- }
-
- path = GetAssetUsageFromMap(m_mapName);
- DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", path.str()));
- fp = TheFileSystem->openFile(path.str());
- if (fp)
- {
- m_mapMask |= 32;
- fp->close();
- fp = NULL;
- }
-
- path = GetReadmeFromMap(m_mapName);
- DEBUG_LOG(("GameInfo::setMap() - Looking for '%s'", path.str()));
- fp = TheFileSystem->openFile(path.str());
- if (fp)
- {
- m_mapMask |= 64;
- fp->close();
- fp = NULL;
- }
- }
- else
- {
- m_mapMask = 0;
- }
- }
-}
-
-void GameInfo::setMapContentsMask( Int mask )
-{
- m_mapMask = mask;
-}
-
-void GameInfo::setMapCRC( UnsignedInt mapCRC )
-{
- m_mapCRC = mapCRC;
- if (!TheMapCache)
- return;
-
- // check the map cache
- if (m_inGame && getLocalSlotNum() >= 0)
- {
- //TheMapCache->updateCache();
- AsciiString lowerMap = m_mapName;
- lowerMap.toLower();
- //DEBUG_LOG(("GameInfo::setMapCRC - looking for map file \"%s\" in the map cache", lowerMap.str()));
- std::map::iterator it = TheMapCache->find(lowerMap);
- if (it == TheMapCache->end())
- {
- /*
- DEBUG_LOG(("GameInfo::setMapCRC - could not find map file."));
- it = TheMapCache->begin();
- while (it != TheMapCache->end())
- {
- DEBUG_LOG(("\t\"%s\"", it->first.str()));
- ++it;
- }
- */
- getSlot(getLocalSlotNum())->setMapAvailability(false);
- }
- else if (m_mapCRC != it->second.m_CRC)
- {
- DEBUG_LOG(("GameInfo::setMapCRC - map CRC's do not match (%X/%X).", m_mapCRC, it->second.m_CRC));
- getSlot(getLocalSlotNum())->setMapAvailability(false);
- }
- else
- {
- //DEBUG_LOG(("GameInfo::setMapCRC - map CRC's match."));
- getSlot(getLocalSlotNum())->setMapAvailability(true);
- }
- }
-}
-
-void GameInfo::setMapSize( UnsignedInt mapSize )
-{
- m_mapSize = mapSize;
- if (!TheMapCache)
- return;
-
- // check the map cache
- if (m_inGame && getLocalSlotNum() >= 0)
- {
- //TheMapCache->updateCache();
- AsciiString lowerMap = m_mapName;
- lowerMap.toLower();
- std::map::iterator it = TheMapCache->find(lowerMap);
- if (it == TheMapCache->end())
- {
- DEBUG_LOG(("GameInfo::setMapSize - could not find map file."));
- getSlot(getLocalSlotNum())->setMapAvailability(false);
- }
- else if (m_mapCRC != it->second.m_CRC)
- {
- DEBUG_LOG(("GameInfo::setMapSize - map CRC's do not match."));
- getSlot(getLocalSlotNum())->setMapAvailability(false);
- }
- else
- {
- //DEBUG_LOG(("GameInfo::setMapSize - map CRC's match."));
- getSlot(getLocalSlotNum())->setMapAvailability(true);
- }
- }
-}
-
-void GameInfo::setSeed( Int seed )
-{
- m_seed = seed;
-}
-
-void GameInfo::setSlotPointer( Int index, GameSlot *slot )
-{
- if (index < 0 || index >= MAX_SLOTS)
- return;
-
- m_slot[index] = slot;
-}
-
-void GameInfo::setSuperweaponRestriction( UnsignedShort restriction )
-{
- m_superweaponRestriction = restriction;
-}
-
-void GameInfo::setStartingCash( const Money & startingCash )
-{
- m_startingCash = startingCash;
-}
-
-Bool GameInfo::isColorTaken(Int colorIdx, Int slotToIgnore ) const
-{
- for (Int i=0; igetColor() == colorIdx && i != slotToIgnore)
- return true;
- }
- return false;
-}
-
-Bool GameInfo::isStartPositionTaken(Int positionIdx, Int slotToIgnore ) const
-{
- for (Int i=0; igetStartPos() == positionIdx && i != slotToIgnore)
- return true;
- }
- return false;
-}
-
-void GameInfo::resetAccepted( void )
-{
- GameSlot *slot = getSlot(0);
- if (slot)
- slot->setAccept();
- for(int i = 1; i< MAX_SLOTS; i++)
- {
- slot = getSlot(i);
- if (slot)
- slot->unAccept();
- }
-}
-
-void GameInfo::resetStartSpots()
-{
- GameSlot *slot = NULL;
- for (Int i = 0; i < MAX_SLOTS; ++i)
- {
- slot = getSlot(i);
- if (slot != NULL)
- {
- slot->setStartPos(-1);
- }
- }
-}
-
-// adjust the slots in the game to open or closed
-// depending on the players in there now and the number of
-// players the map can hold.
-void GameInfo::adjustSlotsForMap()
-{
- const MapMetaData *md = TheMapCache->findMap(m_mapName);
- if (md != NULL)
- {
- // get the number of players allowed from the map.
- Int numPlayers = md->m_numPlayers;
- Int numPlayerSlots = 0;
-
- // first get the number of occupied slots.
- Int i = 0;
- for (; i < MAX_SLOTS; ++i)
- {
- GameSlot *tempSlot = getSlot(i);
- if (tempSlot->isOccupied())
- {
- ++numPlayerSlots;
- }
- }
-
- // now go through and close the appropriate number of slots.
- // note that no players are kicked in this process, we leave
- // that up to the user.
- for (i = 0; i < MAX_SLOTS; ++i)
- {
- // we have room for more players, if this slot is unoccupied, set it to open.
- GameSlot *slot = getSlot(i);
- if (numPlayers > numPlayerSlots)
- {
- if (!(slot->isOccupied()))
- {
- GameSlot newSlot;
- newSlot.setState(SLOT_OPEN);
- setSlot(i, newSlot);
- ++numPlayerSlots;
- }
- }
- else
- {
- if (!(slot->isOccupied()))
- {
- // we don't have any more room, set this slot to closed.
- GameSlot newSlot;
- newSlot.setState(SLOT_CLOSED);
- setSlot(i, newSlot);
- }
- }
- }
- }
-}
-
-void GameInfo::closeOpenSlots()
-{
- for (Int i = 0; i < MAX_SLOTS; ++i)
- {
- GameSlot *slot = getSlot(i);
- if (!(slot->isOccupied()))
- {
- GameSlot newSlot;
- newSlot.setState(SLOT_CLOSED);
- setSlot(i, newSlot);
- }
- }
-}
-
-static Bool isSlotLocalAlly(GameInfo *game, const GameSlot *slot)
-{
- const GameSlot *localSlot = game->getConstSlot(game->getLocalSlotNum());
- if (!localSlot)
- return TRUE;
-
- if (slot == localSlot)
- return TRUE;
-
- if (slot->getTeamNumber() < 0)
- return FALSE;
-
- return slot->getTeamNumber() == localSlot->getTeamNumber();
-}
-
-Bool GameInfo::isSkirmish(void)
-{
- Bool sawAI = FALSE;
-
- for (Int i=0; iisHuman())
- return FALSE;
-
- if (getConstSlot(i)->isAI())
- {
- if (isSlotLocalAlly(getConstSlot(i)))
- return FALSE;
- sawAI = TRUE;
- }
- }
- return sawAI;
-}
-
-Bool GameInfo::isMultiPlayer(void)
-{
- for (Int i=0; iisHuman())
- return TRUE;
- }
-
- return FALSE;
-}
-
-Bool GameInfo::isSandbox(void)
-{
- Int localSlotNum = getLocalSlotNum();
- Int localTeam = getConstSlot(localSlotNum)->getTeamNumber();
- for (Int i=0; iisOccupied() && (slot->getTeamNumber() < 0 || slot->getTeamNumber() != localTeam))
- return FALSE;
- }
- return TRUE;
-}
-
-
-// Convenience Functions ----------------------------------------
-
-static const char slotListID = 'S';
-
-AsciiString GameInfoToAsciiString( const GameInfo *game )
-{
- if (!game)
- return AsciiString::TheEmptyString;
-
- AsciiString mapName = game->getMap();
- mapName = TheGameState->realMapPathToPortableMapPath(mapName);
- AsciiString newMapName;
- if (mapName.getLength() > 0)
- {
- AsciiString token;
- mapName.nextToken(&token, "\\/");
- // add all the tokens except the last one.
- // that way we don't add the filename, just the
- // directory name, we can do this since the filename
- // is just the directory name with the file extention
- // added onto it.
- while (mapName.find('\\') != NULL)
- {
- if (newMapName.getLength() > 0)
- {
- newMapName.concat('/');
- }
- newMapName.concat(token);
- mapName.nextToken(&token, "\\/");
- }
- DEBUG_LOG(("Map name is %s", mapName.str()));
- }
-
- AsciiString optionsString;
-#if RTS_GENERALS
- optionsString.format("M=%2.2x%s;MC=%X;MS=%d;SD=%d;C=%d;", game->getMapContentsMask(), newMapName.str(),
- game->getMapCRC(), game->getMapSize(), game->getSeed(), game->getCRCInterval());
-#else
- optionsString.format("US=%d;M=%2.2x%s;MC=%X;MS=%d;SD=%d;C=%d;SR=%u;SC=%u;O=%c;", game->getUseStats(), game->getMapContentsMask(), newMapName.str(),
- game->getMapCRC(), game->getMapSize(), game->getSeed(), game->getCRCInterval(), game->getSuperweaponRestriction(),
- game->getStartingCash().countMoney(), game->oldFactionsOnly() ? 'Y' : 'N' );
-#endif
-
- //add player info for each slot
- optionsString.concat(slotListID);
- optionsString.concat('=');
- for (Int i=0; igetConstSlot(i);
-
- AsciiString str;
- if (slot && slot->isHuman())
- {
- AsciiString tmp; //all this data goes after name
- tmp.format( ",%X,%d,%c%c,%d,%d,%d,%d,%d:",
- slot->getIP(), slot->getPort(),
- (slot->isAccepted()?'T':'F'),
- (slot->hasMap()?'T':'F'),
- slot->getColor(), slot->getPlayerTemplate(),
- slot->getStartPos(), slot->getTeamNumber(),
- slot->getNATBehavior() );
- //make sure name doesn't cause overflow of m_lanMaxOptionsLength
- int lenCur = tmp.getLength() + optionsString.getLength() + 2; //+2 for H and trailing ;
- int lenRem = m_lanMaxOptionsLength - lenCur; //length remaining before overflowing
- int lenMax = lenRem / (MAX_SLOTS-i); //share lenRem with all remaining slots
- AsciiString name = WideCharStringToMultiByte(slot->getName().str()).c_str();
- while( name.getLength() > lenMax )
- name.removeLastChar(); //what a horrible way to truncate. I hate AsciiString.
-
- str.format( "H%s%s", name.str(), tmp.str() );
- }
- else if (slot && slot->isAI())
- {
- Char c;
- if (slot->getState() == SLOT_EASY_AI)
- c = 'E';
- else if (slot->getState() == SLOT_MED_AI)
- c = 'M';
- else
- c = 'H';
- str.format("C%c,%d,%d,%d,%d:", c,
- slot->getColor(), slot->getPlayerTemplate(),
- slot->getStartPos(), slot->getTeamNumber());
- }
- else if (slot && slot->getState() == SLOT_OPEN)
- {
- str = "O:";
- }
- else if (slot && slot->getState() == SLOT_CLOSED)
- {
- str = "X:";
- }
- else
- {
- DEBUG_ASSERTCRASH(false, ("Bad slot type"));
- str = "X:";
- }
- optionsString.concat(str);
- }
- optionsString.concat(';');
-
- DEBUG_ASSERTCRASH(!TheLAN || (optionsString.getLength() < m_lanMaxOptionsLength),
- ("WARNING: options string is longer than expected! Length is %d, but max is %d!",
- optionsString.getLength(), m_lanMaxOptionsLength));
-
- return optionsString;
-}
-
-static Int grabHexInt(const char *s)
-{
- char tmp[5] = "0xff";
- tmp[2] = s[0];
- tmp[3] = s[1];
- Int b = strtol(tmp, NULL, 16);
- return b;
-}
-Bool ParseAsciiStringToGameInfo(GameInfo *game, AsciiString options)
-{
- // Parse game options
- char *buf = strdup(options.str());
- char *bufPtr = buf;
- char *strPos, *keyValPair;
- GameSlot newSlot[MAX_SLOTS];
- Bool optionsOk = true;
- AsciiString mapName;
- Int mapContentsMask;
- UnsignedInt mapCRC, mapSize;
- Int seed = 0;
- Int crc = 100;
- Bool sawCRC = FALSE;
- Bool oldFactionsOnly = FALSE;
- Int useStats = TRUE;
- Money startingCash = TheGlobalData->m_defaultStartingCash;
- UnsignedShort restriction = 0; // Always the default
-
- Bool sawMap = FALSE;
- Bool sawMapCRC = FALSE;
- Bool sawMapSize = FALSE;
- Bool sawSeed = FALSE;
- Bool sawSlotlist = FALSE;
- Bool sawUseStats = FALSE;
- Bool sawSuperweaponRestriction = FALSE;
- Bool sawStartingCash = FALSE;
- Bool sawOldFactions = FALSE;
-
- //DEBUG_LOG(("Saw options of %s", options.str()));
- DEBUG_LOG(("ParseAsciiStringToGameInfo - parsing [%s]", options.str()));
-
-
- while ( (keyValPair = strtok_r(bufPtr, ";", &strPos)) != NULL )
- {
- bufPtr = NULL; // strtok within the same string
-
- AsciiString key, val;
- char *pos = NULL;
- char *keyPtr, *valPtr;
- keyPtr = (strtok_r(keyValPair, "=", &pos));
- valPtr = (strtok_r(NULL, "\n", &pos));
- if (keyPtr)
- key = keyPtr;
- if (valPtr)
- val = valPtr;
-
- if (val.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - saw empty value, quitting"));
- break;
- }
-
- if (key.compare("US") == 0)
- {
- useStats = atoi(val.str());
- sawUseStats = true;
- }
- else
- if (key.compare("M") == 0)
- {
- if (val.getLength() < 3)
- {
- optionsOk = FALSE;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - saw bogus map; quitting"));
- break;
- }
- mapContentsMask = grabHexInt(val.str());
- AsciiString tempstr;
- AsciiString token;
- tempstr = val.str()+2;
- tempstr.nextToken(&token, "\\/");
- while (tempstr.getLength() > 0)
- {
- mapName.concat(token);
- mapName.concat('\\');
- tempstr.nextToken(&token, "\\/");
- }
- mapName.concat(token);
- mapName.concat('\\');
- mapName.concat(token);
- mapName.concat('.');
- mapName.concat(TheMapCache->getMapExtension());
- AsciiString realMapName = TheGameState->portableMapPathToRealMapPath(mapName);
- if (realMapName.isEmpty())
- {
- // TheSuperHackers @security slurmlord 18/06/2025 As the map file name/path from the AsciiString failed to normalize,
- // in other words is bogus and points outside of the approved target directory for maps, avoid an arbitrary file overwrite vulnerability
- // if the save or network game embeds a custom map to store at the location, by flagging the options as not OK and rejecting the game.
- optionsOk = FALSE;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - saw bogus map name ('%s'); quitting", mapName.str()));
- break;
- }
- mapName = realMapName;
- sawMap = true;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - map name is %s", mapName.str()));
- }
- else if (key.compare("MC") == 0)
- {
- mapCRC = 0;
- sscanf(val.str(), "%X", &mapCRC);
- sawMapCRC = true;
- }
- else if (key.compare("MS") == 0)
- {
- mapSize = atoi(val.str());
- sawMapSize = true;
- }
- else if (key.compare("SD") == 0)
- {
- seed = atoi(val.str());
- sawSeed = true;
-// DEBUG_LOG(("ParseAsciiStringToGameInfo - random seed is %d", seed));
- }
- else if (key.compare("C") == 0)
- {
- crc = atoi(val.str());
- sawCRC = TRUE;
- }
- else if (key.compare("SR") == 0 )
- {
- restriction = (UnsignedShort)atoi(val.str());
- sawSuperweaponRestriction = TRUE;
- }
- else if (key.compare("SC") == 0 )
- {
- UnsignedInt startingCashAmount = strtoul( val.str(), NULL, 10 );
- startingCash.init();
- startingCash.deposit( startingCashAmount, FALSE, FALSE );
- sawStartingCash = TRUE;
- }
- else if (key.compare("O") == 0 )
- {
- oldFactionsOnly = ( val.compareNoCase( "Y" ) == 0 );
- sawOldFactions = TRUE;
- }
- else if (key.getLength() == 1 && *key.str() == slotListID)
- {
- sawSlotlist = true;
- /// @TODO: Need to read in all the slot info... big mess right now.
- char *rawSlotBuf = strdup(val.str());
- char *freeMe = NULL;
- AsciiString rawSlot;
-// Bool slotsOk = true; //flag that lets us know whether or not the slot list is good.
-
-// DEBUG_LOG(("ParseAsciiStringToGameInfo - Parsing slot list"));
- for (int i=0; i= TheMultiplayerSettings->getNumColors())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - player color was invalid, quitting"));
- break;
- }
- newSlot[i].setColor(color);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - player color set to %d", color));
-
- //Read playerTemplate index
- slotValue = strtok_r(NULL,",",&slotPos);
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue player template is empty, quitting"));
- break;
- }
- Int playerTemplate = atoi(slotValue.str());
- if (playerTemplate < PLAYERTEMPLATE_MIN || playerTemplate >= ThePlayerTemplateStore->getPlayerTemplateCount())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - player template value is invalid, quitting"));
- break;
- }
- newSlot[i].setPlayerTemplate(playerTemplate);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - player template is %d", playerTemplate));
-
- //Read start position index
- slotValue = strtok_r(NULL,",",&slotPos);
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue start position is empty, quitting"));
- break;
- }
- Int startPos = atoi(slotValue.str());
- if (startPos < -1 || startPos >= MAX_SLOTS)
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - player start position is invalid, quitting"));
- break;
- }
- newSlot[i].setStartPos(startPos);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - player start position is %d", startPos));
-
- //Read team index
- slotValue = strtok_r(NULL,",",&slotPos);
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue team number is empty, quitting"));
- break;
- }
- Int team = atoi(slotValue.str());
- if (team < -1 || team >= MAX_SLOTS/2)
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - team number is invalid, quitting"));
- break;
- }
- newSlot[i].setTeamNumber(team);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - team number is %d", team));
-
- // Read the NAT behavior
- slotValue = strtok_r(NULL, ",",&slotPos);
- if (slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - NAT behavior is empty, quitting"));
- break;
- }
- FirewallHelperClass::FirewallBehaviorType NATType = (FirewallHelperClass::FirewallBehaviorType)atoi(slotValue.str());
- if ((NATType < FirewallHelperClass::FIREWALL_MIN) ||
- (NATType > FirewallHelperClass::FIREWALL_MAX)) {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - NAT behavior is invalid, quitting"));
- break;
- }
- newSlot[i].setNATBehavior(NATType);
- DEBUG_LOG(("ParseAsciiStringToGameInfo - NAT behavior is %X", NATType));
- }
- break;
- case 'C':
- {
- DEBUG_LOG(("ParseAsciiStringToGameInfo - AI player"));
- char *slotPos = NULL;
- //Parse out the Name
- AsciiString slotValue(strtok_r((char *)rawSlot.str(),",",&slotPos));
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue AI Type is empty, quitting"));
- break;
- }
-
- switch(*(slotValue.str() + 1))
- {
- case 'E':
- {
- newSlot[i].setState(SLOT_EASY_AI);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - Easy AI"));
- }
- break;
- case 'M':
- {
- newSlot[i].setState(SLOT_MED_AI);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - Medium AI"));
- }
- break;
- case 'H':
- {
- newSlot[i].setState(SLOT_BRUTAL_AI);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - Brutal AI"));
- }
- break;
- default:
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - Unknown AI, quitting"));
- }
- break;
- }
-
- //Read color index
- slotValue = strtok_r(NULL,",",&slotPos);
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue color is empty, quitting"));
- break;
- }
- Int color = atoi(slotValue.str());
- if (color < -1 || color >= TheMultiplayerSettings->getNumColors())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - player color was invalid, quitting"));
- break;
- }
- newSlot[i].setColor(color);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - player color set to %d", color));
-
- //Read playerTemplate index
- slotValue = strtok_r(NULL,",",&slotPos);
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue player template is empty, quitting"));
- break;
- }
- Int playerTemplate = atoi(slotValue.str());
- if (playerTemplate < PLAYERTEMPLATE_MIN || playerTemplate >= ThePlayerTemplateStore->getPlayerTemplateCount())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - player template value is invalid, quitting"));
- break;
- }
- newSlot[i].setPlayerTemplate(playerTemplate);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - player template is %d", playerTemplate));
-
- //Read start pos
- slotValue = strtok_r(NULL,",",&slotPos);
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue start pos is empty, quitting"));
- break;
- }
- Int startPos = atoi(slotValue.str());
- Bool isStartPosBad = FALSE;
- if (startPos < -1 || startPos >= MAX_SLOTS)
- {
- isStartPosBad = TRUE;
- }
- for (Int j=0; j= 0 && startPos == newSlot[i].getStartPos())
- {
- isStartPosBad = TRUE; // can't have multiple people using the same start pos
- }
- }
- if (isStartPosBad)
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - start pos is invalid, quitting"));
- break;
- }
- newSlot[i].setStartPos(startPos);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - start spot is %d", startPos));
-
- //Read team index
- slotValue = strtok_r(NULL,",",&slotPos);
- if(slotValue.isEmpty())
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - slotValue team number is empty, quitting"));
- break;
- }
- Int team = atoi(slotValue.str());
- if (team < -1 || team >= MAX_SLOTS/2)
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - team number is invalid, quitting"));
- break;
- }
- newSlot[i].setTeamNumber(team);
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - team number is %d", team));
-
- }
- break;
- case 'O':
- {
- newSlot[i].setState( SLOT_OPEN );
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - Slot is open"));
- }
- break;
- case 'X':
- {
- newSlot[i].setState( SLOT_CLOSED );
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - Slot is closed"));
- }
- break;
- default:
- {
- optionsOk = false;
- DEBUG_LOG(("ParseAsciiStringToGameInfo - unrecognized slot entry, quitting"));
- }
- break;
- }
- }
-
- free(freeMe);
- }
- else
- {
- optionsOk = false;
- break;
- }
- }
-
- free(buf);
-
- // TheSuperHackers @tweak The following settings are no longer
- // a strict requirement in the Zero Hour Replay file:
- // * UseStats
- // * SuperweaponRestriction
- // * StartingCash
- // * OldFactionsOnly
- // In Generals they never were.
- if (optionsOk && sawMap && sawMapCRC && sawMapSize && sawSeed && sawSlotlist && sawCRC)
- {
- // We were setting the Global Data directly here, but Instead, I'm now
- // first setting the data in game. We'll set the global data when
- // we start a game.
- if (!game)
- return true;
-
- //DEBUG_LOG(("ParseAsciiStringToGameInfo - game options all good, setting info"));
-
- for(Int i = 0; isetSlot(i,newSlot[i]);
-
- game->setMap(mapName);
- game->setMapCRC(mapCRC);
- game->setMapSize(mapSize);
- game->setMapContentsMask(mapContentsMask);
- game->setSeed(seed);
- game->setCRCInterval(crc);
- game->setUseStats(useStats);
- game->setSuperweaponRestriction(restriction);
- game->setStartingCash(startingCash);
- game->setOldFactionsOnly(oldFactionsOnly);
-
- return true;
- }
-
- DEBUG_LOG(("ParseAsciiStringToGameInfo - game options messed up"));
- return false;
-}
-
-
-//----------------------------------------------------------------------------------------------------------
-//----------------------------------------------------------------------------------------------------------
-
-//------------------------- SkirmishGameInfo ---------------------------------------------------------------
-
-// ------------------------------------------------------------------------------------------------
-/** CRC */
-// ------------------------------------------------------------------------------------------------
-void SkirmishGameInfo::crc( Xfer *xfer )
-{
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Xfer Method */
-// ------------------------------------------------------------------------------------------------
-void SkirmishGameInfo::xfer( Xfer *xfer )
-{
-#if RTS_GENERALS
- const XferVersion currentVersion = 2;
-#else
- const XferVersion currentVersion = 4;
-#endif
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
-
-
- xfer->xferInt(&m_preorderMask);
- xfer->xferInt(&m_crcInterval);
- xfer->xferBool(&m_inGame);
- xfer->xferBool(&m_inProgress);
- xfer->xferBool(&m_surrendered);
- xfer->xferInt(&m_gameID);
-
- Int slot = MAX_SLOTS;
- xfer->xferInt(&slot);
- DEBUG_ASSERTCRASH(slot==MAX_SLOTS, ("MAX_SLOTS changed, need to change version. jba."));
-
- for (slot = 0; slot < MAX_SLOTS; slot++)
- {
- Int state = m_slot[slot]->getState();
- xfer->xferInt(&state);
-
- UnicodeString name=m_slot[slot]->getName();
- if (version >= 2)
- {
- xfer->xferUnicodeString(&name);
- }
-
- Bool isAccepted=m_slot[slot]->isAccepted();
- xfer->xferBool(&isAccepted);
-
- Bool isMuted=m_slot[slot]->isMuted();
- xfer->xferBool(&isMuted);
- m_slot[slot]->mute(isMuted);
-
- Int color=m_slot[slot]->getColor();
- xfer->xferInt(&color);
-
- Int startPos=m_slot[slot]->getStartPos();
- xfer->xferInt(&startPos);
-
- Int playerTemplate=m_slot[slot]->getPlayerTemplate();
- xfer->xferInt(&playerTemplate);
-
- Int teamNumber=m_slot[slot]->getTeamNumber();
- xfer->xferInt(&teamNumber);
-
- Int origColor=m_slot[slot]->getOriginalColor();
- xfer->xferInt(&origColor);
-
- Int origStartPos=m_slot[slot]->getOriginalStartPos();
- xfer->xferInt(&origStartPos);
-
- Int origPlayerTemplate=m_slot[slot]->getOriginalPlayerTemplate();
- xfer->xferInt(&origPlayerTemplate);
-
- if( xfer->getXferMode() == XFER_LOAD ) {
- m_slot[slot]->setState((SlotState)state, name);
- if (isAccepted) m_slot[slot]->setAccept();
-
- m_slot[slot]->setPlayerTemplate(origPlayerTemplate);
- m_slot[slot]->setStartPos(origStartPos);
- m_slot[slot]->setColor(origColor);
- m_slot[slot]->saveOffOriginalInfo();
-
- m_slot[slot]->setTeamNumber(teamNumber);
- m_slot[slot]->setColor(color);
- m_slot[slot]->setStartPos(startPos);
- m_slot[slot]->setPlayerTemplate(playerTemplate);
- }
- }
-
- xfer->xferUnsignedInt(&m_localIP);
-
- xfer->xferMapName(&m_mapName);
- xfer->xferUnsignedInt(&m_mapCRC);
- xfer->xferUnsignedInt(&m_mapSize);
- xfer->xferInt(&m_mapMask);
- xfer->xferInt(&m_seed);
-
- if ( version >= 3 )
- {
- xfer->xferUnsignedShort( &m_superweaponRestriction );
-
- if ( version == 3 )
- {
- // Version 3 had a bool which is now gone
- Bool obsoleteBool;
- xfer->xferBool( &obsoleteBool );
- }
-
- xfer->xferSnapshot( &m_startingCash );
- }
- else if ( xfer->getXferMode() == XFER_LOAD )
- {
- m_superweaponRestriction = 0;
- m_startingCash = TheGlobalData->m_defaultStartingCash;
- }
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Load post process */
-// ------------------------------------------------------------------------------------------------
-void SkirmishGameInfo::loadPostProcess( void )
-{
-}
-
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameMessageParser.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameMessageParser.cpp
deleted file mode 100644
index c6fa9b90efe..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameMessageParser.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/GameMessageParser.h"
-
-//----------------------------------------------------------------------------
-GameMessageParser::GameMessageParser()
-{
- m_first = NULL;
- m_argTypeCount = 0;
-}
-
-//----------------------------------------------------------------------------
-GameMessageParser::GameMessageParser(GameMessage *msg)
-{
- m_first = NULL;
- m_argTypeCount = 0;
-
- UnsignedByte argCount = msg->getArgumentCount();
- GameMessageArgumentDataType lasttype = ARGUMENTDATATYPE_UNKNOWN;
- Int thisTypeCount = 0;
-
- for (UnsignedByte i = 0; i < argCount; ++i) {
- GameMessageArgumentDataType type = msg->getArgumentDataType(i);
- if (type != lasttype) {
- if (thisTypeCount > 0) {
- addArgType(lasttype, thisTypeCount);
- ++m_argTypeCount;
- }
- lasttype = type;
- thisTypeCount = 0;
- }
- ++thisTypeCount;
- }
- if (thisTypeCount > 0) {
- addArgType(lasttype, thisTypeCount);
- ++m_argTypeCount;
- }
-}
-
-//----------------------------------------------------------------------------
-GameMessageParser::~GameMessageParser()
-{
- GameMessageParserArgumentType *temp = NULL;
- while (m_first != NULL) {
- temp = m_first->getNext();
- deleteInstance(m_first);
- m_first = temp;
- }
-}
-
-//----------------------------------------------------------------------------
-void GameMessageParser::addArgType(GameMessageArgumentDataType type, Int argCount)
-{
- if (m_first == NULL) {
- m_first = newInstance(GameMessageParserArgumentType)(type, argCount);
- m_last = m_first;
- return;
- }
-
- m_last->setNext(newInstance(GameMessageParserArgumentType)(type, argCount));
- m_last = m_last->getNext();
-}
-
-//----------------------------------------------------------------------------
-GameMessageParserArgumentType::GameMessageParserArgumentType(GameMessageArgumentDataType type, Int argCount)
-{
- m_next = NULL;
- m_type = type;
- m_argCount = argCount;
-}
-
-//----------------------------------------------------------------------------
-GameMessageParserArgumentType::~GameMessageParserArgumentType()
-{
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp
deleted file mode 100644
index 190df8a9a68..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Chat.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Chat.cpp //////////////////////////////////////////////////////
-// Generals GameSpy chat-related code
-// Author: Matthew D. Campbell, July 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/AudioEventRTS.h"
-#include "Common/INI.h"
-#include "GameClient/GameText.h"
-#include "GameClient/GadgetListBox.h"
-#include "GameClient/LanguageFilter.h"
-#include "GameClient/GameWindowManager.h"
-#include "GameNetwork/GameSpy/PeerDefsImplementation.h"
-#include "GameNetwork/GameSpy/PeerThread.h"
-#include "GameClient/InGameUI.h"
-
-#define OFFSET(x) (sizeof(Int) * (x))
-static const FieldParse GameSpyColorFieldParse[] =
-{
-
- { "Default", INI::parseColorInt, NULL, OFFSET(GSCOLOR_DEFAULT) },
- { "CurrentRoom", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CURRENTROOM) },
- { "ChatRoom", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ROOM) },
- { "Game", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME) },
- { "GameFull", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME_FULL) },
- { "GameCRCMismatch", INI::parseColorInt, NULL, OFFSET(GSCOLOR_GAME_CRCMISMATCH) },
- { "PlayerNormal", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_NORMAL) },
- { "PlayerOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_OWNER) },
- { "PlayerBuddy", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_BUDDY) },
- { "PlayerSelf", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_SELF) },
- { "PlayerIgnored", INI::parseColorInt, NULL, OFFSET(GSCOLOR_PLAYER_IGNORED) },
- { "ChatNormal", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_NORMAL) },
- { "ChatEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_EMOTE) },
- { "ChatOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_OWNER) },
- { "ChatOwnerEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_OWNER_EMOTE) },
- { "ChatPriv", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE) },
- { "ChatPrivEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_EMOTE) },
- { "ChatPrivOwner", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_OWNER) },
- { "ChatPrivOwnerEmote", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE) },
- { "ChatBuddy", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_BUDDY) },
- { "ChatSelf", INI::parseColorInt, NULL, OFFSET(GSCOLOR_CHAT_SELF) },
- { "AcceptTrue", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ACCEPT_TRUE) },
- { "AcceptFalse", INI::parseColorInt, NULL, OFFSET(GSCOLOR_ACCEPT_FALSE) },
- { "MapSelected", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MAP_SELECTED) },
- { "MapUnselected", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MAP_UNSELECTED) },
- { "MOTD", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MOTD) },
- { "MOTDHeading", INI::parseColorInt, NULL, OFFSET(GSCOLOR_MOTD_HEADING) },
-
- { NULL, NULL, NULL, 0 }
-
-};
-
-void INI::parseOnlineChatColorDefinition( INI* ini )
-{
- // parse the ini definition
- ini->initFromINI( GameSpyColor, GameSpyColorFieldParse );
-}
-
-
-Color GameSpyColor[GSCOLOR_MAX] =
-{
- GameMakeColor(255,255,255,255), // GSCOLOR_DEFAULT
- GameMakeColor(255,255, 0,255), // GSCOLOR_CURRENTROOM
- GameMakeColor(255,255,255,255), // GSCOLOR_ROOM
- GameMakeColor(128,128,0,255), // GSCOLOR_GAME
- GameMakeColor(128,128,128,255), // GSCOLOR_GAME_FULL
- GameMakeColor(128,128,128,255), // GSCOLOR_GAME_CRCMISMATCH
-#if RTS_GENERALS
- GameMakeColor(255, 0, 0,255), // GSCOLOR_PLAYER_NORMAL
-#else
- GameMakeColor(255,255,255,255), // GSCOLOR_PLAYER_NORMAL
-#endif
- GameMakeColor(255, 0,255,255), // GSCOLOR_PLAYER_OWNER
- GameMakeColor(255, 0,128,255), // GSCOLOR_PLAYER_BUDDY
- GameMakeColor(255, 0, 0,255), // GSCOLOR_PLAYER_SELF
- GameMakeColor(128,128,128,255), // GSCOLOR_PLAYER_IGNORED
-#if RTS_GENERALS
- GameMakeColor(255,0,0,255), // GSCOLOR_CHAT_NORMAL
-#else
- GameMakeColor(255,255,255,255), // GSCOLOR_CHAT_NORMAL
-#endif
- GameMakeColor(255,128,0,255), // GSCOLOR_CHAT_EMOTE,
- GameMakeColor(255,255,0,255), // GSCOLOR_CHAT_OWNER,
- GameMakeColor(128,255,0,255), // GSCOLOR_CHAT_OWNER_EMOTE,
- GameMakeColor(0,0,255,255), // GSCOLOR_CHAT_PRIVATE,
- GameMakeColor(0,255,255,255), // GSCOLOR_CHAT_PRIVATE_EMOTE,
- GameMakeColor(255,0,255,255), // GSCOLOR_CHAT_PRIVATE_OWNER,
- GameMakeColor(255,128,255,255), // GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE,
- GameMakeColor(255, 0,255,255), // GSCOLOR_CHAT_BUDDY,
- GameMakeColor(255, 0,128,255), // GSCOLOR_CHAT_SELF,
- GameMakeColor( 0,255, 0,255), // GSCOLOR_ACCEPT_TRUE,
- GameMakeColor(255, 0, 0,255), // GSCOLOR_ACCEPT_FALSE,
- GameMakeColor(255,255, 0,255), // GSCOLOR_MAP_SELECTED,
- GameMakeColor(255,255,255,255), // GSCOLOR_MAP_UNSELECTED,
- GameMakeColor(255,255,255,255), // GSCOLOR_MOTD,
- GameMakeColor(255,255, 0,255), // GSCOLOR_MOTD_HEADING,
-};
-
-Bool GameSpyInfo::sendChat( UnicodeString message, Bool isAction, GameWindow *playerListbox )
-{
- static UnicodeString s_prevMsg = UnicodeString::TheEmptyString; //stop spam before it happens
-
- RoomType roomType = StagingRoom;
- if (getCurrentGroupRoom())
- roomType = GroupRoom;
-
- PeerRequest req;
- req.text = message.str();
-
- message.trim();
- // Echo the user's input to the chat window
- if (!message.isEmpty())
- {
- if (!playerListbox)
- { // Public message
- if( isAction || message.compare(s_prevMsg) != 0 ) //don't send duplicate messages
- {
- req.message.isAction = isAction;
- req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEROOM;
- TheGameSpyPeerMessageQueue->addRequest(req);
- s_prevMsg = message;
- }
- return false;
- }
-
- // Get the selections (is this a private message?)
- Int maxSel = GadgetListBoxGetMaxSelectedLength(playerListbox);
- Int *selections;
- GadgetListBoxGetSelected(playerListbox, (Int *)&selections);
-
- if (selections[0] == -1)
- { // Public message
- if( isAction || message.compare(s_prevMsg) != 0 ) //don't send duplicate messages
- {
- req.message.isAction = isAction;
- req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEROOM;
- TheGameSpyPeerMessageQueue->addRequest(req);
- s_prevMsg = message;
- }
- return false;
- }
- else
- {
- // Private message
-
- // Construct a list
- AsciiString names = AsciiString::TheEmptyString;
- AsciiString tmp = AsciiString::TheEmptyString;
- AsciiString aStr; // AsciiString buf for translating Unicode entries
- names.format("%s", TheGameSpyInfo->getLocalName().str());
- for (int i=0; igetLocalName()))
- {
- tmp.format(",%s", aStr.str());
- names.concat(tmp);
- }
- }
- else
- {
- break;
- }
- }
-
- if (!names.isEmpty())
- {
- req.nick = names.str();
- req.message.isAction = isAction;
- req.peerRequestType = PeerRequest::PEERREQUEST_MESSAGEPLAYER;
- TheGameSpyPeerMessageQueue->addRequest(req);
- }
- s_prevMsg = message;
- return true;
- }
- }
- s_prevMsg = message;
- return false;
-}
-
-void GameSpyInfo::addChat( AsciiString nick, Int profileID, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win )
-{
- PlayerInfoMap::iterator it = getPlayerInfoMap()->find(nick);
- if (it != getPlayerInfoMap()->end())
- {
- addChat( it->second, msg, isPublic, isAction, win );
- }
- else
- {
- }
-}
-
-void GameSpyInfo::addChat( PlayerInfo p, UnicodeString msg, Bool isPublic, Bool isAction, GameWindow *win )
-{
- Int style;
- if(isSavedIgnored(p.m_profileID) || isIgnored(p.m_name))
- return;
-
- Bool isOwner = p.m_flags & PEER_FLAG_OP;
- Bool isBuddy = getBuddyMap()->find(p.m_profileID) != getBuddyMap()->end();
-
- Bool isMe = p.m_name.compare(TheGameSpyInfo->getLocalName()) == 0;
-
- if(!isMe)
- {
- if(m_disallowAsainText)
- {
- const WideChar *buff = msg.str();
- Int length = msg.getLength();
- for(Int i = 0; i < length; ++i)
- {
- if(buff[i] >= 256)
- return;
- }
- }
- else if(m_disallowNonAsianText)
- {
- const WideChar *buff = msg.str();
- Int length = msg.getLength();
- Bool hasUnicode = FALSE;
- for(Int i = 0; i < length; ++i)
- {
- if(buff[i] >= 256)
- {
- hasUnicode = TRUE;
- break;
- }
- }
- if(!hasUnicode)
- return;
- }
-
- if (!isPublic)
- {
- AudioEventRTS privMsgAudio("GUIMessageReceived");
-
- if( TheAudio )
- {
- TheAudio->addAudioEvent( &privMsgAudio );
- }
- }
- }
-
-
- if (isBuddy)
- {
- style = GSCOLOR_CHAT_BUDDY;
- }
- else if (isPublic && isAction)
- {
- style = (isOwner)?GSCOLOR_CHAT_OWNER_EMOTE:GSCOLOR_CHAT_EMOTE;
- }
- else if (isPublic)
- {
- style = (isOwner)?GSCOLOR_CHAT_OWNER:GSCOLOR_CHAT_NORMAL;
- }
- else if (isAction)
- {
- style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER_EMOTE:GSCOLOR_CHAT_PRIVATE_EMOTE;
- }
- else
- {
- style = (isOwner)?GSCOLOR_CHAT_PRIVATE_OWNER:GSCOLOR_CHAT_PRIVATE;
- }
-
- UnicodeString name;
- name.translate(p.m_name);
-
- // filters language
-// if( TheGlobalData->m_languageFilterPref )
-// {
- TheLanguageFilter->filterLine(msg);
-// }
-
- UnicodeString fullMsg;
- if (isAction)
- {
- fullMsg.format( L"%ls %ls", name.str(), msg.str() );
- }
- else
- {
- fullMsg.format( L"[%ls] %ls", name.str(), msg.str() );
- }
-
- Int index = addText(fullMsg, GameSpyColor[style], win);
- if (index >= 0)
- {
- GadgetListBoxSetItemData(win, (void *)p.m_profileID, index);
- }
-}
-
-Int GameSpyInfo::addText( UnicodeString message, Color c, GameWindow *win )
-{
- if (TheGameSpyGame && TheGameSpyGame->isInGame() && TheGameSpyGame->isGameInProgress())
- {
- static AudioEventRTS messageFromChatSound("GUIMessageReceived");
- TheAudio->addAudioEvent(&messageFromChatSound);
-
- TheInGameUI->message(message);
- }
-
- if (!win)
- {
- // try to pick up a registered text window
- if (m_textWindows.empty())
- return -1;
-
- win = *(m_textWindows.begin());
- }
- Int index = GadgetListBoxAddEntryText(win, message, c, -1, -1);
- GadgetListBoxSetItemData(win, (void *)-1, index);
-
- return index;
-}
-
-void GameSpyInfo::registerTextWindow( GameWindow *win )
-{
- m_textWindows.insert(win);
-}
-
-void GameSpyInfo::unregisterTextWindow( GameWindow *win )
-{
- m_textWindows.erase(win);
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp
deleted file mode 100644
index d79709d92e2..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/GSConfig.cpp
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: GSConfig.cpp
-// Author: Matthew D. Campbell, Sept 2002
-// Description: GameSpy online config
-///////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/GameState.h"
-#include "GameClient/MapUtil.h"
-#include "GameNetwork/GameSpy/GSConfig.h"
-#include "GameNetwork/RankPointValue.h"
-
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-GameSpyConfigInterface *TheGameSpyConfig = NULL;
-
-class GameSpyConfig : public GameSpyConfigInterface
-{
-public:
- GameSpyConfig( AsciiString config );
- ~GameSpyConfig() {}
-
- // Pings
- std::list getPingServers(void) { return m_pingServers; }
- Int getNumPingRepetitions(void) { return m_pingReps; }
- Int getPingTimeoutInMs(void) { return m_pingTimeout; }
- virtual Int getPingCutoffGood( void ) { return m_pingCutoffGood; }
- virtual Int getPingCutoffBad( void ) { return m_pingCutoffBad; }
-
- // QM
- std::list getQMMaps(void) { return m_qmMaps; }
- Int getQMBotID(void) { return m_qmBotID; }
- Int getQMChannel(void) { return m_qmChannel; }
- void setQMChannel(Int channel) { m_qmChannel = channel; }
-
- // Player Info
- Int getPointsForRank(Int rank);
- virtual Bool isPlayerVIP(Int id);
-
- virtual Bool getManglerLocation(Int index, AsciiString& host, UnsignedShort& port);
-
- // Ladder / Any other external parsing
- AsciiString getLeftoverConfig(void) { return m_leftoverConfig; }
-
- // NAT Timeouts
- virtual Int getTimeBetweenRetries() { return m_natRetryInterval; }
- virtual Int getMaxManglerRetries() { return m_natMaxManglerRetries; }
- virtual time_t getRetryInterval() { return m_natManglerRetryInterval; }
- virtual time_t getKeepaliveInterval() { return m_natKeepaliveInterval; }
- virtual time_t getPortTimeout() { return m_natPortTimeout; }
- virtual time_t getRoundTimeout() { return m_natRoundTimeout; }
-
- // Custom match
- virtual Bool restrictGamesToLobby() { return m_restrictGamesToLobby; }
-
-protected:
- std::list m_pingServers;
- Int m_pingReps;
- Int m_pingTimeout;
- Int m_pingCutoffGood;
- Int m_pingCutoffBad;
-
- Int m_natRetryInterval;
- Int m_natMaxManglerRetries;
- time_t m_natManglerRetryInterval;
- time_t m_natKeepaliveInterval;
- time_t m_natPortTimeout;
- time_t m_natRoundTimeout;
-
- std::vector m_manglerHosts;
- std::vector m_manglerPorts;
-
- std::list m_qmMaps;
- Int m_qmBotID;
- Int m_qmChannel;
-
- Bool m_restrictGamesToLobby;
-
- std::set m_vip; // VIP people
-
- Int m_rankPoints[MAX_RANKS];
-
- AsciiString m_leftoverConfig;
-};
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-GameSpyConfigInterface* GameSpyConfigInterface::create(AsciiString config)
-{
- return NEW GameSpyConfig(config);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-class SectionChecker
-{
-public:
- typedef std::list SectionList;
- void addVar(const Bool *var) { m_bools.push_back(var); }
- Bool isInSection();
-protected:
- SectionList m_bools;
-};
-Bool SectionChecker::isInSection() {
- Bool ret = FALSE;
- for (SectionList::const_iterator it = m_bools.begin(); it != m_bools.end(); ++it)
- {
- ret = ret || **it;
- }
- return ret;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-GameSpyConfig::GameSpyConfig( AsciiString config ) :
-m_natRetryInterval(1000),
-m_natMaxManglerRetries(25),
-m_natManglerRetryInterval(300),
-m_natKeepaliveInterval(15000),
-m_natPortTimeout(10000),
-m_natRoundTimeout(10000),
-m_pingReps(1),
-m_pingTimeout(1000),
-m_pingCutoffGood(300),
-m_pingCutoffBad(600),
-m_restrictGamesToLobby(FALSE),
-m_qmBotID(0),
-m_qmChannel(0)
-{
- m_rankPoints[0] = 0;
- m_rankPoints[1] = 5;
- m_rankPoints[2] = 10;
- m_rankPoints[3] = 20;
- m_rankPoints[4] = 50;
- m_rankPoints[5] = 100;
- m_rankPoints[6] = 200;
- m_rankPoints[7] = 500;
- m_rankPoints[8] = 1000;
- m_rankPoints[9] = 2000;
-
- AsciiString line;
- Bool inPingServers = FALSE;
- Bool inPingDuration = FALSE;
- Bool inQMMaps = FALSE;
- Bool inQMBot = FALSE;
- Bool inManglers = FALSE;
- Bool inVIP = FALSE;
- Bool inNAT = FALSE;
- Bool inCustom = FALSE;
-
- SectionChecker sections;
- sections.addVar(&inPingServers);
- sections.addVar(&inPingDuration);
- sections.addVar(&inQMMaps);
- sections.addVar(&inQMBot);
- sections.addVar(&inManglers);
- sections.addVar(&inVIP);
- sections.addVar(&inNAT);
- sections.addVar(&inCustom);
-
- while (config.nextToken(&line, "\n"))
- {
- if (line.getCharAt(line.getLength()-1) == '\r')
- line.removeLastChar(); // there is a trailing '\r'
-
- line.trim();
-
- if (line.isEmpty())
- continue;
-
- if (!sections.isInSection() && line.compare("") == 0)
- {
- inPingServers = TRUE;
- }
- else if (inPingServers && line.compare("") == 0)
- {
- inPingServers = FALSE;
- }
- else if (!sections.isInSection() && line.compare("") == 0)
- {
- inPingDuration = TRUE;
- }
- else if (inPingDuration && line.compare("") == 0)
- {
- inPingDuration = FALSE;
- }
- else if (!sections.isInSection() && line.compare("") == 0)
- {
- inQMMaps = TRUE;
- }
- else if (inQMMaps && line.compare("") == 0)
- {
- inQMMaps = FALSE;
- }
- else if (!sections.isInSection() && line.compare("") == 0)
- {
- inManglers = TRUE;
- }
- else if (inManglers && line.compare("") == 0)
- {
- inManglers = FALSE;
- }
- else if (!sections.isInSection() && line.compare("") == 0)
- {
- inQMBot = TRUE;
- }
- else if (inQMBot && line.compare("") == 0)
- {
- inQMBot = FALSE;
- }
- else if (!sections.isInSection() && line.compare("") == 0)
- {
- inVIP = TRUE;
- }
- else if (inVIP && line.compare("") == 0)
- {
- inVIP = FALSE;
- }
- else if (!sections.isInSection() && line.compare("") == 0)
- {
- inNAT = TRUE;
- }
- else if (inNAT && line.compare("") == 0)
- {
- inNAT = FALSE;
- }
- else if (!sections.isInSection() && line.compare("") == 0)
- {
- inCustom = TRUE;
- }
- else if (inCustom && line.compare("") == 0)
- {
- inCustom = FALSE;
- }
- else if (inVIP)
- {
- line.toLower();
- if (line.getLength())
- {
- Int val = atoi(line.str());
- if (val > 0)
- m_vip.insert(val);
- }
- }
- else if (inPingServers)
- {
- line.toLower();
- m_pingServers.push_back(line);
- }
- else if (inPingDuration)
- {
- line.toLower();
- AsciiString key, val;
- if (line.nextToken(&key, " ="))
- {
- if (key == "reps")
- {
- if (line.nextToken(&val, " ="))
- {
- m_pingReps = atoi(val.str());
- }
- }
- else if (key == "timeout")
- {
- if (line.nextToken(&val, " ="))
- {
- m_pingTimeout = atoi(val.str());
- }
- }
- else if (key == "low")
- {
- if (line.nextToken(&val, " ="))
- {
- m_pingCutoffGood = atoi(val.str());
- }
- }
- else if (key == "med")
- {
- if (line.nextToken(&val, " ="))
- {
- m_pingCutoffBad = atoi(val.str());
- }
- }
- }
- }
- else if (inManglers)
- {
- line.trim();
- line.toLower();
- AsciiString hostStr;
- AsciiString portStr;
- line.nextToken(&hostStr, ":");
- line.nextToken(&portStr, ":\n\r");
- if (hostStr.isNotEmpty() && portStr.isNotEmpty())
- {
- m_manglerHosts.push_back(hostStr);
- m_manglerPorts.push_back(atoi(portStr.str()));
- }
- }
- else if (inQMMaps)
- {
- line.toLower();
- AsciiString mapName;
- mapName.format("%s\\%s\\%s.map", TheMapCache->getMapDir().str(), line.str(), line.str());
- mapName = TheGameState->portableMapPathToRealMapPath(TheGameState->realMapPathToPortableMapPath(mapName));
- mapName.toLower();
-
- // [SKB: Jul 01 2003 @ 6:43pm] :
- // German2 is missing some maps because of content. But, we need the m_qmMaps
- // to contain same number of strings as the Retail version so that the
- // QM Bot thinks that they have the same number of maps.
- #if RTS_GENERALS
- m_qmMaps.push_back(mapName);
- #else
- const MapMetaData *md = TheMapCache->findMap(mapName);
- if (md)
- {
- m_qmMaps.push_back(mapName);
- }
- #endif
- }
- else if (inQMBot)
- {
- line.toLower();
- AsciiString key, val;
- if (line.nextToken(&key, " ="))
- {
- if (key == "id")
- {
- if (line.nextToken(&val, " ="))
- {
- m_qmBotID = atoi(val.str());
- }
- }
- }
- }
- else if (inNAT)
- {
- line.toLower();
- AsciiString key, val;
- if (line.nextToken(&key, " ="))
- {
- if (key == "retryinterval")
- {
- if (line.nextToken(&val, " ="))
- {
- m_natRetryInterval = atoi(val.str());
- }
- }
- else if (key == "manglerretries")
- {
- if (line.nextToken(&val, " ="))
- {
- m_natMaxManglerRetries = atoi(val.str());
- }
- }
- else if (key == "manglerinterval")
- {
- if (line.nextToken(&val, " ="))
- {
- m_natManglerRetryInterval = atoi(val.str());
- }
- }
- else if (key == "keepaliveinterval")
- {
- if (line.nextToken(&val, " ="))
- {
- m_natKeepaliveInterval = atoi(val.str());
- }
- }
- else if (key == "porttimeout")
- {
- if (line.nextToken(&val, " ="))
- {
- m_natPortTimeout = atoi(val.str());
- }
- }
- else if (key == "roundtimeout")
- {
- if (line.nextToken(&val, " ="))
- {
- m_natRoundTimeout = atoi(val.str());
- }
- }
- else
- {
- DEBUG_LOG(("Unknown key '%s' = '%s' in NAT block of GameSpy Config", key.str(), val.str()));
- }
- }
- else
- {
- DEBUG_LOG(("Key '%s' missing val in NAT block of GameSpy Config", key.str()));
- }
- }
- else if (inCustom)
- {
- line.toLower();
- AsciiString key, val;
- if (line.nextToken(&key, " =") && line.nextToken(&val, " ="))
- {
- if (key == "restricted")
- {
- m_restrictGamesToLobby = atoi(val.str());
- }
- else
- {
- DEBUG_LOG(("Unknown key '%s' = '%s' in Custom block of GameSpy Config", key.str(), val.str()));
- }
- }
- else
- {
- DEBUG_LOG(("Key '%s' missing val in Custom block of GameSpy Config", key.str()));
- }
- }
- else
- {
- m_leftoverConfig.concat(line);
- m_leftoverConfig.concat('\n');
- }
- }
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-Int GameSpyConfig::getPointsForRank(Int rank)
-{
- if (rank >= MAX_RANKS) rank = MAX_RANKS-1;
- if (rank < 0) rank = 0;
- return m_rankPoints[rank];
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-Bool GameSpyConfig::getManglerLocation(Int index, AsciiString& host, UnsignedShort& port)
-{
- if (index < 0 || index >= m_manglerHosts.size())
- {
- return FALSE;
- }
-
- host = m_manglerHosts[index];
- port = m_manglerPorts[index];
- return TRUE;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-Bool GameSpyConfig::isPlayerVIP(Int id)
-{
- std::set::const_iterator it = std::find(m_vip.begin(), m_vip.end(), id);
- return it != m_vip.end();
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp
deleted file mode 100644
index 75112dc6875..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: LadderDefs.cpp //////////////////////////////////////////////////////
-// Generals ladder code
-// Author: Matthew D. Campbell, August 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/GameSpy/ThreadUtils.h"
-#include "GameNetwork/GameSpy/LadderDefs.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/GSConfig.h"
-#include "Common/GameState.h"
-#include "Common/file.h"
-#include "Common/FileSystem.h"
-#include "Common/PlayerTemplate.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MapUtil.h"
-
-
-LadderList *TheLadderList = NULL;
-
-LadderInfo::LadderInfo()
-{
- playersPerTeam = 1;
- minWins = 0;
- maxWins = 0;
- randomMaps = TRUE;
- randomFactions = TRUE;
- validQM = TRUE;
- validCustom = FALSE;
- port = 0;
- submitReplay = FALSE;
- index = -1;
-}
-
-static LadderInfo *parseLadder(AsciiString raw)
-{
- DEBUG_LOG(("Looking at ladder:\n%s", raw.str()));
- LadderInfo *lad = NULL;
- AsciiString line;
- while (raw.nextToken(&line, "\n"))
- {
- if (line.getCharAt(line.getLength()-1) == '\r')
- line.removeLastChar(); // there is a trailing '\r'
-
- line.trim();
-
- if (line.isEmpty())
- continue;
-
- // woohoo! got a line!
- line.trim();
- if ( !lad && line.startsWith("'
- line = line.str() + 7; // the "name = MultiByteToWideCharSingleLine(tokenName.str()).c_str();
- lad->name.truncateTo(20); // Per Harvard's request, ladder names are limited to 20 chars
- lad->address = tokenAddr;
- lad->port = atoi(tokenPort.str());
- lad->homepageURL = tokenHomepage;
- }
- else if ( lad && line.startsWith("Name ") )
- {
- lad->name = MultiByteToWideCharSingleLine(line.str() + 5).c_str();
- }
- else if ( lad && line.startsWith("Desc ") )
- {
- lad->description = MultiByteToWideCharSingleLine(line.str() + 5).c_str();
- }
- else if ( lad && line.startsWith("Loc ") )
- {
- lad->location = MultiByteToWideCharSingleLine(line.str() + 4).c_str();
- }
- else if ( lad && line.startsWith("TeamSize ") )
- {
- lad->playersPerTeam = atoi(line.str() + 9);
- }
- else if ( lad && line.startsWith("RandomMaps ") )
- {
- lad->randomMaps = atoi(line.str() + 11);
- }
- else if ( lad && line.startsWith("RandomFactions ") )
- {
- lad->randomFactions = atoi(line.str() + 15);
- }
- else if ( lad && line.startsWith("Faction ") )
- {
- AsciiString faction = line.str() + 8;
- AsciiStringList outStringList;
- ThePlayerTemplateStore->getAllSideStrings(&outStringList);
-
- AsciiStringList::iterator aIt = std::find(outStringList.begin(), outStringList.end(), faction);
- if (aIt != outStringList.end())
- {
- // valid faction - now check for dupes
- aIt = std::find(lad->validFactions.begin(), lad->validFactions.end(), faction);
- if (aIt == lad->validFactions.end())
- {
- lad->validFactions.push_back(faction);
- }
- }
- }
- /*
- else if ( lad && line.startsWith("QM ") )
- {
- lad->validQM = atoi(line.str() + 3);
- }
- else if ( lad && line.startsWith("Custom ") )
- {
- lad->validCustom = atoi(line.str() + 7);
- }
- */
- else if ( lad && line.startsWith("MinWins ") )
- {
- lad->minWins = atoi(line.str() + 8);
- }
- else if ( lad && line.startsWith("MaxWins ") )
- {
- lad->maxWins = atoi(line.str() + 8);
- }
- else if ( lad && line.startsWith("CryptedPass ") )
- {
- lad->cryptedPassword = line.str() + 12;
- }
- else if ( lad && line.compare("") == 0 )
- {
- DEBUG_LOG(("Saw a ladder: name=%ls, addr=%s:%d, players=%dv%d, pass=%s, replay=%d, homepage=%s",
- lad->name.str(), lad->address.str(), lad->port, lad->playersPerTeam, lad->playersPerTeam, lad->cryptedPassword.str(),
- lad->submitReplay, lad->homepageURL.str()));
- // end of a ladder
- if (lad->playersPerTeam >= 1 && lad->playersPerTeam <= MAX_SLOTS/2)
- {
- if (lad->validFactions.size() == 0)
- {
- DEBUG_LOG(("No factions specified. Using all."));
- lad->validFactions.clear();
- Int numTemplates = ThePlayerTemplateStore->getPlayerTemplateCount();
- for ( Int i = 0; i < numTemplates; ++i )
- {
- const PlayerTemplate *pt = ThePlayerTemplateStore->getNthPlayerTemplate(i);
- if (!pt)
- continue;
-
- if (pt->isPlayableSide() && pt->getSide().compare("Boss") != 0 )
- lad->validFactions.push_back(pt->getSide());
- }
- }
- else
- {
- AsciiStringList validFactions = lad->validFactions;
- for (AsciiStringListIterator it = validFactions.begin(); it != validFactions.end(); ++it)
- {
- AsciiString faction = *it;
- AsciiString marker;
- marker.format("INI:Faction%s", faction.str());
- DEBUG_LOG(("Faction %s has marker %s corresponding to str %ls", faction.str(), marker.str(), TheGameText->fetch(marker).str()));
- }
- }
-
- if (lad->validMaps.size() == 0)
- {
- DEBUG_LOG(("No maps specified. Using all."));
- std::list qmMaps = TheGameSpyConfig->getQMMaps();
- for (std::list::const_iterator it = qmMaps.begin(); it != qmMaps.end(); ++it)
- {
- AsciiString mapName = *it;
-
- // check sizes on the maps before allowing them
- const MapMetaData *md = TheMapCache->findMap(mapName);
- if (md && md->m_numPlayers >= lad->playersPerTeam*2)
- {
- lad->validMaps.push_back(mapName);
- }
- }
- }
- return lad;
- }
- else
- {
- // no maps? don't play on it!
- delete lad;
- lad = NULL;
- return NULL;
- }
- }
- else if ( lad && line.startsWith("Map ") )
- {
- // valid map
- AsciiString mapName = line.str() + 4;
- mapName.trim();
- if (mapName.isNotEmpty())
- {
- mapName.format("%s\\%s\\%s.map", TheMapCache->getMapDir().str(), mapName.str(), mapName.str());
- mapName = TheGameState->portableMapPathToRealMapPath(TheGameState->realMapPathToPortableMapPath(mapName));
- mapName.toLower();
- std::list qmMaps = TheGameSpyConfig->getQMMaps();
- if (std::find(qmMaps.begin(), qmMaps.end(), mapName) != qmMaps.end())
- {
- // check sizes on the maps before allowing them
- const MapMetaData *md = TheMapCache->findMap(mapName);
- if (md && md->m_numPlayers >= lad->playersPerTeam*2)
- lad->validMaps.push_back(mapName);
- }
- }
- }
- else
- {
- // bad ladder - kill it
- delete lad;
- lad = NULL;
- }
- }
-
- delete lad;
- return NULL;
-}
-
-LadderList::LadderList()
-{
- //Int profile = TheGameSpyInfo->getLocalProfileID();
-
- AsciiString rawMotd = TheGameSpyConfig->getLeftoverConfig();
- AsciiString line;
- Bool inLadders = FALSE;
- Bool inSpecialLadders = FALSE;
- Bool inLadder = FALSE;
- LadderInfo *lad = NULL;
- Int index = 1;
- AsciiString rawLadder;
-
- while (rawMotd.nextToken(&line, "\n"))
- {
- if (line.getCharAt(line.getLength()-1) == '\r')
- line.removeLastChar(); // there is a trailing '\r'
-
- line.trim();
-
- if (line.isEmpty())
- continue;
-
- if (!inLadders && line.compare("") == 0)
- {
- inLadders = TRUE;
- rawLadder.clear();
- }
- else if (inLadders && line.compare("") == 0)
- {
- inLadders = FALSE;
- }
- else if (!inSpecialLadders && line.compare("") == 0)
- {
- inSpecialLadders = TRUE;
- rawLadder.clear();
- }
- else if (inSpecialLadders && line.compare("") == 0)
- {
- inSpecialLadders = FALSE;
- }
- else if (inLadders || inSpecialLadders)
- {
- if (line.startsWith("") == 0 && inLadder)
- {
- inLadder = FALSE;
- rawLadder.concat(line);
- rawLadder.concat('\n');
- if ((lad = parseLadder(rawLadder)) != NULL)
- {
- lad->index = index++;
- if (inLadders)
- {
- DEBUG_LOG(("Adding to standard ladders"));
- m_standardLadders.push_back(lad);
- }
- else
- {
- DEBUG_LOG(("Adding to special ladders"));
- m_specialLadders.push_back(lad);
- }
- }
- rawLadder.clear();
- }
- else if (inLadder)
- {
- rawLadder.concat(line);
- rawLadder.concat('\n');
- }
- }
- }
-
- // look for local ladders
- loadLocalLadders();
-
- DEBUG_LOG(("After looking for ladders, we have %d local, %d special && %d normal", m_localLadders.size(), m_specialLadders.size(), m_standardLadders.size()));
-}
-
-LadderList::~LadderList()
-{
- LadderInfoList::iterator it;
- for (it = m_specialLadders.begin(); it != m_specialLadders.end(); it = m_specialLadders.begin())
- {
- delete *it;
- m_specialLadders.pop_front();
- }
- for (it = m_standardLadders.begin(); it != m_standardLadders.end(); it = m_standardLadders.begin())
- {
- delete *it;
- m_standardLadders.pop_front();
- }
- for (it = m_localLadders.begin(); it != m_localLadders.end(); it = m_localLadders.begin())
- {
- delete *it;
- m_localLadders.pop_front();
- }
-}
-
-const LadderInfo* LadderList::findLadder( const AsciiString& addr, UnsignedShort port )
-{
- LadderInfoList::const_iterator cit;
-
- for (cit = m_specialLadders.begin(); cit != m_specialLadders.end(); ++cit)
- {
- const LadderInfo *li = *cit;
- if (li->address == addr && li->port == port)
- {
- return li;
- }
- }
-
- for (cit = m_standardLadders.begin(); cit != m_standardLadders.end(); ++cit)
- {
- const LadderInfo *li = *cit;
- if (li->address == addr && li->port == port)
- {
- return li;
- }
- }
-
- for (cit = m_localLadders.begin(); cit != m_localLadders.end(); ++cit)
- {
- const LadderInfo *li = *cit;
- if (li->address == addr && li->port == port)
- {
- return li;
- }
- }
-
- return NULL;
-}
-
-const LadderInfo* LadderList::findLadderByIndex( Int index )
-{
- if (index == 0)
- return NULL;
-
- LadderInfoList::const_iterator cit;
-
- for (cit = m_specialLadders.begin(); cit != m_specialLadders.end(); ++cit)
- {
- const LadderInfo *li = *cit;
- if (li->index == index)
- {
- return li;
- }
- }
-
- for (cit = m_standardLadders.begin(); cit != m_standardLadders.end(); ++cit)
- {
- const LadderInfo *li = *cit;
- if (li->index == index)
- {
- return li;
- }
- }
-
- for (cit = m_localLadders.begin(); cit != m_localLadders.end(); ++cit)
- {
- const LadderInfo *li = *cit;
- if (li->index == index)
- {
- return li;
- }
- }
-
- return NULL;
-}
-
-const LadderInfoList* LadderList::getSpecialLadders( void )
-{
- return &m_specialLadders;
-}
-
-const LadderInfoList* LadderList::getStandardLadders( void )
-{
- return &m_standardLadders;
-}
-
-const LadderInfoList* LadderList::getLocalLadders( void )
-{
- return &m_localLadders;
-}
-
-void LadderList::loadLocalLadders( void )
-{
- AsciiString dirname;
- dirname.format("%sGeneralsOnline\\Ladders\\", TheGlobalData->getPath_UserData().str());
- FilenameList filenameList;
- TheFileSystem->getFileListInDirectory(dirname, AsciiString("*.ini"), filenameList, TRUE);
-
- Int index = -1;
-
- FilenameList::iterator it = filenameList.begin();
- while (it != filenameList.end())
- {
- AsciiString filename = *it;
- DEBUG_LOG(("Looking at possible ladder info file '%s'", filename.str()));
- filename.toLower();
- checkLadder( filename, index-- );
- ++it;
- }
-}
-
-void LadderList::checkLadder( AsciiString fname, Int index )
-{
- File *fp = TheFileSystem->openFile(fname.str(), File::READ | File::TEXT);
- char buf[1024];
- AsciiString rawData;
- if (fp)
- {
- Int len;
- while (!fp->eof())
- {
- len = fp->read(buf, 1023);
- buf[len] = 0;
- buf[1023] = 0;
- rawData.concat(buf);
- }
- fp->close();
- fp = NULL;
- }
-
- DEBUG_LOG(("Read %d bytes from '%s'", rawData.getLength(), fname.str()));
- if (rawData.isEmpty())
- return;
-
- LadderInfo *li = parseLadder(rawData);
- if (!li)
- {
- return;
- }
-
- // sanity check
- if (li->address.isEmpty())
- {
- DEBUG_LOG(("Bailing because of li->address.isEmpty()"));
- delete li;
- return;
- }
-
- if (!li->port)
- {
- DEBUG_LOG(("Bailing because of !li->port"));
- delete li;
- return;
- }
-
- if (li->validMaps.size() == 0)
- {
- DEBUG_LOG(("Bailing because of li->validMaps.size() == 0"));
- delete li;
- return;
- }
-
- li->index = index;
-
- // ladders are QM-only at this point, which kinda invalidates the whole concept of local ladders. Oh well.
- li->validQM = FALSE; // no local ladders in QM
- li->validCustom = FALSE;
-
- //for (Int i=0; i<4; ++i)
- // fname.removeLastChar(); // remove .lad
- //li->name = UnicodeString(MultiByteToWideCharSingleLine(fname.reverseFind('\\')+1).c_str());
-
- DEBUG_LOG(("Adding local ladder %ls", li->name.str()));
- m_localLadders.push_back(li);
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp
deleted file mode 100644
index 6c11a86cd48..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp
+++ /dev/null
@@ -1,939 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: LobbyUtils.cpp
-// Author: Matthew D. Campbell, Sept 2002
-// Description: GameSpy lobby utils
-///////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/GameEngine.h"
-#include "Common/MultiplayerSettings.h"
-#include "Common/PlayerTemplate.h"
-#include "Common/version.h"
-#include "GameClient/AnimateWindowManager.h"
-#include "GameClient/WindowLayout.h"
-#include "GameClient/Gadget.h"
-#include "GameClient/Image.h"
-#include "GameClient/Shell.h"
-#include "GameClient/KeyDefs.h"
-#include "GameClient/GameWindowManager.h"
-#include "GameClient/GadgetComboBox.h"
-#include "GameClient/GadgetListBox.h"
-#include "GameClient/GadgetTextEntry.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MapUtil.h"
-#include "GameClient/MessageBox.h"
-#include "GameClient/Mouse.h"
-#include "GameNetwork/GameSpyOverlay.h"
-
-#include "GameClient/LanguageFilter.h"
-#include "GameNetwork/GameSpy/BuddyDefs.h"
-#include "GameNetwork/GameSpy/LadderDefs.h"
-#include "GameNetwork/GameSpy/LobbyUtils.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/PeerThread.h"
-#include "GameNetwork/GameSpy/PersistentStorageDefs.h"
-#include "GameNetwork/GameSpy/GSConfig.h"
-
-#include "Common/STLTypedefs.h"
-
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
-// Note: if you add more columns, you must modify the .wnd files and change the listbox properties (yuck!)
-enum {
- COLUMN_NAME = 0,
- COLUMN_MAP,
- COLUMN_LADDER,
- COLUMN_NUMPLAYERS,
- COLUMN_PASSWORD,
- COLUMN_OBSERVER,
-#if !RTS_GENERALS
- COLUMN_USE_STATS,
-#endif
- COLUMN_PING,
-};
-
-static NameKeyType buttonSortAlphaID = NAMEKEY_INVALID;
-static NameKeyType buttonSortPingID = NAMEKEY_INVALID;
-static NameKeyType buttonSortBuddiesID = NAMEKEY_INVALID;
-static NameKeyType windowSortAlphaID = NAMEKEY_INVALID;
-static NameKeyType windowSortPingID = NAMEKEY_INVALID;
-static NameKeyType windowSortBuddiesID = NAMEKEY_INVALID;
-
-static GameWindow *buttonSortAlpha = NULL;
-static GameWindow *buttonSortPing = NULL;
-static GameWindow *buttonSortBuddies = NULL;
-static GameWindow *windowSortAlpha = NULL;
-static GameWindow *windowSortPing = NULL;
-static GameWindow *windowSortBuddies = NULL;
-
-static GameSortType theGameSortType = GAMESORT_ALPHA_ASCENDING;
-static Bool sortBuddies = TRUE;
-static void showSortIcons(void)
-{
- if (windowSortAlpha && windowSortPing)
- {
- switch(theGameSortType)
- {
- case GAMESORT_ALPHA_ASCENDING:
- windowSortAlpha->winHide(FALSE);
- windowSortAlpha->winEnable(TRUE);
- windowSortPing->winHide(TRUE);
- break;
- case GAMESORT_ALPHA_DESCENDING:
- windowSortAlpha->winHide(FALSE);
- windowSortAlpha->winEnable(FALSE);
- windowSortPing->winHide(TRUE);
- break;
- case GAMESORT_PING_ASCENDING:
- windowSortPing->winHide(FALSE);
- windowSortPing->winEnable(TRUE);
- windowSortAlpha->winHide(TRUE);
- break;
- case GAMESORT_PING_DESCENDING:
- windowSortPing->winHide(FALSE);
- windowSortPing->winEnable(FALSE);
- windowSortAlpha->winHide(TRUE);
- break;
- }
- }
-
- if (sortBuddies)
- {
- if (windowSortBuddies)
- {
- windowSortBuddies->winHide(FALSE);
- }
- }
- else
- {
- if (windowSortBuddies)
- {
- windowSortBuddies->winHide(TRUE);
- }
- }
-}
-void setSortMode( GameSortType sortType ) { theGameSortType = sortType; showSortIcons(); RefreshGameListBoxes(); }
-void sortByBuddies( Bool doSort ) { sortBuddies = doSort; showSortIcons(); RefreshGameListBoxes(); }
-
-Bool HandleSortButton( NameKeyType sortButton )
-{
- if (sortButton == buttonSortBuddiesID)
- {
- sortByBuddies( !sortBuddies );
- return TRUE;
- }
- else if (sortButton == buttonSortAlphaID)
- {
- if (theGameSortType == GAMESORT_ALPHA_ASCENDING)
- {
- setSortMode(GAMESORT_ALPHA_DESCENDING);
- }
- else
- {
- setSortMode(GAMESORT_ALPHA_ASCENDING);
- }
- return TRUE;
- }
- else if (sortButton == buttonSortPingID)
- {
- if (theGameSortType == GAMESORT_PING_ASCENDING)
- {
- setSortMode(GAMESORT_PING_DESCENDING);
- }
- else
- {
- setSortMode(GAMESORT_PING_ASCENDING);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-// window ids ------------------------------------------------------------------------------
-static NameKeyType parentID = NAMEKEY_INVALID;
-//static NameKeyType parentGameListSmallID = NAMEKEY_INVALID;
-static NameKeyType parentGameListLargeID = NAMEKEY_INVALID;
-static NameKeyType listboxLobbyGamesSmallID = NAMEKEY_INVALID;
-static NameKeyType listboxLobbyGamesLargeID = NAMEKEY_INVALID;
-//static NameKeyType listboxLobbyGameInfoID = NAMEKEY_INVALID;
-
-// Window Pointers ------------------------------------------------------------------------
-static GameWindow *parent = NULL;
-//static GameWindow *parentGameListSmall = NULL;
-static GameWindow *parentGameListLarge = NULL;
- //GameWindow *listboxLobbyGamesSmall = NULL;
- GameWindow *listboxLobbyGamesLarge = NULL;
- //GameWindow *listboxLobbyGameInfo = NULL;
-
-static const Image *pingImages[3] = { NULL, NULL, NULL };
-
-static void gameTooltip(GameWindow *window,
- WinInstanceData *instData,
- UnsignedInt mouse)
-{
- Int x, y, row, col;
- x = LOLONGTOSHORT(mouse);
- y = HILONGTOSHORT(mouse);
-
- GadgetListBoxGetEntryBasedOnXY(window, x, y, row, col);
-
- if (row == -1 || col == -1)
- {
- TheMouse->setCursorTooltip( UnicodeString::TheEmptyString);//TheGameText->fetch("TOOLTIP:GamesBeingFormed") );
- return;
- }
-
- Int gameID = (Int)GadgetListBoxGetItemData(window, row, 0);
- GameSpyStagingRoom *room = TheGameSpyInfo->findStagingRoomByID(gameID);
- if (!room)
- {
- TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UnknownGame") );
- return;
- }
-
- if (col == COLUMN_PING)
- {
-#if 0 //def DEBUG_LOGGING
- UnicodeString s;
- s.format(L"Ping is %d ms (cutoffs are %d ms and %d ms\n%hs local pings\n%hs remote pings",
- room->getPingAsInt(), TheGameSpyConfig->getPingCutoffGood(), TheGameSpyConfig->getPingCutoffBad(),
- TheGameSpyInfo->getPingString().str(), room->getPingString().str()
- );
- TheMouse->setCursorTooltip( s, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values.
-#else
- TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:PingInfo"), 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values.
-#endif
- return;
- }
- if (col == COLUMN_NUMPLAYERS)
- {
- TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:NumberOfPlayers"), 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values.
- return;
- }
- if (col == COLUMN_PASSWORD)
- {
- if (room->getHasPassword())
- {
- UnicodeString checkTooltip =TheGameText->fetch("TOOTIP:Password");
- if(!checkTooltip.compare(L"Password required to joing game"))
- checkTooltip.set(L"Password required to join game");
- TheMouse->setCursorTooltip( checkTooltip, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values.
- }
- else
- TheMouse->setCursorTooltip( UnicodeString::TheEmptyString );
- return;
- }
-#if !RTS_GENERALS
- if (col == COLUMN_USE_STATS)
- {
- if ( room->getUseStats() )
- {
- TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UseStatsOn") );
- }
- else
- {
- TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UseStatsOff") );
- }
- return;
- }
-#endif
-
- UnicodeString tooltip;
-
- UnicodeString mapName;
- const MapMetaData *md = TheMapCache->findMap(room->getMap());
- if (md)
- {
- mapName = md->m_displayName;
- }
- else
- {
- const char *start = room->getMap().reverseFind('\\');
- if (start)
- {
- ++start;
- }
- else
- {
- start = room->getMap().str();
- }
- mapName.translate( start );
- }
- UnicodeString tmp;
- tooltip.format(TheGameText->fetch("TOOLTIP:GameInfoGameName"), room->getGameName().str());
- if (room->getLadderPort() != 0)
- {
- const LadderInfo *linfo = TheLadderList->findLadder(room->getLadderIP(), room->getLadderPort());
- if (linfo)
- {
- tmp.format(TheGameText->fetch("TOOLTIP:GameInfoLadderName"), linfo->name.str());
- tooltip.concat(tmp);
- }
- }
- if (room->getExeCRC() != TheGlobalData->m_exeCRC || room->getIniCRC() != TheGlobalData->m_iniCRC)
- {
- tmp.format(TheGameText->fetch("TOOLTIP:InvalidGameVersion"), mapName.str());
- tooltip.concat(tmp);
- }
- tmp.format(TheGameText->fetch("TOOLTIP:GameInfoMap"), mapName.str());
- tooltip.concat(tmp);
-
- AsciiString aPlayer;
- UnicodeString player;
- Int numPlayers = 0;
- for (Int i=0; igetGameSpySlot(i);
- if (i == 0 && (!slot || !slot->isHuman()))
- {
- DEBUG_CRASH(("About to tooltip a non-hosted game!"));
- }
- if (slot && slot->isHuman())
- {
- tmp.format(TheGameText->fetch("TOOLTIP:GameInfoPlayer"), slot->getName().str(), slot->getWins(), slot->getLosses());
- tooltip.concat(tmp);
- ++numPlayers;
- }
- else if (slot && slot->isAI())
- {
- ++numPlayers;
- switch(slot->getState())
- {
- case SLOT_EASY_AI:
- tooltip.concat(L'\n');
- tooltip.concat(TheGameText->fetch("GUI:EasyAI"));
- break;
- case SLOT_MED_AI:
- tooltip.concat(L'\n');
- tooltip.concat(TheGameText->fetch("GUI:MediumAI"));
- break;
- case SLOT_BRUTAL_AI:
- tooltip.concat(L'\n');
- tooltip.concat(TheGameText->fetch("GUI:HardAI"));
- break;
- }
- }
- }
- DEBUG_ASSERTCRASH(numPlayers, ("Tooltipping a 0-player game!"));
-
- TheMouse->setCursorTooltip( tooltip, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values.
-}
-
-static Bool isSmall = TRUE;
-
-GameWindow *GetGameListBox( void )
-{
- return listboxLobbyGamesLarge;
-}
-
-GameWindow *GetGameInfoListBox( void )
-{
- return NULL;
-}
-
-NameKeyType GetGameListBoxID( void )
-{
- return listboxLobbyGamesLargeID;
-}
-
-NameKeyType GetGameInfoListBoxID( void )
-{
- return NAMEKEY_INVALID;
-}
-
-void GrabWindowInfo( void )
-{
- isSmall = TRUE;
- parentID = NAMEKEY( "WOLCustomLobby.wnd:WOLLobbyMenuParent" );
- parent = TheWindowManager->winGetWindowFromId(NULL, parentID);
-
- pingImages[0] = TheMappedImageCollection->findImageByName("Ping03");
- pingImages[1] = TheMappedImageCollection->findImageByName("Ping02");
- pingImages[2] = TheMappedImageCollection->findImageByName("Ping01");
- DEBUG_ASSERTCRASH(pingImages[0], ("Can't find ping image!"));
- DEBUG_ASSERTCRASH(pingImages[1], ("Can't find ping image!"));
- DEBUG_ASSERTCRASH(pingImages[2], ("Can't find ping image!"));
-
-// parentGameListSmallID = NAMEKEY( "WOLCustomLobby.wnd:ParentGameListSmall" );
-// parentGameListSmall = TheWindowManager->winGetWindowFromId(NULL, parentGameListSmallID);
-
- parentGameListLargeID = NAMEKEY( "WOLCustomLobby.wnd:ParentGameListLarge" );
- parentGameListLarge = TheWindowManager->winGetWindowFromId(NULL, parentGameListLargeID);
-
- listboxLobbyGamesSmallID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGames" );
-// listboxLobbyGamesSmall = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGamesSmallID);
-// listboxLobbyGamesSmall->winSetTooltipFunc(gameTooltip);
-
- listboxLobbyGamesLargeID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGamesLarge" );
- listboxLobbyGamesLarge = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGamesLargeID);
- listboxLobbyGamesLarge->winSetTooltipFunc(gameTooltip);
-//
-// listboxLobbyGameInfoID = NAMEKEY( "WOLCustomLobby.wnd:ListboxGameInfo" );
-// listboxLobbyGameInfo = TheWindowManager->winGetWindowFromId(NULL, listboxLobbyGameInfoID);
-
- buttonSortAlphaID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortAlpha");
- buttonSortPingID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortPing");
- buttonSortBuddiesID = NAMEKEY("WOLCustomLobby.wnd:ButtonSortBuddies");
- windowSortAlphaID = NAMEKEY("WOLCustomLobby.wnd:WindowSortAlpha");
- windowSortPingID = NAMEKEY("WOLCustomLobby.wnd:WindowSortPing");
- windowSortBuddiesID = NAMEKEY("WOLCustomLobby.wnd:WindowSortBuddies");
-
- buttonSortAlpha = TheWindowManager->winGetWindowFromId(parent, buttonSortAlphaID);
- buttonSortPing = TheWindowManager->winGetWindowFromId(parent, buttonSortPingID);
- buttonSortBuddies = TheWindowManager->winGetWindowFromId(parent, buttonSortBuddiesID);
- windowSortAlpha = TheWindowManager->winGetWindowFromId(parent, windowSortAlphaID);
- windowSortPing = TheWindowManager->winGetWindowFromId(parent, windowSortPingID);
- windowSortBuddies = TheWindowManager->winGetWindowFromId(parent, windowSortBuddiesID);
-
- showSortIcons();
-}
-
-void ReleaseWindowInfo( void )
-{
- isSmall = TRUE;
- parent = NULL;
-// parentGameListSmall = NULL;
- parentGameListLarge = NULL;
-// listboxLobbyGamesSmall = NULL;
- listboxLobbyGamesLarge = NULL;
-// listboxLobbyGameInfo = NULL;
-
- buttonSortAlpha = NULL;
- buttonSortPing = NULL;
- buttonSortBuddies = NULL;
- windowSortAlpha = NULL;
- windowSortPing = NULL;
- windowSortBuddies = NULL;
-}
-
-typedef std::set BuddyGameSet;
-static BuddyGameSet *theBuddyGames = NULL;
-static void populateBuddyGames(void)
-{
- BuddyInfoMap *m = TheGameSpyInfo->getBuddyMap();
- theBuddyGames = NEW BuddyGameSet;
- if (!m)
- {
- return;
- }
- for (BuddyInfoMap::const_iterator bit = m->begin(); bit != m->end(); ++bit)
- {
- BuddyInfo info = bit->second;
- if (info.m_status == GP_STAGING)
- {
- StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList();
- for (StagingRoomMap::iterator srmIt = srm->begin(); srmIt != srm->end(); ++srmIt)
- {
- GameSpyStagingRoom *game = srmIt->second;
- game->cleanUpSlotPointers();
- const GameSpyGameSlot *slot = game->getGameSpySlot(0);
- if (slot && slot->getName() == info.m_locationString)
- {
- theBuddyGames->insert(game);
- break;
- }
- }
- }
- }
-}
-
-static void clearBuddyGames(void)
-{
- delete theBuddyGames;
- theBuddyGames = NULL;
-}
-
-struct GameSortStruct
-{
- bool operator()(GameSpyStagingRoom *g1, GameSpyStagingRoom *g2) const
- {
- // sort CRC mismatches to the bottom
- Bool g1Good = (g1->getExeCRC() != TheGlobalData->m_exeCRC || g1->getIniCRC() != TheGlobalData->m_iniCRC);
- Bool g2Good = (g1->getExeCRC() != TheGlobalData->m_exeCRC || g1->getIniCRC() != TheGlobalData->m_iniCRC);
- if ( g1Good ^ g2Good )
- {
- return g1Good;
- }
-
- // sort games with private ladders to the bottom
- Bool g1UnknownLadder = (g1->getLadderPort() && TheLadderList->findLadder(g1->getLadderIP(), g1->getLadderPort()) == NULL);
- Bool g2UnknownLadder = (g2->getLadderPort() && TheLadderList->findLadder(g2->getLadderIP(), g2->getLadderPort()) == NULL);
- if ( g1UnknownLadder ^ g2UnknownLadder )
- {
- return g2UnknownLadder;
- }
-
- // sort full games to the bottom
- Bool g1Full = (g1->getNumNonObserverPlayers() == g1->getMaxPlayers() || g1->getNumPlayers() == MAX_SLOTS);
- Bool g2Full = (g2->getNumNonObserverPlayers() == g2->getMaxPlayers() || g2->getNumPlayers() == MAX_SLOTS);
- if ( g1Full ^ g2Full )
- {
- return g2Full;
- }
-
- if (sortBuddies)
- {
- Bool g1HasBuddies = (theBuddyGames->find(g1) != theBuddyGames->end());
- Bool g2HasBuddies = (theBuddyGames->find(g2) != theBuddyGames->end());
- if ( g1HasBuddies ^ g2HasBuddies )
- {
- return g1HasBuddies;
- }
- }
-
- switch(theGameSortType)
- {
- case GAMESORT_ALPHA_ASCENDING:
- return wcsicmp(g1->getGameName().str(), g2->getGameName().str()) < 0;
- break;
- case GAMESORT_ALPHA_DESCENDING:
- return wcsicmp(g1->getGameName().str(),g2->getGameName().str()) > 0;
- break;
- case GAMESORT_PING_ASCENDING:
- return g1->getPingAsInt() < g2->getPingAsInt();
- break;
- case GAMESORT_PING_DESCENDING:
- return g1->getPingAsInt() > g2->getPingAsInt();
- break;
- }
- return false;
- }
-};
-
-static Int insertGame( GameWindow *win, GameSpyStagingRoom *game, Bool showMap )
-{
- game->cleanUpSlotPointers();
- Color gameColor = GameSpyColor[GSCOLOR_GAME];
- if (game->getNumNonObserverPlayers() == game->getMaxPlayers() || game->getNumPlayers() == MAX_SLOTS)
- {
- gameColor = GameSpyColor[GSCOLOR_GAME_FULL];
- }
- if (game->getExeCRC() != TheGlobalData->m_exeCRC || game->getIniCRC() != TheGlobalData->m_iniCRC)
- {
- gameColor = GameSpyColor[GSCOLOR_GAME_CRCMISMATCH];
- }
- UnicodeString gameName = game->getGameName();
-
- if(TheGameSpyInfo->getDisallowAsianText())
- {
- const WideChar *buff = gameName.str();
- Int length = gameName.getLength();
- for(Int i = 0; i < length; ++i)
- {
- if(buff[i] >= 256)
- return -1;
- }
- }
- else if(TheGameSpyInfo->getDisallowNonAsianText())
- {
- const WideChar *buff = gameName.str();
- Int length = gameName.getLength();
- Bool hasUnicode = FALSE;
- for(Int i = 0; i < length; ++i)
- {
- if(buff[i] >= 256)
- {
- hasUnicode = TRUE;
- break;
- }
- }
- if(!hasUnicode)
- return -1;
- }
-
-
-
- Int index = GadgetListBoxAddEntryText(win, game->getGameName(), gameColor, -1, COLUMN_NAME);
- GadgetListBoxSetItemData(win, (void *)game->getID(), index);
-
- UnicodeString s;
-
- if (showMap)
- {
- UnicodeString mapName;
- const MapMetaData *md = TheMapCache->findMap(game->getMap());
- if (md)
- {
- mapName = md->m_displayName;
- }
- else
- {
- const char *start = game->getMap().reverseFind('\\');
- if (start)
- {
- ++start;
- }
- else
- {
- start = game->getMap().str();
- }
- mapName.translate( start );
- }
- GadgetListBoxAddEntryText(win, mapName, gameColor, index, COLUMN_MAP);
-
- const LadderInfo * li = TheLadderList->findLadder(game->getLadderIP(), game->getLadderPort());
- if (li)
- {
- GadgetListBoxAddEntryText(win, li->name, gameColor, index, COLUMN_LADDER);
- }
- else if (game->getLadderPort())
- {
- GadgetListBoxAddEntryText(win, TheGameText->fetch("GUI:UnknownLadder"), gameColor, index, COLUMN_LADDER);
- }
- else
- {
- GadgetListBoxAddEntryText(win, TheGameText->fetch("GUI:NoLadder"), gameColor, index, COLUMN_LADDER);
- }
- }
- else
- {
- GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_MAP);
- GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_LADDER);
- }
-
- s.format(L"%d/%d", game->getReportedNumPlayers(), game->getReportedMaxPlayers());
- GadgetListBoxAddEntryText(win, s, gameColor, index, COLUMN_NUMPLAYERS);
-
- if (game->getHasPassword())
- {
- const Image *img = TheMappedImageCollection->findImageByName("Password");
- Int width = 10, height = 10;
- if (img)
- {
- width = img->getImageWidth();
- height = img->getImageHeight();
- }
- GadgetListBoxAddEntryImage(win, img, index, COLUMN_PASSWORD, width, height);
- }
- else
- {
- GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_PASSWORD);
- }
-
- if (game->getAllowObservers())
- {
- const Image *img = TheMappedImageCollection->findImageByName("Observer");
- GadgetListBoxAddEntryImage(win, img, index, COLUMN_OBSERVER);
- }
- else
- {
- GadgetListBoxAddEntryText(win, UnicodeString(L" "), gameColor, index, COLUMN_OBSERVER);
- }
-
-#if !RTS_GENERALS
- {
- if (game->getUseStats())
- {
- if (const Image *img = TheMappedImageCollection->findImageByName("GoodStatsIcon"))
- {
- GadgetListBoxAddEntryImage(win, img, index, COLUMN_USE_STATS, img->getImageHeight(), img->getImageWidth());
- }
- }
- }
-#endif
-
- s.format(L"%d", game->getPingAsInt());
- GadgetListBoxAddEntryText(win, s, gameColor, index, COLUMN_PING);
- Int ping = game->getPingAsInt();
- Int width = 10, height = 10;
- if (pingImages[0])
- {
- width = pingImages[0]->getImageWidth();
- height = pingImages[0]->getImageHeight();
- }
- // CLH picking an arbitrary number for our ping display
- if (ping < TheGameSpyConfig->getPingCutoffGood())
- {
- GadgetListBoxAddEntryImage(win, pingImages[0], index, COLUMN_PING, width, height);
- }
- else if (ping < TheGameSpyConfig->getPingCutoffBad())
- {
- GadgetListBoxAddEntryImage(win, pingImages[1], index, COLUMN_PING, width, height);
- }
- else
- {
- GadgetListBoxAddEntryImage(win, pingImages[2], index, COLUMN_PING, width, height);
- }
-
- return index;
-}
-
-void RefreshGameListBox( GameWindow *win, Bool showMap )
-{
- if (!win)
- return;
-
- // save off selection
- Int selectedIndex = -1;
- Int indexToSelect = -1;
- Int selectedID = 0;
- GadgetListBoxGetSelected(win, &selectedIndex);
- if (selectedIndex != -1 )
- {
- selectedID = (Int)GadgetListBoxGetItemData(win, selectedIndex);
- }
- int prevPos = GadgetListBoxGetTopVisibleEntry( win );
-
- // empty listbox
- GadgetListBoxReset(win);
-
- // sort our games
- typedef std::multiset SortedGameList;
- SortedGameList sgl;
- StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList();
- populateBuddyGames();
- for (StagingRoomMap::iterator srmIt = srm->begin(); srmIt != srm->end(); ++srmIt)
- {
- sgl.insert(srmIt->second);
- }
-
- // populate listbox
- for (SortedGameList::iterator sglIt = sgl.begin(); sglIt != sgl.end(); ++sglIt)
- {
- GameSpyStagingRoom *game = *sglIt;
- if (game)
- {
- Int index = insertGame(win, game, showMap);
- if (game->getID() == selectedID)
- {
- indexToSelect = index;
- }
- }
- }
-
- clearBuddyGames();
-
- // restore selection
- GadgetListBoxSetSelected(win, indexToSelect); // even for -1, so we can disable the 'Join Game' button
-// if(prevPos > 10)
- GadgetListBoxSetTopVisibleEntry( win, prevPos );//+ 1
-
- if (indexToSelect < 0 && selectedID)
- {
- TheWindowManager->winSetLoneWindow(NULL);
- }
-}
-
-void RefreshGameInfoListBox( GameWindow *mainWin, GameWindow *win )
-{
-// if (!mainWin || !win)
-// return;
-//
-// GadgetListBoxReset(win);
-//
-// Int selected = -1;
-// GadgetListBoxGetSelected(mainWin, &selected);
-// if (selected < 0)
-// {
-// return;
-// }
-//
-// Int selectedID = (Int)GadgetListBoxGetItemData(mainWin, selected);
-// if (selectedID < 0)
-// {
-// return;
-// }
-//
-// StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList();
-// StagingRoomMap::iterator srmIt = srm->find(selectedID);
-// if (srmIt != srm->end())
-// {
-// GameSpyStagingRoom *theRoom = srmIt->second;
-// theRoom->cleanUpSlotPointers();
-//
-// // game name
-//// GadgetListBoxAddEntryText(listboxLobbyGameInfo, theRoom->getGameName(), GameSpyColor[GSCOLOR_DEFAULT], -1);
-//
-// const LadderInfo * li = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort());
-// if (li)
-// {
-// UnicodeString tmp;
-// tmp.format(TheGameText->fetch("TOOLTIP:LadderName"), li->name.str());
-// GadgetListBoxAddEntryText(listboxLobbyGameInfo, tmp, GameSpyColor[GSCOLOR_DEFAULT], -1);
-// }
-// else if (theRoom->getLadderPort())
-// {
-// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:UnknownLadder"), GameSpyColor[GSCOLOR_DEFAULT], -1);
-// }
-// else
-// {
-// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:NoLadder"), GameSpyColor[GSCOLOR_DEFAULT], -1);
-// }
-//
-// if (theRoom->getExeCRC() != TheGlobalData->m_exeCRC || theRoom->getIniCRC() != TheGlobalData->m_iniCRC)
-// {
-// GadgetListBoxAddEntryText(listboxLobbyGameInfo, TheGameText->fetch("TOOLTIP:InvalidGameVersionSingleLine"), GameSpyColor[GSCOLOR_DEFAULT], -1);
-// }
-//
-// // map name
-// UnicodeString mapName;
-// const MapMetaData *md = TheMapCache->findMap(theRoom->getMap());
-// if (md)
-// {
-// mapName = md->m_displayName;
-// }
-// else
-// {
-// const char *start = theRoom->getMap().reverseFind('\\');
-// if (start)
-// {
-// ++start;
-// }
-// else
-// {
-// start = theRoom->getMap().str();
-// }
-// mapName.translate( start );
-// }
-//
-// GadgetListBoxAddEntryText(listboxLobbyGameInfo, mapName, GameSpyColor[GSCOLOR_DEFAULT], -1);
-//
-// // player list (rank, win/loss, side)
-// for (Int i=0; igetGameSpySlot(i);
-// if (slot && slot->isHuman())
-// {
-// UnicodeString theName, theRating, thePlayerTemplate;
-// Int colorIdx = slot->getColor();
-// theName = slot->getName();
-// theRating.format(L" (%d-%d)", slot->getWins(), slot->getLosses());
-// const PlayerTemplate * pt = ThePlayerTemplateStore->getNthPlayerTemplate(slot->getPlayerTemplate());
-// if (pt)
-// {
-// thePlayerTemplate = pt->getDisplayName();
-// }
-// else
-// {
-// thePlayerTemplate = TheGameText->fetch("GUI:Random");
-// }
-//
-// UnicodeString theText;
-// theText.format(L"%ls - %ls - %ls", theName.str(), thePlayerTemplate.str(), theRating.str());
-//
-// Int theColor = GameSpyColor[GSCOLOR_DEFAULT];
-// const MultiplayerColorDefinition *mcd = TheMultiplayerSettings->getColor(colorIdx);
-// if (mcd)
-// {
-// theColor = mcd->getColor();
-// }
-//
-// GadgetListBoxAddEntryText(listboxLobbyGameInfo, theText, theColor, -1);
-// }
-// }
-// }
-
-}
-
-void RefreshGameListBoxes( void )
-{
- GameWindow *main = GetGameListBox();
- GameWindow *info = GetGameInfoListBox();
-
- RefreshGameListBox( main, (info == NULL) );
-
- if (info)
- {
- RefreshGameInfoListBox( main, info );
- }
-}
-
-void ToggleGameListType( void )
-{
- isSmall = !isSmall;
- if(isSmall)
- {
- parentGameListLarge->winHide(TRUE);
-// parentGameListSmall->winHide(FALSE);
- }
- else
- {
- parentGameListLarge->winHide(FALSE);
-// parentGameListSmall->winHide(TRUE);
- }
-
- RefreshGameListBoxes();
-}
-
-// for use by GameWindow::winSetTooltipFunc
-// displays the Army Tooltip for the player templates
-void playerTemplateComboBoxTooltip(GameWindow *wndComboBox, WinInstanceData *instData, UnsignedInt mouse)
-{
- Int index = 0;
- GadgetComboBoxGetSelectedPos(wndComboBox, &index);
- Int templateNum = (Int)GadgetComboBoxGetItemData(wndComboBox, index);
- UnicodeString ustringTooltip;
- if (templateNum == -1)
- {
- // the "Random" template is always first
- ustringTooltip = TheGameText->fetch("TOOLTIP:BioStrategyLong_Random");
- }
- else
- {
- const PlayerTemplate *playerTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(templateNum);
- if (playerTemplate)
- {
- ustringTooltip = TheGameText->fetch(playerTemplate->getTooltip());
- }
- }
- TheMouse->setCursorTooltip(ustringTooltip);
-}
-
-// -----------------------------------------------------------------------------
-
-// for use by GameWindow::winSetTooltipFunc
-// displays the Army Tooltip for the player templates
-void playerTemplateListBoxTooltip(GameWindow *wndListBox, WinInstanceData *instData, UnsignedInt mouse)
-{
- Int x, y, row, col;
- x = LOLONGTOSHORT(mouse);
- y = HILONGTOSHORT(mouse);
- GadgetListBoxGetEntryBasedOnXY(wndListBox, x, y, row, col);
- if (row == -1 || col == -1)
- return;
-
- Int templateNum = (Int)GadgetListBoxGetItemData(wndListBox, row, col);
- UnicodeString ustringTooltip;
- if (templateNum == -1)
- {
- // the "Random" template is always first
- ustringTooltip = TheGameText->fetch("TOOLTIP:BioStrategyLong_Random");
- }
- else
- {
- const PlayerTemplate *playerTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(templateNum);
- if (playerTemplate)
- {
- ustringTooltip = TheGameText->fetch(playerTemplate->getTooltip());
- }
- }
-
- // use no tooltip delay here
- TheMouse->setCursorTooltip(ustringTooltip, 0);
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp
deleted file mode 100644
index e3db2cc3b10..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/MainMenuUtils.cpp
+++ /dev/null
@@ -1,885 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: MainMenuUtils.cpp
-// Author: Matthew D. Campbell, Sept 2002
-// Description: GameSpy version check, patch download, etc utils
-///////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include
-
-//#include "Common/Registry.h"
-#include "Common/UserPreferences.h"
-#include "Common/version.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MessageBox.h"
-#include "GameClient/Shell.h"
-#include "GameLogic/ScriptEngine.h"
-
-#include "GameClient/ShellHooks.h"
-
-#include "gamespy/ghttp/ghttp.h"
-
-#include "GameNetwork/DownloadManager.h"
-#include "GameNetwork/GameSpy/BuddyThread.h"
-#include "GameNetwork/GameSpy/MainMenuUtils.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/PeerThread.h"
-
-#include "WWDownload/Registry.h"
-#include "WWDownload/urlBuilder.h"
-
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static Bool checkingForPatchBeforeGameSpy = FALSE;
-static Int checksLeftBeforeOnline = 0;
-static Int timeThroughOnline = 0; // used to avoid having old callbacks cause problems
-static Bool mustDownloadPatch = FALSE;
-static Bool cantConnectBeforeOnline = FALSE;
-static std::list queuedDownloads;
-
-static char *MOTDBuffer = NULL;
-static char *configBuffer = NULL;
-GameWindow *onlineCancelWindow = NULL;
-
-static Bool s_asyncDNSThreadDone = TRUE;
-static Bool s_asyncDNSThreadSucceeded = FALSE;
-static Bool s_asyncDNSLookupInProgress = FALSE;
-static HANDLE s_asyncDNSThreadHandle = NULL;
-enum {
- LOOKUP_INPROGRESS,
- LOOKUP_FAILED,
- LOOKUP_SUCCEEDED,
-};
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static void startOnline( void );
-static void reallyStartPatchCheck( void );
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-// someone has hit a button allowing downloads to start
-void StartDownloadingPatches( void )
-{
- if (queuedDownloads.empty())
- {
- HandleCanceledDownload();
- return;
- }
-
- WindowLayout *layout;
- layout = TheWindowManager->winCreateLayout( AsciiString( "Menus/DownloadMenu.wnd" ) );
- layout->runInit();
- layout->hide( FALSE );
- layout->bringForward();
- HandleCanceledDownload(FALSE);
- DEBUG_ASSERTCRASH(TheDownloadManager, ("No download manager!"));
- if (TheDownloadManager)
- {
- std::list::iterator it = queuedDownloads.begin();
- while (it != queuedDownloads.end())
- {
- QueuedDownload q = *it;
- TheDownloadManager->queueFileForDownload(q.server, q.userName, q.password,
- q.file, q.localFile, q.regKey, q.tryResume);
- queuedDownloads.pop_front();
- it = queuedDownloads.begin();
- }
- TheDownloadManager->downloadNextQueuedFile();
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-// user agrees to patch before going online
-static void patchBeforeOnlineCallback( void )
-{
- StartDownloadingPatches();
-}
-
-// user doesn't want to patch before going online
-static void noPatchBeforeOnlineCallback( void )
-{
- queuedDownloads.clear();
- if (mustDownloadPatch || cantConnectBeforeOnline)
- {
- // go back to normal
- HandleCanceledDownload();
- }
- else
- {
- // clear out unneeded downloads and go on
- startOnline();
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static Bool hasWriteAccess()
-{
- const char* filename = "PatchAccessTest.txt";
-
- remove(filename);
-
- int handle = _open( filename, _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE);
- if (handle == -1)
- {
- return false;
- }
-
- _close(handle);
- remove(filename);
-
- unsigned int val;
- if (!GetUnsignedIntFromRegistry("", "Version", val))
- {
- return false;
- }
-
- if (!SetUnsignedIntInRegistry("", "Version", val))
- {
- return false;
- }
-
- return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static void startOnline( void )
-{
- checkingForPatchBeforeGameSpy = FALSE;
-
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline==0, ("starting online with pending callbacks"));
- if (onlineCancelWindow)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
-
- if (cantConnectBeforeOnline)
- {
- MessageBoxOk(TheGameText->fetch("GUI:CannotConnectToServservTitle"),
- TheGameText->fetch("GUI:CannotConnectToServserv"),
- noPatchBeforeOnlineCallback);
- return;
- }
- if (queuedDownloads.size())
- {
- if (!hasWriteAccess())
- {
- MessageBoxOk(TheGameText->fetch("GUI:Error"),
- TheGameText->fetch("GUI:MustHaveAdminRights"),
- noPatchBeforeOnlineCallback);
- }
- else if (mustDownloadPatch)
- {
- MessageBoxOkCancel(TheGameText->fetch("GUI:PatchAvailable"),
- TheGameText->fetch("GUI:MustPatchForOnline"),
- patchBeforeOnlineCallback, noPatchBeforeOnlineCallback);
- }
- else
- {
- MessageBoxYesNo(TheGameText->fetch("GUI:PatchAvailable"),
- TheGameText->fetch("GUI:CanPatchForOnline"),
- patchBeforeOnlineCallback, noPatchBeforeOnlineCallback);
- }
- return;
- }
-
- TheScriptEngine->signalUIInteract(TheShellHookNames[SHELL_SCRIPT_HOOK_MAIN_MENU_ONLINE_SELECTED]);
-
- DEBUG_ASSERTCRASH( !TheGameSpyBuddyMessageQueue, ("TheGameSpyBuddyMessageQueue exists!") );
- DEBUG_ASSERTCRASH( !TheGameSpyPeerMessageQueue, ("TheGameSpyPeerMessageQueue exists!") );
- DEBUG_ASSERTCRASH( !TheGameSpyInfo, ("TheGameSpyInfo exists!") );
- SetUpGameSpy(MOTDBuffer, configBuffer);
-
- delete[] MOTDBuffer;
- MOTDBuffer = NULL;
-
- delete[] configBuffer;
- configBuffer = NULL;
-
-#ifdef ALLOW_NON_PROFILED_LOGIN
- UserPreferences pref;
- pref.load("GameSpyLogin.ini");
- UserPreferences::const_iterator it = pref.find("useProfiles");
- if (it != pref.end() && it->second.compareNoCase("yes") == 0)
-#endif // ALLOW_NON_PROFILED_LOGIN
- TheShell->push( AsciiString("Menus/GameSpyLoginProfile.wnd") );
-#ifdef ALLOW_NON_PROFILED_LOGIN
- else
- TheShell->push( AsciiString("Menus/GameSpyLoginQuick.wnd") );
-#endif // ALLOW_NON_PROFILED_LOGIN
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static void queuePatch(Bool mandatory, AsciiString downloadURL)
-{
- QueuedDownload q;
- Bool success = TRUE;
-
- AsciiString connectionType;
- success &= downloadURL.nextToken(&connectionType, ":");
-
- AsciiString server;
- success &= downloadURL.nextToken(&server, ":/");
-
- AsciiString user;
- success &= downloadURL.nextToken(&user, ":@");
-
- AsciiString pass;
- success &= downloadURL.nextToken(&pass, "@/");
-
- AsciiString filePath;
- success &= downloadURL.nextToken(&filePath, "");
-
- if (!success && user.isNotEmpty())
- {
- // no user/pass combo - move the file into it's proper place
- filePath = user;
- user = ""; // LFeenanEA - Credentials removed as per Security requirements
- pass = "";
- success = TRUE;
- }
-
- AsciiString fileStr = filePath;
- const char *s = filePath.reverseFind('/');
- if (s)
- fileStr = s+1;
- AsciiString fileName = "patches\\";
- fileName.concat(fileStr);
-
- DEBUG_LOG(("download URL split: %d [%s] [%s] [%s] [%s] [%s] [%s]",
- success, connectionType.str(), server.str(), user.str(), pass.str(),
- filePath.str(), fileName.str()));
-
- if (!success)
- return;
-
- q.file = filePath;
- q.localFile = fileName;
- q.password = pass;
- q.regKey = "";
- q.server = server;
- q.tryResume = TRUE;
- q.userName = user;
-
- std::list::iterator it = queuedDownloads.begin();
- while (it != queuedDownloads.end())
- {
- if (it->localFile == q.localFile)
- return; // don't add it if it exists already (because we can check multiple times)
- ++it;
- }
-
- queuedDownloads.push_back(q);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static GHTTPBool motdCallback( GHTTPRequest request, GHTTPResult result,
- char * buffer, GHTTPByteCount bufferLen, void * param )
-{
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
-
- delete[] MOTDBuffer;
- MOTDBuffer = NEW char[bufferLen];
- memcpy(MOTDBuffer, buffer, bufferLen);
- MOTDBuffer[bufferLen-1] = 0;
-
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
-
- DEBUG_LOG(("------- Got MOTD before going online -------"));
- DEBUG_LOG(("%s", (MOTDBuffer)?MOTDBuffer:""));
- DEBUG_LOG(("--------------------------------------------"));
-
- if (!checksLeftBeforeOnline)
- startOnline();
-
- return GHTTPTrue;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static GHTTPBool configCallback( GHTTPRequest request, GHTTPResult result,
- char * buffer, GHTTPByteCount bufferLen, void * param )
-{
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
-
- delete[] configBuffer;
- configBuffer = NULL;
-
- if (result != GHTTPSuccess || bufferLen < 100)
- {
- if (!checkingForPatchBeforeGameSpy)
- return GHTTPTrue;
- --checksLeftBeforeOnline;
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- cantConnectBeforeOnline = TRUE;
- if (!checksLeftBeforeOnline)
- {
- startOnline();
- }
- return GHTTPTrue;
- }
-
- configBuffer = NEW char[bufferLen];
- memcpy(configBuffer, buffer, bufferLen);
- configBuffer[bufferLen-1] = 0;
-
- AsciiString fname;
- fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str());
- FILE *fp = fopen(fname.str(), "wb");
- if (fp)
- {
- fwrite(configBuffer, bufferLen, 1, fp);
- fclose(fp);
- }
-
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
-
- DEBUG_LOG(("Got Config before going online"));
-
- if (!checksLeftBeforeOnline)
- startOnline();
-
- return GHTTPTrue;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static GHTTPBool configHeadCallback( GHTTPRequest request, GHTTPResult result,
- char * buffer, GHTTPByteCount bufferLen, void * param )
-{
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
-
- DEBUG_LOG(("HTTP head resp: res=%d, len=%d, buf=[%s]", result, bufferLen, buffer));
-
- if (result == GHTTPSuccess)
- {
- DEBUG_LOG(("Headers are [%s]", ghttpGetHeaders( request )));
-
- AsciiString headers(ghttpGetHeaders( request ));
- AsciiString line;
- while (headers.nextToken(&line, "\n\r"))
- {
- AsciiString key, val;
- line.nextToken(&key, ": ");
- line.nextToken(&val, ": \r\n");
-
- if (key.compare("Content-Length") == 0 && val.isNotEmpty())
- {
- Int serverLen = atoi(val.str());
- Int fileLen = 0;
- AsciiString fname;
- fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str());
- FILE *fp = fopen(fname.str(), "rb");
- if (fp)
- {
- fseek(fp, 0, SEEK_END);
- fileLen = ftell(fp);
- fclose(fp);
- }
-
- if (serverLen == fileLen)
- {
- // we don't need to download the MOTD again
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
- if (onlineCancelWindow && !checksLeftBeforeOnline)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
-
- delete[] configBuffer;
- configBuffer = NULL;
-
- AsciiString fname;
- fname.format("%sGeneralsOnline\\Config.txt", TheGlobalData->getPath_UserData().str());
- FILE *fp = fopen(fname.str(), "rb");
- if (fp)
- {
- configBuffer = NEW char[fileLen];
- fread(configBuffer, fileLen, 1, fp);
- configBuffer[fileLen-1] = 0;
- fclose(fp);
-
- DEBUG_LOG(("Got Config before going online"));
-
- if (!checksLeftBeforeOnline)
- startOnline();
-
- return GHTTPTrue;
- }
- }
- }
- }
- }
-
- // we need to download the MOTD again
- std::string gameURL, mapURL;
- std::string configURL, motdURL;
- FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL);
- ghttpGet( configURL.c_str(), GHTTPFalse, configCallback, param );
-
- return GHTTPTrue;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static GHTTPBool gamePatchCheckCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param )
-{
- Int run = (Int)param;
- if (run != timeThroughOnline)
- {
- DEBUG_CRASH(("Old callback being called!"));
- return GHTTPTrue;
- }
-
- --checksLeftBeforeOnline;
- DEBUG_ASSERTCRASH(checksLeftBeforeOnline>=0, ("Too many callbacks"));
-
- DEBUG_LOG(("Result=%d, buffer=[%s], len=%d", result, buffer, bufferLen));
- if (result != GHTTPSuccess)
- {
- if (!checkingForPatchBeforeGameSpy)
- return GHTTPTrue;
- cantConnectBeforeOnline = TRUE;
- if (!checksLeftBeforeOnline)
- {
- startOnline();
- }
- return GHTTPTrue;
- }
-
- AsciiString message = buffer;
- AsciiString line;
- while (message.nextToken(&line, "\r\n"))
- {
- AsciiString type, req, url;
- Bool ok = TRUE;
- ok &= line.nextToken(&type, " ");
- ok &= line.nextToken(&req, " ");
- ok &= line.nextToken(&url, " ");
- if (ok && type == "patch")
- {
- DEBUG_LOG(("Saw a patch: %d/[%s]", atoi(req.str()), url.str()));
- queuePatch( atoi(req.str()), url );
- if (atoi(req.str()))
- {
- mustDownloadPatch = TRUE;
- }
- }
- else if (ok && type == "server")
- {
- }
- }
-
- if (!checksLeftBeforeOnline)
- {
- startOnline();
- }
-
- return GHTTPTrue;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void CancelPatchCheckCallbackAndReopenDropdown( void )
-{
- HandleCanceledDownload();
- CancelPatchCheckCallback();
-}
-
-void CancelPatchCheckCallback( void )
-{
- s_asyncDNSLookupInProgress = FALSE;
- HandleCanceledDownload(FALSE); // don't dropdown
- checkingForPatchBeforeGameSpy = FALSE;
- checksLeftBeforeOnline = 0;
- if (onlineCancelWindow)
- {
- TheWindowManager->winDestroy(onlineCancelWindow);
- onlineCancelWindow = NULL;
- }
- queuedDownloads.clear();
-
- delete[] MOTDBuffer;
- MOTDBuffer = NULL;
-
- delete[] configBuffer;
- configBuffer = NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static GHTTPBool overallStatsCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param )
-{
- DEBUG_LOG(("overallStatsCallback() - Result=%d, len=%d", result, bufferLen));
- if (result != GHTTPSuccess)
- {
- return GHTTPTrue;
- }
-
-#if RTS_GENERALS
- OverallStats USA, China, GLA;
- AsciiString message = buffer;
-
- Int state = STATS_MAX; // STATS_MAX == none
- AsciiString line;
- OverallStats *stats = NULL;
- while (message.nextToken(&line, "\n"))
- {
- line.trim();
- line.toLower();
- if (strstr(line.str(), "today"))
- {
- state = STATS_TODAY;
- }
- else if (strstr(line.str(), "yesterday"))
- {
- state = STATS_YESTERDAY;
- }
- else if (strstr(line.str(), "all time"))
- {
- state = STATS_ALLTIME;
- }
- else if (strstr(line.str(), "last week"))
- {
- state = STATS_LASTWEEK;
- }
- else if (state != STATS_MAX && strstr(line.str(), "usa"))
- {
- stats = &USA;
- }
- else if (state != STATS_MAX && strstr(line.str(), "china"))
- {
- stats = &China;
- }
- else if (state != STATS_MAX && strstr(line.str(), "gla"))
- {
- stats = &GLA;
- }
-
- if (stats)
- {
- AsciiString totalLine, winsLine, lossesLine;
- message.nextToken(&totalLine, "\n");
- message.nextToken(&winsLine, "\n");
- message.nextToken(&lossesLine, "\n");
- while (totalLine.isNotEmpty() && !isdigit(totalLine.getCharAt(0)))
- {
- totalLine = totalLine.str()+1;
- }
- while (winsLine.isNotEmpty() && !isdigit(winsLine.getCharAt(0)))
- {
- winsLine = winsLine.str()+1;
- }
- while (lossesLine.isNotEmpty() && !isdigit(lossesLine.getCharAt(0)))
- {
- lossesLine = lossesLine.str()+1;
- }
- if (totalLine.isNotEmpty() && winsLine.isNotEmpty() && lossesLine.isNotEmpty())
- {
- stats->wins[state] = atoi(winsLine.str());
- stats->losses[state] = atoi(lossesLine.str());
- }
-
- stats = NULL;
- }
- }
-
- HandleOverallStats(USA, China, GLA);
-#elif RTS_ZEROHOUR
- HandleOverallStats( buffer, bufferLen );
-#endif
-
- return GHTTPTrue;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static GHTTPBool numPlayersOnlineCallback( GHTTPRequest request, GHTTPResult result, char * buffer, GHTTPByteCount bufferLen, void * param )
-{
- DEBUG_LOG(("numPlayersOnlineCallback() - Result=%d, buffer=[%s], len=%d", result, buffer, bufferLen));
- if (result != GHTTPSuccess)
- {
- return GHTTPTrue;
- }
-
- AsciiString message = buffer;
- message.trim();
- const char *s = message.reverseFind('\\');
- if (!s)
- {
- return GHTTPTrue;
- }
-
- if (*s == '\\')
- ++s;
-
- DEBUG_LOG(("Message was '%s', trimmed to '%s'=%d", buffer, s, atoi(s)));
- HandleNumPlayersOnline(atoi(s));
-
- return GHTTPTrue;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void CheckOverallStats( void )
-{
-#if RTS_GENERALS
- const char *const url = "http://gamestats.gamespy.com/ccgenerals/display.html";
-#elif RTS_ZEROHOUR
- const char *const url = "http://gamestats.gamespy.com/ccgenzh/display.html";
-#endif
- ghttpGet(url, GHTTPFalse, overallStatsCallback, NULL);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void CheckNumPlayersOnline( void )
-{
-#if RTS_GENERALS
- const char *const url = "http://launch.gamespyarcade.com/software/launch/arcadecount2.dll?svcname=ccgenerals";
-#elif RTS_ZEROHOUR
- const char *const url = "http://launch.gamespyarcade.com/software/launch/arcadecount2.dll?svcname=ccgenzh";
-#endif
- ghttpGet(url, GHTTPFalse, numPlayersOnlineCallback, NULL);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-DWORD WINAPI asyncGethostbynameThreadFunc( void * szName )
-{
- HOSTENT *he = gethostbyname( (const char *)szName );
-
- if (he)
- {
- s_asyncDNSThreadSucceeded = TRUE;
- }
- else
- {
- s_asyncDNSThreadSucceeded = FALSE;
- }
-
- s_asyncDNSThreadDone = TRUE;
- return 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-int asyncGethostbyname(char * szName)
-{
- static int stat = 0;
- static unsigned long threadid;
-
- if( stat == 0 )
- {
- /* Kick off gethostname thread */
- s_asyncDNSThreadDone = FALSE;
- s_asyncDNSThreadHandle = CreateThread( NULL, 0, asyncGethostbynameThreadFunc, szName, 0, &threadid );
-
- if( s_asyncDNSThreadHandle == NULL )
- {
- return( LOOKUP_FAILED );
- }
- stat = 1;
- }
- if( stat == 1 )
- {
- if( s_asyncDNSThreadDone )
- {
- /* Thread finished */
- stat = 0;
- s_asyncDNSLookupInProgress = FALSE;
- s_asyncDNSThreadHandle = NULL;
- return( (s_asyncDNSThreadSucceeded)?LOOKUP_SUCCEEDED:LOOKUP_FAILED );
- }
- }
-
- return( LOOKUP_INPROGRESS );
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-// GameSpy's HTTP SDK has had at least 1 crash bug, so we're going to just bail and
-// never try again if they crash us. We won't be able to get back online again (we'll
-// time out) but at least we'll live.
-static Bool isHttpOk = TRUE;
-
-void HTTPThinkWrapper( void )
-{
- if (s_asyncDNSLookupInProgress)
- {
- Char hostname[] = "servserv.generals.ea.com";
- Int ret = asyncGethostbyname(hostname);
- switch(ret)
- {
- case LOOKUP_FAILED:
- cantConnectBeforeOnline = TRUE;
- startOnline();
- break;
- case LOOKUP_SUCCEEDED:
- reallyStartPatchCheck();
- break;
- }
- }
-
- if (isHttpOk)
- {
- try
- {
- ghttpThink();
- }
- catch (...)
- {
- isHttpOk = FALSE; // we can't abort the login, since we might be done with the
- // required checks and are fetching extras. If it is a required
- // check, we'll time out normally.
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void StopAsyncDNSCheck( void )
-{
- if (s_asyncDNSThreadHandle)
- {
-#ifdef DEBUG_CRASHING
- Int res =
-#endif
- TerminateThread(s_asyncDNSThreadHandle,0);
- DEBUG_ASSERTCRASH(res, ("Could not terminate the Async DNS Lookup thread!")); // Thread still not killed!
- }
- s_asyncDNSThreadHandle = NULL;
- s_asyncDNSLookupInProgress = FALSE;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-void StartPatchCheck( void )
-{
- checkingForPatchBeforeGameSpy = TRUE;
- cantConnectBeforeOnline = FALSE;
- timeThroughOnline++;
- checksLeftBeforeOnline = 0;
-
- onlineCancelWindow = MessageBoxCancel(TheGameText->fetch("GUI:CheckingForPatches"),
- TheGameText->fetch("GUI:CheckingForPatches"), CancelPatchCheckCallbackAndReopenDropdown);
-
- s_asyncDNSLookupInProgress = TRUE;
- Char hostname[] = "servserv.generals.ea.com";
- Int ret = asyncGethostbyname(hostname);
- switch(ret)
- {
- case LOOKUP_FAILED:
- cantConnectBeforeOnline = TRUE;
- startOnline();
- break;
- case LOOKUP_SUCCEEDED:
- reallyStartPatchCheck();
- break;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
-
-static void reallyStartPatchCheck( void )
-{
- checksLeftBeforeOnline = 4;
-
- std::string gameURL, mapURL;
- std::string configURL, motdURL;
-
- FormatURLFromRegistry(gameURL, mapURL, configURL, motdURL);
-
- std::string proxy;
- if (GetStringFromRegistry("", "Proxy", proxy))
- {
- if (!proxy.empty())
- {
- ghttpSetProxy(proxy.c_str());
- }
- }
-
- // check for a patch first
- DEBUG_LOG(("Game patch check: [%s]", gameURL.c_str()));
- DEBUG_LOG(("Map patch check: [%s]", mapURL.c_str()));
- DEBUG_LOG(("Config: [%s]", configURL.c_str()));
- DEBUG_LOG(("MOTD: [%s]", motdURL.c_str()));
- ghttpGet(gameURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline);
- ghttpGet(mapURL.c_str(), GHTTPFalse, gamePatchCheckCallback, (void *)timeThroughOnline);
- ghttpHead(configURL.c_str(), GHTTPFalse, configHeadCallback, (void *)timeThroughOnline);
- ghttpGet(motdURL.c_str(), GHTTPFalse, motdCallback, (void *)timeThroughOnline);
-
- // check total game stats
- CheckOverallStats();
-
- // check the users online
- CheckNumPlayersOnline();
-}
-
-///////////////////////////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp
deleted file mode 100644
index fc540e92468..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/PeerDefs.cpp
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-// FILE: PeerDefs.cpp //////////////////////////////////////////////////////
-// Generals GameSpy Peer (chat) definitions
-// Author: Matthew D. Campbell, June 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-#include
-
-#include "Common/GameState.h"
-#include "Common/RandomValue.h"
-#include "Common/IgnorePreferences.h"
-#include "Common/CustomMatchPreferences.h"
-#include "Common/GameSpyMiscPreferences.h"
-#include "Common/Recorder.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "Common/PlayerTemplate.h"
-#include "GameClient/MapUtil.h"
-#include "GameClient/ShellHooks.h"
-#include "GameClient/GameText.h"
-#include "GameNetwork/GameSpy/LadderDefs.h"
-#include "GameNetwork/GameSpy/PeerDefsImplementation.h"
-#include "GameNetwork/GameSpy/BuddyThread.h"
-#include "GameNetwork/GameSpy/PeerThread.h"
-#include "GameNetwork/GameSpy/PingThread.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-#include "GameNetwork/GameSpy/GSConfig.h"
-#include "GameNetwork/GameSpyOverlay.h"
-#include "GameNetwork/RankPointValue.h"
-#include "GameLogic/GameLogic.h"
-
-
-GameSpyInfoInterface *TheGameSpyInfo = NULL;
-extern GameSpyStagingRoom *TheGameSpyGame = NULL;
-void deleteNotificationBox( void );
-
-bool AsciiComparator::operator()(AsciiString s1, AsciiString s2) const
-{
- return stricmp(s1.str(), s2.str()) < 0;
-}
-
-GameSpyInfo::GameSpyInfo()
-{
- reset();
- TheGameSpyGame = &m_localStagingRoom;
- m_isDisconAfterGameStart = FALSE;
-}
-
-GameSpyInfo::~GameSpyInfo()
-{
- TheGameSpyGame = NULL;
- reset();
-}
-
-void GameSpyInfo::reset( void )
-{
- m_sawFullGameList = FALSE;
- m_isDisconAfterGameStart = FALSE;
- m_currentGroupRoomID = 0;
- clearGroupRoomList();
- clearStagingRoomList();
- m_localStagingRoomID = 0;
- m_buddyRequestMap.clear();
- m_buddyMap.clear();
- m_buddyMessages.clear();
- m_joinedStagingRoom = 0;
- m_isHosting = false;
- m_localStagingRoomID = 0;
- m_localStagingRoom.reset();
- m_gotGroupRoomList = false;
- m_localName = "";
- m_localProfileID = 0;
- m_maxMessagesPerUpdate = 100;
-
- // Added By Sadullah Nader
- // Initialization missing and needed
- m_disallowAsainText = FALSE;
- m_disallowNonAsianText = FALSE;
- m_disconReason = 0;
- m_localBaseName.clear();
- m_localEmail.clear();
- m_localPasswd.clear();
- m_pingString.clear();
- m_rawConfig.clear();
- m_rawMotd.clear();
- //
-
- m_internalIP = m_externalIP = 0;
-
- m_savedIgnoreMap.clear();
- m_preorderPlayers.clear();
-
- m_cachedLocalPlayerStats.reset();
-
- m_additionalDisconnects = -1;
-}
-
-Bool GameSpyInfo::didPlayerPreorder( Int profileID ) const
-{
- std::set::const_iterator it = m_preorderPlayers.find(profileID);
- return (it != m_preorderPlayers.end());
-}
-
-void GameSpyInfo::markPlayerAsPreorder( Int profileID )
-{
- m_preorderPlayers.insert(profileID);
-}
-
-void GameSpyInfo::setLocalIPs(UnsignedInt internalIP, UnsignedInt externalIP)
-{
- m_internalIP = internalIP;
- m_externalIP = externalIP;
-}
-
-void GameSpyInfo::readAdditionalDisconnects( void )
-{
- m_additionalDisconnects = GetAdditionalDisconnectsFromUserFile(m_localProfileID);
- DEBUG_LOG(("GameSpyInfo::readAdditionalDisconnects() found %d disconnects.", m_additionalDisconnects));
-}
-
-Int GameSpyInfo::getAdditionalDisconnects( void )
-{
- DEBUG_LOG(("GameSpyInfo::getAdditionalDisconnects() would have returned %d. Returning 0 instead.", m_additionalDisconnects));
- return 0;
-}
-
-void GameSpyInfo::clearAdditionalDisconnects( void )
-{
- m_additionalDisconnects = 0;
-}
-
-GameSpyInfoInterface* GameSpyInfoInterface::createNewGameSpyInfoInterface( void )
-{
- return NEW GameSpyInfo;
-}
-
-Bool GameSpyInfo::amIHost( void )
-{
- return m_isHosting;
-}
-
-GameSpyStagingRoom* GameSpyInfo::getCurrentStagingRoom( void )
-{
- if (m_isHosting || m_joinedStagingRoom)
- return &m_localStagingRoom;
-
- StagingRoomMap::iterator it = m_stagingRooms.find(m_joinedStagingRoom);
- if (it != m_stagingRooms.end())
- return it->second;
-
- return NULL;
-}
-
-void GameSpyInfo::setGameOptions( void )
-{
- if (!m_isHosting)
- return;
-
- // set options for game lists, and UTM players in-game
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_SETGAMEOPTIONS;
- req.options = GameInfoToAsciiString(&m_localStagingRoom).str();
-
- Int i;
- AsciiString mapName = TheGameState->realMapPathToPortableMapPath(m_localStagingRoom.getMap());
- AsciiString newMapName;
- for (i=0; igetGameSpySlot(i);
- req.gameOptsPlayerNames[i] = "";
- if (!slot->isOccupied())
- {
- if (slot->isOpen())
- ++numOpenSlots;
- }
- else
- {
- AsciiString playerName;
- if (slot->isHuman())
- {
- playerName.translate(slot->getName());
- req.gameOptsPlayerNames[i] = playerName.str();
- PlayerInfoMap::iterator it = m_playerInfoMap.find(playerName);
- if (it != m_playerInfoMap.end())
- {
- wins = it->second.m_wins;
- losses = it->second.m_losses;
- profileID = it->second.m_profileID;
- }
- req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = wins;
- req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = losses;
- req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = profileID;
- req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate();
- req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor();
- if (slot->getPlayerTemplate() == PLAYERTEMPLATE_OBSERVER)
- {
- ++req.gameOptions.numObservers;
- }
- else
- {
- ++req.gameOptions.numPlayers;
- }
- }
- else if (slot->isAI())
- {
- // add in AI players
- switch (slot->getState())
- {
- case SLOT_EASY_AI:
- playerName = "CE";
- break;
- case SLOT_MED_AI:
- playerName = "CM";
- break;
- case SLOT_BRUTAL_AI:
- playerName = "CH";
- break;
- }
- req.gameOptsPlayerNames[i] = playerName.str(); // name is unused - we go off of the profileID
- req.gameOptions.wins[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0;
- req.gameOptions.losses[req.gameOptions.numObservers+req.gameOptions.numPlayers] = 0;
- req.gameOptions.profileID[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getState();
- req.gameOptions.faction[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getPlayerTemplate();
- req.gameOptions.color[req.gameOptions.numObservers+req.gameOptions.numPlayers] = slot->getColor();
- ++req.gameOptions.numPlayers;
- }
- }
- }
- req.gameOptions.maxPlayers = numOpenSlots + req.gameOptions.numPlayers + req.gameOptions.numObservers;
- TheGameSpyPeerMessageQueue->addRequest(req);
-
- req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM;
- req.UTM.isStagingRoom = TRUE;
- req.id = "Pings/";
- AsciiString pings;
- for (i=0; igetGameSpySlot(i);
- if (slot && slot->isHuman())
- {
- pings.concat(slot->getPingString());
- }
- else
- {
- pings.concat("0");
- }
- }
- req.options = pings.str();
- TheGameSpyPeerMessageQueue->addRequest(req);
-}
-
-Bool GameSpyInfo::isBuddy( Int id )
-{
- return m_buddyMap.find(id) != m_buddyMap.end();
-}
-
-void GameSpyInfo::addGroupRoom( GameSpyGroupRoom room )
-{
- if (room.m_groupID == 0)
- {
- m_gotGroupRoomList = TRUE;
-
- GroupRoomMap::iterator iter;
-
- // figure out how many good strings we've got
- std::vector names;
- Int numRooms = 0;
- for (iter = getGroupRoomList()->begin(); iter != getGroupRoomList()->end(); ++iter)
- {
- GameSpyGroupRoom room = iter->second;
- if (room.m_groupID != TheGameSpyConfig->getQMChannel())
- {
- ++numRooms;
-
- AsciiString groupLabel;
- groupLabel.format("GUI:%s", room.m_name.str());
-
- Bool exists = FALSE;
- UnicodeString groupName = TheGameText->fetch(groupLabel, &exists);
- if (exists)
- {
- names.push_back(groupName);
- }
- }
- }
-
- if (!names.empty() && names.size() != numRooms)
- {
- // didn't get all names. fix up
- Int nameIndex = 0;
- Int timesThrough = 1; // start with USA Lobby 1
- for (iter = TheGameSpyInfo->getGroupRoomList()->begin(); iter != TheGameSpyInfo->getGroupRoomList()->end(); ++iter)
- {
- GameSpyGroupRoom room = iter->second;
- if (room.m_groupID != TheGameSpyConfig->getQMChannel())
- {
- room.m_translatedName.format(L"%ls %d", names[nameIndex].str(), timesThrough);
- nameIndex = (nameIndex+1)%names.size();
- m_groupRooms[room.m_groupID] = room;
- if (!nameIndex)
- {
- // we've looped through the name list already. increment the timesThrough counter
- ++timesThrough;
- }
- }
- }
- }
- }
- else
- {
- DEBUG_LOG(("Adding group room %d (%s)", room.m_groupID, room.m_name.str()));
- AsciiString groupLabel;
- groupLabel.format("GUI:%s", room.m_name.str());
- room.m_translatedName = TheGameText->fetch(groupLabel);
- m_groupRooms[room.m_groupID] = room;
- if ( !stricmp("quickmatch", room.m_name.str()) )
- {
- DEBUG_LOG(("Group room %d (%s) is the QuickMatch room", room.m_groupID, room.m_name.str()));
- TheGameSpyConfig->setQMChannel(room.m_groupID);
- }
- }
-}
-
-void GameSpyInfo::joinGroupRoom( Int groupID )
-{
- if (groupID > 0)
- {
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM;
- req.groupRoom.id = groupID;
- TheGameSpyPeerMessageQueue->addRequest(req);
- m_playerInfoMap.clear();
- }
-}
-
-void GameSpyInfo::leaveGroupRoom( void )
-{
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_LEAVEGROUPROOM;
- TheGameSpyPeerMessageQueue->addRequest(req);
- setCurrentGroupRoom(0);
- m_playerInfoMap.clear();
-}
-
-void GameSpyInfo::joinBestGroupRoom( void )
-{
- if (m_currentGroupRoomID)
- {
- DEBUG_LOG(("Bailing from GameSpyInfo::joinBestGroupRoom() - we were already in a room"));
- m_currentGroupRoomID = 0;
- return;
- }
-
- if (m_groupRooms.size())
- {
- int minID = -1;
- int minPlayers = 1000;
- GroupRoomMap::iterator iter = m_groupRooms.begin();
- while (iter != m_groupRooms.end())
- {
- GameSpyGroupRoom room = iter->second;
- DEBUG_LOG(("Group room %d: %s (%d, %d, %d, %d)", room.m_groupID, room.m_name.str(), room.m_numWaiting, room.m_maxWaiting,
- room.m_numGames, room.m_numPlaying));
-
- if (TheGameSpyConfig->getQMChannel() != room.m_groupID && minPlayers > 25 && room.m_numWaiting < minPlayers)
- {
- minID = room.m_groupID;
- minPlayers = room.m_numWaiting;
- }
-
- ++iter;
- }
-
- if (minID > 0)
- {
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_JOINGROUPROOM;
- req.groupRoom.id = minID;
- TheGameSpyPeerMessageQueue->addRequest(req);
- m_playerInfoMap.clear();
- }
- else
- {
- GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL);
- }
- }
- else
- {
- GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:GSGroupRoomJoinFail"), NULL);
- }
-}
-
-void GameSpyInfo::updatePlayerInfo( PlayerInfo pi, AsciiString oldNick )
-{
- if (!oldNick.isEmpty())
- playerLeftGroupRoom(oldNick);
-
- m_playerInfoMap[pi.m_name] = pi;
-
- if (pi.m_preorder != 0)
- markPlayerAsPreorder(pi.m_profileID);
-}
-
-void GameSpyInfo::playerLeftGroupRoom( AsciiString nick )
-{
- PlayerInfoMap::iterator it = m_playerInfoMap.find(nick);
- if (it != m_playerInfoMap.end())
- {
- m_playerInfoMap.erase(it);
- }
-}
-
-void GameSpyInfo::clearStagingRoomList( void )
-{
- Int numRoomsRemoved = 0;
- m_sawFullGameList = FALSE;
- m_stagingRoomsDirty = FALSE;
-
- StagingRoomMap::iterator it = m_stagingRooms.begin();
- while (it != m_stagingRooms.end())
- {
- ++numRoomsRemoved;
-
- delete it->second;
- m_stagingRooms.erase(it);
- it = m_stagingRooms.begin();
- }
- if (numRoomsRemoved > 0)
- {
- //m_stagingRoomsDirty = true; // only consider ourselves dirty if we actually removed some games.
- }
-}
-
-void GameSpyInfo::addStagingRoom( GameSpyStagingRoom room )
-{
- removeStagingRoom(room);
- GameSpyStagingRoom *newRoom = NEW GameSpyStagingRoom;
- *newRoom = room;
- newRoom->cleanUpSlotPointers();
- m_stagingRooms[room.getID()] = newRoom;
- m_stagingRoomsDirty = m_sawFullGameList;
-}
-
-void GameSpyInfo::updateStagingRoom( GameSpyStagingRoom room )
-{
- addStagingRoom(room);
-}
-
-void GameSpyInfo::removeStagingRoom( GameSpyStagingRoom room )
-{
- StagingRoomMap::iterator it = m_stagingRooms.find(room.getID());
- if (it != m_stagingRooms.end())
- {
- delete it->second;
- m_stagingRooms.erase(it);
-
- m_stagingRoomsDirty = m_sawFullGameList;
- }
-}
-
-Bool GameSpyInfo::hasStagingRoomListChanged( void )
-{
- Bool val = m_stagingRoomsDirty;
- m_stagingRoomsDirty = false;
- return val;
-}
-
-GameSpyStagingRoom* GameSpyInfo::findStagingRoomByID( Int id )
-{
- StagingRoomMap::iterator it = m_stagingRooms.find(id);
- if (it != m_stagingRooms.end())
- return it->second;
-
- return NULL;
-}
-
-void GameSpyInfo::leaveStagingRoom( void )
-{
- m_localStagingRoomID = 0;
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_LEAVESTAGINGROOM;
- TheGameSpyPeerMessageQueue->addRequest(req);
- m_playerInfoMap.clear();
- m_joinedStagingRoom = FALSE;
- m_isHosting = FALSE;
-}
-
-void GameSpyInfo::markAsStagingRoomHost( void )
-{
- m_localStagingRoomID = 0;
- m_joinedStagingRoom = FALSE; m_isHosting = TRUE;
-
- // There are a few options we don't want to reset when we are hosting (they carry over
- // from the the create game dialog).
- // Interesting fact: oldFactionsOnly will be carried over correctly if I remove these
- // lines. UseStats won't be. I have no idea why.
- Int useStats = m_localStagingRoom.getUseStats();
- Bool oldFactionsOnly = m_localStagingRoom.oldFactionsOnly();
-
- m_localStagingRoom.reset();
- m_localStagingRoom.enterGame();
- m_localStagingRoom.setSeed(GetTickCount());
-
- m_localStagingRoom.setUseStats( useStats );
- m_localStagingRoom.setOldFactionsOnly( oldFactionsOnly );
-
- GameSlot newSlot;
- UnicodeString uName;
- uName.translate(m_localName);
- newSlot.setState(SLOT_PLAYER, uName);
-
- m_localStagingRoom.setLocalIP(m_externalIP);
- newSlot.setIP(m_externalIP);
-
- m_localStagingRoom.setSlot(0,newSlot);
- m_localStagingRoom.setLocalName(m_localName);
-
- TheMapCache->updateCache();
- m_localStagingRoom.setMap(getDefaultMap(TRUE));
- m_localStagingRoom.adjustSlotsForMap(); // close slots that the map can't hold. BGC
-}
-
-void GameSpyInfo::markAsStagingRoomJoiner( Int game )
-{
- m_localStagingRoomID = game;
- m_joinedStagingRoom = TRUE; m_isHosting = FALSE;
- m_localStagingRoom.reset();
- m_localStagingRoom.enterGame();
- StagingRoomMap::iterator it = m_stagingRooms.find(game);
- if (it != m_stagingRooms.end())
- {
- GameSpyStagingRoom *info = it->second;
- info->cleanUpSlotPointers();
- AsciiString options = GameInfoToAsciiString(info);
-#ifdef DEBUG_CRASHING
- Bool res =
-#endif
- ParseAsciiStringToGameInfo(&m_localStagingRoom, options);
- DEBUG_ASSERTCRASH(res, ("Could not parse game info \"%s\"", options.str()));
- m_localStagingRoom.setInGame();
- m_localStagingRoom.setLocalName(m_localName);
- m_localStagingRoom.setExeCRC(info->getExeCRC());
- m_localStagingRoom.setIniCRC(info->getIniCRC());
- m_localStagingRoom.setAllowObservers(info->getAllowObservers());
- m_localStagingRoom.setHasPassword(info->getHasPassword());
- m_localStagingRoom.setGameName(info->getGameName());
- DEBUG_LOG(("Joining game: host is %ls", m_localStagingRoom.getConstSlot(0)->getName().str()));
- }
-}
-
-void GameSpyInfo::setMOTD( const AsciiString& motd )
-{
- m_rawMotd = motd;
-}
-
-const AsciiString& GameSpyInfo::getMOTD( void )
-{
- return m_rawMotd;
-}
-
-void GameSpyInfo::setConfig( const AsciiString& config )
-{
- m_rawConfig = config;
-}
-
-const AsciiString& GameSpyInfo::getConfig( void )
-{
- return m_rawConfig;
-}
-
-// --------------------------------------------------------------
-void SetUpGameSpy( const char *motdBuffer, const char *configBuffer )
-{
- if (!motdBuffer)
- motdBuffer = "";
- if (!configBuffer)
- configBuffer = "";
- TearDownGameSpy();
-
- AsciiString dir = TheGlobalData->getPath_UserData();
- CreateDirectory(dir.str(), NULL);
- dir.format("%sGeneralsOnline", TheGlobalData->getPath_UserData().str());
- CreateDirectory(dir.str(), NULL);
- dir.format("%sGeneralsOnline\\Ladders", TheGlobalData->getPath_UserData().str());
- CreateDirectory(dir.str(), NULL);
-
- TheGameSpyBuddyMessageQueue = GameSpyBuddyMessageQueueInterface::createNewMessageQueue();
- TheGameSpyBuddyMessageQueue->startThread();
-
- TheGameSpyPeerMessageQueue = GameSpyPeerMessageQueueInterface::createNewMessageQueue();
- TheGameSpyPeerMessageQueue->startThread();
-
- TheGameSpyPSMessageQueue = GameSpyPSMessageQueueInterface::createNewMessageQueue();
- TheGameSpyPSMessageQueue->startThread();
-
- /*
- TheGameSpyGame = NEW GameSpyStagingRoom;
- */
-
- TheGameSpyInfo = GameSpyInfoInterface::createNewGameSpyInfoInterface();
- TheGameSpyInfo->setMOTD(motdBuffer);
- TheGameSpyInfo->setConfig(configBuffer);
-
- CustomMatchPreferences pref;
- TheGameSpyInfo->setDisallowAsianText(pref.getDisallowAsianText());
- TheGameSpyInfo->setDisallowNonAsianText( pref.getDisallowNonAsianText());
-
-
- TheGameSpyConfig = GameSpyConfigInterface::create(configBuffer);
-
- TheLadderList = NEW LadderList;
-
- ThePinger = PingerInterface::createNewPingerInterface();
- ThePinger->startThreads();
-
- TheRankPointValues = NEW RankPoints;
-}
-
-void TearDownGameSpy( void )
-{
- // save off cached stats
- if (TheGameSpyInfo && TheGameSpyInfo->getLocalProfileID())
- {
-// /* This was done on the score screen, so there is no need to do it now.
-// *
- PSPlayerStats localPSStats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID());
- if (localPSStats.id != 0)
- {
- GameSpyMiscPreferences mPref;
- mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(localPSStats).c_str());
- mPref.write();
- }
-// */
- }
-
- // End our threads before we kill off the singletons they reference. No crashy-crash for you!
- if (TheGameSpyPSMessageQueue)
- TheGameSpyPSMessageQueue->endThread();
- if (TheGameSpyBuddyMessageQueue)
- TheGameSpyBuddyMessageQueue->endThread();
- if (TheGameSpyPeerMessageQueue)
- TheGameSpyPeerMessageQueue->endThread();
- if (ThePinger)
- ThePinger->endThreads();
-
- delete TheRankPointValues;
- TheRankPointValues = NULL;
-
- delete TheGameSpyPSMessageQueue;
- TheGameSpyPSMessageQueue = NULL;
-
- delete TheGameSpyBuddyMessageQueue;
- TheGameSpyBuddyMessageQueue = NULL;
-
- delete TheGameSpyPeerMessageQueue;
- TheGameSpyPeerMessageQueue = NULL;
-
- if (TheGameSpyInfo)
- {
- if (TheGameSpyInfo->getInternalIP())
- {
- // we've logged in before. mark us as logging out.
- SignalUIInteraction(SHELL_SCRIPT_HOOK_GENERALS_ONLINE_LOGOUT);
- }
- delete TheGameSpyInfo;
- TheGameSpyInfo = NULL;
- }
-
- delete ThePinger;
- ThePinger = NULL;
-
- delete TheLadderList;
- TheLadderList = NULL;
-
- delete TheGameSpyConfig;
- TheGameSpyConfig = NULL;
-
- // make sure the notification box doesn't exist
- deleteNotificationBox();
-}
-
-
-void GameSpyInfo::addToIgnoreList( AsciiString nick )
-{
- m_ignoreList.insert(nick);
-}
-
-void GameSpyInfo::removeFromIgnoreList( AsciiString nick )
-{
- m_ignoreList.erase(nick);
-}
-
-Bool GameSpyInfo::isIgnored( AsciiString nick )
-{
- return m_ignoreList.find(nick) != m_ignoreList.end();
-}
-
-IgnoreList GameSpyInfo::returnIgnoreList( void )
-{
- return m_ignoreList;
-}
-
-void GameSpyInfo::addToSavedIgnoreList( Int profileID, AsciiString nick)
-{
- m_savedIgnoreMap[profileID] = nick;
- IgnorePreferences pref;
- pref.setIgnore(nick, profileID, true);
- pref.write();
-}
-
-void GameSpyInfo::removeFromSavedIgnoreList( Int profileID )
-{
- m_savedIgnoreMap.erase(profileID);
- IgnorePreferences pref;
- pref.setIgnore(AsciiString::TheEmptyString, profileID, false);
- pref.write();
-}
-
-Bool GameSpyInfo::isSavedIgnored( Int profileID )
-{
- return m_savedIgnoreMap.find(profileID) != m_savedIgnoreMap.end();
-}
-
-SavedIgnoreMap GameSpyInfo::returnSavedIgnoreList( void )
-{
- return m_savedIgnoreMap;
-}
-
-static Int grabHexInt(const char *s)
-{
- char tmp[5] = "0xff";
- tmp[2] = s[0];
- tmp[3] = s[1];
- Int b = strtol(tmp, NULL, 16);
- return b;
-}
-
-Int GameSpyInfo::getPingValue( const AsciiString& otherPing )
-{
- if (m_pingString.getLength() != otherPing.getLength())
- {
- return TheGameSpyConfig->getPingTimeoutInMs();
- }
-
- if (m_pingString.getLength() % 2 != 0)
- {
- return TheGameSpyConfig->getPingTimeoutInMs();
- }
-
- Int best = 255+255;
- const char *myStr = m_pingString.str();
- const char *otherStr = otherPing.str();
-
- while (*myStr)
- {
- Int myVal = grabHexInt(myStr);
- Int otherVal = grabHexInt(otherStr);
- Int val = myVal + otherVal;
- best = (val < best) ? val : best;
- myStr += 2;
- otherStr += 2;
- }
-
- return best * TheGameSpyConfig->getPingTimeoutInMs() / (255+255);
-}
-
-Bool PlayerInfo::isIgnored( void )
-{
- return (m_profileID)?TheGameSpyInfo->isSavedIgnored(m_profileID):TheGameSpyInfo->isIgnored(m_name);
-}
-
-void GameSpyInfo::loadSavedIgnoreList( void )
-{
- m_savedIgnoreMap.clear();
- IgnorePreferences prefs;
- m_savedIgnoreMap = prefs.getIgnores();
-}
-
-void GameSpyInfo::setDisallowAsianText( Bool val )
-{
- m_disallowAsainText = val;
-}
-
-void GameSpyInfo::setDisallowNonAsianText( Bool val )
-{
- m_disallowNonAsianText = val;
-}
-
-Bool GameSpyInfo::getDisallowAsianText( void )
-{
- return m_disallowAsainText;
-}
-Bool GameSpyInfo::getDisallowNonAsianText(void )
-{
- return m_disallowNonAsianText;
-}
-
-void GameSpyInfo::setMaxMessagesPerUpdate( Int num )
-{
- m_maxMessagesPerUpdate = num;
-}
-
-Int GameSpyInfo::getMaxMessagesPerUpdate( void )
-{
- return m_maxMessagesPerUpdate;
-}
-
-/**This function is used to force an update of player's gamespy stats with an additional
-disconnection. This is used upon starting a new game so that if user disconnects prior
-to finishing game, the disconnection stays on the server. If he completes the game, we
-remove this extra disconnection inside of populatePlayerInfo() on the ScoreScreen. This
-seems like the only secure way to handle this issue since users can abort the process
-before we can detect/log disconnections.*/
-void GameSpyInfo::updateAdditionalGameSpyDisconnections(Int count)
-{
- if (TheRecorder->isMultiplayer() && TheGameLogic->isInInternetGame() && TheGameSpyGame && TheGameSpyGame->getUseStats())
- {
- Int localID = TheGameSpyInfo->getLocalProfileID();
- PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(localID);
-
- Player *player=ThePlayerList->getLocalPlayer();
-
- Int ptIdx;
- const PlayerTemplate *myTemplate = player->getPlayerTemplate();
- DEBUG_LOG(("myTemplate = %X(%s)", myTemplate, myTemplate->getName().str()));
- for (ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx)
- {
- const PlayerTemplate *nthTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx);
- DEBUG_LOG(("nthTemplate = %X(%s)", nthTemplate, nthTemplate->getName().str()));
- if (nthTemplate == myTemplate)
- {
- break;
- }
- }
-
- Bool anyAI = FALSE;
- for (Int i=0; igetConstSlot(i);
-
- if (slot->isAI())
- {
- anyAI = TRUE;
- }
- }
-
- //Check for cases where we're not tracking stats.
- if (anyAI || stats.id == 0 || myTemplate->isObserver() || player->getPlayerType() != PLAYER_HUMAN || player->isPlayerObserver())
- return;
-
- Int disCons=stats.discons[ptIdx];
- disCons += count;
- if (disCons < 0)
- { DEBUG_LOG(("updateAdditionalGameSpyDisconnections() - disconnection count below zero"));
- return; //something is wrong here
- }
- stats.discons[ptIdx] = disCons; //add an additional disconnection to their stats.
-
- //Add an additional disconnection to player stats.
- PSRequest req;
-
- req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS;
- req.email = TheGameSpyInfo->getLocalEmail().str();
- req.nick = TheGameSpyInfo->getLocalBaseName().str();
- req.password = TheGameSpyInfo->getLocalPassword().str();
- req.player = stats;
- req.addDesync = FALSE;
- req.addDiscon = FALSE;
- req.lastHouse = ptIdx;
-
- TheGameSpyPSMessageQueue->addRequest(req);
- TheGameSpyPSMessageQueue->trackPlayerStats(stats);
-
- // force an update of our shtuff
- PSResponse newResp;
- newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS;
- newResp.player = stats;
- TheGameSpyPSMessageQueue->addResponse(newResp);
-
- // cache our stuff for easy reading next time
- GameSpyMiscPreferences mPref;
- mPref.setCachedStats(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(stats).c_str());
- mPref.write();
- }
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
deleted file mode 100644
index 6256aa26ba3..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/StagingRoomGameInfo.cpp
+++ /dev/null
@@ -1,886 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: StagingRoomGameInfo.cpp //////////////////////////////////////////////////////
-// Generals GameSpy GameInfo-related code
-// Author: Matthew D. Campbell, July 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/GameState.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "Common/PlayerTemplate.h"
-#include "Common/RandomValue.h"
-#include "Common/ScoreKeeper.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MapUtil.h"
-#include "GameClient/Shell.h"
-#include "GameLogic/GameLogic.h"
-#include "GameLogic/VictoryConditions.h"
-#include "GameNetwork/FileTransfer.h"
-#include "GameNetwork/GameSpy/BuddyThread.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-#include "GameNetwork/GameSpy/ThreadUtils.h"
-#include "GameNetwork/GameSpyOverlay.h"
-#include "GameNetwork/NAT.h"
-#include "GameNetwork/NetworkInterface.h"
-
-
-// GameSpyGameSlot -------------------------------------------
-
-GameSpyGameSlot::GameSpyGameSlot()
- : GameSlot()
-{
- m_gameSpyLogin.clear();
- m_gameSpyLocale.clear();
- m_profileID = 0;
- m_wins = 0;
- m_losses = 0;
- m_rankPoints = 0;
- m_favoriteSide = 0;
- m_pingInt = 0;
- // Added By Sadullah Nader
- // Initializations missing and needed
- m_profileID = 0;
- m_pingStr.clear();
-}
-
-// Helper Functions ----------------------------------------
-/*
-** Function definitions for the MIB-II entry points.
-*/
-
-BOOL (__stdcall *SnmpExtensionInitPtr)(IN DWORD dwUpTimeReference, OUT HANDLE *phSubagentTrapEvent, OUT AsnObjectIdentifier *pFirstSupportedRegion);
-BOOL (__stdcall *SnmpExtensionQueryPtr)(IN BYTE bPduType, IN OUT RFC1157VarBindList *pVarBindList, OUT AsnInteger32 *pErrorStatus, OUT AsnInteger32 *pErrorIndex);
-LPVOID (__stdcall *SnmpUtilMemAllocPtr)(IN DWORD bytes);
-VOID (__stdcall *SnmpUtilMemFreePtr)(IN LPVOID pMem);
-
-typedef struct tConnInfoStruct {
- unsigned int State;
- unsigned long LocalIP;
- unsigned short LocalPort;
- unsigned long RemoteIP;
- unsigned short RemotePort;
-} ConnInfoStruct;
-
-/***********************************************************************************************
- * Get_Local_Chat_Connection_Address -- Which address are we using to talk to the chat server? *
- * *
- * *
- * *
- * INPUT: Ptr to address to return local address * *
- * *
- * OUTPUT: True if success *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 10/27/00 3:24PM ST : Created *
- *=============================================================================================*/
-Bool GetLocalChatConnectionAddress(AsciiString serverName, UnsignedShort serverPort, UnsignedInt& localIP)
-{
- //return false;
- /*
- ** Local defines.
- */
- enum {
- CLOSED = 1,
- LISTENING,
- SYN_SENT,
- SEN_RECEIVED,
- ESTABLISHED,
- FIN_WAIT,
- FIN_WAIT2,
- CLOSE_WAIT,
- LAST_ACK,
- CLOSING,
- TIME_WAIT,
- DELETE_TCB
- };
-
- enum {
- tcpConnState = 1,
- tcpConnLocalAddress,
- tcpConnLocalPort,
- tcpConnRemAddress,
- tcpConnRemPort
- };
-
-
- /*
- ** Locals.
- */
- unsigned char serverAddress[4];
- unsigned char remoteAddress[4];
- HANDLE trap_handle;
- AsnObjectIdentifier first_supported_region;
- std::vector connectionVector;
- int last_field;
- int index;
- AsnInteger error_status;
- AsnInteger error_index;
- int conn_entry_type_index;
- int conn_entry_type;
- Bool found;
-
- /*
- ** Statics.
- */
- static char _conn_state[][32] = {
- "?",
- "CLOSED",
- "LISTENING",
- "SYN_SENT",
- "SEN_RECEIVED",
- "ESTABLISHED",
- "FIN_WAIT",
- "FIN_WAIT2",
- "CLOSE_WAIT",
- "LAST_ACK",
- "CLOSING",
- "TIME_WAIT",
- "DELETE_TCB"
- };
-
- DEBUG_LOG(("Finding local address used to talk to the chat server"));
- DEBUG_LOG(("Current chat server name is %s", serverName.str()));
- DEBUG_LOG(("Chat server port is %d", serverPort));
-
- /*
- ** Get the address of the chat server.
- */
- DEBUG_LOG( ("About to call gethostbyname"));
- struct hostent *host_info = gethostbyname(serverName.str());
-
- if (!host_info) {
- DEBUG_LOG( ("gethostbyname failed! Error code %d", WSAGetLastError()));
- return(false);
- }
-
- memcpy(serverAddress, &host_info->h_addr_list[0][0], 4);
- unsigned long temp = *((unsigned long*)(&serverAddress[0]));
- temp = ntohl(temp);
- *((unsigned long*)(&serverAddress[0])) = temp;
-
- DEBUG_LOG(("Host address is %d.%d.%d.%d", serverAddress[3], serverAddress[2], serverAddress[1], serverAddress[0]));
-
- /*
- ** Load the MIB-II SNMP DLL.
- */
- DEBUG_LOG(("About to load INETMIB1.DLL"));
-
- HINSTANCE mib_ii_dll = LoadLibrary("inetmib1.dll");
- if (mib_ii_dll == NULL) {
- DEBUG_LOG(("Failed to load INETMIB1.DLL"));
- return(false);
- }
-
- DEBUG_LOG(("About to load SNMPAPI.DLL"));
-
- HINSTANCE snmpapi_dll = LoadLibrary("snmpapi.dll");
- if (snmpapi_dll == NULL) {
- DEBUG_LOG(("Failed to load SNMPAPI.DLL"));
- FreeLibrary(mib_ii_dll);
- return(false);
- }
-
- /*
- ** Get the function pointers into the .dll
- */
- SnmpExtensionInitPtr = (int (__stdcall *)(unsigned long,void ** ,AsnObjectIdentifier *)) GetProcAddress(mib_ii_dll, "SnmpExtensionInit");
- SnmpExtensionQueryPtr = (int (__stdcall *)(unsigned char,SnmpVarBindList *,long *,long *)) GetProcAddress(mib_ii_dll, "SnmpExtensionQuery");
- SnmpUtilMemAllocPtr = (void *(__stdcall *)(unsigned long)) GetProcAddress(snmpapi_dll, "SnmpUtilMemAlloc");
- SnmpUtilMemFreePtr = (void (__stdcall *)(void *)) GetProcAddress(snmpapi_dll, "SnmpUtilMemFree");
- if (SnmpExtensionInitPtr == NULL || SnmpExtensionQueryPtr == NULL || SnmpUtilMemAllocPtr == NULL || SnmpUtilMemFreePtr == NULL) {
- DEBUG_LOG(("Failed to get proc addresses for linked functions"));
- FreeLibrary(snmpapi_dll);
- FreeLibrary(mib_ii_dll);
- return(false);
- }
-
-
- RFC1157VarBindList *bind_list_ptr = (RFC1157VarBindList *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBindList));
- RFC1157VarBind *bind_ptr = (RFC1157VarBind *) SnmpUtilMemAllocPtr(sizeof(RFC1157VarBind));
-
- /*
- ** OK, here we go. Try to initialise the .dll
- */
- DEBUG_LOG(("About to init INETMIB1.DLL"));
- int ok = SnmpExtensionInitPtr(GetCurrentTime(), &trap_handle, &first_supported_region);
-
- if (!ok) {
- /*
- ** Aw crap.
- */
- DEBUG_LOG(("Failed to init the .dll"));
- SnmpUtilMemFreePtr(bind_list_ptr);
- SnmpUtilMemFreePtr(bind_ptr);
- FreeLibrary(snmpapi_dll);
- FreeLibrary(mib_ii_dll);
- return(false);
- }
-
- /*
- ** Name of mib_ii object we want to query. See RFC 1213.
- **
- ** iso.org.dod.internet.mgmt.mib-2.tcp.tcpConnTable.TcpConnEntry.tcpConnState
- ** 1 3 6 1 2 1 6 13 1 1
- */
- unsigned int mib_ii_name[] = {1,3,6,1,2,1,6,13,1,1};
- unsigned int *mib_ii_name_ptr = (unsigned int *) SnmpUtilMemAllocPtr(sizeof(mib_ii_name));
- memcpy(mib_ii_name_ptr, mib_ii_name, sizeof(mib_ii_name));
-
- /*
- ** Get the index of the conn entry data.
- */
- conn_entry_type_index = ARRAY_SIZE(mib_ii_name) - 1;
-
- /*
- ** Set up the bind list.
- */
- bind_ptr->name.idLength = ARRAY_SIZE(mib_ii_name);
- bind_ptr->name.ids = mib_ii_name;
- bind_list_ptr->list = bind_ptr;
- bind_list_ptr->len = 1;
-
-
- /*
- ** We start with the tcpConnLocalAddress field.
- */
- last_field = 1;
-
- /*
- ** First connection.
- */
- index = 0;
-
- /*
- ** Suck out that tcp connection info....
- */
- while (true) {
-
- if (!SnmpExtensionQueryPtr(SNMP_PDU_GETNEXT, bind_list_ptr, &error_status, &error_index)) {
- //if (!SnmpExtensionQueryPtr(ASN_RFC1157_GETNEXTREQUEST, bind_list_ptr, &error_status, &error_index)) {
- DEBUG_LOG(("SnmpExtensionQuery returned false"));
- SnmpUtilMemFreePtr(bind_list_ptr);
- SnmpUtilMemFreePtr(bind_ptr);
- FreeLibrary(snmpapi_dll);
- FreeLibrary(mib_ii_dll);
- return(false);
- }
-
- /*
- ** If this is something new we aren't looking for then we are done.
- */
- if (bind_ptr->name.idLength < ARRAY_SIZE(mib_ii_name)) {
- break;
- }
-
- /*
- ** Get the type of info we are looking at. See RFC1213.
- **
- ** 1 = tcpConnState
- ** 2 = tcpConnLocalAddress
- ** 3 = tcpConnLocalPort
- ** 4 = tcpConnRemAddress
- ** 5 = tcpConnRemPort
- **
- ** tcpConnState is one of the following...
- **
- ** 1 closed
- ** 2 listen
- ** 3 synSent
- ** 4 synReceived
- ** 5 established
- ** 6 finWait1
- ** 7 finWait2
- ** 8 closeWait
- ** 9 lastAck
- ** 10 closing
- ** 11 timeWait
- ** 12 deleteTCB
- */
- conn_entry_type = bind_ptr->name.ids[conn_entry_type_index];
-
- if (last_field != conn_entry_type) {
- index = 0;
- last_field = conn_entry_type;
- }
-
- switch (conn_entry_type) {
-
- /*
- ** 1. First field in the entry. Need to create a new connection info struct
- ** here to store this connection in.
- */
- case tcpConnState:
- {
- ConnInfoStruct new_conn;
- new_conn.State = bind_ptr->value.asnValue.number;
- connectionVector.push_back(new_conn);
- break;
- }
-
- /*
- ** 2. Local address field.
- */
- case tcpConnLocalAddress:
- DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index"));
- connectionVector[index].LocalIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream);
- index++;
- break;
-
- /*
- ** 3. Local port field.
- */
- case tcpConnLocalPort:
- DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index"));
- connectionVector[index].LocalPort = bind_ptr->value.asnValue.number;
- //connectionVector[index]->LocalPort = ntohs(connectionVector[index]->LocalPort);
- index++;
- break;
-
- /*
- ** 4. Remote address field.
- */
- case tcpConnRemAddress:
- DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index"));
- connectionVector[index].RemoteIP = *((unsigned long*)bind_ptr->value.asnValue.address.stream);
- index++;
- break;
-
- /*
- ** 5. Remote port field.
- */
- case tcpConnRemPort:
- DEBUG_ASSERTCRASH(index < connectionVector.size(), ("Bad connection index"));
- connectionVector[index].RemotePort = bind_ptr->value.asnValue.number;
- //connectionVector[index]->RemotePort = ntohs(connectionVector[index]->RemotePort);
- index++;
- break;
- }
- }
-
- SnmpUtilMemFreePtr(bind_list_ptr);
- SnmpUtilMemFreePtr(bind_ptr);
- SnmpUtilMemFreePtr(mib_ii_name_ptr);
-
- DEBUG_LOG(("Got %d connections in list, parsing...", connectionVector.size()));
-
- /*
- ** Right, we got the lot. Lets see if any of them have the same address as the chat
- ** server we think we are talking to.
- */
- found = false;
- for (size_t i=0; igetPingValue(pingStr);
-}
-
-// GameSpyStagingRoom ----------------------------------------
-
-GameSpyStagingRoom::GameSpyStagingRoom()
-{
- cleanUpSlotPointers();
-
- setLocalIP(0);
- m_transport = NULL;
-
- m_localName = "localhost";
-
- m_ladderIP.clear();
- m_ladderPort = 0;
-}
-
-void GameSpyStagingRoom::cleanUpSlotPointers( void )
-{
- for (Int i = 0; i< MAX_SLOTS; ++i)
- setSlotPointer(i, &m_GameSpySlot[i]);
-}
-
-GameSpyGameSlot * GameSpyStagingRoom::getGameSpySlot( Int index )
-{
- GameSlot *slot = getSlot(index);
- DEBUG_ASSERTCRASH(slot && (slot == &(m_GameSpySlot[index])), ("Bad game slot pointer"));
- return (GameSpyGameSlot *)slot;
-}
-
-void GameSpyStagingRoom::init( void )
-{
- GameInfo::init();
-}
-
-void GameSpyStagingRoom::setPingString( AsciiString pingStr )
-{
- m_pingStr = pingStr;
- m_pingInt = TheGameSpyInfo->getPingValue(pingStr);
-}
-
-Bool GameSpyStagingRoom::amIHost( void ) const
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for game slot while not in game"));
- if (!m_inGame)
- return false;
-
- return getConstSlot(0)->isPlayer(m_localName);
-}
-
-void GameSpyStagingRoom::resetAccepted( void )
-{
- GameInfo::resetAccepted();
-
- if (amIHost())
- {
- /*
- peerStateChanged(TheGameSpyChat->getPeer());
- m_hasBeenQueried = false;
- DEBUG_LOG(("resetAccepted() called peerStateChange()"));
- */
- }
-}
-
-Int GameSpyStagingRoom::getLocalSlotNum( void ) const
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for local game slot while not in game"));
- if (!m_inGame)
- return -1;
-
- AsciiString localName = TheGameSpyInfo->getLocalName();
-
- for (Int i=0; iisPlayer(localName))
- return i;
- }
- return -1;
-}
-
-void GameSpyStagingRoom::startGame(Int gameID)
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Starting a game while not in game"));
- DEBUG_LOG(("GameSpyStagingRoom::startGame - game id = %d", gameID));
- DEBUG_ASSERTCRASH(m_transport == NULL, ("m_transport is not NULL when it should be"));
- DEBUG_ASSERTCRASH(TheNAT == NULL, ("TheNAT is not NULL when it should be"));
-
- UnsignedInt localIP = TheGameSpyInfo->getInternalIP();
- setLocalIP(localIP);
-
- delete TheNAT;
- TheNAT = NULL;
-
- // fill in GS-specific info
- Int numHumans = 0;
- for (Int i=0; igetLocalProfileID()); // hehe - we know our own. the rest, they'll tell us.
- }
- else
- {
- PlayerInfoMap *pInfoMap = TheGameSpyInfo->getPlayerInfoMap();
- PlayerInfoMap::iterator it = pInfoMap->find(gsName);
- if (it != pInfoMap->end())
- {
- m_GameSpySlot[i].setProfileID(it->second.m_profileID);
- m_GameSpySlot[i].setLocale(it->second.m_locale);
- m_GameSpySlot[i].setSlotRankPoints(it->second.m_rankPoints);
- m_GameSpySlot[i].setFavoriteSide(it->second.m_side);
- }
- else
- {
- DEBUG_CRASH(("No player info for %s", gsName.str()));
- }
- }
- }
- }
-
-//#if defined(RTS_DEBUG)
- if (numHumans < 2)
- {
- launchGame();
- if (TheGameSpyInfo)
- TheGameSpyInfo->leaveStagingRoom();
- }
- else
-//#endif // defined(RTS_DEBUG)
- {
- TheNAT = NEW NAT();
- TheNAT->attachSlotList(m_slot, getLocalSlotNum(), m_localIP);
- TheNAT->establishConnectionPaths();
- }
-}
-
-AsciiString GameSpyStagingRoom::generateGameSpyGameResultsPacket( void )
-{
- Int i;
- Int endFrame = TheVictoryConditions->getEndFrame();
- Int localSlotNum = getLocalSlotNum();
- Int winningTeam = -1;
- Int numHumans = 0;
- Int numPlayers = 0;
- Int numAIs = 0;
- Int numTeamsAtGameEnd = 0;
- Int lastTeamAtGameEnd = -1;
- for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName));
- if (p)
- {
- ++numHumans;
- if (TheVictoryConditions->hasAchievedVictory(p))
- {
- winningTeam = getSlot(i)->getTeamNumber();
- }
-
- // check if he lasted
- GameSlot *slot = getSlot(i);
- if (!slot->disconnected())
- {
- if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0)
- {
- lastTeamAtGameEnd = slot->getTeamNumber();
- ++numTeamsAtGameEnd;
- }
- }
- }
- else
- {
- if (m_GameSpySlot[i].isAI())
- ++numAIs;
- }
- }
- numPlayers = numHumans + numAIs;
-
- AsciiString mapName;
- for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName));
- if (p)
- {
- GameSpyGameSlot *slot = &(m_GameSpySlot[i]);
- AsciiString playerName = (slot->isHuman())?slot->getLoginName():"AIPlayer";
- Int gsPlayerID = slot->getProfileID();
- Bool disconnected = slot->disconnected();
-
- AsciiString result = "loss";
- if (disconnected)
- result = "discon";
- else if (TheNetwork->sawCRCMismatch())
- result = "desync";
- else if (TheVictoryConditions->hasAchievedVictory(p))
- result = "win";
-
- AsciiString side = p->getPlayerTemplate()->getSide();
- if (side == "America")
- side = "USA"; //conform to GameSpy
-
- AsciiString playerStr;
- playerStr.format("\\player_%d\\%s\\pid_%d\\%d\\team_%d\\%d\\result_%d\\%s\\side_%d\\%s",
- playerID, playerName.str(), playerID, gsPlayerID, playerID, slot->getTeamNumber(),
- playerID, result.str(), playerID, side.str());
- results.concat(playerStr);
-
- ++playerID;
- }
- }
-
- return results;
-}
-
-AsciiString GameSpyStagingRoom::generateLadderGameResultsPacket( void )
-{
- Int i;
- Int endFrame = TheVictoryConditions->getEndFrame();
- Int localSlotNum = getLocalSlotNum();
- Bool sawGameEnd = (endFrame > 0);
- Int winningTeam = -1;
- Int numPlayers = 0;
- Int numTeamsAtGameEnd = 0;
- Int lastTeamAtGameEnd = -1;
- Player* p[MAX_SLOTS];
- for (i=0; ifindPlayerWithNameKey(NAMEKEY(playerName));
- if (p[i])
- {
- ++numPlayers;
- if (TheVictoryConditions->hasAchievedVictory(p[i]))
- {
- winningTeam = getSlot(i)->getTeamNumber();
- }
-
- // check if he lasted
- GameSlot *slot = getSlot(i);
- if (!slot->disconnected())
- {
- if (slot->getTeamNumber() != lastTeamAtGameEnd || numTeamsAtGameEnd == 0)
- {
- lastTeamAtGameEnd = slot->getTeamNumber();
- ++numTeamsAtGameEnd;
- }
- }
- }
- }
-
- AsciiString results;
- results.format("seed=%d,slotNum=%d,sawDesync=%d,sawGameEnd=%d,winningTeam=%d,disconEnd=%d,duration=%d,numPlayers=%d,isQM=%d,map=%s",
- getSeed(), localSlotNum, TheNetwork->sawCRCMismatch(), sawGameEnd, winningTeam, (numTeamsAtGameEnd < 2),
- endFrame, numPlayers, m_isQM, TheGameState->realMapPathToPortableMapPath(getMap()).str());
-
- AsciiString tempStr;
- tempStr.format(",ladderIP=%s,ladderPort=%d", getLadderIP().str(), getLadderPort());
- results.concat(tempStr);
-
- Int playerID = 0;
- for (i=0; igetScoreKeeper();
- AsciiString playerName = slot->getLoginName();
- Int gsPlayerID = slot->getProfileID();
- PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(gsPlayerID);
- Int fps = TheNetwork->getAverageFPS();
- Int unitsKilled = keeper->getTotalUnitsDestroyed();
- Int unitsLost = keeper->getTotalUnitsLost();
- Int unitsBuilt = keeper->getTotalUnitsBuilt();
- Int buildingsKilled = keeper->getTotalBuildingsDestroyed();
- Int buildingsLost = keeper->getTotalBuildingsLost();
- Int buildingsBuilt = keeper->getTotalBuildingsBuilt();
- Int earnings = keeper->getTotalMoneyEarned();
- Int techCaptured = keeper->getTotalTechBuildingsCaptured();
- Bool disconnected = slot->disconnected();
-
- AsciiString playerStr;
- playerStr.format(",player%d=%s,playerID%d=%d,locale%d=%d",
- playerID, playerName.str(), playerID, gsPlayerID, playerID, stats.locale);
- results.concat(playerStr);
- playerStr.format(",unitsKilled%d=%d,unitsLost%d=%d,unitsBuilt%d=%d",
- playerID, unitsKilled, playerID, unitsLost, playerID, unitsBuilt);
- results.concat(playerStr);
- playerStr.format(",buildingsKilled%d=%d,buildingsLost%d=%d,buildingsBuilt%d=%d",
- playerID, buildingsKilled, playerID, buildingsLost, playerID, buildingsBuilt);
- results.concat(playerStr);
-#if RTS_GENERALS
- playerStr.format(",fps%d=%d,cash%d=%d,capturedTech%d=%d,discon%d=%d,side%d=%s,team%d=%d",
- playerID, fps, playerID, earnings, playerID, techCaptured, playerID, disconnected, playerID, p[i]->getPlayerTemplate()->getSide().str(), playerID, slot->getTeamNumber());
-#elif RTS_ZEROHOUR
- playerStr.format(",fps%d=%d,cash%d=%d,capturedTech%d=%d,discon%d=%d,side%d=%s",
- playerID, fps, playerID, earnings, playerID, techCaptured, playerID, disconnected, playerID, p[i]->getPlayerTemplate()->getSide().str());
-#endif
- results.concat(playerStr);
-
- ++playerID;
- }
- }
-
- // Add a trailing size value (so the server can ensure it got the entire packet)
- results.concat(",size=");
- int resultsLen = results.getLength()+10;
- AsciiString tail;
- tail.format("%10.10d", resultsLen);
- results.concat(tail);
-
- return results;
-}
-
-void GameSpyStagingRoom::launchGame( void )
-{
- setGameInProgress(TRUE);
-
- for (Int i=0; iisHuman())
- {
- if (TheGameSpyInfo->didPlayerPreorder(slot->getProfileID()))
- markPlayerAsPreorder(i);
- }
- }
-
- // Set up the game network
- AsciiString user;
- AsciiString userList;
- DEBUG_ASSERTCRASH(TheNetwork == NULL, ("For some reason TheNetwork isn't NULL at the start of this game. Better look into that."));
-
- delete TheNetwork;
- TheNetwork = NULL;
-
- // Time to initialize TheNetwork for this game.
- TheNetwork = NetworkInterface::createNetwork();
- TheNetwork->init();
-
- TheNetwork->setLocalAddress(getLocalIP(), (TheNAT)?TheNAT->getSlotPort(getLocalSlotNum()):8888);
- if (TheNAT)
- TheNetwork->attachTransport(TheNAT->getTransport());
- else
- TheNetwork->initTransport();
-
- TheNetwork->parseUserList(this);
-
-
- if (TheGameLogic->isInGame()) {
- TheGameLogic->clearGameData();
- }
-
- Bool filesOk = DoAnyMapTransfers(this);
-
- // see if we really have the map. if not, back out.
- TheMapCache->updateCache();
- if (!filesOk || TheMapCache->findMap(getMap()) == NULL)
- {
- DEBUG_LOG(("After transfer, we didn't really have the map. Bailing..."));
-
- delete TheNetwork;
- TheNetwork = NULL;
-
- GSMessageBoxOk(TheGameText->fetch("GUI:Error"), TheGameText->fetch("GUI:CouldNotTransferMap"));
-
- void PopBackToLobby( void );
- PopBackToLobby();
- return;
- }
-
-
- // shutdown the top, but do not pop it off the stack
-// TheShell->hideShell();
- // setup the Global Data with the Map and Seed
- TheWritableGlobalData->m_pendingFile = TheGameSpyGame->getMap();
-
- // send a message to the logic for a new game
- GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
- msg->appendIntegerArgument(GAME_INTERNET);
-
- TheWritableGlobalData->m_useFpsLimit = false;
-
- // Set the random seed
- InitGameLogicRandom( getSeed() );
- DEBUG_LOG(("InitGameLogicRandom( %d )", getSeed()));
-
- // mark us as "Loading" in the buddy list
- BuddyRequest req;
- req.buddyRequestType = BuddyRequest::BUDDYREQUEST_SETSTATUS;
- req.arg.status.status = GP_PLAYING;
- strcpy(req.arg.status.statusString, "Loading");
- sprintf(req.arg.status.locationString, "%s", WideCharStringToMultiByte(TheGameSpyGame->getGameName().str()).c_str());
- TheGameSpyBuddyMessageQueue->addRequest(req);
-
- delete TheNAT;
- TheNAT = NULL;
-}
-
-void GameSpyStagingRoom::reset(void)
-{
-#ifdef DEBUG_LOGGING
- if (this == TheGameSpyGame)
- {
- WindowLayout *theLayout = TheShell->findScreenByFilename("Menus/GameSpyGameOptionsMenu.wnd");
- if (theLayout)
- {
- DEBUG_LOG(("Resetting TheGameSpyGame on the game options menu!"));
- }
- }
-#endif
- GameInfo::reset();
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
deleted file mode 100644
index 8af5511a63e..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/BuddyThread.cpp
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: BuddyThread.cpp //////////////////////////////////////////////////////
-// GameSpy Presence & Messaging (Buddy) thread
-// This thread communicates with GameSpy's buddy server
-// and talks through a message queue with the rest of
-// the game.
-// Author: Matthew D. Campbell, June 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/GameSpy/BuddyThread.h"
-#include "GameNetwork/GameSpy/PeerThread.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-#include "GameNetwork/GameSpy/ThreadUtils.h"
-
-#include "mutex.h"
-#include "thread.h"
-
-
-//-------------------------------------------------------------------------
-
-typedef std::queue RequestQueue;
-typedef std::queue ResponseQueue;
-class BuddyThreadClass;
-
-class GameSpyBuddyMessageQueue : public GameSpyBuddyMessageQueueInterface
-{
-public:
- virtual ~GameSpyBuddyMessageQueue();
- GameSpyBuddyMessageQueue();
- virtual void startThread( void );
- virtual void endThread( void );
- virtual Bool isThreadRunning( void );
- virtual Bool isConnected( void );
- virtual Bool isConnecting( void );
-
- virtual void addRequest( const BuddyRequest& req );
- virtual Bool getRequest( BuddyRequest& req );
-
- virtual void addResponse( const BuddyResponse& resp );
- virtual Bool getResponse( BuddyResponse& resp );
-
- virtual GPProfile getLocalProfileID( void );
-
- BuddyThreadClass* getThread( void );
-
-private:
- MutexClass m_requestMutex;
- MutexClass m_responseMutex;
- RequestQueue m_requests;
- ResponseQueue m_responses;
- BuddyThreadClass *m_thread;
-};
-
-GameSpyBuddyMessageQueueInterface* GameSpyBuddyMessageQueueInterface::createNewMessageQueue( void )
-{
- return NEW GameSpyBuddyMessageQueue;
-}
-
-GameSpyBuddyMessageQueueInterface *TheGameSpyBuddyMessageQueue;
-#define MESSAGE_QUEUE ((GameSpyBuddyMessageQueue *)TheGameSpyBuddyMessageQueue)
-
-//-------------------------------------------------------------------------
-
-class BuddyThreadClass : public ThreadClass
-{
-
-public:
- BuddyThreadClass() : ThreadClass() { m_isNewAccount = m_isdeleting = m_isConnecting = m_isConnected = false; m_profileID = 0; m_lastErrorCode = 0; }
-
- void Thread_Function();
-
- void errorCallback( GPConnection *con, GPErrorArg *arg );
- void messageCallback( GPConnection *con, GPRecvBuddyMessageArg *arg );
- void connectCallback( GPConnection *con, GPConnectResponseArg *arg );
- void requestCallback( GPConnection *con, GPRecvBuddyRequestArg *arg );
- void statusCallback( GPConnection *con, GPRecvBuddyStatusArg *arg );
-
- Bool isConnecting( void ) { return m_isConnecting; }
- Bool isConnected( void ) { return m_isConnected; }
-
- GPProfile getLocalProfileID( void ) { return m_profileID; }
-
-private:
- Bool m_isNewAccount;
- Bool m_isConnecting;
- Bool m_isConnected;
- GPProfile m_profileID;
- Int m_lastErrorCode;
- Bool m_isdeleting;
- std::string m_nick, m_email, m_pass;
-};
-
-enum CallbackType
-{
- CALLBACK_CONNECT,
- CALLBACK_ERROR,
- CALLBACK_RECVMESSAGE,
- CALLBACK_RECVREQUEST,
- CALLBACK_RECVSTATUS,
-};
-
-void callbackWrapper( GPConnection *con, void *arg, void *param )
-{
- CallbackType info = (CallbackType)(Int)param;
- BuddyThreadClass *thread = MESSAGE_QUEUE->getThread() ? MESSAGE_QUEUE->getThread() : NULL /*(TheGameSpyBuddyMessageQueue)?TheGameSpyBuddyMessageQueue->getThread():NULL*/;
- if (!thread)
- return;
-
- switch (info)
- {
- case CALLBACK_CONNECT:
- thread->connectCallback( con, (GPConnectResponseArg *)arg );
- break;
- case CALLBACK_ERROR:
- thread->errorCallback( con, (GPErrorArg *)arg );
- break;
- case CALLBACK_RECVMESSAGE:
- thread->messageCallback( con, (GPRecvBuddyMessageArg *)arg );
- break;
- case CALLBACK_RECVREQUEST:
- thread->requestCallback( con, (GPRecvBuddyRequestArg *)arg );
- break;
- case CALLBACK_RECVSTATUS:
- thread->statusCallback( con, (GPRecvBuddyStatusArg *)arg );
- break;
- }
-}
-
-//-------------------------------------------------------------------------
-
-GameSpyBuddyMessageQueue::GameSpyBuddyMessageQueue()
-{
- m_thread = NULL;
-}
-
-GameSpyBuddyMessageQueue::~GameSpyBuddyMessageQueue()
-{
- endThread();
-}
-
-void GameSpyBuddyMessageQueue::startThread( void )
-{
- if (!m_thread)
- {
- m_thread = NEW BuddyThreadClass;
- m_thread->Execute();
- }
- else
- {
- if (!m_thread->Is_Running())
- {
- m_thread->Execute();
- }
- }
-}
-
-void GameSpyBuddyMessageQueue::endThread( void )
-{
- delete m_thread;
- m_thread = NULL;
-}
-
-Bool GameSpyBuddyMessageQueue::isThreadRunning( void )
-{
- return (m_thread) ? m_thread->Is_Running() : false;
-}
-
-Bool GameSpyBuddyMessageQueue::isConnected( void )
-{
- return (m_thread) ? m_thread->isConnected() : false;
-}
-
-Bool GameSpyBuddyMessageQueue::isConnecting( void )
-{
- return (m_thread) ? m_thread->isConnecting() : false;
-}
-
-void GameSpyBuddyMessageQueue::addRequest( const BuddyRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex);
- if (m.Failed())
- return;
-
- m_requests.push(req);
-}
-
-Bool GameSpyBuddyMessageQueue::getRequest( BuddyRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_requests.empty())
- return false;
- req = m_requests.front();
- m_requests.pop();
- return true;
-}
-
-void GameSpyBuddyMessageQueue::addResponse( const BuddyResponse& resp )
-{
- MutexClass::LockClass m(m_responseMutex);
- if (m.Failed())
- return;
-
- m_responses.push(resp);
-}
-
-Bool GameSpyBuddyMessageQueue::getResponse( BuddyResponse& resp )
-{
- MutexClass::LockClass m(m_responseMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_responses.empty())
- return false;
- resp = m_responses.front();
- m_responses.pop();
- return true;
-}
-
-BuddyThreadClass* GameSpyBuddyMessageQueue::getThread( void )
-{
- return m_thread;
-}
-
-GPProfile GameSpyBuddyMessageQueue::getLocalProfileID( void )
-{
- return (m_thread) ? m_thread->getLocalProfileID() : 0;
-}
-
-//-------------------------------------------------------------------------
-
-void BuddyThreadClass::Thread_Function()
-{
- try {
- GPConnection gpCon;
- GPConnection *con = &gpCon;
-#if RTS_GENERALS
- const int productID = 675;
-#elif RTS_ZEROHOUR
- const int productID = 823;
-#endif
- gpInitialize( con, productID, 0, GP_PARTNERID_GAMESPY );
- m_isConnected = m_isConnecting = false;
-
- gpSetCallback( con, GP_ERROR, callbackWrapper, (void *)CALLBACK_ERROR );
- gpSetCallback( con, GP_RECV_BUDDY_MESSAGE, callbackWrapper, (void *)CALLBACK_RECVMESSAGE );
- gpSetCallback( con, GP_RECV_BUDDY_REQUEST, callbackWrapper, (void *)CALLBACK_RECVREQUEST );
- gpSetCallback( con, GP_RECV_BUDDY_STATUS, callbackWrapper, (void *)CALLBACK_RECVSTATUS );
-
- GPEnum lastStatus = GP_OFFLINE;
- std::string lastStatusString;
-
- BuddyRequest incomingRequest;
- while ( running )
- {
- // deal with requests
- if (TheGameSpyBuddyMessageQueue->getRequest(incomingRequest))
- {
- switch (incomingRequest.buddyRequestType)
- {
- case BuddyRequest::BUDDYREQUEST_LOGIN:
- m_isConnecting = true;
- m_nick = incomingRequest.arg.login.nick;
- m_email = incomingRequest.arg.login.email;
- m_pass = incomingRequest.arg.login.password;
- m_isConnected = (gpConnect( con, incomingRequest.arg.login.nick, incomingRequest.arg.login.email,
- incomingRequest.arg.login.password, (incomingRequest.arg.login.hasFirewall)?GP_FIREWALL:GP_NO_FIREWALL,
- GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR);
- m_isConnecting = false;
- break;
-
- case BuddyRequest::BUDDYREQUEST_RELOGIN:
- m_isConnecting = true;
- m_isConnected = (gpConnect( con, m_nick.c_str(), m_email.c_str(), m_pass.c_str(), GP_FIREWALL,
- GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR);
- m_isConnecting = false;
- break;
- case BuddyRequest::BUDDYREQUEST_DELETEACCT:
- m_isdeleting = true;
- // TheSuperHackers @tweak OmniBlade API was updated since Generals released to require a callback. Passing -1 will make our wrapper ignore this.
- gpDeleteProfile( con, callbackWrapper, (void *)(-1) );
- break;
- case BuddyRequest::BUDDYREQUEST_LOGOUT:
- m_isConnecting = m_isConnected = false;
- gpDisconnect( con );
- break;
- case BuddyRequest::BUDDYREQUEST_MESSAGE:
- {
- std::string s = WideCharStringToMultiByte( incomingRequest.arg.message.text );
- DEBUG_LOG(("Sending a buddy message to %d [%s]", incomingRequest.arg.message.recipient, s.c_str()));
- gpSendBuddyMessage( con, incomingRequest.arg.message.recipient, s.c_str() );
- }
- break;
- case BuddyRequest::BUDDYREQUEST_LOGINNEW:
- {
- m_isConnecting = true;
- m_nick = incomingRequest.arg.login.nick;
- m_email = incomingRequest.arg.login.email;
- m_pass = incomingRequest.arg.login.password;
- m_isNewAccount = TRUE;
- // TheSuperHackers @tweak OmniBlade API was updated since Generals release to require uniquenick which is the same as nick and cdkey is an empty string here.
- m_isConnected = (gpConnectNewUser( con, incomingRequest.arg.login.nick, incomingRequest.arg.login.nick, incomingRequest.arg.login.email,
- incomingRequest.arg.login.password, "", (incomingRequest.arg.login.hasFirewall)?GP_FIREWALL:GP_NO_FIREWALL,
- GP_BLOCKING, callbackWrapper, (void *)CALLBACK_CONNECT ) == GP_NO_ERROR);
- if (m_isNewAccount) // if we didn't re-login
- {
- gpSetInfoMask( con, GP_MASK_NONE ); // don't share info
- }
- m_isConnecting = false;
- }
- break;
- case BuddyRequest::BUDDYREQUEST_ADDBUDDY:
- {
- std::string s = WideCharStringToMultiByte( incomingRequest.arg.addbuddy.text );
- gpSendBuddyRequest( con, incomingRequest.arg.addbuddy.id, s.c_str() );
- }
- break;
- case BuddyRequest::BUDDYREQUEST_DELBUDDY:
- {
- gpDeleteBuddy( con, incomingRequest.arg.profile.id );
- }
- break;
- case BuddyRequest::BUDDYREQUEST_OKADD:
- {
- gpAuthBuddyRequest( con, incomingRequest.arg.profile.id );
- }
- break;
- case BuddyRequest::BUDDYREQUEST_DENYADD:
- {
- gpDenyBuddyRequest( con, incomingRequest.arg.profile.id );
- }
- break;
- case BuddyRequest::BUDDYREQUEST_SETSTATUS:
- {
- //don't blast our 'Loading' status with 'Online'.
- if (lastStatus == GP_PLAYING && lastStatusString == "Loading" && incomingRequest.arg.status.status == GP_ONLINE)
- break;
-
- DEBUG_LOG(("BUDDYREQUEST_SETSTATUS: status is now %d:%s/%s",
- incomingRequest.arg.status.status, incomingRequest.arg.status.statusString, incomingRequest.arg.status.locationString));
- gpSetStatus( con, incomingRequest.arg.status.status, incomingRequest.arg.status.statusString,
- incomingRequest.arg.status.locationString );
- lastStatus = incomingRequest.arg.status.status;
- lastStatusString = incomingRequest.arg.status.statusString;
- }
- break;
- }
- }
-
- // update the network
- GPEnum isConnected = GP_CONNECTED;
- GPResult res = GP_NO_ERROR;
- res = gpIsConnected( con, &isConnected );
- if ( isConnected == GP_CONNECTED && res == GP_NO_ERROR )
- gpProcess( con );
-
- // end our timeslice
- Switch_Thread();
- }
-
- gpDestroy( con );
- } catch ( ... ) {
- DEBUG_CRASH(("Exception in buddy thread!"));
- }
-}
-
-void BuddyThreadClass::errorCallback( GPConnection *con, GPErrorArg *arg )
-{
- // log the error
- DEBUG_LOG(("GPErrorCallback"));
- m_lastErrorCode = arg->errorCode;
-
- char errorCodeString[256];
- char resultString[256];
-
- #define RESULT(x) case x: strcpy(resultString, #x); break;
- switch(arg->result)
- {
- RESULT(GP_NO_ERROR)
- RESULT(GP_MEMORY_ERROR)
- RESULT(GP_PARAMETER_ERROR)
- RESULT(GP_NETWORK_ERROR)
- RESULT(GP_SERVER_ERROR)
- default:
- strcpy(resultString, "Unknown result!");
- }
- #undef RESULT
-
- #define ERRORCODE(x) case x: strcpy(errorCodeString, #x); break;
- switch(arg->errorCode)
- {
- ERRORCODE(GP_GENERAL)
- ERRORCODE(GP_PARSE)
- ERRORCODE(GP_NOT_LOGGED_IN)
- ERRORCODE(GP_BAD_SESSKEY)
- ERRORCODE(GP_DATABASE)
- ERRORCODE(GP_NETWORK)
- ERRORCODE(GP_FORCED_DISCONNECT)
- ERRORCODE(GP_CONNECTION_CLOSED)
- ERRORCODE(GP_LOGIN)
- ERRORCODE(GP_LOGIN_TIMEOUT)
- ERRORCODE(GP_LOGIN_BAD_NICK)
- ERRORCODE(GP_LOGIN_BAD_EMAIL)
- ERRORCODE(GP_LOGIN_BAD_PASSWORD)
- ERRORCODE(GP_LOGIN_BAD_PROFILE)
- ERRORCODE(GP_LOGIN_PROFILE_DELETED)
- ERRORCODE(GP_LOGIN_CONNECTION_FAILED)
- ERRORCODE(GP_LOGIN_SERVER_AUTH_FAILED)
- ERRORCODE(GP_NEWUSER)
- ERRORCODE(GP_NEWUSER_BAD_NICK)
- ERRORCODE(GP_NEWUSER_BAD_PASSWORD)
- ERRORCODE(GP_UPDATEUI)
- ERRORCODE(GP_UPDATEUI_BAD_EMAIL)
- ERRORCODE(GP_NEWPROFILE)
- ERRORCODE(GP_NEWPROFILE_BAD_NICK)
- ERRORCODE(GP_NEWPROFILE_BAD_OLD_NICK)
- ERRORCODE(GP_UPDATEPRO)
- ERRORCODE(GP_UPDATEPRO_BAD_NICK)
- ERRORCODE(GP_ADDBUDDY)
- ERRORCODE(GP_ADDBUDDY_BAD_FROM)
- ERRORCODE(GP_ADDBUDDY_BAD_NEW)
- ERRORCODE(GP_ADDBUDDY_ALREADY_BUDDY)
- ERRORCODE(GP_AUTHADD)
- ERRORCODE(GP_AUTHADD_BAD_FROM)
- ERRORCODE(GP_AUTHADD_BAD_SIG)
- ERRORCODE(GP_STATUS)
- ERRORCODE(GP_BM)
- ERRORCODE(GP_BM_NOT_BUDDY)
- ERRORCODE(GP_GETPROFILE)
- ERRORCODE(GP_GETPROFILE_BAD_PROFILE)
- ERRORCODE(GP_DELBUDDY)
- ERRORCODE(GP_DELBUDDY_NOT_BUDDY)
- ERRORCODE(GP_DELPROFILE)
- ERRORCODE(GP_DELPROFILE_LAST_PROFILE)
- ERRORCODE(GP_SEARCH)
- ERRORCODE(GP_SEARCH_CONNECTION_FAILED)
- default:
- strcpy(errorCodeString, "Unknown error code!");
- }
- #undef ERRORCODE
-
- if(arg->fatal)
- {
- DEBUG_LOG(( "-----------"));
- DEBUG_LOG(( "GP FATAL ERROR"));
- DEBUG_LOG(( "-----------"));
- }
- else
- {
- DEBUG_LOG(( "-----"));
- DEBUG_LOG(( "GP ERROR"));
- DEBUG_LOG(( "-----"));
- }
- DEBUG_LOG(( "RESULT: %s (%d)", resultString, arg->result));
- DEBUG_LOG(( "ERROR CODE: %s (0x%X)", errorCodeString, arg->errorCode));
- DEBUG_LOG(( "ERROR STRING: %s", arg->errorString));
-
- if (arg->fatal == GP_FATAL)
- {
- BuddyResponse errorResponse;
- errorResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_DISCONNECT;
- errorResponse.result = arg->result;
- errorResponse.arg.error.errorCode = arg->errorCode;
- errorResponse.arg.error.fatal = arg->fatal;
- strlcpy(errorResponse.arg.error.errorString, arg->errorString, MAX_BUDDY_CHAT_LEN);
- m_isConnecting = m_isConnected = false;
- TheGameSpyBuddyMessageQueue->addResponse( errorResponse );
- if (m_isdeleting)
- {
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT;
- TheGameSpyPeerMessageQueue->addRequest( req );
- m_isdeleting = false;
- }
- }
-}
-
-static void getNickForMessage( GPConnection *con, GPGetInfoResponseArg *arg, void *param )
-{
- BuddyResponse *resp = (BuddyResponse *)param;
- static_assert(ARRAY_SIZE(resp->arg.message.nick) >= ARRAY_SIZE(arg->nick), "Incorrect array size");
- strcpy(resp->arg.message.nick, arg->nick);
-}
-
-void BuddyThreadClass::messageCallback( GPConnection *con, GPRecvBuddyMessageArg *arg )
-{
- BuddyResponse messageResponse;
- messageResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_MESSAGE;
- messageResponse.profile = arg->profile;
-
- // get info about the person asking to be our buddy
- gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getNickForMessage, &messageResponse);
-
- std::wstring s = MultiByteToWideCharSingleLine( arg->message );
- wcslcpy(messageResponse.arg.message.text, s.c_str(), MAX_BUDDY_CHAT_LEN);
- messageResponse.arg.message.date = arg->date;
- DEBUG_LOG(("Got a buddy message from %d [%ls]", arg->profile, s.c_str()));
- TheGameSpyBuddyMessageQueue->addResponse( messageResponse );
-}
-
-void BuddyThreadClass::connectCallback( GPConnection *con, GPConnectResponseArg *arg )
-{
- BuddyResponse loginResponse;
- if (arg->result == GP_NO_ERROR)
- {
- loginResponse.buddyResponseType = BuddyResponse::BUDDYRESPONSE_LOGIN;
- loginResponse.result = arg->result;
- loginResponse.profile = arg->profile;
- TheGameSpyBuddyMessageQueue->addResponse( loginResponse );
- m_profileID = arg->profile;
-
- if (!TheGameSpyPeerMessageQueue->isConnected() && !TheGameSpyPeerMessageQueue->isConnecting())
- {
- DEBUG_LOG(("Buddy connect: trying chat connect"));
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_LOGIN;
- req.nick = m_nick;
- req.password = m_pass;
- req.email = m_email;
- req.login.profileID = arg->profile;
- TheGameSpyPeerMessageQueue->addRequest(req);
- }
- }
- else
- {
- if (!TheGameSpyPeerMessageQueue->isConnected() && !TheGameSpyPeerMessageQueue->isConnecting())
- {
- if (m_lastErrorCode == GP_NEWUSER_BAD_NICK)
- {
- m_isNewAccount = FALSE;
- // they just hit 'create account' instead of 'log in'. Fix them.
- DEBUG_LOG(("User Error: Create Account instead of Login. Fixing them..."));
- BuddyRequest req;
- req.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGIN;
- strlcpy(req.arg.login.nick, m_nick.c_str(), ARRAY_SIZE(req.arg.login.nick));
- strlcpy(req.arg.login.email, m_email.c_str(), ARRAY_SIZE(req.arg.login.email));
- strlcpy(req.arg.login.password, m_pass.c_str(), ARRAY_SIZE(req.arg.login.password));
- req.arg.login.hasFirewall = true;
- TheGameSpyBuddyMessageQueue->addRequest( req );
- return;
- }
- DEBUG_LOG(("Buddy connect failed (%d/%d): posting a failed chat connect", arg->result, m_lastErrorCode));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_COULDNOTCONNECT;
- switch (m_lastErrorCode)
- {
- case GP_LOGIN_TIMEOUT:
- resp.discon.reason = DISCONNECT_GP_LOGIN_TIMEOUT;
- break;
- case GP_LOGIN_BAD_NICK:
- resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_NICK;
- break;
- case GP_LOGIN_BAD_EMAIL:
- resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_EMAIL;
- break;
- case GP_LOGIN_BAD_PASSWORD:
- resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_PASSWORD;
- break;
- case GP_LOGIN_BAD_PROFILE:
- resp.discon.reason = DISCONNECT_GP_LOGIN_BAD_PROFILE;
- break;
- case GP_LOGIN_PROFILE_DELETED:
- resp.discon.reason = DISCONNECT_GP_LOGIN_PROFILE_DELETED;
- break;
- case GP_LOGIN_CONNECTION_FAILED:
- resp.discon.reason = DISCONNECT_GP_LOGIN_CONNECTION_FAILED;
- break;
- case GP_LOGIN_SERVER_AUTH_FAILED:
- resp.discon.reason = DISCONNECT_GP_LOGIN_SERVER_AUTH_FAILED;
- break;
- case GP_NEWUSER_BAD_NICK:
- resp.discon.reason = DISCONNECT_GP_NEWUSER_BAD_NICK;
- break;
- case GP_NEWUSER_BAD_PASSWORD:
- resp.discon.reason = DISCONNECT_GP_NEWUSER_BAD_PASSWORD;
- break;
- case GP_NEWPROFILE_BAD_NICK:
- resp.discon.reason = DISCONNECT_GP_NEWPROFILE_BAD_NICK;
- break;
- case GP_NEWPROFILE_BAD_OLD_NICK:
- resp.discon.reason = DISCONNECT_GP_NEWPROFILE_BAD_OLD_NICK;
- break;
- }
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
-}
-
-// -----------------------
-
-static void getInfoResponseForRequest( GPConnection *con, GPGetInfoResponseArg *arg, void *param )
-{
- BuddyResponse *resp = (BuddyResponse *)param;
- resp->profile = arg->profile;
- static_assert(ARRAY_SIZE(resp->arg.request.nick) >= ARRAY_SIZE(arg->nick), "Incorrect array size");
- static_assert(ARRAY_SIZE(resp->arg.request.email) >= ARRAY_SIZE(arg->email), "Incorrect array size");
- static_assert(ARRAY_SIZE(resp->arg.request.countrycode) >= ARRAY_SIZE(arg->countrycode), "Incorrect array size");
- strcpy(resp->arg.request.nick, arg->nick);
- strcpy(resp->arg.request.email, arg->email);
- strcpy(resp->arg.request.countrycode, arg->countrycode);
-}
-
-void BuddyThreadClass::requestCallback( GPConnection *con, GPRecvBuddyRequestArg *arg )
-{
- BuddyResponse response;
- response.buddyResponseType = BuddyResponse::BUDDYRESPONSE_REQUEST;
- response.profile = arg->profile;
-
- // get info about the person asking to be our buddy
- gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getInfoResponseForRequest, &response);
-
- std::wstring s = MultiByteToWideCharSingleLine( arg->reason );
- wcslcpy(response.arg.request.text, s.c_str(), GP_REASON_LEN);
-
- TheGameSpyBuddyMessageQueue->addResponse( response );
-}
-
-// -----------------------
-
-static void getInfoResponseForStatus(GPConnection * connection, GPGetInfoResponseArg * arg, void * param)
-{
- BuddyResponse *resp = (BuddyResponse *)param;
- resp->profile = arg->profile;
- static_assert(ARRAY_SIZE(resp->arg.status.nick) >= ARRAY_SIZE(arg->nick), "Incorrect array size");
- static_assert(ARRAY_SIZE(resp->arg.status.email) >= ARRAY_SIZE(arg->email), "Incorrect array size");
- static_assert(ARRAY_SIZE(resp->arg.status.countrycode) >= ARRAY_SIZE(arg->countrycode), "Incorrect array size");
- strcpy(resp->arg.status.nick, arg->nick);
- strcpy(resp->arg.status.email, arg->email);
- strcpy(resp->arg.status.countrycode, arg->countrycode);
-}
-
-void BuddyThreadClass::statusCallback( GPConnection *con, GPRecvBuddyStatusArg *arg )
-{
- BuddyResponse response;
-
- // get user's name
- response.buddyResponseType = BuddyResponse::BUDDYRESPONSE_STATUS;
- gpGetInfo( con, arg->profile, GP_CHECK_CACHE, GP_BLOCKING, (GPCallback)getInfoResponseForStatus, &response);
-
- // get user's status
- GPBuddyStatus status;
- gpGetBuddyStatus( con, arg->index, &status );
- static_assert(ARRAY_SIZE(response.arg.status.location) >= ARRAY_SIZE(status.locationString), "Incorrect array size");
- static_assert(ARRAY_SIZE(response.arg.status.statusString) >= ARRAY_SIZE(status.statusString), "Incorrect array size");
- strcpy(response.arg.status.location, status.locationString);
- strcpy(response.arg.status.statusString, status.statusString);
- response.arg.status.status = status.status;
- DEBUG_LOG(("Got buddy status for %d(%s) - status %d", status.profile, response.arg.status.nick, status.status));
-
- // relay to UI
- TheGameSpyBuddyMessageQueue->addResponse( response );
-}
-
-
-//-------------------------------------------------------------------------
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
deleted file mode 100644
index 062997e806b..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/GameResultsThread.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PingThread.cpp //////////////////////////////////////////////////////
-// Ping thread
-// Author: Matthew D. Campbell, August 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include // This one has to be here. Prevents collisions with winsock2.h
-
-#include "GameNetwork/GameSpy/GameResultsThread.h"
-#include "mutex.h"
-#include "thread.h"
-
-#include "Common/SubsystemInterface.h"
-
-//-------------------------------------------------------------------------
-
-static const Int NumWorkerThreads = 1;
-
-typedef std::queue RequestQueue;
-typedef std::queue ResponseQueue;
-class GameResultsThreadClass;
-
-class GameResultsQueue : public GameResultsInterface
-{
-public:
- virtual ~GameResultsQueue();
- GameResultsQueue();
-
- virtual void init() {}
- virtual void reset() {}
- virtual void update() {}
-
- virtual void startThreads( void );
- virtual void endThreads( void );
- virtual Bool areThreadsRunning( void );
-
- virtual void addRequest( const GameResultsRequest& req );
- virtual Bool getRequest( GameResultsRequest& resp );
-
- virtual void addResponse( const GameResultsResponse& resp );
- virtual Bool getResponse( GameResultsResponse& resp );
-
- virtual Bool areGameResultsBeingSent( void );
-
-private:
- MutexClass m_requestMutex;
- MutexClass m_responseMutex;
- RequestQueue m_requests;
- ResponseQueue m_responses;
- Int m_requestCount;
- Int m_responseCount;
-
- GameResultsThreadClass *m_workerThreads[NumWorkerThreads];
-};
-
-GameResultsInterface* GameResultsInterface::createNewGameResultsInterface( void )
-{
- return NEW GameResultsQueue;
-}
-
-GameResultsInterface *TheGameResultsQueue;
-
-//-------------------------------------------------------------------------
-
-class GameResultsThreadClass : public ThreadClass
-{
-
-public:
- GameResultsThreadClass() : ThreadClass() {}
-
- void Thread_Function();
-
-private:
- Int sendGameResults( UnsignedInt IP, UnsignedShort port, const std::string& results );
-};
-
-
-//-------------------------------------------------------------------------
-
-GameResultsQueue::GameResultsQueue() : m_requestCount(0), m_responseCount(0)
-{
- for (Int i=0; iExecute();
- }
-}
-
-void GameResultsQueue::endThreads( void )
-{
- for (Int i=0; iIs_Running())
- return true;
- }
- }
- return false;
-}
-
-void GameResultsQueue::addRequest( const GameResultsRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex);
-
- ++m_requestCount;
- m_requests.push(req);
-}
-
-Bool GameResultsQueue::getRequest( GameResultsRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_requests.empty())
- return false;
- req = m_requests.front();
- m_requests.pop();
- return true;
-}
-
-void GameResultsQueue::addResponse( const GameResultsResponse& resp )
-{
- {
- MutexClass::LockClass m(m_responseMutex);
-
- ++m_responseCount;
- m_responses.push(resp);
- }
-}
-
-Bool GameResultsQueue::getResponse( GameResultsResponse& resp )
-{
- MutexClass::LockClass m(m_responseMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_responses.empty())
- return false;
- resp = m_responses.front();
- m_responses.pop();
- return true;
-}
-
-Bool GameResultsQueue::areGameResultsBeingSent( void )
-{
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return true;
-
- return m_requestCount > 0;
-}
-
-//-------------------------------------------------------------------------
-
-void GameResultsThreadClass::Thread_Function()
-{
- try {
- GameResultsRequest req;
-
- WSADATA wsaData;
-
- // Fire up winsock (prob already done, but doesn't matter)
- WORD wVersionRequested = MAKEWORD(1, 1);
- WSAStartup( wVersionRequested, &wsaData );
-
- while ( running )
- {
- // deal with requests
- if (TheGameResultsQueue && TheGameResultsQueue->getRequest(req))
- {
- // resolve the hostname
- const char *hostnameBuffer = req.hostname.c_str();
- UnsignedInt IP = 0xFFFFFFFF;
- if (isdigit(hostnameBuffer[0]))
- {
- IP = inet_addr(hostnameBuffer);
- in_addr hostNode;
- hostNode.s_addr = IP;
- DEBUG_LOG(("sending game results to %s - IP = %s", hostnameBuffer, inet_ntoa(hostNode) ));
- }
- else
- {
- HOSTENT *hostStruct;
- in_addr *hostNode;
- hostStruct = gethostbyname(hostnameBuffer);
- if (hostStruct == NULL)
- {
- DEBUG_LOG(("sending game results to %s - host lookup failed", hostnameBuffer));
-
- // Even though this failed to resolve IP, still need to send a
- // callback.
- IP = 0xFFFFFFFF; // flag for IP resolve failed
- }
- else
- {
- hostNode = (in_addr *) hostStruct->h_addr;
- IP = hostNode->s_addr;
- DEBUG_LOG(("sending game results to %s IP = %s", hostnameBuffer, inet_ntoa(*hostNode) ));
- }
- }
-
- int result = sendGameResults( IP, req.port, req.results );
- GameResultsResponse resp;
- resp.hostname = req.hostname;
- resp.port = req.port;
- resp.sentOk = (result == req.results.length());
-
- }
-
- // end our timeslice
- Switch_Thread();
- }
-
- WSACleanup();
- } catch ( ... ) {
- DEBUG_CRASH(("Exception in results thread!"));
- }
-}
-
-//-------------------------------------------------------------------------
-
-#ifdef DEBUG_LOGGING
-#define CASE(x) case (x): return #x;
-
-static const char *getWSAErrorString( Int error )
-{
- switch (error)
- {
- CASE(WSABASEERR)
- CASE(WSAEINTR)
- CASE(WSAEBADF)
- CASE(WSAEACCES)
- CASE(WSAEFAULT)
- CASE(WSAEINVAL)
- CASE(WSAEMFILE)
- CASE(WSAEWOULDBLOCK)
- CASE(WSAEINPROGRESS)
- CASE(WSAEALREADY)
- CASE(WSAENOTSOCK)
- CASE(WSAEDESTADDRREQ)
- CASE(WSAEMSGSIZE)
- CASE(WSAEPROTOTYPE)
- CASE(WSAENOPROTOOPT)
- CASE(WSAEPROTONOSUPPORT)
- CASE(WSAESOCKTNOSUPPORT)
- CASE(WSAEOPNOTSUPP)
- CASE(WSAEPFNOSUPPORT)
- CASE(WSAEAFNOSUPPORT)
- CASE(WSAEADDRINUSE)
- CASE(WSAEADDRNOTAVAIL)
- CASE(WSAENETDOWN)
- CASE(WSAENETUNREACH)
- CASE(WSAENETRESET)
- CASE(WSAECONNABORTED)
- CASE(WSAECONNRESET)
- CASE(WSAENOBUFS)
- CASE(WSAEISCONN)
- CASE(WSAENOTCONN)
- CASE(WSAESHUTDOWN)
- CASE(WSAETOOMANYREFS)
- CASE(WSAETIMEDOUT)
- CASE(WSAECONNREFUSED)
- CASE(WSAELOOP)
- CASE(WSAENAMETOOLONG)
- CASE(WSAEHOSTDOWN)
- CASE(WSAEHOSTUNREACH)
- CASE(WSAENOTEMPTY)
- CASE(WSAEPROCLIM)
- CASE(WSAEUSERS)
- CASE(WSAEDQUOT)
- CASE(WSAESTALE)
- CASE(WSAEREMOTE)
- CASE(WSAEDISCON)
- CASE(WSASYSNOTREADY)
- CASE(WSAVERNOTSUPPORTED)
- CASE(WSANOTINITIALISED)
- CASE(WSAHOST_NOT_FOUND)
- CASE(WSATRY_AGAIN)
- CASE(WSANO_RECOVERY)
- CASE(WSANO_DATA)
- default:
- return "Not a Winsock error";
- }
-}
-
-#undef CASE
-
-#endif
-//-------------------------------------------------------------------------
-
-Int GameResultsThreadClass::sendGameResults( UnsignedInt IP, UnsignedShort port, const std::string& results )
-{
- int error = 0;
-
- // create the socket
- Int sock = socket( AF_INET, SOCK_STREAM, 0 );
- if (sock < 0)
- {
- DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - socket() returned %d(%s)", sock, getWSAErrorString(sock)));
- return sock;
- }
-
- // fill in address info
- struct sockaddr_in sockAddr;
- memset( &sockAddr, 0, sizeof( sockAddr ) );
- sockAddr.sin_family = AF_INET;
- sockAddr.sin_addr.s_addr = IP;
- sockAddr.sin_port = htons(port);
-
- // Start the connection process....
- if( connect( sock, (struct sockaddr *)&sockAddr, sizeof( sockAddr ) ) == -1 )
- {
- error = WSAGetLastError();
- DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - connect() returned %d(%s)", error, getWSAErrorString(error)));
- if( ( error == WSAEWOULDBLOCK ) || ( error == WSAEINVAL ) || ( error == WSAEALREADY ) )
- {
- return( -1 );
- }
-
- if( error != WSAEISCONN )
- {
- closesocket( sock );
- return( -1 );
- }
- }
-
- if (send( sock, results.c_str(), results.length(), 0 ) == SOCKET_ERROR)
- {
- error = WSAGetLastError();
- DEBUG_LOG(("GameResultsThreadClass::sendGameResults() - send() returned %d(%s)", error, getWSAErrorString(error)));
- closesocket(sock);
- return WSAGetLastError();
- }
-
- closesocket(sock);
-
- return results.length();
-}
-
-
-//-------------------------------------------------------------------------
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
deleted file mode 100644
index 92ae388c5a9..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
+++ /dev/null
@@ -1,2999 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PeerThread.cpp //////////////////////////////////////////////////////
-// GameSpy Peer (chat) thread
-// This thread communicates with GameSpy's chat server
-// and talks through a message queue with the rest of
-// the game.
-// Author: Matthew D. Campbell, June 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/Registry.h"
-#include "Common/UserPreferences.h"
-#include "Common/version.h"
-#include "GameNetwork/IPEnumeration.h"
-#include "GameNetwork/GameSpy/BuddyThread.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/PeerThread.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-#include "GameNetwork/GameSpy/ThreadUtils.h"
-
-#include "strtok_r.h"
-#include "mutex.h"
-#include "thread.h"
-
-#include "Common/MiniLog.h"
-
-
-// enable this for trying to track down why SBServers are losing their keyvals -MDC 2/20/2003
-#undef SERVER_DEBUGGING
-#ifdef SERVER_DEBUGGING
-void CheckServers(PEER peer);
-#endif // SERVER_DEBUGGING
-
-#ifdef DEBUG_LOGGING
-//#define PING_TEST
-static LogClass s_pingLog("Ping.txt");
-#define PING_LOG(x) s_pingLog.log x
-#else // DEBUG_LOGGING
-#define PING_LOG(x) {}
-#endif // DEBUG_LOGGING
-
-#ifdef DEBUG_LOGGING
-static LogClass s_stateChangedLog("StateChanged.txt");
-
-#define STATECHANGED_LOG(x) s_stateChangedLog.log x
-
-#else // DEBUG_LOGGING
-
-#define STATECHANGED_LOG(x) {}
-
-#endif // DEBUG_LOGGING
-
-// we should always be using broadcast keys from now on. Remove the old code sometime when
-// we're not in a rush, ok?
-// -MDC 2/14/2003
-#define USE_BROADCAST_KEYS
-
-
-int isThreadHosting = 0;
-static UnsignedInt s_lastStateChangedHeartbeat = 0;
-static Bool s_wantStateChangedHeartbeat = FALSE;
-static UnsignedInt s_heartbeatInterval = 10000;
-
-static SOCKET qr2Sock = INVALID_SOCKET;
-
-enum
-{
- EXECRC_KEY = NUM_RESERVED_KEYS + 1,
- INICRC_KEY,
- PW_KEY,
- OBS_KEY,
-#if !RTS_GENERALS
- USE_STATS_KEY,
-#endif
- LADIP_KEY,
- LADPORT_KEY,
- PINGSTR_KEY,
- NUMPLAYER_KEY,
- MAXPLAYER_KEY,
- NUMOBS_KEY,
- NAME__KEY,
- FACTION__KEY,
- COLOR__KEY,
- WINS__KEY,
- LOSSES__KEY
-};
-
-#define EXECRC_STR "exeCRC"
-#define INICRC_STR "iniCRC"
-#define PW_STR "pw"
-#define OBS_STR "obs"
-#define USE_STATS_STR "stat"
-#define LADIP_STR "ladIP"
-#define LADPORT_STR "ladPort"
-#define PINGSTR_STR "pings"
-#define NUMPLAYER_STR "numRealPlayers"
-#define MAXPLAYER_STR "maxRealPlayers"
-#define NUMOBS_STR "numObservers"
-#define NAME__STR "name"
-#define FACTION__STR "faction"
-#define COLOR__STR "color"
-#define WINS__STR "wins"
-#define LOSSES__STR "losses"
-
-//-------------------------------------------------------------------------
-
-typedef std::queue RequestQueue;
-typedef std::queue ResponseQueue;
-class PeerThreadClass;
-
-class GameSpyPeerMessageQueue : public GameSpyPeerMessageQueueInterface
-{
-public:
- virtual ~GameSpyPeerMessageQueue();
- GameSpyPeerMessageQueue();
- virtual void startThread( void );
- virtual void endThread( void );
- virtual Bool isThreadRunning( void );
- virtual Bool isConnected( void );
- virtual Bool isConnecting( void );
-
- virtual void addRequest( const PeerRequest& req );
- virtual Bool getRequest( PeerRequest& req );
-
- virtual void addResponse( const PeerResponse& resp );
- virtual Bool getResponse( PeerResponse& resp );
-
- virtual SerialAuthResult getSerialAuthResult( void ) { return m_serialAuth; }
- void setSerialAuthResult( SerialAuthResult result ) { m_serialAuth = result; }
-
- PeerThreadClass* getThread( void );
-
-private:
- MutexClass m_requestMutex;
- MutexClass m_responseMutex;
- RequestQueue m_requests;
- ResponseQueue m_responses;
- PeerThreadClass *m_thread;
-
- SerialAuthResult m_serialAuth;
-};
-
-GameSpyPeerMessageQueueInterface* GameSpyPeerMessageQueueInterface::createNewMessageQueue( void )
-{
- return NEW GameSpyPeerMessageQueue;
-}
-
-GameSpyPeerMessageQueueInterface *TheGameSpyPeerMessageQueue;
-#define MESSAGE_QUEUE ((GameSpyPeerMessageQueue *)TheGameSpyPeerMessageQueue)
-
-//-------------------------------------------------------------------------
-
-class PeerThreadClass : public ThreadClass
-{
-
-public:
- PeerThreadClass() : ThreadClass()
- {
- //Added By Sadullah Nader
- //Initializations inserted
- m_roomJoined = m_allowObservers = m_hasPassword = FALSE;
- m_useStats = TRUE;
- m_exeCRC = m_iniCRC = 0;
- m_gameVersion = 0;
- m_ladderPort = 0;
- m_localRoomID = 0;
- m_maxPlayers = 0;
- m_numObservers = 0;
- m_maxPlayers = 0;
- m_qmGroupRoom = 0;
- m_sawEndOfEnumPlayers = m_sawMatchbot = FALSE;
- m_sawCompleteGameList = FALSE;
- //
- m_isConnecting = m_isConnected = false;
- m_groupRoomID = m_profileID = 0;
- m_nextStagingServer = 1; m_stagingServers.clear();
- m_pingStr = ""; m_mapName = ""; m_ladderIP = ""; m_isHosting = false;
- for (Int i=0; i PlayerStatMap;
- PlayerStatMap m_groupRoomStats;
- PlayerStatMap m_stagingRoomStats;
- std::string packStatKey(const char *nick, const char *key);
-#endif // USE_BROADCAST_KEYS
-
- // game-hosting info for GOA callbacks
- Bool m_isHosting;
- Bool m_hasPassword;
- std::string m_mapName;
- std::string m_playerNames[MAX_SLOTS];
- UnsignedInt m_exeCRC;
- UnsignedInt m_iniCRC;
- UnsignedInt m_gameVersion;
- Bool m_allowObservers;
- Bool m_useStats;
- std::string m_pingStr;
- std::string m_ladderIP;
- UnsignedShort m_ladderPort;
- Int m_playerWins[MAX_SLOTS];
- Int m_playerLosses[MAX_SLOTS];
- Int m_playerProfileID[MAX_SLOTS];
- Int m_playerColors[MAX_SLOTS];
- Int m_playerFactions[MAX_SLOTS];
- Int m_numPlayers;
- Int m_maxPlayers;
- Int m_numObservers;
-
- Int m_nextStagingServer;
- std::map m_stagingServers;
- std::wstring m_localStagingServerName;
- Int m_localRoomID;
-
- void doQuickMatch( PEER peer );
- QMStatus m_qmStatus;
- PeerRequest m_qmInfo;
- Bool m_roomJoined;
- Int m_qmGroupRoom;
- Bool m_sawEndOfEnumPlayers;
- Bool m_sawMatchbot;
- std::string m_matchbotName;
-};
-
-#ifdef USE_BROADCAST_KEYS
-const char* PeerThreadClass::s_keys[6] = { "b_locale", "b_wins", "b_losses", "b_points", "b_side", "b_pre" };
-char PeerThreadClass::s_valueBuffers[6][20] = { "", "", "", "", "", "" };
-const char* PeerThreadClass::s_values[6] = { s_valueBuffers[0], s_valueBuffers[1], s_valueBuffers[2],
- s_valueBuffers[3], s_valueBuffers[4], s_valueBuffers[5]};
-
-void PeerThreadClass::trackStatsForPlayer(RoomType roomType, const char *nick, const char *key, const char *val)
-{
- switch (roomType)
- {
- case GroupRoom:
- m_groupRoomStats[packStatKey(nick, key)] = atoi(val);
- break;
- case StagingRoom:
- m_stagingRoomStats[packStatKey(nick, key)] = atoi(val);
- break;
- }
-}
-
-std::string PeerThreadClass::packStatKey(const char *nick, const char *key)
-{
- std::string s = nick;
- s.append(key);
- return s;
-}
-
-int PeerThreadClass::lookupStatForPlayer(RoomType roomType, const char *nick, const char *key)
-{
- std::string fullKey = packStatKey(nick, key);
- PlayerStatMap::const_iterator it;
- switch (roomType)
- {
- case GroupRoom:
- it = m_groupRoomStats.find(fullKey);
- if (it != m_groupRoomStats.end())
- return it->second;
- break;
- case StagingRoom:
- it = m_stagingRoomStats.find(fullKey);
- if (it != m_stagingRoomStats.end())
- return it->second;
- break;
- }
- return 0;
-}
-
-void PeerThreadClass::clearPlayerStats(RoomType roomType)
-{
- switch (roomType)
- {
- case GroupRoom:
- m_groupRoomStats.clear();
- break;
- case StagingRoom:
- m_stagingRoomStats.clear();
- break;
- }
-}
-
-void PeerThreadClass::pushStatsToRoom(PEER peer)
-{
- DEBUG_LOG(("PeerThreadClass::pushStatsToRoom(): stats are %s=%s,%s=%s,%s=%s,%s=%s,%s=%s,%s=%s",
- s_keys[0], s_values[0],
- s_keys[1], s_values[1],
- s_keys[2], s_values[2],
- s_keys[3], s_values[3],
- s_keys[4], s_values[4],
- s_keys[5], s_values[5]));
- peerSetRoomKeys(peer, GroupRoom, m_loginName.c_str(), 6, s_keys, s_values);
- peerSetRoomKeys(peer, StagingRoom, m_loginName.c_str(), 6, s_keys, s_values);
-}
-
-void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param);
-void PeerThreadClass::getStatsFromRoom(PEER peer, RoomType roomType)
-{
- peerGetRoomKeys(peer, GroupRoom, "*", NumKeys, s_keys, getRoomKeysCallback, this, PEERFalse);
-}
-#endif // USE_BROADCAST_KEYS
-
-Int PeerThreadClass::addServerToMap( SBServer server )
-{
- Int val = m_nextStagingServer++;
- m_stagingServers[val] = server;
- return val;
-}
-
-Int PeerThreadClass::removeServerFromMap( SBServer server )
-{
- for (std::map::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it)
- {
- if (it->second == server)
- {
- Int val = it->first;
- m_stagingServers.erase(it);
- return val;
- }
- }
-
- return 0;
-}
-
-void PeerThreadClass::clearServers( void )
-{
- m_stagingServers.clear();
-}
-
-SBServer PeerThreadClass::findServerByID( Int id )
-{
- std::map::iterator it = m_stagingServers.find(id);
- if (it != m_stagingServers.end())
- {
- SBServer server = it->second;
- if (server && !server->keyvals)
- {
- DEBUG_CRASH(("Referencing a missing server!"));
- return 0;
- }
- return it->second;
- }
- return 0;
-}
-
-Int PeerThreadClass::findServer( SBServer server )
-{
- char tmp[10] = "";
- const char *newName = SBServerGetStringValue(server, "gamename", tmp);
- UnsignedInt newPrivateIP = SBServerGetPrivateInetAddress(server);
- UnsignedShort newPrivatePort = SBServerGetPrivateQueryPort(server);
- UnsignedInt newPublicIP = SBServerGetPublicInetAddress(server);
-
- SBServer serverToRemove = NULL;
-
- for (std::map::iterator it = m_stagingServers.begin(); it != m_stagingServers.end(); ++it)
- {
- if (it->second == server)
- {
- return it->first;
- }
- else
- {
- const char *oldName = SBServerGetStringValue(it->second, "gamename", tmp);
- UnsignedInt oldPrivateIP = SBServerGetPrivateInetAddress(it->second);
- UnsignedShort oldPrivatePort = SBServerGetPrivateQueryPort(it->second);
- UnsignedInt oldPublicIP = SBServerGetPublicInetAddress(it->second);
- if (!strcmp(oldName, newName) &&
- oldPrivateIP == newPrivateIP &&
- oldPublicIP == newPublicIP &&
- oldPrivatePort == newPrivatePort)
- {
- serverToRemove = it->second;
- }
- }
- }
-
- if (serverToRemove)
- {
- // this is the same as another game - it has just migrated to another port. Remove the old and replace it.
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM;
- resp.stagingRoom.id = removeServerFromMap( serverToRemove );
- resp.stagingRoom.action = PEER_REMOVE;
- resp.stagingRoom.isStaging = TRUE;
- resp.stagingRoom.percentComplete = -1;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
-
- return addServerToMap(server);
-}
-
-enum CallbackType
-{
- CALLBACK_CONNECT,
- CALLBACK_ERROR,
- CALLBACK_RECVMESSAGE,
- CALLBACK_RECVREQUEST,
- CALLBACK_RECVSTATUS,
-};
-
-void connectCallbackWrapper( PEER peer, PEERBool success, int failureReason, void *param )
-{
-#ifdef SERVER_DEBUGGING
- DEBUG_LOG(("In connectCallbackWrapper()"));
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
- if (param != NULL)
- {
- ((PeerThreadClass *)param)->connectCallback( peer, success );
- }
-}
-
-void nickErrorCallbackWrapper( PEER peer, Int type, const char *nick, int numSuggestedNicks, const gsi_char** suggestedNicks, void *param )
-{
- if (param != NULL)
- {
- ((PeerThreadClass *)param)->nickErrorCallback( peer, type, nick );
- }
-}
-
-static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param);
-
-//-------------------------------------------------------------------------
-
-GameSpyPeerMessageQueue::GameSpyPeerMessageQueue()
-{
- m_thread = NULL;
- m_serialAuth = SERIAL_OK;
-}
-
-GameSpyPeerMessageQueue::~GameSpyPeerMessageQueue()
-{
- endThread();
-}
-
-void GameSpyPeerMessageQueue::startThread( void )
-{
- if (!m_thread)
- {
- m_thread = NEW PeerThreadClass;
- m_thread->Execute();
- }
- else
- {
- if (!m_thread->Is_Running())
- {
- m_thread->Execute();
- }
- }
-}
-
-void GameSpyPeerMessageQueue::endThread( void )
-{
- delete m_thread;
- m_thread = NULL;
-}
-
-Bool GameSpyPeerMessageQueue::isThreadRunning( void )
-{
- return (m_thread) ? m_thread->Is_Running() : false;
-}
-
-Bool GameSpyPeerMessageQueue::isConnected( void )
-{
- return (m_thread) ? m_thread->isConnected() : false;
-}
-
-Bool GameSpyPeerMessageQueue::isConnecting( void )
-{
- return (m_thread) ? m_thread->isConnecting() : false;
-}
-
-void GameSpyPeerMessageQueue::addRequest( const PeerRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex);
- if (m.Failed())
- return;
-
- m_requests.push(req);
-}
-
-//PeerRequest GameSpyPeerMessageQueue::getRequest( void )
-Bool GameSpyPeerMessageQueue::getRequest( PeerRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_requests.empty())
- return false;
- req = m_requests.front();
- m_requests.pop();
- return true;
-}
-
-void GameSpyPeerMessageQueue::addResponse( const PeerResponse& resp )
-{
- if (resp.nick == "(END)")
- return;
-
- MutexClass::LockClass m(m_responseMutex);
- if (m.Failed())
- return;
-
- m_responses.push(resp);
-}
-
-//PeerResponse GameSpyPeerMessageQueue::getResponse( void )
-Bool GameSpyPeerMessageQueue::getResponse( PeerResponse& resp )
-{
- MutexClass::LockClass m(m_responseMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_responses.empty())
- return false;
- resp = m_responses.front();
- m_responses.pop();
- return true;
-}
-
-PeerThreadClass* GameSpyPeerMessageQueue::getThread( void )
-{
- return m_thread;
-}
-
-//-------------------------------------------------------------------------
-static void disconnectedCallback(PEER peer, const char * reason, void * param);
-static void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param);
-static void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param);
-static void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param);
-static void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param);
-static void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param);
-static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param);
-static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param);
-static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param);
-static void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param);
-static void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param);
-static void gameStartedCallback(PEER peer, SBServer server, const char *message, void *param);
-static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param);
-static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param);
-
-// convenience function to set buddy status
-static void updateBuddyStatus( GameSpyBuddyStatus status, Int groupRoom = 0, std::string gameName = "" )
-{
- if (!TheGameSpyBuddyMessageQueue)
- return;
-
- BuddyRequest req;
- req.buddyRequestType = BuddyRequest::BUDDYREQUEST_SETSTATUS;
- switch(status)
- {
- case BUDDY_OFFLINE:
- req.arg.status.status = GP_OFFLINE;
- strcpy(req.arg.status.statusString, "Offline");
- strcpy(req.arg.status.locationString, "");
- break;
- case BUDDY_ONLINE:
- req.arg.status.status = GP_ONLINE;
- strcpy(req.arg.status.statusString, "Online");
- strcpy(req.arg.status.locationString, "");
- break;
- case BUDDY_LOBBY:
- req.arg.status.status = GP_CHATTING;
- strcpy(req.arg.status.statusString, "Chatting");
- sprintf(req.arg.status.locationString, "%d", groupRoom);
- break;
- case BUDDY_STAGING:
- req.arg.status.status = GP_STAGING;
- strcpy(req.arg.status.statusString, "Staging");
- sprintf(req.arg.status.locationString, "%s", gameName.c_str());
- break;
- case BUDDY_LOADING:
- req.arg.status.status = GP_PLAYING;
- strcpy(req.arg.status.statusString, "Loading");
- sprintf(req.arg.status.locationString, "%s", gameName.c_str());
- break;
- case BUDDY_PLAYING:
- req.arg.status.status = GP_PLAYING;
- strcpy(req.arg.status.statusString, "Playing");
- sprintf(req.arg.status.locationString, "%s", gameName.c_str());
- break;
- case BUDDY_MATCHING:
- req.arg.status.status = GP_ONLINE;
- strcpy(req.arg.status.statusString, "Matching");
- strcpy(req.arg.status.locationString, "");
- break;
- }
- DEBUG_LOG(("updateBuddyStatus %d:%s", req.arg.status.status, req.arg.status.statusString));
- TheGameSpyBuddyMessageQueue->addRequest(req);
-}
-
-static void createRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param)
-{
- Int *s = (Int *)param;
- if (s)
- *s = result;
-}
-
-static const char * KeyTypeToString(qr2_key_type type)
-{
- switch(type)
- {
- case key_server:
- return "server";
- case key_player:
- return "player";
- case key_team:
- return "team";
- }
-
- return "Unkown key type";
-}
-
-static const char * ErrorTypeToString(qr2_error_t error)
-{
- switch(error)
- {
- case e_qrnoerror:
- return "noerror";
- case e_qrwsockerror:
- return "wsockerror";
- case e_qrbinderror:
- return "rbinderror";
- case e_qrdnserror:
- return "dnserror";
- case e_qrconnerror:
- return "connerror";
- }
-
- return "Unknown error type";
-}
-
-static void QRServerKeyCallback
-(
- PEER peer,
- int key,
- qr2_buffer_t buffer,
- void * param
-)
-{
- //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)", key, qr2_registered_key_list[key]));
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRServerKeyCallback: bailing because of no thread info"));
- return;
- }
-
- if (!t->isHosting())
- t->stopHostingAlready(peer);
-
-#ifdef DEBUG_LOGGING
- AsciiString val = "";
-#define ADD(x) { qr2_buffer_add(buffer, x); val = x; }
-#define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); }
-#else
-#define ADD(x) { qr2_buffer_add(buffer, x); }
-#define ADDINT(x) { qr2_buffer_add_int(buffer, x); }
-#endif
-
- switch(key)
- {
- case HOSTNAME_KEY:
- ADD(t->getPlayerName(0).c_str());
- break;
- case GAMEVER_KEY:
- ADDINT(t->gameVersion());
- break;
- case EXECRC_KEY:
- ADDINT(t->exeCRC());
- break;
- case INICRC_KEY:
- ADDINT(t->iniCRC());
- break;
- case GAMENAME_KEY:
- {
- std::string tmp = t->getPlayerName(0);
- tmp.append(" ");
- tmp.append(WideCharStringToMultiByte(t->getLocalStagingServerName().c_str()));
- ADD(tmp.c_str());
- }
- break;
- case MAPNAME_KEY:
- ADD(t->getMapName().c_str());
- break;
- case PW_KEY:
- ADDINT(t->hasPassword());
- break;
- case OBS_KEY:
- ADDINT(t->allowObservers());
- break;
-#if !RTS_GENERALS
- case USE_STATS_KEY:
- ADDINT(t->useStats());
- break;
-#endif
- case LADIP_KEY:
- ADD(t->ladderIP().c_str());
- break;
- case LADPORT_KEY:
- ADDINT(t->ladderPort());
- break;
- case PINGSTR_KEY:
- ADD(t->pingStr().c_str());
- break;
- case NUMPLAYER_KEY:
- ADDINT(t->getNumPlayers());
- break;
- case MAXPLAYER_KEY:
- ADDINT(t->getMaxPlayers());
- break;
- case NUMOBS_KEY:
- ADDINT(t->getNumObservers());
- break;
- default:
- ADD("");
- //DEBUG_LOG(("QR_SERVER_KEY | %d (%s)", key, qr2_registered_key_list[key]));
- break;
- }
-
- DEBUG_LOG(("QR_SERVER_KEY | %d (%s) = [%s]", key, qr2_registered_key_list[key], val.str()));
-}
-
-static void QRPlayerKeyCallback
-(
- PEER peer,
- int key,
- int index,
- qr2_buffer_t buffer,
- void * param
-)
-{
- //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)", key, index, qr2_registered_key_list[key]));
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRPlayerKeyCallback: bailing because of no thread info"));
- return;
- }
-
- if (!t->isHosting())
- t->stopHostingAlready(peer);
-
-#undef ADD
-#undef ADDINT
-#ifdef DEBUG_LOGGING
- AsciiString val = "";
-#define ADD(x) { qr2_buffer_add(buffer, x); val = x; }
-#define ADDINT(x) { qr2_buffer_add_int(buffer, x); val.format("%d",x); }
-#else
-#define ADD(x) { qr2_buffer_add(buffer, x); }
-#define ADDINT(x) { qr2_buffer_add_int(buffer, x); }
-#endif
-
- switch(key)
- {
- case NAME__KEY:
- ADD(t->getPlayerName(index).c_str());
- break;
- case WINS__KEY:
- ADDINT(t->getPlayerWins(index));
- break;
- case LOSSES__KEY:
- ADDINT(t->getPlayerLosses(index));
- break;
- case PID__KEY:
- ADDINT(t->getPlayerProfileID(index));
- break;
- case FACTION__KEY:
- ADDINT(t->getPlayerLosses(index));
- break;
- case COLOR__KEY:
- ADDINT(t->getPlayerLosses(index));
- break;
- default:
- ADD("");
- //DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s)", key, index, qr2_registered_key_list[key]));
- break;
- }
-
- DEBUG_LOG(("QR_PLAYER_KEY | %d | %d (%s) = [%s]", key, index, qr2_registered_key_list[key], val.str()));
-}
-
-static void QRTeamKeyCallback
-(
- PEER peer,
- int key,
- int index,
- qr2_buffer_t buffer,
- void * param
-)
-{
- //DEBUG_LOG(("QR_TEAM_KEY | %d | %d", key, index));
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRTeamKeyCallback: bailing because of no thread info"));
- return;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
-
- // we don't report teams, so this shouldn't get called
- qr2_buffer_add(buffer, "");
-}
-
-static void QRKeyListCallback
-(
- PEER peer,
- qr2_key_type type,
- qr2_keybuffer_t keyBuffer,
- void * param
-)
-{
- DEBUG_LOG(("QR_KEY_LIST | %s", KeyTypeToString(type)));
-
- /*
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRKeyListCallback: bailing because of no thread info"));
- return;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
- */
-
- // register the keys we use
- switch(type)
- {
- case key_server:
- qr2_keybuffer_add(keyBuffer, HOSTNAME_KEY);
- qr2_keybuffer_add(keyBuffer, GAMEVER_KEY);
- //qr2_keybuffer_add(keyBuffer, GAMENAME_KEY);
- qr2_keybuffer_add(keyBuffer, MAPNAME_KEY);
- qr2_keybuffer_add(keyBuffer, EXECRC_KEY);
- qr2_keybuffer_add(keyBuffer, INICRC_KEY);
- qr2_keybuffer_add(keyBuffer, PW_KEY);
- qr2_keybuffer_add(keyBuffer, OBS_KEY);
-#if !RTS_GENERALS
- qr2_keybuffer_add(keyBuffer, USE_STATS_KEY);
-#endif
- qr2_keybuffer_add(keyBuffer, LADIP_KEY);
- qr2_keybuffer_add(keyBuffer, LADPORT_KEY);
- qr2_keybuffer_add(keyBuffer, PINGSTR_KEY);
- qr2_keybuffer_add(keyBuffer, NUMPLAYER_KEY);
- qr2_keybuffer_add(keyBuffer, MAXPLAYER_KEY);
- qr2_keybuffer_add(keyBuffer, NUMOBS_KEY);
- break;
- case key_player:
- qr2_keybuffer_add(keyBuffer, NAME__KEY);
- qr2_keybuffer_add(keyBuffer, WINS__KEY);
- qr2_keybuffer_add(keyBuffer, LOSSES__KEY);
- qr2_keybuffer_add(keyBuffer, PID__KEY);
- qr2_keybuffer_add(keyBuffer, FACTION__KEY);
- qr2_keybuffer_add(keyBuffer, COLOR__KEY);
- break;
- case key_team:
- // no custom team keys
- break;
- }
-}
-
-static int QRCountCallback
-(
- PEER peer,
- qr2_key_type type,
- void * param
-)
-{
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("QRCountCallback: bailing because of no thread info"));
- return 0;
- }
- if (!t->isHosting())
- t->stopHostingAlready(peer);
-
- if(type == key_player)
- {
- DEBUG_LOG(("QR_COUNT | %s = %d", KeyTypeToString(type), t->getNumPlayers() + t->getNumObservers()));
- return t->getNumPlayers() + t->getNumObservers();
- }
- else if(type == key_team)
- {
- DEBUG_LOG(("QR_COUNT | %s = %d", KeyTypeToString(type), 0));
- return 0;
- }
-
- DEBUG_LOG(("QR_COUNT | %s = %d", KeyTypeToString(type), 0));
- return 0;
-}
-
-void PeerThreadClass::stopHostingAlready(PEER peer)
-{
- isThreadHosting = 0; // debugging
- s_lastStateChangedHeartbeat = 0;
- s_wantStateChangedHeartbeat = FALSE;
- peerStopGame(peer);
- if (qr2Sock != INVALID_SOCKET)
- {
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- }
-}
-
-static void QRAddErrorCallback
-(
- PEER peer,
- qr2_error_t error,
- char * errorString,
- void * param
-)
-{
- DEBUG_LOG(("QR_ADD_ERROR | %s | %s", ErrorTypeToString(error), errorString));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_FAILEDTOHOST;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-static void QRNatNegotiateCallback
-(
- PEER peer,
- int cookie,
- void * param
-)
-{
- DEBUG_LOG(("QR_NAT_NEGOTIATE | 0x%08X", cookie));
-}
-
-static void KickedCallback
-(
- PEER peer,
- RoomType roomType,
- const char * nick,
- const char * reason,
- void * param
-)
-{
- DEBUG_LOG(("Kicked from %d by %s: \"%s\"", roomType, nick, reason));
-}
-
-static void NewPlayerListCallback
-(
- PEER peer,
- RoomType roomType,
- void * param
-)
-{
- DEBUG_LOG(("NewPlayerListCallback"));
-}
-
-static void AuthenticateCDKeyCallback
-(
- PEER peer,
- int result,
- const char * message,
- void * param
-)
-{
- DEBUG_LOG(("CD Key Result: %s (%d) %X", message, result, param));
-#ifdef SERVER_DEBUGGING
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
- SerialAuthResult *val = (SerialAuthResult *)param;
- if (val)
- {
- if (result >= 1)
- {
- *val = SERIAL_OK;
- }
- else
- {
- *val = SERIAL_AUTHFAILED;
- }
- }
-#ifdef SERVER_DEBUGGING
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
-}
-
-static SerialAuthResult doCDKeyAuthentication( PEER peer )
-{
- SerialAuthResult retval = SERIAL_NONEXISTENT;
- if (!peer)
- return retval;
-
- AsciiString s = "";
- if (GetStringFromRegistry("\\ergc", "", s) && s.isNotEmpty())
- {
-#ifdef SERVER_DEBUGGING
- DEBUG_LOG(("Before peerAuthenticateCDKey()"));
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
- peerAuthenticateCDKey(peer, s.str(), AuthenticateCDKeyCallback, &retval, PEERTrue);
-#ifdef SERVER_DEBUGGING
- DEBUG_LOG(("After peerAuthenticateCDKey()"));
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
- }
-
- if (retval == SERIAL_OK)
- {
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_READCDKEYSTATS;
- req.cdkey = s.str();
- TheGameSpyPSMessageQueue->addRequest(req);
- }
-
- return retval;
-}
-
-#define INBUF_LEN 256
-void checkQR2Queries( PEER peer, SOCKET sock )
-{
- static char indata[INBUF_LEN];
- struct sockaddr_in saddr;
- int saddrlen = sizeof(struct sockaddr_in);
- fd_set set;
- struct timeval timeout = {0,0};
- int error;
-
- FD_ZERO ( &set );
- FD_SET ( sock, &set );
-
- while (1)
- {
- error = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
- if (SOCKET_ERROR == error || 0 == error)
- return;
- //else we have data
- error = recvfrom(sock, indata, INBUF_LEN - 1, 0, (struct sockaddr *)&saddr, &saddrlen);
- if (error != SOCKET_ERROR)
- {
- indata[error] = '\0';
- peerParseQuery( peer, indata, error, (sockaddr *)&saddr );
- }
- }
-}
-
-static UnsignedInt localIP = 0;
-
-void PeerThreadClass::Thread_Function()
-{
- try {
-
- PEER peer;
-
- // Setup the callbacks.
- ///////////////////////
- PEERCallbacks callbacks;
- memset(&callbacks, 0, sizeof(PEERCallbacks));
- callbacks.disconnected = disconnectedCallback;
- //callbacks.readyChanged = readyChangedCallback;
- callbacks.roomMessage = roomMessageCallback;
- callbacks.playerMessage = playerMessageCallback;
- callbacks.gameStarted = gameStartedCallback;
- callbacks.playerJoined = playerJoinedCallback;
- callbacks.playerLeft = playerLeftCallback;
- callbacks.playerChangedNick = playerChangedNickCallback;
- callbacks.playerFlagsChanged = playerFlagsChangedCallback;
- callbacks.playerInfo = playerInfoCallback;
- callbacks.roomUTM = roomUTMCallback;
- callbacks.playerUTM = playerUTMCallback;
- callbacks.globalKeyChanged = globalKeyChangedCallback;
- callbacks.roomKeyChanged = roomKeyChangedCallback;
-
- callbacks.qrServerKey = QRServerKeyCallback;
- callbacks.qrPlayerKey = QRPlayerKeyCallback;
- callbacks.qrTeamKey = QRTeamKeyCallback;
- callbacks.qrKeyList = QRKeyListCallback;
- callbacks.qrCount = QRCountCallback;
- callbacks.qrAddError = QRAddErrorCallback;
- callbacks.qrNatNegotiateCallback = QRNatNegotiateCallback;
-
- callbacks.kicked = KickedCallback;
- callbacks.newPlayerList = NewPlayerListCallback;
-
- callbacks.param = this;
-
- m_qmGroupRoom = 0;
-
- peer = peerInitialize( &callbacks );
- DEBUG_ASSERTCRASH( peer != NULL, ("NULL peer!") );
- m_isConnected = m_isConnecting = false;
-
- qr2_register_key(EXECRC_KEY, EXECRC_STR);
- qr2_register_key(INICRC_KEY, INICRC_STR);
- qr2_register_key(PW_KEY, PW_STR);
- qr2_register_key(OBS_KEY, OBS_STR);
-#if !RTS_GENERALS
- qr2_register_key(USE_STATS_KEY, USE_STATS_STR);
-#endif
- qr2_register_key(LADIP_KEY, LADIP_STR);
- qr2_register_key(LADPORT_KEY, LADPORT_STR);
- qr2_register_key(PINGSTR_KEY, PINGSTR_STR);
- qr2_register_key(NUMOBS_KEY, NUMOBS_STR);
- qr2_register_key(NUMPLAYER_KEY, NUMPLAYER_STR);
- qr2_register_key(MAXPLAYER_KEY, MAXPLAYER_STR);
- qr2_register_key(NAME__KEY, NAME__STR "_");
- qr2_register_key(WINS__KEY, WINS__STR "_");
- qr2_register_key(LOSSES__KEY, LOSSES__STR "_");
- qr2_register_key(FACTION__KEY, FACTION__STR "_");
- qr2_register_key(COLOR__KEY, COLOR__STR "_");
-
-#if RTS_GENERALS
- const Int NumKeys = 14;
-#else
- const Int NumKeys = 15;
-#endif
- unsigned char allKeysArray[NumKeys] = {
- /*
- PID__KEY,
- NAME__KEY,
- WINS__KEY,
- LOSSES__KEY,
- FACTION__KEY,
- COLOR__KEY,
- */
- MAPNAME_KEY,
- GAMEVER_KEY,
- GAMENAME_KEY,
- EXECRC_KEY,
- INICRC_KEY,
- PW_KEY,
- OBS_KEY,
-#if !RTS_GENERALS
- USE_STATS_KEY,
-#endif
- LADIP_KEY,
- LADPORT_KEY,
- PINGSTR_KEY,
- NUMOBS_KEY,
- NUMPLAYER_KEY,
- MAXPLAYER_KEY,
- HOSTNAME_KEY
- };
-
- /*
- const char *allKeys = "\\pid_\\mapname\\gamever\\gamename" \
- "\\" EXECRC_STR "\\" INICRC_STR \
- "\\" PW_STR "\\" OBS_STR "\\" USE_STATS_STR "\\" LADIP_STR "\\" LADPORT_STR \
- "\\" PINGSTR_STR "\\" NUMOBS_STR \
- "\\" NUMPLAYER_STR "\\" MAXPLAYER_STR \
- "\\" NAME__STR "_" "\\" WINS__STR "_" "\\" LOSSES__STR "_" "\\" FACTION__STR "_" "\\" COLOR__STR "_";
- */
-
- const char * key = "username";
- peerSetRoomWatchKeys(peer, StagingRoom, 1, &key, PEERTrue);
- peerSetRoomWatchKeys(peer, GroupRoom, 1, &key, PEERTrue);
-
- m_localRoomID = 0;
- m_localStagingServerName = L"";
-
- m_qmStatus = QM_IDLE;
-
- // Setup which rooms to do pings and cross-pings in.
- ////////////////////////////////////////////////////
- PEERBool pingRooms[NumRooms];
- PEERBool crossPingRooms[NumRooms];
- pingRooms[TitleRoom] = PEERFalse;
- pingRooms[GroupRoom] = PEERFalse;
- pingRooms[StagingRoom] = PEERFalse;
- crossPingRooms[TitleRoom] = PEERFalse;
- crossPingRooms[GroupRoom] = PEERFalse;
- crossPingRooms[StagingRoom] = PEERFalse;
-
- /*********
- First step, set our game authentication info
- We could do:
- Generals:
- strcpy(gcd_gamename,"ccgenerals");
- strcpy(gcd_secret_key,"h5T2f6");
- ZeroHour:
- strcpy(gcd_gamename,"ccgenzh");
- strcpy(gcd_secret_key,"D6s9k3");
- or
- Generals:
- strcpy(gcd_gamename,"ccgeneralsb");
- strcpy(gcd_secret_key,"g3T9s2");
- ZeroHour:
- strcpy(gcd_gamename,"ccgeneralsb");
- strcpy(gcd_secret_key,"whatever the key is");
- ...but this is more secure:
- **********/
- char gameName[12] = {0};
- char secretKey[7] = {0};
- /**
- gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e';
- gameName[4]='n';gameName[5]='e';gameName[6]='r';gameName[7]='a';
- gameName[8]='l';gameName[9]='s';gameName[10]='b';gameName[11]='\0';
- secretKey[0]='g';secretKey[1]='3';secretKey[2]='T';secretKey[3]='9';
- secretKey[4]='s';secretKey[5]='2';secretKey[6]='\0';
- /**/
-#if RTS_GENERALS
- gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e';
- gameName[4]='n';gameName[5]='e';gameName[6]='r';gameName[7]='a';
- gameName[8]='l';gameName[9]='s';gameName[10]='\0';
- secretKey[0]='h';secretKey[1]='5';secretKey[2]='T';secretKey[3]='2';
- secretKey[4]='f';secretKey[5]='6';secretKey[6]='\0';
-#elif RTS_ZEROHOUR
- gameName[0]='c';gameName[1]='c';gameName[2]='g';gameName[3]='e';
- gameName[4]='n';gameName[5]='z';gameName[6]='h';gameName[7]='\0';
- secretKey[0]='D';secretKey[1]='6';secretKey[2]='s';secretKey[3]='9';
- secretKey[4]='k';secretKey[5]='3';secretKey[6]='\0';
-#endif
- /**/
-
- // Set the title.
- /////////////////
- if(!peerSetTitle( peer , gameName, secretKey, gameName, secretKey, GetRegistryVersion(), 30, PEERTrue, pingRooms, crossPingRooms))
- {
- DEBUG_CRASH(("Error setting title"));
- peerShutdown( peer );
- peer = NULL;
- return;
- }
-
- OptionPreferences pref;
- UnsignedInt preferredIP = INADDR_ANY;
- UnsignedInt selectedIP = pref.getOnlineIPAddress();
- DEBUG_LOG(("Looking for IP %X", selectedIP));
- IPEnumeration IPs;
- EnumeratedIP *IPlist = IPs.getAddresses();
- while (IPlist)
- {
- DEBUG_LOG(("Looking at IP %s", IPlist->getIPstring().str()));
- if (selectedIP == IPlist->getIP())
- {
- preferredIP = IPlist->getIP();
- DEBUG_LOG(("Connecting to GameSpy chat server via IP address %8.8X", preferredIP));
- break;
- }
- IPlist = IPlist->getNext();
- }
- chatSetLocalIP(preferredIP);
-
- UnsignedInt preferredQRPort = 0;
- AsciiString selectedQRPort = pref["GameSpyQRPort"];
- if (selectedQRPort.isNotEmpty())
- {
- preferredQRPort = atoi(selectedQRPort.str());
- }
-
- PeerRequest incomingRequest;
- while ( running )
- {
- // deal with requests
- if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest))
- {
- DEBUG_LOG(("TheGameSpyPeerMessageQueue->getRequest() got request of type %d", incomingRequest.peerRequestType));
- switch (incomingRequest.peerRequestType)
- {
- case PeerRequest::PEERREQUEST_LOGIN:
- {
- m_isConnecting = true;
- m_originalName = incomingRequest.nick;
- m_loginName = incomingRequest.nick;
- m_profileID = incomingRequest.login.profileID;
- m_password = incomingRequest.password;
- m_email = incomingRequest.email;
- peerConnect( peer, incomingRequest.nick.c_str(), incomingRequest.login.profileID, nickErrorCallbackWrapper, connectCallbackWrapper, this, PEERTrue );
-#ifdef SERVER_DEBUGGING
- DEBUG_LOG(("After peerConnect()"));
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
- if (m_isConnected)
- {
- SerialAuthResult ret = doCDKeyAuthentication( peer );
- if (ret != SERIAL_OK)
- {
- m_isConnecting = m_isConnected = false;
- MESSAGE_QUEUE->setSerialAuthResult( ret );
- peerDisconnect( peer );
- }
- }
- m_isConnecting = false;
-
- // check our connection
- //if (m_isConnected)
- //{
- // GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP);
- //}
- }
-
- break;
-
- case PeerRequest::PEERREQUEST_LOGOUT:
- m_isConnecting = m_isConnected = false;
- peerDisconnect( peer );
- break;
-
- case PeerRequest::PEERREQUEST_JOINGROUPROOM:
- m_groupRoomID = incomingRequest.groupRoom.id;
- isThreadHosting = 0; // debugging
- s_lastStateChangedHeartbeat = 0;
- s_wantStateChangedHeartbeat = FALSE;
- peerStopGame( peer );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL );
- if (qr2Sock != INVALID_SOCKET)
- {
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- }
- m_isHosting = false;
- m_localRoomID = m_groupRoomID;
- DEBUG_LOG(("Requesting to join room %d in thread %X", m_localRoomID, this));
- peerJoinGroupRoom( peer, incomingRequest.groupRoom.id, joinRoomCallback, (void *)this, PEERTrue );
- break;
-
- case PeerRequest::PEERREQUEST_LEAVEGROUPROOM:
- m_groupRoomID = 0;
- updateBuddyStatus( BUDDY_ONLINE );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
- break;
-
- case PeerRequest::PEERREQUEST_JOINSTAGINGROOM:
- {
- m_groupRoomID = 0;
- updateBuddyStatus( BUDDY_ONLINE );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
- SBServer server = findServerByID(incomingRequest.stagingRoom.id);
- m_localStagingServerName = incomingRequest.text;
- DEBUG_LOG(("Setting m_localStagingServerName to [%ls]", m_localStagingServerName.c_str()));
- m_localRoomID = incomingRequest.stagingRoom.id;
- DEBUG_LOG(("Requesting to join room %d", m_localRoomID));
- if (server)
- {
- peerJoinStagingRoom( peer, server, incomingRequest.password.c_str(), joinRoomCallback, (void *)this, PEERTrue );
- }
- else
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM;
- resp.joinStagingRoom.id = incomingRequest.stagingRoom.id;
- resp.joinStagingRoom.ok = FALSE;
- resp.joinStagingRoom.result = PEERJoinFailed;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
- break;
-
- case PeerRequest::PEERREQUEST_LEAVESTAGINGROOM:
- m_groupRoomID = 0;
- updateBuddyStatus( BUDDY_ONLINE );
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL );
- isThreadHosting = 0; // debugging
- s_lastStateChangedHeartbeat = 0;
- s_wantStateChangedHeartbeat = FALSE;
- if (m_isHosting)
- {
- peerStopGame( peer );
- if (qr2Sock != INVALID_SOCKET)
- {
- closesocket(qr2Sock);
- qr2Sock = INVALID_SOCKET;
- }
- m_isHosting = false;
- }
- break;
-
- case PeerRequest::PEERREQUEST_MESSAGEPLAYER:
- {
- std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str());
- peerMessagePlayer( peer, incomingRequest.nick.c_str(), s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage );
- }
- break;
-
- case PeerRequest::PEERREQUEST_MESSAGEROOM:
- {
- std::string s = WideCharStringToMultiByte(incomingRequest.text.c_str());
- peerMessageRoom( peer, (m_groupRoomID)?GroupRoom:StagingRoom, s.c_str(), (incomingRequest.message.isAction)?ActionMessage:NormalMessage );
- }
- break;
-
- case PeerRequest::PEERREQUEST_PUSHSTATS:
- {
- DEBUG_LOG(("PEERREQUEST_PUSHSTATS: stats are %d,%d,%d,%d,%d,%d",
- incomingRequest.statsToPush.locale, incomingRequest.statsToPush.wins, incomingRequest.statsToPush.losses, incomingRequest.statsToPush.rankPoints, incomingRequest.statsToPush.side, incomingRequest.statsToPush.preorder));
-
- // Testing alternate way to push stats
-#ifdef USE_BROADCAST_KEYS
- snprintf(s_valueBuffers[0], 20, "%d", incomingRequest.statsToPush.locale);
- snprintf(s_valueBuffers[1], 20, "%d", incomingRequest.statsToPush.wins);
- snprintf(s_valueBuffers[2], 20, "%d", incomingRequest.statsToPush.losses);
- snprintf(s_valueBuffers[3], 20, "%d", incomingRequest.statsToPush.rankPoints);
- snprintf(s_valueBuffers[4], 20, "%d", incomingRequest.statsToPush.side);
- snprintf(s_valueBuffers[5], 20, "%d", incomingRequest.statsToPush.preorder);
- pushStatsToRoom(peer);
-#else
- const char *keys[6] = { "locale", "wins", "losses", "points", "side", "pre" };
- char valueStrings[6][20];
- char *values[6] = { valueStrings[0], valueStrings[1], valueStrings[2],
- valueStrings[3], valueStrings[4], valueStrings[5]};
- snprintf(values[0], 20, "%d", incomingRequest.statsToPush.locale);
- snprintf(values[1], 20, "%d", incomingRequest.statsToPush.wins);
- snprintf(values[2], 20, "%d", incomingRequest.statsToPush.losses);
- snprintf(values[3], 20, "%d", incomingRequest.statsToPush.rankPoints);
- snprintf(values[4], 20, "%d", incomingRequest.statsToPush.side);
- snprintf(values[5], 20, "%d", incomingRequest.statsToPush.preorder);
- peerSetGlobalKeys(peer, 6, (const char **)keys, (const char **)values);
- peerSetGlobalWatchKeys(peer, GroupRoom, 0, NULL, PEERFalse);
- peerSetGlobalWatchKeys(peer, StagingRoom, 0, NULL, PEERFalse);
- peerSetGlobalWatchKeys(peer, GroupRoom, 6, keys, PEERTrue);
- peerSetGlobalWatchKeys(peer, StagingRoom, 6, keys, PEERTrue);
-#endif
- }
- break;
-
- case PeerRequest::PEERREQUEST_SETGAMEOPTIONS:
- {
- m_mapName = incomingRequest.gameOptsMapName;
- m_numPlayers = incomingRequest.gameOptions.numPlayers;
- m_numObservers = incomingRequest.gameOptions.numObservers;
- m_maxPlayers = incomingRequest.gameOptions.maxPlayers;
- DEBUG_LOG(("peerStateChanged(): Marking game options state as changed - %d players, %d observers", m_numPlayers, m_numObservers));
- for (Int i=0; iaddResponse(resp);
-
- if (res != PEERJoinSuccess && res != PEERAlreadyInRoom)
- {
- m_localRoomID = oldGroupID;
- DEBUG_LOG(("Requesting to join room %d", m_localRoomID));
- if (incomingRequest.stagingRoomCreation.restrictGameList)
- {
- peerLeaveRoom( peer, StagingRoom, NULL );
- }
- else
- {
- peerJoinGroupRoom( peer, oldGroupID, joinRoomCallback, (void *)this, PEERTrue );
- }
- m_isHosting = FALSE;
- m_localStagingServerName = L"";
- m_playerNames[0] = "";
- }
- else
- {
- if (incomingRequest.stagingRoomCreation.restrictGameList)
- {
- peerLeaveRoom( peer, GroupRoom, NULL );
- }
- isThreadHosting = 1; // debugging
- s_lastStateChangedHeartbeat = timeGetTime(); // wait the full interval before updating state
- s_wantStateChangedHeartbeat = FALSE;
- m_isHosting = TRUE;
- m_allowObservers = incomingRequest.stagingRoomCreation.allowObservers;
- m_useStats = incomingRequest.stagingRoomCreation.useStats;
- m_mapName = "";
- for (Int i=0; i 0)
- m_hasPassword = true;
- else
- m_hasPassword = false;
- m_playerNames[0] = m_loginName;
- m_exeCRC = incomingRequest.stagingRoomCreation.exeCRC;
- m_iniCRC = incomingRequest.stagingRoomCreation.iniCRC;
- m_gameVersion = incomingRequest.stagingRoomCreation.gameVersion;
- m_localStagingServerName = incomingRequest.text;
- m_ladderIP = incomingRequest.ladderIP;
- m_pingStr = incomingRequest.hostPingStr;
- m_ladderPort = incomingRequest.stagingRoomCreation.ladPort;
-
-#ifdef USE_BROADCAST_KEYS
- pushStatsToRoom(peer);
-#endif // USE_BROADCAST_KEYS
-
- DEBUG_LOG(("Setting m_localStagingServerName to [%ls]", m_localStagingServerName.c_str()));
- updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(m_localStagingServerName.c_str()) );
- }
- }
- break;
-
- case PeerRequest::PEERREQUEST_STARTGAMELIST:
- {
- m_sawCompleteGameList = FALSE;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM;
- resp.stagingRoom.action = PEER_CLEAR;
- resp.stagingRoom.isStaging = TRUE;
- resp.stagingRoom.percentComplete = 0;
- clearServers();
- TheGameSpyPeerMessageQueue->addResponse(resp);
- peerStartListingGames( peer, allKeysArray, NumKeys, (incomingRequest.gameList.restrictGameList?"~":NULL), listingGamesCallback, this );
- }
- break;
-
- case PeerRequest::PEERREQUEST_STOPGAMELIST:
- {
- peerStopListingGames( peer );
- }
- break;
-
- case PeerRequest::PEERREQUEST_STARTGAME:
- {
- peerStartGame( peer, NULL, PEER_STOP_REPORTING);
- }
- break;
-
- case PeerRequest::PEERREQUEST_UTMPLAYER:
- {
- if (incomingRequest.nick.length() > 0)
- {
- peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse );
- }
- }
- break;
-
- case PeerRequest::PEERREQUEST_UTMROOM:
- {
- peerUTMRoom( peer, (incomingRequest.UTM.isStagingRoom)?StagingRoom:GroupRoom, incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse );
- }
- break;
-
- case PeerRequest::PEERREQUEST_STARTQUICKMATCH:
- {
- m_qmInfo = incomingRequest;
- doQuickMatch( peer );
- }
- break;
-
- }
- }
-
- if (isThreadHosting && s_wantStateChangedHeartbeat)
- {
- UnsignedInt now = timeGetTime();
- if (now > s_lastStateChangedHeartbeat + s_heartbeatInterval)
- {
- s_lastStateChangedHeartbeat = now;
- s_wantStateChangedHeartbeat = FALSE;
- peerStateChanged( peer );
-
-#ifdef DEBUG_LOGGING
- static UnsignedInt prev = 0;
- UnsignedInt now = timeGetTime();
- UnsignedInt diff = now - prev;
- prev = now;
-#endif
- STATECHANGED_LOG(("peerStateChanged() at time %d (difference of %d ms)", now, diff));
- }
- }
-
- // update the network
- PEERBool isConnected = PEERTrue;
- isConnected = peerIsConnected( peer );
- if ( isConnected == PEERTrue )
- {
- if (qr2Sock != INVALID_SOCKET)
- {
- // check hosting activity
- checkQR2Queries( peer, qr2Sock );
- }
- peerThink( peer );
- }
-
- // end our timeslice
- Switch_Thread();
- }
-
- DEBUG_LOG(("voluntarily ending peer thread %d", running));
- peerShutdown( peer );
-
- } catch ( ... ) {
- DEBUG_CRASH(("Exception in peer thread!"));
-
- try {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_LOSTCON;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- catch (...)
- {
- }
- }
-}
-
-static void qmProfileIDCallback( PEER peer, PEERBool success, const char *nick, int profileID, void *param )
-{
- Int *i = (Int *)param;
- if (!i || !success || !nick)
- return;
-
- *i = profileID;
-}
-
-static Int matchbotProfileID = 0;
-void quickmatchEnumPlayersCallback( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param )
-{
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t || !success || nick == NULL || nick[0] == '\0')
- {
- t->sawEndOfEnumPlayers();
- return;
- }
-
- Int id = 0;
- peerGetPlayerProfileID(peer, nick, qmProfileIDCallback, &id, PEERTrue);
- DEBUG_LOG(("Saw player %s with id %d (looking for %d)", nick, id, matchbotProfileID));
- if (id == matchbotProfileID)
- {
- t->sawMatchbot(nick);
- }
-
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN;
- resp.nick = nick;
- resp.player.roomType = roomType;
- resp.player.IP = 0;
-
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-void PeerThreadClass::handleQMMatch(PEER peer, Int mapIndex, Int seed,
- char *playerName[MAX_SLOTS],
- char *playerIP[MAX_SLOTS],
- char *playerSide[MAX_SLOTS],
- char *playerColor[MAX_SLOTS],
- char *playerNAT[MAX_SLOTS])
-{
- if (m_qmStatus == QM_WORKING)
- {
- m_qmStatus = QM_MATCHED;
- peerLeaveRoom(peer, GroupRoom, "");
-
- Int i=0;
- for (; iaddResponse(resp);
- }
-}
-
-void PeerThreadClass::doQuickMatch( PEER peer )
-{
- m_qmStatus = QM_JOININGQMCHANNEL;
- Bool done = false;
- matchbotProfileID = m_qmInfo.QM.botID;
- setQMGroupRoom( m_qmInfo.QM.roomID );
- m_sawMatchbot = false;
- updateBuddyStatus( BUDDY_MATCHING );
- while (!done && running)
- {
- if (!peerIsConnected( peer ))
- {
- done = true;
- }
- else
- {
- // update the network
- peerThink( peer );
-
- // end our timeslice
- Switch_Thread();
-
- PeerRequest incomingRequest;
- if (TheGameSpyPeerMessageQueue->getRequest(incomingRequest))
- {
- switch (incomingRequest.peerRequestType)
- {
- case PeerRequest::PEERREQUEST_WIDENQUICKMATCHSEARCH:
- {
- if (m_qmStatus != QM_IDLE && m_qmStatus != QM_STOPPED && m_sawMatchbot)
- {
- peerMessagePlayer( peer, m_matchbotName.c_str(), "\\WIDEN", NormalMessage );
- }
- }
- break;
- case PeerRequest::PEERREQUEST_STOPQUICKMATCH:
- {
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case PeerRequest::PEERREQUEST_LOGOUT:
- {
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case PeerRequest::PEERREQUEST_LEAVEGROUPROOM:
- {
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case PeerRequest::PEERREQUEST_UTMPLAYER:
- {
- peerUTMPlayer( peer, incomingRequest.nick.c_str(), incomingRequest.id.c_str(), incomingRequest.options.c_str(), PEERFalse );
- }
- break;
- default:
- {
- DEBUG_CRASH(("Unanticipated request %d to peer thread!", incomingRequest.peerRequestType));
- }
- break;
- }
- }
-
- if (!done)
- {
- // do the next bit of QM
- switch (m_qmStatus)
- {
- case QM_JOININGQMCHANNEL:
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_JOININGQMCHANNEL;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- m_groupRoomID = m_qmGroupRoom;
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
- m_localRoomID = m_groupRoomID;
- m_roomJoined = false;
- DEBUG_LOG(("Requesting to join room %d in thread %X", m_localRoomID, this));
- peerJoinGroupRoom( peer, m_localRoomID, joinRoomCallback, (void *)this, PEERTrue );
- if (m_roomJoined)
- {
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_LOOKINGFORBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- m_qmStatus = QM_LOOKINGFORBOT;
- m_sawMatchbot = false;
- m_sawEndOfEnumPlayers = false;
- peerEnumPlayers( peer, GroupRoom, quickmatchEnumPlayersCallback, this );
- }
- else
- {
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_COULDNOTFINDBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- done = true;
- m_qmStatus = QM_STOPPED;
- }
- }
- break;
- case QM_LOOKINGFORBOT:
- {
- if (m_sawEndOfEnumPlayers)
- {
- if (m_sawMatchbot)
- {
- char buf[64];
- std::string msg = "\\CINFO";
- snprintf(buf, 64, "\\Widen\\%d", m_qmInfo.QM.widenTime);
- msg.append(buf);
- snprintf(buf, 64, "\\LadID\\%d", m_qmInfo.QM.ladderID);
- msg.append(buf);
- snprintf(buf, 64, "\\LadPass\\%d", m_qmInfo.QM.ladderPassCRC);
- msg.append(buf);
- snprintf(buf, 64, "\\PointsMin\\%d", m_qmInfo.QM.minPointPercentage);
- msg.append(buf);
- snprintf(buf, 64, "\\PointsMax\\%d", m_qmInfo.QM.maxPointPercentage);
- msg.append(buf);
- snprintf(buf, 64, "\\Points\\%d", m_qmInfo.QM.points);
- msg.append(buf);
- snprintf(buf, 64, "\\Discons\\%d", m_qmInfo.QM.discons);
- msg.append(buf);
- snprintf(buf, 64, "\\DisconMax\\%d", m_qmInfo.QM.maxDiscons);
- msg.append(buf);
- snprintf(buf, 64, "\\NumPlayers\\%d", m_qmInfo.QM.numPlayers);
- msg.append(buf);
- snprintf(buf, 64, "\\Pings\\%s", m_qmInfo.QM.pings);
- msg.append(buf);
- snprintf(buf, 64, "\\IP\\%d", ntohl(peerGetLocalIP(peer)));// not ntohl(localIP), as we need EXTERNAL address for proper NAT negotiation!
- msg.append(buf);
- snprintf(buf, 64, "\\Side\\%d", m_qmInfo.QM.side);
- msg.append(buf);
- snprintf(buf, 64, "\\Color\\%d", m_qmInfo.QM.color);
- msg.append(buf);
- snprintf(buf, 64, "\\NAT\\%d", m_qmInfo.QM.NAT);
- msg.append(buf);
- snprintf(buf, 64, "\\EXE\\%d", m_qmInfo.QM.exeCRC);
- msg.append(buf);
- snprintf(buf, 64, "\\INI\\%d", m_qmInfo.QM.iniCRC);
- msg.append(buf);
- buf[0] = 0;
- msg.append("\\Maps\\");
- for (size_t i=0; iaddResponse(resp);
- }
- else
- {
- // no QM bot. Bail.
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_COULDNOTFINDBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- }
- }
- break;
- case QM_WORKING:
- {
- }
- break;
- case QM_MATCHED:
- {
- // leave QM channel, and clean up. Our work here is done.
- peerLeaveRoom( peer, GroupRoom, NULL );
- peerLeaveRoom( peer, StagingRoom, NULL ); m_isHosting = false;
-
- m_qmStatus = QM_STOPPED;
- peerLeaveRoom(peer, GroupRoom, "");
- done = true;
- }
- break;
- case QM_INCHANNEL:
- {
- }
- break;
- case QM_NEGOTIATINGFIREWALLS:
- {
- }
- break;
- case QM_STARTINGGAME:
- {
- }
- break;
- case QM_COULDNOTFINDCHANNEL:
- {
- }
- break;
- case QM_COULDNOTNEGOTIATEFIREWALLS:
- {
- }
- break;
- }
- }
- }
- }
- updateBuddyStatus( BUDDY_ONLINE );
-}
-
-static void getPlayerProfileIDCallback(PEER peer, PEERBool success, const char * nick, int profileID, void * param)
-{
- if (success && param != NULL)
- {
- *((Int *)param) = profileID;
- }
-}
-
-static void stagingRoomPlayerEnum( PEER peer, PEERBool success, RoomType roomType, int index, const char * nick, int flags, void * param )
-{
- DEBUG_LOG(("Enum: success=%d, index=%d, nick=%s, flags=%d", success, index, nick, flags));
- if (!nick || !success)
- return;
-
- Int id = 0;
- peerGetPlayerProfileID(peer, nick, getPlayerProfileIDCallback, &id, PEERTrue);
- DEBUG_ASSERTCRASH(id != 0, ("Failed to fetch player ID!"));
-
- PeerResponse *resp = (PeerResponse *)param;
- if (flags & PEER_FLAG_OP)
- {
- resp->joinStagingRoom.isHostPresent = TRUE;
- }
- if (index < MAX_SLOTS)
- {
- resp->stagingRoomPlayerNames[index] = nick;
- }
-
- if (id)
- {
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
- req.player.id = id;
- TheGameSpyPSMessageQueue->addRequest(req);
- }
-}
-
-static void joinRoomCallback(PEER peer, PEERBool success, PEERJoinResult result, RoomType roomType, void *param)
-{
- DEBUG_LOG(("JoinRoomCallback: success==%d, result==%d", success, result));
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- return;
- DEBUG_LOG(("Room id was %d from thread %X", t->getLocalRoomID(), t));
- DEBUG_LOG(("Current staging server name is [%ls]", t->getLocalStagingServerName().c_str()));
- DEBUG_LOG(("Room type is %d (GroupRoom=%d, StagingRoom=%d, TitleRoom=%d)", roomType, GroupRoom, StagingRoom, TitleRoom));
-
-#ifdef USE_BROADCAST_KEYS
- if (success)
- {
- t->pushStatsToRoom(peer);
- t->getStatsFromRoom(peer, roomType);
- }
-#endif // USE_BROADCAST_KEYS
-
- switch (roomType)
- {
- case GroupRoom:
- {
-#ifdef USE_BROADCAST_KEYS
- t->clearPlayerStats(GroupRoom);
-#endif // USE_BROADCAST_KEYS
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINGROUPROOM;
- resp.joinGroupRoom.id = t->getLocalRoomID();
- resp.joinGroupRoom.ok = success;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- t->roomJoined(success == PEERTrue);
- DEBUG_LOG(("Entered group room %d, qm is %d", t->getLocalRoomID(), t->getQMGroupRoom()));
- if ((!t->getQMGroupRoom()) || (t->getQMGroupRoom() != t->getLocalRoomID()))
- {
- DEBUG_LOG(("Updating buddy status"));
- updateBuddyStatus( BUDDY_LOBBY, t->getLocalRoomID() );
- }
- }
- break;
- case StagingRoom:
- {
-#ifdef USE_BROADCAST_KEYS
- t->clearPlayerStats(StagingRoom);
-#endif // USE_BROADCAST_KEYS
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_JOINSTAGINGROOM;
- resp.joinStagingRoom.id = t->getLocalRoomID();
- resp.joinStagingRoom.ok = success;
- resp.joinStagingRoom.result = result;
- if (success)
- {
- DEBUG_LOG(("joinRoomCallback() - game name is now '%ls'", t->getLocalStagingServerName().c_str()));
- updateBuddyStatus( BUDDY_STAGING, 0, WideCharStringToMultiByte(t->getLocalStagingServerName().c_str()) );
- }
-
- resp.joinStagingRoom.isHostPresent = FALSE;
- DEBUG_LOG(("Enum of staging room players"));
- peerEnumPlayers(peer, StagingRoom, stagingRoomPlayerEnum, &resp);
- DEBUG_LOG(("Host %s present", (resp.joinStagingRoom.isHostPresent)?"is":"is not"));
-
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- break;
- }
-}
-
-// Gets called once for each group room when listing group rooms.
-// After this has been called for each group room, it will be
-// called one more time with groupID==0 and name==NULL.
-/////////////////////////////////////////////////////////////////
-static void listGroupRoomsCallback(PEER peer, PEERBool success,
- int groupID, SBServer server,
- const char * name, int numWaiting,
- int maxWaiting, int numGames,
- int numPlaying, void * param)
-{
- DEBUG_LOG(("listGroupRoomsCallback, success=%d, server=%X, groupID=%d", success, server, groupID));
-#ifdef SERVER_DEBUGGING
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t)
- {
- DEBUG_LOG(("No thread! Bailing!"));
- return;
- }
-
- if (success)
- {
- DEBUG_LOG(("Saw group room of %d (%s) at address %X %X", groupID, name, server, (server)?server->keyvals:0));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_GROUPROOM;
- resp.groupRoom.id = groupID;
- resp.groupRoom.numWaiting = numWaiting;
- resp.groupRoom.maxWaiting = maxWaiting;
- resp.groupRoom.numGames = numGames;
- resp.groupRoom.numPlaying = numPlaying;
- if (name)
- {
- resp.groupRoomName = name;
- //t->setQMGroupRoom(groupID);
- }
- TheGameSpyPeerMessageQueue->addResponse(resp);
-#ifdef SERVER_DEBUGGING
- CheckServers(peer);
- DEBUG_LOG((""));
-#endif // SERVER_DEBUGGING
- }
- else
- {
- DEBUG_LOG(("Failure!"));
- }
-}
-
-void PeerThreadClass::connectCallback( PEER peer, PEERBool success )
-{
- PeerResponse resp;
- if(!success)
- {
- //updateBuddyStatus( BUDDY_OFFLINE );
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_COULDNOTCONNECT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- return;
- }
-
- updateBuddyStatus( BUDDY_ONLINE );
-
- m_isConnected = true;
- DEBUG_LOG(("Connected as profile %d (%s)", m_profileID, m_loginName.c_str()));
- resp.peerResponseType = PeerResponse::PEERRESPONSE_LOGIN;
- resp.player.profileID = m_profileID;
- resp.nick = m_loginName;
- GetLocalChatConnectionAddress("peerchat.gamespy.com", 6667, localIP);
- chatSetLocalIP(localIP);
- resp.player.internalIP = ntohl(localIP);
- resp.player.externalIP = ntohl(peerGetLocalIP(peer));
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- PSRequest psReq;
- psReq.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
- psReq.player.id = m_profileID;
- psReq.nick = m_originalName;
- psReq.email = m_email;
- psReq.password = m_password;
- TheGameSpyPSMessageQueue->addRequest(psReq);
-
-#ifdef SERVER_DEBUGGING
- DEBUG_LOG(("Before peerListGroupRooms()"));
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
- peerListGroupRooms( peer, NULL, listGroupRoomsCallback, this, PEERTrue );
-#ifdef SERVER_DEBUGGING
- DEBUG_LOG(("After peerListGroupRooms()"));
- CheckServers(peer);
-#endif // SERVER_DEBUGGING
-}
-
-void PeerThreadClass::nickErrorCallback( PEER peer, Int type, const char *nick )
-{
- if(type == PEER_IN_USE)
- {
- Int len = strlen(nick);
- std::string nickStr = nick;
- Int newVal = 0;
- if (nick[len-1] == '}' && nick[len-3] == '{' && isdigit(nick[len-2]))
- {
- newVal = nick[len-2] - '0' + 1;
- nickStr.erase(len-3, 3);
- }
-
- DEBUG_LOG(("Nickname taken: was %s, new val = %d, new nick = %s", nick, newVal, nickStr.c_str()));
-
- if (newVal < 10)
- {
- nickStr.append("{");
- char tmp[2];
- tmp[0] = '0'+newVal;
- tmp[1] = '\0';
- nickStr.append(tmp);
- nickStr.append("}");
- // Retry the connect with a similar nick.
- m_loginName = nickStr;
- peerRetryWithNick(peer, nickStr.c_str());
- }
- else
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_NICKTAKEN;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- // Cancel the connect.
- peerRetryWithNick(peer, NULL);
- }
- }
- else
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_BADNICK;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- // Cancel the connect.
- peerRetryWithNick(peer, NULL);
- }
-}
-
-void disconnectedCallback(PEER peer, const char * reason, void * param)
-{
- DEBUG_LOG(("disconnectedCallback(): reason was '%s'", reason));
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (t)
- t->markAsDisconnected();
- //updateBuddyStatus( BUDDY_OFFLINE );
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_DISCONNECT;
- resp.discon.reason = DISCONNECT_LOSTCON;
- SerialAuthResult res = TheGameSpyPeerMessageQueue->getSerialAuthResult();
- switch (res)
- {
- case SERIAL_NONEXISTENT:
- resp.discon.reason = DISCONNECT_SERIAL_NOT_PRESENT;
- break;
- case SERIAL_AUTHFAILED:
- resp.discon.reason = DISCONNECT_SERIAL_INVALID;
- break;
- case SERIAL_BANNED:
- resp.discon.reason = DISCONNECT_SERIAL_BANNED;
- break;
- }
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-void roomMessageCallback(PEER peer, RoomType roomType, const char * nick, const char * message, MessageType messageType, void * param)
-{
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE;
- resp.nick = nick;
- resp.text = MultiByteToWideCharSingleLine(message);
- resp.message.isPrivate = FALSE;
- resp.message.isAction = (messageType == ActionMessage);
- TheGameSpyPeerMessageQueue->addResponse(resp);
- DEBUG_LOG(("Saw text [%hs] (%ls) %d chars Orig was %s (%d chars)", nick, resp.text.c_str(), resp.text.length(), message, strlen(message)));
-
- UnsignedInt IP;
- peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID);
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED))
- {
- if (resp.message.profileID == matchbotProfileID)
- {
- char *lastStr = NULL;
- char *cmd = strtok_r((char *)message, " ", &lastStr);
- if ( cmd && strcmp(cmd, "MBOT:POOLSIZE") == 0 )
- {
- Int poolSize = 0;
-
- while (1)
- {
- char *poolStr = strtok_r(NULL, " ", &lastStr);
- char *sizeStr = strtok_r(NULL, " ", &lastStr);
- if (poolStr && sizeStr)
- {
- Int pool = atoi(poolStr);
- Int size = atoi(sizeStr);
- if (pool == t->getQMLadder())
- {
- poolSize = size;
- break;
- }
- }
- else
- break;
- }
-
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_POOLSIZE;
- resp.qmStatus.poolSize = poolSize;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
- }
-}
-
-void gameStartedCallback( PEER peer, SBServer server, const char *message, void *param )
-{
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_GAMESTART;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-void playerMessageCallback(PEER peer, const char * nick, const char * message, MessageType messageType, void * param)
-{
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_MESSAGE;
- resp.nick = nick;
- resp.text = MultiByteToWideCharSingleLine(message);
- resp.message.isPrivate = TRUE;
- resp.message.isAction = (messageType == ActionMessage);
- UnsignedInt IP;
- peerGetPlayerInfoNoWait(peer, nick, &IP, &resp.message.profileID);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (t && (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED))
- {
- if (resp.message.isPrivate && resp.message.profileID == matchbotProfileID)
- {
- char *lastStr = NULL;
- char *cmd = strtok_r((char *)message, " ", &lastStr);
- if ( cmd && strcmp(cmd, "MBOT:MATCHED") == 0 )
- {
- char *mapNumStr = strtok_r(NULL, " ", &lastStr);
- char *seedStr = strtok_r(NULL, " ", &lastStr);
- char *playerStr[MAX_SLOTS];
- char *playerIPStr[MAX_SLOTS];
- char *playerSideStr[MAX_SLOTS];
- char *playerColorStr[MAX_SLOTS];
- char *playerNATStr[MAX_SLOTS];
- Int numPlayers = 0;
- for (Int i=0; i 1)
- {
- // woohoo! got everything needed for a match!
- DEBUG_LOG(("Saw %d-player QM match: map index = %s, seed = %s", numPlayers, mapNumStr, seedStr));
- t->handleQMMatch(peer, atoi(mapNumStr), atoi(seedStr), playerStr, playerIPStr, playerSideStr, playerColorStr, playerNATStr);
- }
- }
- else if ( cmd && strcmp(cmd, "MBOT:WORKING") == 0 )
- {
- Int poolSize = 0;
- char *poolStr = strtok_r(NULL, " ", &lastStr);
- if (poolStr)
- poolSize = atoi(poolStr);
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_WORKING;
- resp.qmStatus.poolSize = poolSize;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- else if ( cmd && strcmp(cmd, "MBOT:WIDENINGSEARCH") == 0 )
- {
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_WIDENINGSEARCH;
- TheGameSpyPeerMessageQueue->addResponse(resp);
- }
- }
- }
-}
-
-void roomUTMCallback(PEER peer, RoomType roomType, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param)
-{
- DEBUG_LOG(("roomUTMCallback: %s says %s = [%s]", nick, command, parameters));
- if (roomType != StagingRoom)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_ROOMUTM;
- resp.nick = nick;
- resp.command = command;
- resp.commandOptions = parameters;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-void playerUTMCallback(PEER peer, const char * nick, const char * command, const char * parameters, PEERBool authenticated, void * param)
-{
- DEBUG_LOG(("playerUTMCallback: %s says %s = [%s]", nick, command, parameters));
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERUTM;
- resp.nick = nick;
- resp.command = command;
- resp.commandOptions = parameters;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-static void getPlayerInfo(PeerThreadClass *t, PEER peer, const char *nick, Int& id, UnsignedInt& IP,
- std::string& locale, Int& wins, Int& losses, Int& rankPoints, Int& side, Int& preorder,
- RoomType roomType, Int& flags)
-{
- if (!t || !nick)
- return;
- peerGetPlayerInfoNoWait(peer, nick, &IP, &id);
-#ifdef USE_BROADCAST_KEYS
- //locale.printf
- Int localeIndex = t->lookupStatForPlayer(roomType, nick, "b_locale");
- AsciiString tmp;
- tmp.format("%d", localeIndex);
- locale = tmp.str();
-
- wins = t->lookupStatForPlayer(roomType, nick, "b_wins");
- losses = t->lookupStatForPlayer(roomType, nick, "b_losses");
- rankPoints = t->lookupStatForPlayer(roomType, nick, "b_points");
- side = t->lookupStatForPlayer(roomType, nick, "b_side");
- preorder = t->lookupStatForPlayer(roomType, nick, "b_pre");
-#else // USE_BROADCAST_KEYS
- const char *s;
- s = peerGetGlobalWatchKey(peer, nick, "locale");
- locale = (s)?s:"";
- s = peerGetGlobalWatchKey(peer, nick, "wins");
- wins = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "losses");
- losses = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "points");
- rankPoints = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "side");
- side = atoi((s)?s:"");
- s = peerGetGlobalWatchKey(peer, nick, "pre");
- preorder = atoi((s)?s:"");
-#endif // USE_BROADCAST_KEYS
- flags = 0;
- peerGetPlayerFlags(peer, nick, roomType, &flags);
- DEBUG_LOG(("getPlayerInfo(%d) - %s has locale %s, wins:%d, losses:%d, rankPoints:%d, side:%d, preorder:%d",
- id, nick, locale.c_str(), wins, losses, rankPoints, side, preorder));
-}
-
-static void roomKeyChangedCallback(PEER peer, RoomType roomType, const char *nick, const char *key, const char *val, void *param)
-{
-#ifdef USE_BROADCAST_KEYS
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t || !nick || !key || !val)
- {
- DEBUG_ASSERTCRASH(nick && strcmp(nick,"(END)")==0, ("roomKeyChangedCallback bad values = nick:%X:%s, key:%X:%s, val:%X:%s", nick, nick, key, key, val, val));
- return;
- }
-
-#ifdef DEBUG_LOGGING
- if (strcmp(key, "username") && strcmp(key, "b_flags"))
- {
- DEBUG_LOG(("roomKeyChangedCallback() - %s set %s=%s", nick, key, val));
- }
-#endif
-
- t->trackStatsForPlayer(roomType, nick, key, val);
-
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = roomType;
-
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- resp.player.roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-#endif // USE_BROADCAST_KEYS
-}
-
-#ifdef USE_BROADCAST_KEYS
-void getRoomKeysCallback(PEER peer, PEERBool success, RoomType roomType, const char *nick, int num, char **keys, char **values, void *param)
-{
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t || !nick || !num || !success || !keys || !values)
- {
- DEBUG_ASSERTCRASH(!nick || strcmp(nick,"(END)")==0, ("getRoomKeysCallback bad key/value %X/%X, nick=%s", keys, values, nick));
- return;
- }
-
- for (Int i=0; itrackStatsForPlayer(roomType, nick, keys[i], values[i]);
- }
-
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = roomType;
-
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- resp.player.roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-#endif // USE_BROADCAST_KEYS
-
-static void globalKeyChangedCallback(PEER peer, const char *nick, const char *key, const char *val, void *param)
-{
- if (!nick)
- return;
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
-
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = t->getCurrentGroupRoom()?GroupRoom:StagingRoom;
-
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- resp.player.roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-void playerJoinedCallback(PEER peer, RoomType roomType, const char * nick, void * param)
-{
- if (!nick)
- return;
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
-
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERJOIN;
- resp.nick = nick;
- resp.player.roomType = roomType;
-
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-void playerLeftCallback(PEER peer, RoomType roomType, const char * nick, const char * reason, void * param)
-{
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERLEFT;
- resp.nick = nick;
- resp.player.roomType = roomType;
- resp.player.profileID = 0;
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
-
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- if (t->getQMStatus() != QM_IDLE && t->getQMStatus() != QM_STOPPED)
- {
- if (!stricmp(t->getQMBotName().c_str(), nick))
- {
- // matchbot left - bail
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_QUICKMATCHSTATUS;
- resp.qmStatus.status = QM_COULDNOTFINDBOT;
- TheGameSpyPeerMessageQueue->addResponse(resp);
-
- PeerRequest req;
- req.peerRequestType = PeerRequest::PEERREQUEST_STOPQUICKMATCH;
- TheGameSpyPeerMessageQueue->addRequest(req);
- }
- }
-}
-
-void playerChangedNickCallback(PEER peer, RoomType roomType, const char * oldNick, const char * newNick, void * param)
-{
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDNICK;
- resp.nick = newNick;
- resp.oldNick = oldNick;
- resp.player.roomType = roomType;
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
-
- getPlayerInfo(t, peer, newNick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-static void playerInfoCallback(PEER peer, RoomType roomType, const char * nick, unsigned int IP, int profileID, void * param)
-{
- if (!nick)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERINFO;
- resp.nick = nick;
- resp.player.roomType = roomType;
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
-
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
-DEBUG_LOG(("**GS playerInfoCallback name=%s, local=%s", nick, resp.locale.c_str() ));
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-static void playerFlagsChangedCallback(PEER peer, RoomType roomType, const char * nick, int oldFlags, int newFlags, void * param)
-{
- if (!nick)
- return;
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_PLAYERCHANGEDFLAGS;
- resp.nick = nick;
- resp.player.roomType = roomType;
-
- PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(t, ("No Peer thread!"));
- if (!t)
- return;
-
- getPlayerInfo(t, peer, nick, resp.player.profileID, resp.player.IP,
- resp.locale, resp.player.wins, resp.player.losses,
- resp.player.rankPoints, resp.player.side, resp.player.preorder,
- roomType, resp.player.flags);
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-#ifdef DEBUG_LOGGING
-/*
-static void enumFunc(char *key, char *val, void *param)
-{
- DEBUG_LOG((" [%s] = [%s]", key, val));
-}
-*/
-#endif
-
-static void listingGamesCallback(PEER peer, PEERBool success, const char * name, SBServer server, PEERBool staging, int msg, Int percentListed, void * param)
-{
- PeerThreadClass *t = (PeerThreadClass *)param;
- if (!t || !success)
- return;
-
-#ifdef DEBUG_LOGGING
- AsciiString cmdStr = "";
- switch(msg)
- {
- case PEER_ADD:
- cmdStr = "PEER_ADD";
- break;
- case PEER_UPDATE:
- cmdStr = "PEER_UPDATE";
- break;
- case PEER_REMOVE:
- cmdStr = "PEER_REMOVE";
- break;
- case PEER_CLEAR:
- cmdStr = "PEER_CLEAR";
- break;
- case PEER_COMPLETE:
- cmdStr = "PEER_COMPLETE";
- break;
- }
- DEBUG_LOG(("listingGamesCallback() - doing command %s on server %X", cmdStr.str(), server));
-#endif // DEBUG_LOGGING
-
-// PeerThreadClass *t = (PeerThreadClass *)param;
- DEBUG_ASSERTCRASH(name || msg==PEER_CLEAR || msg==PEER_COMPLETE, ("Game has no name!"));
- if (!t || !success || (!name && (msg == PEER_ADD || msg == PEER_UPDATE)))
- {
- DEBUG_LOG(("Bailing from listingGamesCallback() - success=%d, name=%X, server=%X, msg=%X", success, name, server, msg));
- return;
- }
- if (!name)
- name = "bogus";
-
- if (server && (msg == PEER_ADD || msg == PEER_UPDATE))
- {
- DEBUG_ASSERTCRASH(server->keyvals, ("Looking at an already-freed server for msg type %d!", msg));
- if (!server->keyvals)
- {
- msg = PEER_REMOVE;
- }
- }
-
- if (server && success && (msg == PEER_ADD || msg == PEER_UPDATE))
- {
- DEBUG_LOG(("Game name is '%s'", name));
- const char *newname = SBServerGetStringValue(server, "gamename", (char *)name);
-#if RTS_GENERALS
- if (strcmp(newname, "ccgenerals"))
-#elif RTS_ZEROHOUR
- if (strcmp(newname, "ccgenzh"))
-#endif
- name = newname;
- DEBUG_LOG(("Game name is now '%s'", name));
- }
-
- DEBUG_LOG(("listingGamesCallback - got percent complete %d", percentListed));
- if (percentListed == 100)
- {
- if (!t->getSawCompleteGameList())
- {
- t->setSawCompleteGameList(TRUE);
- PeerResponse completeResp;
- completeResp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOMLISTCOMPLETE;
- TheGameSpyPeerMessageQueue->addResponse(completeResp);
- }
- }
-
- AsciiString gameName = name;
- AsciiString tmp = gameName;
- AsciiString hostName;
- tmp.nextToken(&hostName, " ");
- const char *firstSpace = gameName.find(' ');
- if(firstSpace)
- {
- gameName.set(firstSpace + 1);
- //gameName.trim();
- DEBUG_LOG(("Hostname/Gamename split leaves '%s' hosting '%s'", hostName.str(), gameName.str()));
- }
- PeerResponse resp;
- resp.peerResponseType = PeerResponse::PEERRESPONSE_STAGINGROOM;
- resp.stagingRoom.action = msg;
- resp.stagingRoom.isStaging = staging;
- resp.stagingRoom.percentComplete = percentListed;
-
- if (server && (msg == PEER_ADD || msg == PEER_UPDATE))
- {
- Bool hasPassword = (Bool)SBServerGetIntValue(server, PW_STR, FALSE);
- Bool allowObservers = (Bool)SBServerGetIntValue(server, OBS_STR, FALSE);
- Bool usesStats = (Bool)SBServerGetIntValue(server, USE_STATS_STR, TRUE);
- const char *verStr = SBServerGetStringValue(server, "gamever", "000000");
- const char *exeStr = SBServerGetStringValue(server, EXECRC_STR, "000000");
- const char *iniStr = SBServerGetStringValue(server, INICRC_STR, "000000");
- const char *ladIPStr = SBServerGetStringValue(server, LADIP_STR, "000000");
- const char *pingStr = SBServerGetStringValue(server, PINGSTR_STR, "FFFFFFFFFFFFFFFF");
- UnsignedShort ladPort = (UnsignedShort)SBServerGetIntValue(server, LADPORT_STR, 0);
- UnsignedInt verVal = strtoul(verStr, NULL, 10);
- UnsignedInt exeVal = strtoul(exeStr, NULL, 10);
- UnsignedInt iniVal = strtoul(iniStr, NULL, 10);
- resp.stagingRoom.requiresPassword = hasPassword;
- resp.stagingRoom.allowObservers = allowObservers;
- resp.stagingRoom.useStats = usesStats;
- resp.stagingRoom.version = verVal;
- resp.stagingRoom.exeCRC = exeVal;
- resp.stagingRoom.iniCRC = iniVal;
- resp.stagingServerLadderIP = ladIPStr;
- resp.stagingServerPingString = pingStr;
- resp.stagingRoom.ladderPort = ladPort;
- resp.stagingRoom.numPlayers = SBServerGetIntValue(server, NUMPLAYER_STR, 0);
- resp.stagingRoom.numObservers = SBServerGetIntValue(server, NUMOBS_STR, 0);
- resp.stagingRoom.maxPlayers = SBServerGetIntValue(server, MAXPLAYER_STR, 8);
- resp.stagingRoomMapName = SBServerGetStringValue(server, "mapname", "");
- for (Int i=0; ifindServer( server );
- DEBUG_LOG(("Add/update a 0/0 server %X (%d, %s) - requesting full update to see if that helps.",
- server, resp.stagingRoom.id, gameName.str()));
- TheGameSpyPeerMessageQueue->addRequest(req);
- }
- return; // don't actually try to list it.
- }
- }
-
- switch (msg)
- {
- case PEER_CLEAR:
- t->clearServers();
- break;
- case PEER_ADD:
- case PEER_UPDATE:
- resp.stagingRoom.id = t->findServer( server );
- DEBUG_LOG(("Add/update on server %X (%d, %s)", server, resp.stagingRoom.id, gameName.str()));
- resp.stagingServerName = MultiByteToWideCharSingleLine( gameName.str() );
- DEBUG_LOG(("Server had basic=%d, full=%d", SBServerHasBasicKeys(server), SBServerHasFullKeys(server)));
-#ifdef DEBUG_LOGGING
- //SBServerEnumKeys(server, enumFunc, NULL);
-#endif
- break;
- case PEER_REMOVE:
- DEBUG_LOG(("Removing server %X (%d)", server, resp.stagingRoom.id));
- resp.stagingRoom.id = t->removeServerFromMap( server );
- break;
- }
-
- TheGameSpyPeerMessageQueue->addResponse(resp);
-}
-
-//-------------------------------------------------------------------------
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
deleted file mode 100644
index 34ff36f3a19..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PersistentStorageThread.cpp
+++ /dev/null
@@ -1,1488 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PersistentStorageThread.cpp //////////////////////////////////////////////////////
-// GameSpy Persistent Storage thread
-// This thread communicates with GameSpy's persistent storage server
-// and talks through a message queue with the rest of
-// the game.
-// Author: Matthew D. Campbell, July 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/UserPreferences.h"
-#include "Common/PlayerTemplate.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-
-#include "mutex.h"
-#include "thread.h"
-
-#include "Common/SubsystemInterface.h"
-
-
-//-------------------------------------------------------------------------
-
-PSRequest::PSRequest()
-{
- player.reset();
- requestType = PSREQUEST_READPLAYERSTATS;
- addDiscon = addDesync = FALSE;
- lastHouse = -1;
-}
-
-//-------------------------------------------------------------------------
-
-#define DEBUG_MAP(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \
-{ \
- if (it->second > 0) \
- { \
- DEBUG_LOG(("%s(%d): %d", #x, it->first, it->second)); \
- } \
-}
-
-static void debugDumpPlayerStats( const PSPlayerStats& stats )
-{
- DEBUG_LOG(("-----------------------------------------"));
- DEBUG_LOG(("Tracking player stats for player %d:", stats.id));
- PerGeneralMap::const_iterator it;
- DEBUG_MAP(wins);
- DEBUG_MAP(losses);
- DEBUG_MAP(games);
- DEBUG_MAP(duration);
- DEBUG_MAP(unitsKilled);
- DEBUG_MAP(unitsLost);
- DEBUG_MAP(unitsBuilt);
- DEBUG_MAP(buildingsKilled);
- DEBUG_MAP(buildingsLost);
- DEBUG_MAP(buildingsBuilt);
- DEBUG_MAP(earnings);
- DEBUG_MAP(techCaptured);
- DEBUG_MAP(discons);
- DEBUG_MAP(desyncs);
- DEBUG_MAP(surrenders);
- DEBUG_MAP(gamesOf2p);
- DEBUG_MAP(gamesOf3p);
- DEBUG_MAP(gamesOf4p);
- DEBUG_MAP(gamesOf5p);
- DEBUG_MAP(gamesOf6p);
- DEBUG_MAP(gamesOf7p);
- DEBUG_MAP(gamesOf8p);
- DEBUG_MAP(customGames);
- DEBUG_MAP(QMGames);
-
- if (stats.locale > 0)
- {
- DEBUG_LOG(("Locale: %d", stats.locale));
- }
-
- if (stats.gamesAsRandom > 0)
- {
- DEBUG_LOG(("gamesAsRandom: %d", stats.gamesAsRandom));
- }
-
- if (stats.options.length())
- {
- DEBUG_LOG(("Options: %s", stats.options.c_str()));
- }
-
- if (stats.systemSpec.length())
- {
- DEBUG_LOG(("systemSpec: %s", stats.systemSpec.c_str()));
- }
-
- if (stats.lastFPS > 0.0f)
- {
- DEBUG_LOG(("lastFPS: %g", stats.lastFPS));
- }
-
- if (stats.battleHonors > 0)
- {
- DEBUG_LOG(("battleHonors: %x", stats.battleHonors));
- }
- if (stats.challengeMedals > 0)
- {
- DEBUG_LOG(("challengeMedals: %x", stats.challengeMedals));
- }
- if (stats.lastGeneral >= 0)
- {
- DEBUG_LOG(("lastGeneral: %d", stats.lastGeneral));
- }
- if (stats.gamesInRowWithLastGeneral >= 0)
- {
- DEBUG_LOG(("gamesInRowWithLastGeneral: %d", stats.gamesInRowWithLastGeneral));
- }
- if (stats.builtSCUD >= 0)
- {
- DEBUG_LOG(("builtSCUD: %d", stats.builtSCUD));
- }
- if (stats.builtNuke >= 0)
- {
- DEBUG_LOG(("builtNuke: %d", stats.builtNuke));
- }
- if (stats.builtParticleCannon >= 0)
- {
- DEBUG_LOG(("builtParticleCannon: %d", stats.builtParticleCannon));
- }
-
- if (stats.winsInARow >= 0)
- {
- DEBUG_LOG(("winsInARow: %d", stats.winsInARow));
- }
- if (stats.maxWinsInARow >= 0)
- {
- DEBUG_LOG(("maxWinsInARow: %d", stats.maxWinsInARow));
- }
- if (stats.disconsInARow >= 0)
- {
- DEBUG_LOG(("disconsInARow: %d", stats.disconsInARow));
- }
- if (stats.maxDisconsInARow >= 0)
- {
- DEBUG_LOG(("maxDisconsInARow: %d", stats.maxDisconsInARow));
- }
- if (stats.lossesInARow >= 0)
- {
- DEBUG_LOG(("lossesInARow: %d", stats.lossesInARow));
- }
- if (stats.maxLossesInARow >= 0)
- {
- DEBUG_LOG(("maxLossesInARow: %d", stats.maxLossesInARow));
- }
- if (stats.desyncsInARow >= 0)
- {
- DEBUG_LOG(("desyncsInARow: %d", stats.desyncsInARow));
- }
- if (stats.maxDesyncsInARow >= 0)
- {
- DEBUG_LOG(("maxDesyncsInARow: %d", stats.maxDesyncsInARow));
- }
-
- if (stats.lastLadderPort >= 0)
- {
- DEBUG_LOG(("lastLadderPort: %d", stats.lastLadderPort));
- }
-
- if (stats.lastLadderHost.length())
- {
- DEBUG_LOG(("lastLadderHost: %s", stats.lastLadderHost.c_str()));
- }
-
-
-
-}
-
-//-------------------------------------------------------------------------
-
-#define INCORPORATE_MAP(x) for (it = other.x.begin(); it != other.x.end(); ++it) \
-{ \
- if (it->second > 0) \
- { \
- x[it->first] = it->second; \
- } \
-}
-
-void PSPlayerStats::incorporate( const PSPlayerStats& other )
-{
- PerGeneralMap::const_iterator it;
- INCORPORATE_MAP(wins);
- INCORPORATE_MAP(losses);
- INCORPORATE_MAP(games);
- INCORPORATE_MAP(duration);
- INCORPORATE_MAP(unitsKilled);
- INCORPORATE_MAP(unitsLost);
- INCORPORATE_MAP(unitsBuilt);
- INCORPORATE_MAP(buildingsKilled);
- INCORPORATE_MAP(buildingsLost);
- INCORPORATE_MAP(buildingsBuilt);
- INCORPORATE_MAP(earnings);
- INCORPORATE_MAP(techCaptured);
-
- //GS Clear all disconnects so that we don't retain any that were
- //previously reported as 1 by updateAdditionalGameSpyDisconnections
- discons.clear();
- INCORPORATE_MAP(discons);
-
- INCORPORATE_MAP(desyncs);
- INCORPORATE_MAP(surrenders);
- INCORPORATE_MAP(gamesOf2p);
- INCORPORATE_MAP(gamesOf3p);
- INCORPORATE_MAP(gamesOf4p);
- INCORPORATE_MAP(gamesOf5p);
- INCORPORATE_MAP(gamesOf6p);
- INCORPORATE_MAP(gamesOf7p);
- INCORPORATE_MAP(gamesOf8p);
- INCORPORATE_MAP(customGames);
- INCORPORATE_MAP(QMGames);
-
- if (other.locale > 0)
- {
- locale = other.locale;
- }
-
- if (other.gamesAsRandom > 0)
- {
- gamesAsRandom = other.gamesAsRandom;
- }
-
- if (other.options.length())
- {
- options = other.options;
- }
-
- if (other.systemSpec.length())
- {
- systemSpec = other.systemSpec;
- }
-
- if (other.lastFPS > 0.0f)
- {
- lastFPS = other.lastFPS;
- }
-
- if (other.battleHonors > 0)
- {
- battleHonors |= other.battleHonors;
- }
- if (other.challengeMedals > 0)
- {
- challengeMedals |= other.challengeMedals;
- }
- if (other.lastGeneral >= 0)
- {
- lastGeneral = other.lastGeneral;
- }
- if (other.gamesInRowWithLastGeneral >= 0)
- {
- gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral;
- }
- if (other.builtParticleCannon >= 0)
- {
- builtParticleCannon = other.builtParticleCannon;
- }
- if (other.builtNuke >= 0)
- {
- builtNuke = other.builtNuke;
- }
- if (other.builtSCUD >= 0)
- {
- builtSCUD = other.builtSCUD;
- }
- if (other.winsInARow >= 0)
- {
- winsInARow = other.winsInARow;
- }
- if (other.maxWinsInARow >= 0)
- {
- maxWinsInARow = other.maxWinsInARow;
- }
- if (other.lossesInARow >= 0)
- {
- lossesInARow = other.lossesInARow;
- }
- if (other.maxLossesInARow >= 0)
- {
- maxLossesInARow = other.maxLossesInARow;
- }
- if (other.disconsInARow >= 0)
- {
- disconsInARow = other.disconsInARow;
- }
- if (other.maxDisconsInARow >= 0)
- {
- maxDisconsInARow = other.maxDisconsInARow;
- }
- if (other.desyncsInARow >= 0)
- {
- desyncsInARow = other.desyncsInARow;
- }
- if (other.maxDesyncsInARow >= 0)
- {
- maxDesyncsInARow = other.maxDesyncsInARow;
- }
- if (other.lastLadderPort >= 0)
- {
- lastLadderPort = other.lastLadderPort;
- }
- if (other.lastLadderHost.length())
- {
- lastLadderHost = other.lastLadderHost;
- }
-}
-
-PSPlayerStats::PSPlayerStats( const PSPlayerStats& other )
-{
- incorporate(other);
- id = other.id;
- locale = other.locale;
- gamesAsRandom = other.gamesAsRandom;
- options = other.options;
- systemSpec = other.systemSpec;
- lastFPS = other.lastFPS;
- lastGeneral = other.lastGeneral;
- gamesInRowWithLastGeneral = other.gamesInRowWithLastGeneral;
- builtParticleCannon = other.builtParticleCannon;
- builtNuke = other.builtNuke;
- builtSCUD = other.builtSCUD;
- challengeMedals = other.challengeMedals;
- battleHonors = other.battleHonors;
- winsInARow = other.winsInARow;
- maxWinsInARow = other.maxWinsInARow;
- lossesInARow = other.lossesInARow;
- maxLossesInARow = other.maxLossesInARow;
- disconsInARow = other.disconsInARow;
- maxDisconsInARow = other.maxDisconsInARow;
- desyncsInARow = other.desyncsInARow;
- maxDesyncsInARow = other.maxDesyncsInARow;
- lastLadderHost = other.lastLadderHost;
- lastLadderPort = other.lastLadderPort;
-}
-
-//-------------------------------------------------------------------------
-
-typedef std::queue RequestQueue;
-typedef std::queue ResponseQueue;
-class PSThreadClass;
-
-class GameSpyPSMessageQueue : public GameSpyPSMessageQueueInterface
-{
-public:
- virtual ~GameSpyPSMessageQueue();
- GameSpyPSMessageQueue();
- virtual void startThread( void );
- virtual void endThread( void );
- virtual Bool isThreadRunning( void );
-
- virtual void addRequest( const PSRequest& req );
- virtual Bool getRequest( PSRequest& req );
-
- virtual void addResponse( const PSResponse& resp );
- virtual Bool getResponse( PSResponse& resp );
-
- virtual void trackPlayerStats( PSPlayerStats stats );
- virtual PSPlayerStats findPlayerStatsByID( Int id );
-
- PSThreadClass* getThread( void );
-
- Int getLocalPlayerID(void) { return m_localPlayerID; }
- void setLocalPlayerID(Int localPlayerID) { m_localPlayerID = localPlayerID; }
-
- std::string getEmail() { return m_email; }
- std::string getNick() { return m_nick; }
- std::string getPassword() { return m_password; }
-
- void setEmail(std::string email) { m_email = email; }
- void setNick(std::string nick) { m_nick = nick; }
- void setPassword(std::string password) { m_password = password; }
-
-private:
- MutexClass m_requestMutex;
- MutexClass m_responseMutex;
- RequestQueue m_requests;
- ResponseQueue m_responses;
- PSThreadClass *m_thread;
- Int m_localPlayerID;
-
- std::string m_email;
- std::string m_nick;
- std::string m_password;
-
- std::map m_playerStats;
-};
-
-GameSpyPSMessageQueueInterface* GameSpyPSMessageQueueInterface::createNewMessageQueue( void )
-{
- return NEW GameSpyPSMessageQueue;
-}
-
-GameSpyPSMessageQueueInterface *TheGameSpyPSMessageQueue = NULL;
-#define MESSAGE_QUEUE ((GameSpyPSMessageQueue *)TheGameSpyPSMessageQueue)
-
-//-------------------------------------------------------------------------
-
-class PSThreadClass : public ThreadClass
-{
-
-public:
- PSThreadClass() : ThreadClass()
- {
- m_loginOK = m_sawLocalData = m_doneTryingToLogin = false;
- m_opCount = 0;
- }
-
- void Thread_Function();
-
- void persAuthCallback( Bool val ) { m_loginOK = val; m_doneTryingToLogin = true; }
- void decrOpCount( void ) { --m_opCount; }
- void incrOpCount( void ) { ++m_opCount; }
- Int getOpCount( void ) { return m_opCount; }
- Bool sawLocalPlayerData( void ) { return m_sawLocalData; }
- void gotLocalPlayerData( void ) { m_sawLocalData = TRUE; }
-
-private:
- Bool tryConnect( void );
- Bool tryLogin( Int id, std::string nick, std::string password, std::string email );
- Bool m_loginOK;
- Bool m_doneTryingToLogin;
- Int m_opCount;
- Bool m_sawLocalData;
-};
-
-
-//-------------------------------------------------------------------------
-
-GameSpyPSMessageQueue::GameSpyPSMessageQueue()
-{
- m_thread = NULL;
- m_localPlayerID = 0;
-}
-
-GameSpyPSMessageQueue::~GameSpyPSMessageQueue()
-{
- endThread();
-}
-
-void GameSpyPSMessageQueue::startThread( void )
-{
- if (!m_thread)
- {
- m_thread = NEW PSThreadClass;
- m_thread->Execute();
- }
- else
- {
- if (!m_thread->Is_Running())
- {
- m_thread->Execute();
- }
- }
-}
-
-void GameSpyPSMessageQueue::endThread( void )
-{
- delete m_thread;
- m_thread = NULL;
-}
-
-Bool GameSpyPSMessageQueue::isThreadRunning( void )
-{
- return (m_thread) ? m_thread->Is_Running() : false;
-}
-
-void GameSpyPSMessageQueue::addRequest( const PSRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex);
- if (m.Failed())
- return;
-
- m_requests.push(req);
-}
-
-Bool GameSpyPSMessageQueue::getRequest( PSRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_requests.empty())
- return false;
- req = m_requests.front();
- m_requests.pop();
- return true;
-}
-
-void GameSpyPSMessageQueue::addResponse( const PSResponse& resp )
-{
- MutexClass::LockClass m(m_responseMutex);
- if (m.Failed())
- return;
-
- m_responses.push(resp);
-}
-
-Bool GameSpyPSMessageQueue::getResponse( PSResponse& resp )
-{
- MutexClass::LockClass m(m_responseMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_responses.empty())
- return false;
- resp = m_responses.front();
- m_responses.pop();
- return true;
-}
-
-PSThreadClass* GameSpyPSMessageQueue::getThread( void )
-{
- return m_thread;
-}
-
-void GameSpyPSMessageQueue::trackPlayerStats( PSPlayerStats stats )
-{
-#ifdef DEBUG_LOGGING
- debugDumpPlayerStats( stats );
- DEBUG_ASSERTCRASH(stats.id != 0, ("Tracking stats with ID of 0"));
-#endif
- PSPlayerStats newStats;
- std::map::iterator it = m_playerStats.find(stats.id);
- if (it != m_playerStats.end())
- {
- newStats = it->second;
- newStats.incorporate(stats);
- m_playerStats[stats.id] = newStats;
- }
- else
- {
- m_playerStats[stats.id] = stats;
- }
-}
-
-PSPlayerStats GameSpyPSMessageQueue::findPlayerStatsByID( Int id )
-{
- std::map::iterator it = m_playerStats.find(id);
- if (it != m_playerStats.end())
- {
- return it->second;
- }
-
- PSPlayerStats empty;
- empty.id = 0;
- return empty;
-}
-
-//-------------------------------------------------------------------------
-
-Bool PSThreadClass::tryConnect( void )
-{
- Int result;
-
- DEBUG_LOG(("m_opCount = %d - opening connection", m_opCount));
-
- if (IsStatsConnected())
- {
- DEBUG_LOG(("connection already open!"));
- return true;
- }
-
- // this may block for 1-2 seconds (according to GS) so it's nice we're not in the UI thread :)
- result = InitStatsConnection(0);
-
- if (result != GE_NOERROR)
- {
- DEBUG_LOG(("InitStatsConnection() returned %d", result));
- return false;
- }
-
- return true;
-}
-
-static void persAuthCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance)
-{
- PSThreadClass *t = (PSThreadClass *)instance;
- DEBUG_LOG(("Auth callback: localid: %d profileid: %d auth: %d err: %s",localid, profileid, authenticated, errmsg));
- if (t)
- t->persAuthCallback(authenticated != 0);
-}
-
-Bool PSThreadClass::tryLogin( Int id, std::string nick, std::string password, std::string email )
-{
- char validate[33];
- DEBUG_LOG(("PSThreadClass::tryLogin id = %d, nick = %s, password = %s, email = %s", id, nick.c_str(), password.c_str(), email.c_str()));
- /***********
- We'll go ahead and start the authentication, using a Presence & Messaging SDK
- profileid / password. To generate the new validation token, we'll need to pass
- in the password for the profile we are authenticating.
- Again, if this is done in a client/server setting, with the Persistent Storage
- access being done on the server, and the P&M SDK is used on the client, the
- server will need to send the challenge (GetChallenge(NULL)) to the client, the
- client will create the validation token using GenerateAuth, and send it
- back to the server for use in PreAuthenticatePlayerPM
- ***********/
- char *munkeeHack = strdup(password.c_str()); // GenerateAuth takes a char*, not a const char* :P
- GenerateAuth(GetChallenge(NULL), munkeeHack, validate);
- free (munkeeHack);
-
- /************
- After we get the validation token, we pass it and the profileid of the user
- we are authenticating into PreAuthenticatePlayerPM.
- We pass the same authentication callback as for the first user, but a different
- localid this time.
- ************/
- m_loginOK = false;
- m_doneTryingToLogin = false;
- PreAuthenticatePlayerPM(id, id, validate, ::persAuthCallback, this);
- while (!m_doneTryingToLogin && IsStatsConnected())
- PersistThink();
- DEBUG_LOG(("Persistant Storage Login success %d", m_loginOK));
- return m_loginOK;
-}
-
-static void getPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, char *data, int len, void *instance)
-{
- DEBUG_LOG(("Data get callback: localid: %d profileid: %d success: %d len: %d data: %s",localid, profileid, success, len, data));
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
-
- t->decrOpCount();
-
- PSResponse resp;
-
- if (!success)
- {
- resp.responseType = PSResponse::PSRESPONSE_COULDNOTCONNECT;
- resp.player.id = profileid;
- TheGameSpyPSMessageQueue->addResponse(resp);
- if (!t->getOpCount() && !t->sawLocalPlayerData())
- {
- // we haven't gotten stats for ourselves - try again
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_READPLAYERSTATS;
- req.player.id = MESSAGE_QUEUE->getLocalPlayerID();
- TheGameSpyPSMessageQueue->addRequest(req);
- }
- return;
- }
-
- if (profileid == MESSAGE_QUEUE->getLocalPlayerID() && TheGameSpyGame && TheGameSpyGame->getUseStats())
- {
- t->gotLocalPlayerData();
- DEBUG_LOG(("getPersistentDataCallback() - got local player info"));
-
- // check if we have discons we should update on the server
- UserPreferences pref;
- AsciiString userPrefFilename;
- userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID());
- DEBUG_LOG(("using the file %s", userPrefFilename.str()));
- pref.load(userPrefFilename);
- Int addedInDesyncs2 = pref.getInt("0", 0);
- DEBUG_LOG(("addedInDesyncs2 = %d", addedInDesyncs2));
- if (addedInDesyncs2 < 0)
- addedInDesyncs2 = 10;
- Int addedInDesyncs3 = pref.getInt("1", 0);
- DEBUG_LOG(("addedInDesyncs3 = %d", addedInDesyncs3));
- if (addedInDesyncs3 < 0)
- addedInDesyncs3 = 10;
- Int addedInDesyncs4 = pref.getInt("2", 0);
- DEBUG_LOG(("addedInDesyncs4 = %d", addedInDesyncs4));
- if (addedInDesyncs4 < 0)
- addedInDesyncs4 = 10;
- Int addedInDiscons2 = pref.getInt("3", 0);
- DEBUG_LOG(("addedInDiscons2 = %d", addedInDiscons2));
- if (addedInDiscons2 < 0)
- addedInDiscons2 = 10;
- Int addedInDiscons3 = pref.getInt("4", 0);
- DEBUG_LOG(("addedInDiscons3 = %d", addedInDiscons3));
- if (addedInDiscons3 < 0)
- addedInDiscons3 = 10;
- Int addedInDiscons4 = pref.getInt("5", 0);
- DEBUG_LOG(("addedInDiscons4 = %d", addedInDiscons4));
- if (addedInDiscons4 < 0)
- addedInDiscons4 = 10;
-
- DEBUG_LOG(("addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d",
- addedInDesyncs2, addedInDesyncs3, addedInDesyncs4,
- addedInDiscons2, addedInDiscons3, addedInDiscons4));
-
- if (addedInDesyncs2 || addedInDesyncs3 || addedInDesyncs4 || addedInDiscons2 || addedInDiscons3 || addedInDiscons4)
- {
- DEBUG_LOG(("We have a previous discon we can attempt to update! Bummer..."));
-
- PSRequest req;
- req.requestType = PSRequest::PSREQUEST_UPDATEPLAYERSTATS;
- req.email = MESSAGE_QUEUE->getEmail();
- req.nick = MESSAGE_QUEUE->getNick();
- req.password = MESSAGE_QUEUE->getPassword();
- req.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:"");
- req.player.id = profileid;
- req.addDesync = FALSE;
- req.addDiscon = FALSE;
- req.lastHouse = 0;
- TheGameSpyPSMessageQueue->addRequest(req);
- }
- }
-
- resp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS;
- resp.player = GameSpyPSMessageQueueInterface::parsePlayerKVPairs((len)?data:"");
- resp.player.id = profileid;
-
- TheGameSpyPSMessageQueue->addResponse(resp);
-}
-
-static void setPersistentDataLocaleCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, void *instance)
-{
- DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d", localid, profileid, success));
-
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
-
- t->decrOpCount();
-}
-
-static void setPersistentDataCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, void *instance)
-{
- DEBUG_LOG(("Data save callback: localid: %d profileid: %d success: %d", localid, profileid, success));
-
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
-
- if (success)
- {
- UserPreferences pref;
- AsciiString userPrefFilename;
- userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", profileid);
- DEBUG_LOG(("setPersistentDataCallback - writing stats to file %s", userPrefFilename.str()));
- pref.load(userPrefFilename);
- pref.clear();
- pref.write();
- }
- t->decrOpCount();
-}
-
-struct CDAuthInfo
-{
- Bool success;
- Bool done;
- Int id;
-};
-
-void preAuthCDCallback(int localid, int profileid, int authenticated, char *errmsg, void *instance)
-{
- DEBUG_LOG(("preAuthCDCallback(): profileid: %d auth: %d err: %s", profileid, authenticated, errmsg));
-
- CDAuthInfo *authInfo = (CDAuthInfo *)instance;
- authInfo->success = authenticated;
- authInfo->done = TRUE;
- authInfo->id = profileid;
-}
-
-static void getPreorderCallback(int localid, int profileid, persisttype_t type, int index, int success, time_t modified, char *data, int len, void *instance)
-{
- PSThreadClass *t = (PSThreadClass *)instance;
- if (!t)
- return;
-
- t->decrOpCount();
-
- PSResponse resp;
-
- if (!success)
- {
- DEBUG_LOG(("Failed getPreorderCallback()"));
- return;
- }
-
- resp.responseType = PSResponse::PSRESPONSE_PREORDER;
- resp.preorder = (data && strcmp(data, "\\preorder\\1") == 0);
- DEBUG_LOG(("getPreorderCallback() - data was '%s'", data));
-
- TheGameSpyPSMessageQueue->addResponse(resp);
-}
-
-void PSThreadClass::Thread_Function()
-{
- try {
- /*********
- First step, set our game authentication info
- We could do:
- Generals:
- strcpy(gcd_gamename,"ccgenerals");
- strcpy(gcd_secret_key,"h5T2f6");
- ZeroHour:
- strcpy(gcd_gamename,"ccgenzh");
- strcpy(gcd_secret_key,"D6s9k3");
- or
- Generals:
- strcpy(gcd_gamename,"ccgeneralsb");
- strcpy(gcd_secret_key,"g3T9s2");
- ZeroHour:
- strcpy(gcd_gamename,"ccgeneralsb");
- strcpy(gcd_secret_key,"whatever the key is");
- ...but this is more secure:
- **********/
- /**
- gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e';
- gcd_gamename[4]='n';gcd_gamename[5]='e';gcd_gamename[6]='r';gcd_gamename[7]='a';
- gcd_gamename[8]='l';gcd_gamename[9]='s';gcd_gamename[10]='b';gcd_gamename[11]='\0';
- gcd_secret_key[0]='g';gcd_secret_key[1]='3';gcd_secret_key[2]='T';gcd_secret_key[3]='9';
- gcd_secret_key[4]='s';gcd_secret_key[5]='2';gcd_secret_key[6]='\0';
- /**/
-#if RTS_GENERALS
- gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e';
- gcd_gamename[4]='n';gcd_gamename[5]='e';gcd_gamename[6]='r';gcd_gamename[7]='a';
- gcd_gamename[8]='l';gcd_gamename[9]='s';gcd_gamename[10]='\0';
- gcd_secret_key[0]='h';gcd_secret_key[1]='5';gcd_secret_key[2]='T';gcd_secret_key[3]='2';
- gcd_secret_key[4]='f';gcd_secret_key[5]='6';gcd_secret_key[6]='\0';
-#elif RTS_ZEROHOUR
- gcd_gamename[0]='c';gcd_gamename[1]='c';gcd_gamename[2]='g';gcd_gamename[3]='e';
- gcd_gamename[4]='n';gcd_gamename[5]='z';gcd_gamename[6]='h';gcd_gamename[7]='\0';
- gcd_secret_key[0]='D';gcd_secret_key[1]='6';gcd_secret_key[2]='s';gcd_secret_key[3]='9';
- gcd_secret_key[4]='k';gcd_secret_key[5]='3';gcd_secret_key[6]='\0';
-#endif
- /**/
-
- //strcpy(StatsServerHostname, "sdkdev.gamespy.com");
-
- PSRequest req;
- while ( running )
- {
- // deal with requests
- if (TheGameSpyPSMessageQueue->getRequest(req))
- {
- switch (req.requestType)
- {
- case PSRequest::PSREQUEST_SENDGAMERESTOGAMESPY:
- {
- if (tryConnect())
- {
- NewGame(0);
-#ifdef DEBUG_LOGGING
- Int res =
-#endif // DEBUG_LOGGING
- SendGameSnapShot(NULL, req.results.c_str(), SNAP_FINAL);
- DEBUG_LOG(("Just sent game results - res was %d", res));
- FreeGame(NULL);
- }
- }
- break;
- case PSRequest::PSREQUEST_READPLAYERSTATS:
- {
- if (!MESSAGE_QUEUE->getLocalPlayerID())
- {
- MESSAGE_QUEUE->setLocalPlayerID(req.player.id); // first request is for ourselves
- MESSAGE_QUEUE->setEmail(req.email);
- MESSAGE_QUEUE->setNick(req.nick);
- MESSAGE_QUEUE->setPassword(req.password);
- DEBUG_LOG(("Setting email/nick/password = %s/%s/%s", req.email.c_str(), req.nick.c_str(), req.password.c_str()));
- }
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_READPLAYERSTATS"));
- if (tryConnect())
- {
- incrOpCount();
- gsi_char keys[] = "";
- GetPersistDataValues(0, req.player.id, pd_public_rw, 0, keys, getPersistentDataCallback, this);
- }
- }
- break;
- case PSRequest::PSREQUEST_UPDATEPLAYERLOCALE:
- {
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERLOCALE"));
- if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email))
- {
- char kvbuf[256];
- sprintf(kvbuf, "\\locale\\%d", req.player.locale);
- incrOpCount();
- SetPersistDataValues(0, req.player.id, pd_public_rw, 0, kvbuf, setPersistentDataLocaleCallback, this);
- }
- }
- break;
- case PSRequest::PSREQUEST_UPDATEPLAYERSTATS:
- {
- /*
- ** NOTE THAT THIS IS HIGHLY DEPENDENT ON INI ORDERING FOR THE PLAYERTEMPLATES!!!
- */
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_UPDATEPLAYERSTATS"));
- UserPreferences pref;
- AsciiString userPrefFilename;
- userPrefFilename.format("GeneralsOnline\\MiscPref%d.ini", MESSAGE_QUEUE->getLocalPlayerID());
- DEBUG_LOG(("using the file %s", userPrefFilename.str()));
- pref.load(userPrefFilename);
- Int addedInDesyncs2 = pref.getInt("0", 0);
- DEBUG_LOG(("addedInDesyncs2 = %d", addedInDesyncs2));
- if (addedInDesyncs2 < 0)
- addedInDesyncs2 = 10;
- Int addedInDesyncs3 = pref.getInt("1", 0);
- DEBUG_LOG(("addedInDesyncs3 = %d", addedInDesyncs3));
- if (addedInDesyncs3 < 0)
- addedInDesyncs3 = 10;
- Int addedInDesyncs4 = pref.getInt("2", 0);
- DEBUG_LOG(("addedInDesyncs4 = %d", addedInDesyncs4));
- if (addedInDesyncs4 < 0)
- addedInDesyncs4 = 10;
- Int addedInDiscons2 = pref.getInt("3", 0);
- DEBUG_LOG(("addedInDiscons2 = %d", addedInDiscons2));
- if (addedInDiscons2 < 0)
- addedInDiscons2 = 10;
- Int addedInDiscons3 = pref.getInt("4", 0);
- DEBUG_LOG(("addedInDiscons3 = %d", addedInDiscons3));
- if (addedInDiscons3 < 0)
- addedInDiscons3 = 10;
- Int addedInDiscons4 = pref.getInt("5", 0);
- DEBUG_LOG(("addedInDiscons4 = %d", addedInDiscons4));
- if (addedInDiscons4 < 0)
- addedInDiscons4 = 10;
-
- DEBUG_LOG(("req.addDesync=%d, req.addDiscon=%d, addedInDesync=%d,%d,%d, addedInDiscon=%d,%d,%d",
- req.addDesync, req.addDiscon, addedInDesyncs2, addedInDesyncs3, addedInDesyncs4,
- addedInDiscons2, addedInDiscons3, addedInDiscons4));
-
- if (req.addDesync || req.addDiscon)
- {
- AsciiString val;
- if (req.lastHouse == 2)
- {
- val.format("%d", addedInDesyncs2 + req.addDesync);
- pref["0"] = val;
- val.format("%d", addedInDiscons2 + req.addDiscon);
- pref["3"] = val;
- DEBUG_LOG(("house 2 req.addDesync || req.addDiscon: %d %d",
- addedInDesyncs2 + req.addDesync, addedInDiscons2 + req.addDiscon));
- }
- else if (req.lastHouse == 3)
- {
- val.format("%d", addedInDesyncs3 + req.addDesync);
- pref["1"] = val;
- val.format("%d", addedInDiscons3 + req.addDiscon);
- pref["4"] = val;
- DEBUG_LOG(("house 3 req.addDesync || req.addDiscon: %d %d",
- addedInDesyncs3 + req.addDesync, addedInDiscons3 + req.addDiscon));
- }
- else
- {
- val.format("%d", addedInDesyncs4 + req.addDesync);
- pref["2"] = val;
- val.format("%d", addedInDiscons4 + req.addDiscon);
- pref["5"] = val;
- DEBUG_LOG(("house 4 req.addDesync || req.addDiscon: %d %d",
- addedInDesyncs4 + req.addDesync, addedInDiscons4 + req.addDiscon));
- }
- pref.write();
- if (req.password.size() == 0)
- return;
- }
- if (!req.player.id)
- {
- DEBUG_LOG(("Bailing because ID is NULL!"));
- return;
- }
- req.player.desyncs[2] += addedInDesyncs2;
- req.player.games[2] += addedInDesyncs2;
- req.player.discons[2] += addedInDiscons2;
- req.player.games[2] += addedInDiscons2;
- req.player.desyncs[3] += addedInDesyncs3;
- req.player.games[3] += addedInDesyncs3;
- req.player.discons[3] += addedInDiscons3;
- req.player.games[3] += addedInDiscons3;
- req.player.desyncs[4] += addedInDesyncs4;
- req.player.games[4] += addedInDesyncs4;
- req.player.discons[4] += addedInDiscons4;
- req.player.games[4] += addedInDiscons4;
- DEBUG_LOG(("House2: %d/%d/%d, House3: %d/%d/%d, House4: %d/%d/%d",
- req.player.desyncs[2], req.player.discons[2], req.player.games[2],
- req.player.desyncs[3], req.player.discons[3], req.player.games[3],
- req.player.desyncs[4], req.player.discons[4], req.player.games[4]
- ));
- if (tryConnect() && tryLogin(req.player.id, req.nick, req.password, req.email))
- {
- DEBUG_LOG(("Logged in!"));
- if (TheGameSpyPSMessageQueue)
- TheGameSpyPSMessageQueue->trackPlayerStats(req.player);
-
- char *munkeeHack = strdup(GameSpyPSMessageQueueInterface::formatPlayerKVPairs(req.player).c_str()); // GS takes a char* for some reason
- incrOpCount();
- DEBUG_LOG(("Setting values %s", munkeeHack));
- SetPersistDataValues(0, req.player.id, pd_public_rw, 0, munkeeHack, setPersistentDataCallback, this);
- free(munkeeHack);
- }
- else
- {
- DEBUG_LOG(("Cannot connect!"));
- //if (IsStatsConnected())
- //CloseStatsConnection();
- }
- }
- break;
- case PSRequest::PSREQUEST_READCDKEYSTATS:
- {
- DEBUG_LOG(("Processing PSRequest::PSREQUEST_READCDKEYSTATS"));
- if (tryConnect())
- {
- incrOpCount();
- CDAuthInfo cdAuthInfo;
- cdAuthInfo.done = FALSE;
- cdAuthInfo.success = FALSE;
- cdAuthInfo.id = 0;
- char cdkeyHash[33] = "";
- char validationToken[33] = "";
- char *munkeeHack = strdup(req.cdkey.c_str()); // GenerateAuth takes a char*, not a const char* :P
-
- GenerateAuth(GetChallenge(NULL), munkeeHack, validationToken); // validation token
- GenerateAuth("", munkeeHack, cdkeyHash); // cdkey hash
-
- free (munkeeHack);
-
- PreAuthenticatePlayerCD( 0, "preorder", cdkeyHash, validationToken, preAuthCDCallback , &cdAuthInfo);
-
- while (running && IsStatsConnected() && !cdAuthInfo.done)
- PersistThink();
-
- DEBUG_LOG(("Looking for preorder status for %d (success=%d, done=%d) from CDKey %s with hash %s",
- cdAuthInfo.id, cdAuthInfo.success, cdAuthInfo.done, req.cdkey.c_str(), cdkeyHash));
- if (cdAuthInfo.done && cdAuthInfo.success)
- {
- gsi_char keys[] = "\\preorder";
- GetPersistDataValues(0, cdAuthInfo.id, pd_public_ro, 0, keys, getPreorderCallback, this);
- }
- else
- decrOpCount();
- }
- }
- break;
- }
- }
-
- // update the network
- if (IsStatsConnected())
- {
- PersistThink();
- if (m_opCount <= 0)
- {
- DEBUG_ASSERTCRASH(m_opCount == 0, ("Negative operations pending!!!"));
- DEBUG_LOG(("m_opCount = %d - closing connection", m_opCount));
- CloseStatsConnection();
- m_opCount = 0;
- }
- }
-
- // end our timeslice
- Switch_Thread();
- }
-
- if (IsStatsConnected())
- CloseStatsConnection();
- } catch ( ... ) {
- DEBUG_CRASH(("Exception in storage thread!"));
- }
-}
-
-//-------------------------------------------------------------------------
-PSPlayerStats::PSPlayerStats( void )
-{
- reset();
-}
-
-void PSPlayerStats::reset( void )
-{
- id = 0;
- locale = 0;
- gamesAsRandom = 0;
- lastFPS = 0;
- lastGeneral = 0;
- gamesInRowWithLastGeneral = 0;
- builtNuke = 0;
- builtSCUD = 0;
- builtParticleCannon = 0;
- challengeMedals = 0;
- battleHonors = 0;
- winsInARow = 0;
- maxWinsInARow = 0;
- lossesInARow = 0;
- maxLossesInARow = 0;
- disconsInARow = 0;
- maxDisconsInARow = 0;
- desyncsInARow = 0;
- maxDesyncsInARow = 0;
- lastLadderPort = 0;
-
- //Added By Sadullah Nader
- maxQMwinsInARow = 0;
- QMwinsInARow = 0;
- //
-}
-
-//-------------------------------------------------------------------------
-#define CHECK(x) if (k == #x && generalMarker >= 0) { s.x[generalMarker] = atoi(v.c_str()); continue; }
-
-PSPlayerStats GameSpyPSMessageQueueInterface::parsePlayerKVPairs( std::string kvPairs )
-{
- PSPlayerStats s;
- kvPairs.append("\\");
-
- Int offset = 0;
- while (1)
- {
- Int firstMarker = kvPairs.find_first_of('\\', offset);
- if (firstMarker < 0)
- break;
- Int secondMarker = kvPairs.find_first_of('\\', firstMarker + 1);
- if (secondMarker < 0)
- break;
- Int thirdMarker = kvPairs.find_first_of('\\', secondMarker + 1);
- if (thirdMarker < 0)
- break;
- Int generalMarker = kvPairs.find_last_not_of("0123456789", secondMarker - 1);
- std::string k, v, g;
- if (generalMarker == secondMarker - 1)
- {
- k = kvPairs.substr(firstMarker + 1, secondMarker - firstMarker - 1);
- generalMarker = -1;
- }
- else
- {
- k = kvPairs.substr(firstMarker + 1, generalMarker - firstMarker);
- g = kvPairs.substr(generalMarker + 1, secondMarker - generalMarker - 1);
- generalMarker = atoi(g.c_str());
- }
- v = kvPairs.substr(secondMarker + 1, thirdMarker - secondMarker - 1);
- //DEBUG_LOG(("%d [%s] [%s]", generalMarker, k.c_str(), v.c_str()));
- offset = thirdMarker - 1;
-
- CHECK(wins);
- CHECK(losses);
- CHECK(games);
- CHECK(duration);
- CHECK(unitsKilled);
- CHECK(unitsLost);
- CHECK(unitsBuilt);
- CHECK(buildingsKilled);
- CHECK(buildingsLost);
- CHECK(buildingsBuilt);
- CHECK(earnings);
- CHECK(techCaptured);
- CHECK(discons);
- CHECK(desyncs);
- CHECK(surrenders);
- CHECK(gamesOf2p);
- CHECK(gamesOf3p);
- CHECK(gamesOf4p);
- CHECK(gamesOf5p);
- CHECK(gamesOf6p);
- CHECK(gamesOf7p);
- CHECK(gamesOf8p);
- CHECK(customGames);
- CHECK(QMGames);
-
- if (k == "locale" && generalMarker < 0)
- {
- s.locale = atoi(v.c_str());
- continue;
- }
-
- if (k == "random" && generalMarker < 0)
- {
- s.gamesAsRandom = atoi(v.c_str());
- continue;
- }
-
- if (k == "options" && generalMarker < 0)
- {
- s.options = v;
- continue;
- }
-
- if (k == "systemSpec" && generalMarker < 0)
- {
- s.systemSpec = v;
- continue;
- }
-
- if (k == "fps" && generalMarker < 0)
- {
- s.lastFPS = atof(v.c_str());
- continue;
- }
-
- if (k == "lastGeneral" && generalMarker < 0)
- {
- s.lastGeneral = atoi(v.c_str());
- continue;
- }
- if (k == "genInRow" && generalMarker < 0)
- {
- s.gamesInRowWithLastGeneral = atoi(v.c_str());
- continue;
- }
- if (k == "builtNuke" && generalMarker < 0)
- {
- s.builtNuke = atoi(v.c_str());
- continue;
- }
- if (k == "builtSCUD" && generalMarker < 0)
- {
- s.builtSCUD = atoi(v.c_str());
- continue;
- }
- if (k == "builtCannon" && generalMarker < 0)
- {
- s.builtParticleCannon = atoi(v.c_str());
- continue;
- }
- if (k == "challenge" && generalMarker < 0)
- {
- s.challengeMedals = atoi(v.c_str());
- continue;
- }
- if (k == "battle" && generalMarker < 0)
- {
- s.battleHonors = atoi(v.c_str());
- continue;
- }
-
- if (k == "WinRow" && generalMarker < 0)
- {
- s.winsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "WinRowMax" && generalMarker < 0)
- {
- s.maxWinsInARow = atoi(v.c_str());
- continue;
- }
-
- if (k == "LossRow" && generalMarker < 0)
- {
- s.lossesInARow = atoi(v.c_str());
- continue;
- }
- if (k == "LossRowMax" && generalMarker < 0)
- {
- s.maxLossesInARow = atoi(v.c_str());
- continue;
- }
-
- if (k == "DSRow" && generalMarker < 0)
- {
- s.desyncsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "DSRowMax" && generalMarker < 0)
- {
- s.maxDesyncsInARow = atoi(v.c_str());
- continue;
- }
-
- if (k == "DCRow" && generalMarker < 0)
- {
- s.disconsInARow = atoi(v.c_str());
- continue;
- }
- if (k == "DCRowMax" && generalMarker < 0)
- {
- s.maxDisconsInARow = atoi(v.c_str());
- continue;
- }
-
- if (k == "ladderPort" && generalMarker < 0)
- {
- s.lastLadderPort = atoi(v.c_str());
- continue;
- }
- if (k == "ladderHost" && generalMarker < 0)
- {
- s.lastLadderHost = v;
- continue;
- }
-
- //DEBUG_ASSERTCRASH(generalMarker >= 0, ("Unknown KV Pair in persistent storage: [%s] = [%s]", k.c_str(), v.c_str()));
- //DEBUG_ASSERTCRASH(generalMarker < 0, ("Unknown KV Pair in persistent storage for PlayerTemplate %d: [%s] = [%s]", generalMarker, k.c_str(), v.c_str()));
- }
-
- return s;
-}
-
-#define ITERATE_OVER(x) for (it = stats.x.begin(); it != stats.x.end(); ++it) \
-{ \
- if (it->second > 0) \
- { \
- sprintf(kvbuf, "\\" #x "%d\\%d", it->first, it->second); \
- s.append(kvbuf); \
- } \
-}
-
-#include "Common/PlayerTemplate.h"
-
-std::string GameSpyPSMessageQueueInterface::formatPlayerKVPairs( PSPlayerStats stats )
-{
- char kvbuf[256];
- std::string s = "";
- PerGeneralMap::iterator it;
-
- ITERATE_OVER(wins);
- ITERATE_OVER(losses);
- ITERATE_OVER(games);
- ITERATE_OVER(duration);
- ITERATE_OVER(unitsKilled);
- ITERATE_OVER(unitsLost);
- ITERATE_OVER(unitsBuilt);
- ITERATE_OVER(buildingsKilled);
- ITERATE_OVER(buildingsLost);
- ITERATE_OVER(buildingsBuilt);
- ITERATE_OVER(earnings);
- ITERATE_OVER(techCaptured);
-
- //GS Report all disconnects, even if zero, because might have been
- //previously reported as 1 by updateAdditionalGameSpyDisconnections
-// ITERATE_OVER(discons);
- for (Int ptIdx = 0; ptIdx < ThePlayerTemplateStore->getPlayerTemplateCount(); ++ptIdx)
- {
-// const PlayerTemplate* pTemplate = ThePlayerTemplateStore->getNthPlayerTemplate(ptIdx);
-// const GeneralPersona* pGeneral = TheChallengeGenerals->getGeneralByTemplateName(pTemplate->getName());
-// BOOL isReported = pGeneral ? pGeneral->isStartingEnabled() : FALSE;
-// if( !isReported )
-// continue; //don't report unplayable templates (observer, boss, etc.)
-
- sprintf(kvbuf, "\\discons%d\\%d", ptIdx, stats.discons[ptIdx]);
- s.append(kvbuf);
- }
-
- ITERATE_OVER(desyncs);
- ITERATE_OVER(surrenders);
- ITERATE_OVER(gamesOf2p);
- ITERATE_OVER(gamesOf3p);
- ITERATE_OVER(gamesOf4p);
- ITERATE_OVER(gamesOf5p);
- ITERATE_OVER(gamesOf6p);
- ITERATE_OVER(gamesOf7p);
- ITERATE_OVER(gamesOf8p);
- ITERATE_OVER(customGames);
- ITERATE_OVER(QMGames);
-
- if (stats.locale > 0)
- {
- sprintf(kvbuf, "\\locale\\%d", stats.locale);
- s.append(kvbuf);
- }
-
- if (stats.gamesAsRandom > 0)
- {
- sprintf(kvbuf, "\\random\\%d", stats.gamesAsRandom);
- s.append(kvbuf);
- }
-
- if (stats.options.length())
- {
- snprintf(kvbuf, 256, "\\options\\%s", stats.options.c_str());
- s.append(kvbuf);
- }
-
- if (stats.systemSpec.length())
- {
- snprintf(kvbuf, 256, "\\systemSpec\\%s", stats.systemSpec.c_str());
- s.append(kvbuf);
- }
-
- if (stats.lastFPS > 0.0f)
- {
- sprintf(kvbuf, "\\fps\\%g", stats.lastFPS);
- s.append(kvbuf);
- }
- if (stats.lastGeneral >= 0)
- {
- sprintf(kvbuf, "\\lastGeneral\\%d", stats.lastGeneral);
- s.append(kvbuf);
- }
- if (stats.gamesInRowWithLastGeneral >= 0)
- {
- sprintf(kvbuf, "\\genInRow\\%d", stats.gamesInRowWithLastGeneral);
- s.append(kvbuf);
- }
- if (stats.builtParticleCannon >= 0)
- {
- sprintf(kvbuf, "\\builtCannon\\%d", stats.builtParticleCannon);
- s.append(kvbuf);
- }
- if (stats.builtNuke >= 0)
- {
- sprintf(kvbuf, "\\builtNuke\\%d", stats.builtNuke);
- s.append(kvbuf);
- }
- if (stats.builtSCUD >= 0)
- {
- sprintf(kvbuf, "\\builtSCUD\\%d", stats.builtSCUD);
- s.append(kvbuf);
- }
- if (stats.challengeMedals > 0)
- {
- sprintf(kvbuf, "\\challenge\\%d", stats.challengeMedals);
- s.append(kvbuf);
- }
- if (stats.battleHonors > 0)
- {
- sprintf(kvbuf, "\\battle\\%d", stats.battleHonors);
- s.append(kvbuf);
- }
-
- //if (stats.winsInARow > 0)
- {
- sprintf(kvbuf, "\\WinRow\\%d", stats.winsInARow);
- s.append(kvbuf);
- }
- if (stats.maxWinsInARow > 0)
- {
- sprintf(kvbuf, "\\WinRowMax\\%d", stats.maxWinsInARow);
- s.append(kvbuf);
- }
-
- //if (stats.lossesInARow > 0)
- {
- sprintf(kvbuf, "\\LossRow\\%d", stats.lossesInARow);
- s.append(kvbuf);
- }
- if (stats.maxLossesInARow > 0)
- {
- sprintf(kvbuf, "\\LossRowMax\\%d", stats.maxLossesInARow);
- s.append(kvbuf);
- }
-
- //if (stats.disconsInARow > 0)
- {
- sprintf(kvbuf, "\\DCRow\\%d", stats.disconsInARow);
- s.append(kvbuf);
- }
- if (stats.maxDisconsInARow > 0)
- {
- sprintf(kvbuf, "\\DCRowMax\\%d", stats.maxDisconsInARow);
- s.append(kvbuf);
- }
-
- //if (stats.desyncsInARow > 0)
- {
- sprintf(kvbuf, "\\DSRow\\%d", stats.desyncsInARow);
- s.append(kvbuf);
- }
- if (stats.maxDesyncsInARow > 0)
- {
- sprintf(kvbuf, "\\DSRowMax\\%d", stats.maxDesyncsInARow);
- s.append(kvbuf);
- }
-
- if (stats.lastLadderPort > 0)
- {
- sprintf(kvbuf, "\\ladderPort\\%d", stats.lastLadderPort);
- s.append(kvbuf);
- }
- if (stats.lastLadderHost.length())
- {
- snprintf(kvbuf, 256, "\\ladderHost\\%s", stats.lastLadderHost.c_str());
- s.append(kvbuf);
- }
-
- DEBUG_LOG(("Formatted persistent values as '%s'", s.c_str()));
- return s;
-}
-
-//-------------------------------------------------------------------------
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp
deleted file mode 100644
index b084e9a8c5e..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/PingThread.cpp
+++ /dev/null
@@ -1,573 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: PingThread.cpp //////////////////////////////////////////////////////
-// Ping thread
-// Author: Matthew D. Campbell, August 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include // This one has to be here. Prevents collisions with windsock2.h
-
-#include "GameNetwork/GameSpy/PingThread.h"
-#include "mutex.h"
-#include "thread.h"
-
-#include "Common/SubsystemInterface.h"
-
-//-------------------------------------------------------------------------
-
-static const Int NumWorkerThreads = 10;
-
-typedef std::queue RequestQueue;
-typedef std::queue ResponseQueue;
-class PingThreadClass;
-
-class Pinger : public PingerInterface
-{
-public:
- virtual ~Pinger();
- Pinger();
- virtual void startThreads( void );
- virtual void endThreads( void );
- virtual Bool areThreadsRunning( void );
-
- virtual void addRequest( const PingRequest& req );
- virtual Bool getRequest( PingRequest& resp );
-
- virtual void addResponse( const PingResponse& resp );
- virtual Bool getResponse( PingResponse& resp );
-
- virtual Bool arePingsInProgress( void );
- virtual Int getPing( AsciiString hostname );
-
- virtual void clearPingMap( void );
- virtual AsciiString getPingString( Int timeout );
-
-private:
- MutexClass m_requestMutex;
- MutexClass m_responseMutex;
- MutexClass m_pingMapMutex;
- RequestQueue m_requests;
- ResponseQueue m_responses;
- Int m_requestCount;
- Int m_responseCount;
-
- std::map m_pingMap;
-
- PingThreadClass *m_workerThreads[NumWorkerThreads];
-};
-
-PingerInterface* PingerInterface::createNewPingerInterface( void )
-{
- return NEW Pinger;
-}
-
-PingerInterface *ThePinger;
-
-//-------------------------------------------------------------------------
-
-class PingThreadClass : public ThreadClass
-{
-
-public:
- PingThreadClass() : ThreadClass() {}
-
- void Thread_Function();
-
-private:
- Int doPing( UnsignedInt IP, Int timeout );
-};
-
-
-//-------------------------------------------------------------------------
-
-Pinger::Pinger() : m_requestCount(0), m_responseCount(0)
-{
- for (Int i=0; iExecute();
- }
-}
-
-void Pinger::endThreads( void )
-{
- for (Int i=0; iIs_Running())
- return true;
- }
- }
- return false;
-}
-
-void Pinger::addRequest( const PingRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex);
-
- ++m_requestCount;
- m_requests.push(req);
-}
-
-Bool Pinger::getRequest( PingRequest& req )
-{
- MutexClass::LockClass m(m_requestMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_requests.empty())
- return false;
- req = m_requests.front();
- m_requests.pop();
- return true;
-}
-
-void Pinger::addResponse( const PingResponse& resp )
-{
- {
- MutexClass::LockClass m(m_pingMapMutex);
-
- m_pingMap[resp.hostname] = resp.avgPing;
- }
- {
- MutexClass::LockClass m(m_responseMutex);
-
- ++m_responseCount;
- m_responses.push(resp);
- }
-}
-
-Bool Pinger::getResponse( PingResponse& resp )
-{
- MutexClass::LockClass m(m_responseMutex, 0);
- if (m.Failed())
- return false;
-
- if (m_responses.empty())
- return false;
- resp = m_responses.front();
- m_responses.pop();
- return true;
-}
-
-Bool Pinger::arePingsInProgress( void )
-{
- return (m_requestCount != m_responseCount);
-}
-
-Int Pinger::getPing( AsciiString hostname )
-{
- MutexClass::LockClass m(m_pingMapMutex, 0);
- if (m.Failed())
- return false;
-
- std::map::const_iterator it = m_pingMap.find(hostname.str());
- if (it != m_pingMap.end())
- return it->second;
-
- return -1;
-}
-
-void Pinger::clearPingMap( void )
-{
- MutexClass::LockClass m(m_pingMapMutex);
- m_pingMap.clear();
-}
-
-AsciiString Pinger::getPingString( Int timeout )
-{
- MutexClass::LockClass m(m_pingMapMutex);
-
- AsciiString pingString;
- AsciiString tmp;
- for (std::map::const_iterator it = m_pingMap.begin(); it != m_pingMap.end(); ++it)
- {
- Int ping = it->second;
- if (ping < 0 || ping > timeout)
- ping = timeout;
- ping = ping * 255 / timeout;
- tmp.format("%2.2X", ping);
- pingString.concat(tmp);
- }
- return pingString;
-}
-
-//-------------------------------------------------------------------------
-
-void PingThreadClass::Thread_Function()
-{
- try {
- PingRequest req;
-
- WSADATA wsaData;
-
- // Fire up winsock (prob already done, but doesn't matter)
- WORD wVersionRequested = MAKEWORD(1, 1);
- WSAStartup( wVersionRequested, &wsaData );
-
- while ( running )
- {
- // deal with requests
- if (ThePinger->getRequest(req))
- {
- // resolve the hostname
- const char *hostnameBuffer = req.hostname.c_str();
- UnsignedInt IP = 0xFFFFFFFF;
- if (isdigit(hostnameBuffer[0]))
- {
- IP = inet_addr(hostnameBuffer);
- in_addr hostNode;
- hostNode.s_addr = IP;
- DEBUG_LOG(("pinging %s - IP = %s", hostnameBuffer, inet_ntoa(hostNode) ));
- }
- else
- {
- HOSTENT *hostStruct;
- in_addr *hostNode;
- hostStruct = gethostbyname(hostnameBuffer);
- if (hostStruct == NULL)
- {
- DEBUG_LOG(("pinging %s - host lookup failed", hostnameBuffer));
-
- // Even though this failed to resolve IP, still need to send a
- // callback.
- IP = 0xFFFFFFFF; // flag for IP resolve failed
- }
- else
- {
- hostNode = (in_addr *) hostStruct->h_addr;
- IP = hostNode->s_addr;
- DEBUG_LOG(("pinging %s IP = %s", hostnameBuffer, inet_ntoa(*hostNode) ));
- }
- }
-
- // do ping
- Int totalPing = 0;
- Int goodReps = 0;
- Int reps = req.repetitions;
- while (reps-- && running && IP != 0xFFFFFFFF)
- {
- Int ping = doPing(IP, req.timeout);
- if (ping >= 0)
- {
- totalPing += ping;
- ++goodReps;
- }
-
- // end our timeslice
- Switch_Thread();
- }
- if (!goodReps)
- totalPing = -1;
- else
- totalPing = totalPing / goodReps;
-
- PingResponse resp;
- resp.hostname = req.hostname;
- resp.avgPing = totalPing;
- resp.repetitions = goodReps;
- ThePinger->addResponse(resp);
- }
-
- // end our timeslice
- Switch_Thread();
- }
-
- WSACleanup();
- } catch ( ... ) {
- DEBUG_CRASH(("Exception in ping thread!"));
- }
-}
-
-//-------------------------------------------------------------------------
-//-------------------------------------------------------------------------
-//-------------------------------------------------------------------------
-//-------------------------------------------------------------------------
-//-------------------------------------------------------------------------
-//-------------------------------------------------------------------------
-
-HANDLE WINAPI IcmpCreateFile(VOID); /* INVALID_HANDLE_VALUE on error */
-BOOL WINAPI IcmpCloseHandle(HANDLE IcmpHandle); /* FALSE on error */
-
-/* Note 2: For the most part, you can refer to RFC 791 for detials
- * on how to fill in values for the IP option information structure.
- */
-typedef struct ip_option_information
-{
- UnsignedByte Ttl; /* Time To Live (used for traceroute) */
- UnsignedByte Tos; /* Type Of Service (usually 0) */
- UnsignedByte Flags; /* IP header flags (usually 0) */
- UnsignedByte OptionsSize; /* Size of options data (usually 0, max 40) */
- UnsignedByte FAR *OptionsData; /* Options data buffer */
-}
-IPINFO, *PIPINFO, FAR *LPIPINFO;
-
-
-/* Note 1: The Reply Buffer will have an array of ICMP_ECHO_REPLY
- * structures, followed by options and the data in ICMP echo reply
- * datagram received. You must have room for at least one ICMP
- * echo reply structure, plus 8 bytes for an ICMP header.
- */
-typedef struct icmp_echo_reply
-{
- UnsignedInt Address; /* source address */
- ////////UnsignedInt Status; /* IP status value (see below) */
- UnsignedInt RTTime; /* Round Trip Time in milliseconds */
- UnsignedShort DataSize; /* reply data size */
- UnsignedShort Reserved; /* */
- void FAR *Data; /* reply data buffer */
- struct ip_option_information Options; /* reply options */
-}
-ICMPECHO, *PICMPECHO, FAR *LPICMPECHO;
-
-
-DWORD WINAPI IcmpSendEcho(
- HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */
- UnsignedInt DestAddress, /* destination IP address (in network order) */
- LPVOID RequestData, /* pointer to buffer to send */
- WORD RequestSize, /* length of data in buffer */
- LPIPINFO RequestOptns, /* see Note 2 */
- LPVOID ReplyBuffer, /* see Note 1 */
- DWORD ReplySize, /* length of reply (must allow at least 1 reply) */
- DWORD Timeout /* time in milliseconds to wait for reply */
-);
-
-
-#define IP_STATUS_BASE 11000
-#define IP_SUCCESS 0
-#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1)
-#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2)
-#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3)
-#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4)
-#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)
-#define IP_NO_RESOURCES (IP_STATUS_BASE + 6)
-#define IP_BAD_OPTION (IP_STATUS_BASE + 7)
-#define IP_HW_ERROR (IP_STATUS_BASE + 8)
-#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9)
-#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10)
-#define IP_BAD_REQ (IP_STATUS_BASE + 11)
-#define IP_BAD_ROUTE (IP_STATUS_BASE + 12)
-#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13)
-#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14)
-#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15)
-#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16)
-#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17)
-#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18)
-#define IP_ADDR_DELETED (IP_STATUS_BASE + 19)
-#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20)
-#define IP_MTU_CHANGE (IP_STATUS_BASE + 21)
-#define IP_UNLOAD (IP_STATUS_BASE + 22)
-#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50)
-#define MAX_IP_STATUS IP_GENERAL_FAILURE
-#define IP_PENDING (IP_STATUS_BASE + 255)
-
-
-#define BUFSIZE 8192
-#define DEFAULT_LEN 32
-#define LOOPLIMIT 4
-#define DEFAULT_TTL 64
-
-Int PingThreadClass::doPing(UnsignedInt IP, Int timeout)
-{
- /*
- * Initialize default settings
- */
-
- IPINFO stIPInfo, *lpstIPInfo;
- HANDLE hICMP, hICMP_DLL;
- int i, j, nDataLen, nLoopLimit, nTimeOut, nTTL, nTOS;
- DWORD dwReplyCount;
- ///////IN_ADDR stDestAddr;
- BOOL fRet, fDontStop;
- ///BOOL fTraceRoute;
-
- nDataLen = DEFAULT_LEN;
- nLoopLimit = LOOPLIMIT;
- nTimeOut = timeout;
- fDontStop = FALSE;
- lpstIPInfo = NULL;
- nTTL = DEFAULT_TTL;
- nTOS = 0;
-
- Int pingTime = -1; // in case of error
-
- char achReqData[BUFSIZE];
- char achRepData[sizeof(ICMPECHO) + BUFSIZE];
-
-
- HANDLE ( WINAPI *lpfnIcmpCreateFile )( VOID ) = NULL;
- BOOL ( WINAPI *lpfnIcmpCloseHandle )( HANDLE ) = NULL;
- DWORD (WINAPI *lpfnIcmpSendEcho)(HANDLE, DWORD, LPVOID, WORD, LPVOID,
- LPVOID, DWORD, DWORD) = NULL;
-
-
- /*
- * Load the ICMP.DLL
- */
- hICMP_DLL = LoadLibrary("ICMP.DLL");
- if (hICMP_DLL == 0)
- {
- DEBUG_LOG(("LoadLibrary() failed: Unable to locate ICMP.DLL!"));
- goto cleanup;
- }
-
- /*
- * Get pointers to ICMP.DLL functions
- */
- lpfnIcmpCreateFile = (void * (__stdcall *)(void))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpCreateFile");
- lpfnIcmpCloseHandle = (int (__stdcall *)(void *))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpCloseHandle");
- lpfnIcmpSendEcho = (unsigned long (__stdcall *)(void *, unsigned long, void *, unsigned short,
- void *, void *, unsigned long, unsigned long))GetProcAddress( (HINSTANCE)hICMP_DLL, "IcmpSendEcho" );
-
- if ((!lpfnIcmpCreateFile) ||
- (!lpfnIcmpCloseHandle) ||
- (!lpfnIcmpSendEcho))
- {
- DEBUG_LOG(("GetProcAddr() failed for at least one function."));
- goto cleanup;
- }
-
-
- /*
- * IcmpCreateFile() - Open the ping service
- */
- hICMP = (HANDLE) lpfnIcmpCreateFile();
- if (hICMP == INVALID_HANDLE_VALUE)
- {
- DEBUG_LOG(("IcmpCreateFile() failed"));
- goto cleanup;
- }
-
- /*
- * Init data buffer printable ASCII
- * 32 (space) through 126 (tilde)
- */
- for (j = 0, i = 32; j < nDataLen; j++, i++)
- {
- if (i >= 126)
- i = 32;
- achReqData[j] = i;
- }
-
- /*
- * Init IPInfo structure
- */
- lpstIPInfo = &stIPInfo;
- stIPInfo.Ttl = nTTL;
- stIPInfo.Tos = nTOS;
- stIPInfo.Flags = 0;
- stIPInfo.OptionsSize = 0;
- stIPInfo.OptionsData = NULL;
-
-
-
- /*
- * IcmpSendEcho() - Send the ICMP Echo Request
- * and read the Reply
- */
- dwReplyCount = lpfnIcmpSendEcho(
- hICMP,
- IP,
- achReqData,
- nDataLen,
- lpstIPInfo,
- achRepData,
- sizeof(achRepData),
- nTimeOut);
- if (dwReplyCount != 0)
- {
- //////////IN_ADDR stDestAddr;
- DWORD dwStatus;
-
- pingTime = (*(UnsignedInt *) & (achRepData[8]));
-
- // I've seen the ping time bigger than the timeout by a little
- // bit. How lame.
- if (pingTime > timeout)
- pingTime = timeout;
-
- dwStatus = *(DWORD *) & (achRepData[4]);
- if (dwStatus != IP_SUCCESS)
- {
- DEBUG_LOG(("ICMPERR: %d", dwStatus));
- }
-
- }
- else
- {
- DEBUG_LOG(("IcmpSendEcho() failed: %d", dwReplyCount));
- // Ok we didn't get a packet, just say everything's OK
- // and the time was -1
- pingTime = -1;
- goto cleanup;
- }
-
-
- /*
- * IcmpCloseHandle - Close the ICMP handle
- */
- fRet = lpfnIcmpCloseHandle(hICMP);
- if (fRet == FALSE)
- {
- DEBUG_LOG(("Error closing ICMP handle"));
- }
-
- // Say what you will about goto's but it's handy for stuff like this
-cleanup:
-
- // Shut down...
- if (hICMP_DLL)
- FreeLibrary((HINSTANCE)hICMP_DLL);
-
- return pingTime;
-}
-
-
-//-------------------------------------------------------------------------
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
deleted file mode 100644
index 4ddc8c0eadd..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy/Thread/ThreadUtils.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: ThreadUtils.cpp //////////////////////////////////////////////////////
-// GameSpy thread utils
-// Author: Matthew D. Campbell, July 2002
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-//-------------------------------------------------------------------------
-
-std::wstring MultiByteToWideCharSingleLine( const char *orig )
-{
- Int len = strlen(orig);
- WideChar *dest = NEW WideChar[len+1];
-
- MultiByteToWideChar(CP_UTF8, 0, orig, -1, dest, len);
- WideChar *c = NULL;
- do
- {
- c = wcschr(dest, L'\n');
- if (c)
- {
- *c = L' ';
- }
- }
- while ( c != NULL );
- do
- {
- c = wcschr(dest, L'\r');
- if (c)
- {
- *c = L' ';
- }
- }
- while ( c != NULL );
-
- dest[len] = 0;
- std::wstring ret = dest;
- delete[] dest;
- return ret;
-}
-
-std::string WideCharStringToMultiByte( const WideChar *orig )
-{
- std::string ret;
- Int len = WideCharToMultiByte( CP_UTF8, 0, orig, wcslen(orig), NULL, 0, NULL, NULL ) + 1;
- if (len > 0)
- {
- char *dest = NEW char[len];
- WideCharToMultiByte( CP_UTF8, 0, orig, -1, dest, len, NULL, NULL );
- dest[len-1] = 0;
- ret = dest;
- delete[] dest;
- }
- return ret;
-}
-
-//-------------------------------------------------------------------------
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp
deleted file mode 100644
index 329f5c79c5f..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpyOverlay.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: wolscreens.cpp //////////////////////////////////////////////////////
-// Westwood Online screen setup/teardown
-// Author: Matthew D. Campbell, November 2001
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-#include "Common/AudioEventRTS.h"
-
-#include "GameClient/GadgetListBox.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MessageBox.h"
-#include "GameClient/ShellHooks.h"
-//#include "GameNetwork/GameSpy.h"
-//#include "GameNetwork/GameSpyGP.h"
-
-#include "GameNetwork/GameSpyOverlay.h"
-//#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/BuddyThread.h"
-
-void deleteNotificationBox( void );
-static void raiseOverlays( void );
-
-// Message boxes -------------------------------------
-static GameWindow *messageBoxWindow = NULL;
-static GameWinMsgBoxFunc okFunc = NULL;
-static GameWinMsgBoxFunc cancelFunc = NULL;
-static Bool reOpenPlayerInfoFlag = FALSE;
-/**
- * messageBoxOK is called when a message box is destroyed
- * by way of an OK button, so we can clear our pointers to it.
- */
-static void messageBoxOK( void )
-{
- DEBUG_ASSERTCRASH(messageBoxWindow, ("Message box window went away without being there in the first place!"));
- messageBoxWindow = NULL;
- if (okFunc)
- {
- okFunc();
- okFunc = NULL;
- }
-}
-
-/**
- * messageBoxCancel is called when a message box is destroyed
- * by way of a Cancel button, so we can clear our pointers to it.
- */
-static void messageBoxCancel( void )
-{
- DEBUG_ASSERTCRASH(messageBoxWindow, ("Message box window went away without being there in the first place!"));
- messageBoxWindow = NULL;
- if (cancelFunc)
- {
- cancelFunc();
- cancelFunc = NULL;
- }
-}
-
-/**
- * clearGSMessageBoxes removes the current message box if
- * one is present. This is usually done when putting up a
- * second messageBox.
- */
-void ClearGSMessageBoxes( void )
-{
- if (messageBoxWindow)
- {
- TheWindowManager->winDestroy(messageBoxWindow);
- messageBoxWindow = NULL;
- }
-
- if (okFunc)
- {
- okFunc = NULL;
- }
-
- if (cancelFunc)
- {
- cancelFunc = NULL;
- }
-}
-
-/**
- * GSMessageBoxOk puts up an OK dialog box and saves the
- * pointers to it and its callbacks.
- */
-void GSMessageBoxOk(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newOkFunc)
-{
- ClearGSMessageBoxes();
- messageBoxWindow = MessageBoxOk(title, message, messageBoxOK);
- okFunc = newOkFunc;
-}
-
-/**
- * GSMessageBoxOkCancel puts up an OK/Cancel dialog box and saves the
- * pointers to it and its callbacks.
- */
-void GSMessageBoxOkCancel(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newOkFunc, GameWinMsgBoxFunc newCancelFunc)
-{
- ClearGSMessageBoxes();
- messageBoxWindow = MessageBoxOkCancel(title, message, messageBoxOK, messageBoxCancel);
- okFunc = newOkFunc;
- cancelFunc = newCancelFunc;
-}
-
-/**
- * GSMessageBoxYesNo puts up a Yes/No dialog box and saves the
- * pointers to it and its callbacks.
- */
-void GSMessageBoxYesNo(UnicodeString title, UnicodeString message, GameWinMsgBoxFunc newYesFunc, GameWinMsgBoxFunc newNoFunc)
-{
- ClearGSMessageBoxes();
- messageBoxWindow = MessageBoxYesNo(title, message, messageBoxOK, messageBoxCancel);
- okFunc = newYesFunc;
- cancelFunc = newNoFunc;
-}
-
-/**
- * If the screen transitions underneath the dialog box, we
- * need to raise it to keep it visible.
- */
-void RaiseGSMessageBox( void )
-{
- raiseOverlays();
-
- if (!messageBoxWindow)
- return;
-
- messageBoxWindow->winBringToTop();
-}
-
-// Overlay screens -------------------------------------
-
-/**
- * gsOverlays holds a list of the .wnd files used in GS overlays.
- * The entries *MUST* be in the same order as the GSOverlayType enum.
- */
-static const char * gsOverlays[GSOVERLAY_MAX] =
-{
- "Menus/PopupPlayerInfo.wnd", // Player info (right-click)
- "Menus/WOLMapSelectMenu.wnd", // Map select
- "Menus/WOLBuddyOverlay.wnd", // Buddy list
- "Menus/WOLPageOverlay.wnd", // Find/page
- "Menus/PopupHostGame.wnd", // Hosting options (game name, password, etc)
- "Menus/PopupJoinGame.wnd", // Joining options (password, etc)
- "Menus/PopupLadderSelect.wnd",// LadderSelect
- "Menus/PopupLocaleSelect.wnd",// Prompt for user's locale
- "Menus/OptionsMenu.wnd", // popup options
-};
-
-static WindowLayout *overlayLayouts[GSOVERLAY_MAX] =
-{
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
-};
-
-static void buddyTryReconnect( void )
-{
- BuddyRequest req;
- req.buddyRequestType = BuddyRequest::BUDDYREQUEST_RELOGIN;
- TheGameSpyBuddyMessageQueue->addRequest( req );
-}
-
-void GameSpyOpenOverlay( GSOverlayType overlay )
-{
- if (overlay == GSOVERLAY_BUDDY)
- {
- if (!TheGameSpyBuddyMessageQueue->isConnected())
- {
- // not connected - is it because we were disconnected?
- if (TheGameSpyBuddyMessageQueue->getLocalProfileID())
- {
- // used to be connected
- GSMessageBoxYesNo(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPDisconnected"), buddyTryReconnect, NULL);
- }
- else
- {
- // no profile
- GSMessageBoxOk(TheGameText->fetch("GUI:GPErrorTitle"), TheGameText->fetch("GUI:GPNoProfile"), NULL);
- }
- return;
- }
- AudioEventRTS buttonClick("GUICommunicatorOpen");
-
- if( TheAudio )
- {
- TheAudio->addAudioEvent( &buttonClick );
- }
- }
- if (overlayLayouts[overlay])
- {
- overlayLayouts[overlay]->hide( FALSE );
- overlayLayouts[overlay]->bringForward();
- }
- else
- {
- overlayLayouts[overlay] = TheWindowManager->winCreateLayout( AsciiString( gsOverlays[overlay] ) );
- overlayLayouts[overlay]->runInit();
- overlayLayouts[overlay]->hide( FALSE );
- overlayLayouts[overlay]->bringForward();
- }
-}
-
-void GameSpyCloseOverlay( GSOverlayType overlay )
-{
- switch(overlay)
- {
- case GSOVERLAY_PLAYERINFO:
- DEBUG_LOG(("Closing overlay GSOVERLAY_PLAYERINFO"));
- break;
- case GSOVERLAY_MAPSELECT:
- DEBUG_LOG(("Closing overlay GSOVERLAY_MAPSELECT"));
- break;
- case GSOVERLAY_BUDDY:
- DEBUG_LOG(("Closing overlay GSOVERLAY_BUDDY"));
- break;
- case GSOVERLAY_PAGE:
- DEBUG_LOG(("Closing overlay GSOVERLAY_PAGE"));
- break;
- case GSOVERLAY_GAMEOPTIONS:
- DEBUG_LOG(("Closing overlay GSOVERLAY_GAMEOPTIONS"));
- break;
- case GSOVERLAY_GAMEPASSWORD:
- DEBUG_LOG(("Closing overlay GSOVERLAY_GAMEPASSWORD"));
- break;
- case GSOVERLAY_LADDERSELECT:
- DEBUG_LOG(("Closing overlay GSOVERLAY_LADDERSELECT"));
- break;
- case GSOVERLAY_OPTIONS:
- DEBUG_LOG(("Closing overlay GSOVERLAY_OPTIONS"));
- if( overlayLayouts[overlay] )
- {
- SignalUIInteraction(SHELL_SCRIPT_HOOK_OPTIONS_CLOSED);
- }
- break;
- }
- if( overlayLayouts[overlay] )
- {
- overlayLayouts[overlay]->runShutdown();
- overlayLayouts[overlay]->destroyWindows();
- deleteInstance(overlayLayouts[overlay]);
- overlayLayouts[overlay] = NULL;
- }
-}
-
-Bool GameSpyIsOverlayOpen( GSOverlayType overlay )
-{
- return (overlayLayouts[overlay] != NULL);
-}
-
-void GameSpyToggleOverlay( GSOverlayType overlay )
-{
- if (GameSpyIsOverlayOpen(overlay))
- GameSpyCloseOverlay(overlay);
- else
- GameSpyOpenOverlay(overlay);
-}
-
-void raiseOverlays( void )
-{
- for (int i=0; ibringForward();
- }
- }
-}
-
-void GameSpyCloseAllOverlays( void )
-{
- for (int i=0; irunUpdate();
- }
- }
-}
-
-void ReOpenPlayerInfo( void )
-{
- reOpenPlayerInfoFlag = TRUE;
-}
-void CheckReOpenPlayerInfo(void )
-{
- if(!reOpenPlayerInfoFlag)
- return;
-
- GameSpyOpenOverlay(GSOVERLAY_PLAYERINFO);
- reOpenPlayerInfoFlag = FALSE;
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/IPEnumeration.cpp b/Generals/Code/GameEngine/Source/GameNetwork/IPEnumeration.cpp
deleted file mode 100644
index 53ae8eecd0e..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/IPEnumeration.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/IPEnumeration.h"
-#include "GameNetwork/networkutil.h"
-#include "GameClient/ClientInstance.h"
-
-IPEnumeration::IPEnumeration( void )
-{
- m_IPlist = NULL;
- m_isWinsockInitialized = false;
-}
-
-IPEnumeration::~IPEnumeration( void )
-{
- if (m_isWinsockInitialized)
- {
- WSACleanup();
- m_isWinsockInitialized = false;
- }
-
- EnumeratedIP *ip = m_IPlist;
- while (ip)
- {
- ip = ip->getNext();
- deleteInstance(m_IPlist);
- m_IPlist = ip;
- }
-}
-
-EnumeratedIP * IPEnumeration::getAddresses( void )
-{
- if (m_IPlist)
- return m_IPlist;
-
- if (!m_isWinsockInitialized)
- {
- WORD verReq = MAKEWORD(2, 2);
- WSADATA wsadata;
-
- int err = WSAStartup(verReq, &wsadata);
- if (err != 0) {
- return NULL;
- }
-
- if ((LOBYTE(wsadata.wVersion) != 2) || (HIBYTE(wsadata.wVersion) !=2)) {
- WSACleanup();
- return NULL;
- }
- m_isWinsockInitialized = true;
- }
-
- // get the local machine's host name
- char hostname[256];
- if (gethostname(hostname, sizeof(hostname)))
- {
- DEBUG_LOG(("Failed call to gethostname; WSAGetLastError returned %d", WSAGetLastError()));
- return NULL;
- }
- DEBUG_LOG(("Hostname is '%s'", hostname));
-
- // get host information from the host name
- HOSTENT* hostEnt = gethostbyname(hostname);
- if (hostEnt == NULL)
- {
- DEBUG_LOG(("Failed call to gethostbyname; WSAGetLastError returned %d", WSAGetLastError()));
- return NULL;
- }
-
- // sanity-check the length of the IP adress
- if (hostEnt->h_length != 4)
- {
- DEBUG_LOG(("gethostbyname returns oddly-sized IP addresses!"));
- return NULL;
- }
-
- // TheSuperHackers @feature Add one unique local host IP address for each multi client instance.
- if (rts::ClientInstance::isMultiInstance())
- {
- const UnsignedInt id = rts::ClientInstance::getInstanceId();
- addNewIP(
- 127,
- (UnsignedByte)(id >> 16),
- (UnsignedByte)(id >> 8),
- (UnsignedByte)(id));
- }
-
- // construct a list of addresses
- int numAddresses = 0;
- char *entry;
- while ( (entry = hostEnt->h_addr_list[numAddresses++]) != 0 )
- {
- addNewIP(
- (UnsignedByte)entry[0],
- (UnsignedByte)entry[1],
- (UnsignedByte)entry[2],
- (UnsignedByte)entry[3]);
- }
-
- return m_IPlist;
-}
-
-void IPEnumeration::addNewIP( UnsignedByte a, UnsignedByte b, UnsignedByte c, UnsignedByte d )
-{
- EnumeratedIP *newIP = newInstance(EnumeratedIP);
-
- AsciiString str;
- str.format("%d.%d.%d.%d", (int)a, (int)b, (int)c, (int)d);
-
- UnsignedInt ip = AssembleIp(a, b, c, d);
-
- newIP->setIPstring(str);
- newIP->setIP(ip);
-
- DEBUG_LOG(("IP: 0x%8.8X (%s)", ip, str.str()));
-
- // Add the IP to the list in ascending order
- if (!m_IPlist)
- {
- m_IPlist = newIP;
- newIP->setNext(NULL);
- }
- else
- {
- if (newIP->getIP() < m_IPlist->getIP())
- {
- newIP->setNext(m_IPlist);
- m_IPlist = newIP;
- }
- else
- {
- EnumeratedIP *p = m_IPlist;
- while (p->getNext() && p->getNext()->getIP() < newIP->getIP())
- {
- p = p->getNext();
- }
- newIP->setNext(p->getNext());
- p->setNext(newIP);
- }
- }
-}
-
-AsciiString IPEnumeration::getMachineName( void )
-{
- if (!m_isWinsockInitialized)
- {
- WORD verReq = MAKEWORD(2, 2);
- WSADATA wsadata;
-
- int err = WSAStartup(verReq, &wsadata);
- if (err != 0) {
- return NULL;
- }
-
- if ((LOBYTE(wsadata.wVersion) != 2) || (HIBYTE(wsadata.wVersion) !=2)) {
- WSACleanup();
- return NULL;
- }
- m_isWinsockInitialized = true;
- }
-
- // get the local machine's host name
- char hostname[256];
- if (gethostname(hostname, sizeof(hostname)))
- {
- DEBUG_LOG(("Failed call to gethostname; WSAGetLastError returned %d", WSAGetLastError()));
- return NULL;
- }
-
- return AsciiString(hostname);
-}
-
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/LANAPI.cpp b/Generals/Code/GameEngine/Source/GameNetwork/LANAPI.cpp
deleted file mode 100644
index 5398c52ad05..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/LANAPI.cpp
+++ /dev/null
@@ -1,1283 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#define WIN32_LEAN_AND_MEAN // only bare bones windows stuff wanted
-
-#include "Common/crc.h"
-#include "Common/GameState.h"
-#include "Common/Registry.h"
-#include "GameNetwork/LANAPI.h"
-#include "GameNetwork/networkutil.h"
-#include "Common/GlobalData.h"
-#include "Common/RandomValue.h"
-#include "GameClient/GameText.h"
-#include "GameClient/MapUtil.h"
-#include "Common/UserPreferences.h"
-#include "GameLogic/GameLogic.h"
-
-
-static const UnsignedShort lobbyPort = 8086; ///< This is the UDP port used by all LANAPI communication
-
-AsciiString GetMessageTypeString(UnsignedInt type);
-
-const UnsignedInt LANAPI::s_resendDelta = 10 * 1000; ///< This is how often we announce ourselves to the world
-/*
-LANGame::LANGame( void )
-{
- m_gameName = L"";
-
- int player;
- for (player = 0; player < MAX_SLOTS; ++player)
- {
- m_playerName[player] = L"";
- m_playerIP[player]= 0;
- m_playerAccepted[player] = false;
- }
- m_lastHeard = 0;
- m_inProgress = false;
- m_next = NULL;
-}
-*/
-
-
-
-
-LANAPI::LANAPI( void ) : m_transport(NULL)
-{
- DEBUG_LOG(("LANAPI::LANAPI() - max game option size is %d, sizeof(LANMessage)=%d, MAX_PACKET_SIZE=%d",
- m_lanMaxOptionsLength, sizeof(LANMessage), MAX_PACKET_SIZE));
-
- m_lastResendTime = 0;
- //
- m_lobbyPlayers = NULL;
- m_games = NULL;
- m_name = L""; // safe default?
- m_pendingAction = ACT_NONE;
- m_expiration = 0;
- m_localIP = 0;
- m_inLobby = true;
- m_isInLANMenu = TRUE;
- m_currentGame = NULL;
- m_broadcastAddr = INADDR_BROADCAST;
- m_directConnectRemoteIP = 0;
- m_actionTimeout = 5000; // ms
- m_lastUpdate = 0;
- m_transport = new Transport;
- m_isActive = TRUE;
-}
-
-LANAPI::~LANAPI( void )
-{
- reset();
- delete m_transport;
-}
-
-void LANAPI::init( void )
-{
- m_gameStartTime = 0;
- m_gameStartSeconds = 0;
- m_transport->reset();
- m_transport->init(m_localIP, lobbyPort);
- m_transport->allowBroadcasts(true);
-
- m_pendingAction = ACT_NONE;
- m_expiration = 0;
- m_inLobby = true;
- m_isInLANMenu = TRUE;
- m_currentGame = NULL;
- m_directConnectRemoteIP = 0;
-
- m_lastGameopt = "";
-
-#if TELL_COMPUTER_IDENTITY_IN_LAN_LOBBY
- char userName[UNLEN + 1];
- DWORD bufSize = ARRAY_SIZE(userName);
- if (GetUserNameA(userName, &bufSize))
- {
- m_userName.set(userName, bufSize - 1);
- }
- else
- {
- m_userName = "unknown";
- }
-
- char computerName[MAX_COMPUTERNAME_LENGTH + 1];
- bufSize = ARRAY_SIZE(computerName);
- if (GetComputerNameA(computerName, &bufSize))
- {
- m_hostName.set(computerName, bufSize - 1);
- }
- else
- {
- m_hostName = "unknown";
- }
-#endif
-}
-
-void LANAPI::reset( void )
-{
- if (m_inLobby)
- {
- LANMessage msg;
- fillInLANMessage( &msg );
- msg.messageType = LANMessage::MSG_REQUEST_LOBBY_LEAVE;
- sendMessage(&msg);
- }
- m_transport->update();
-
- LANGameInfo *theGame = m_games;
- LANGameInfo *deletableGame = NULL;
-
- while (theGame)
- {
- deletableGame = theGame;
- theGame = theGame->getNext();
- delete deletableGame;
- }
-
- LANPlayer *thePlayer = m_lobbyPlayers;
- LANPlayer *deletablePlayer = NULL;
-
- while (thePlayer)
- {
- deletablePlayer = thePlayer;
- thePlayer = thePlayer->getNext();
- delete deletablePlayer;
- }
-
- m_games = NULL;
- m_lobbyPlayers = NULL;
- m_directConnectRemoteIP = 0;
- m_pendingAction = ACT_NONE;
- m_expiration = 0;
- m_inLobby = true;
- m_isInLANMenu = TRUE;
- m_currentGame = NULL;
-
-}
-
-void LANAPI::sendMessage(LANMessage *msg, UnsignedInt ip /* = 0 */)
-{
- if (ip != 0)
- {
- m_transport->queueSend(ip, lobbyPort, (unsigned char *)msg, sizeof(LANMessage) /*, 0, 0 */);
- }
- else if ((m_currentGame != NULL) && (m_currentGame->getIsDirectConnect()))
- {
- Int localSlot = m_currentGame->getLocalSlotNum();
- for (Int i = 0; i < MAX_SLOTS; ++i)
- {
- if (i != localSlot) {
- GameSlot *slot = m_currentGame->getSlot(i);
- if ((slot != NULL) && (slot->isHuman())) {
- m_transport->queueSend(slot->getIP(), lobbyPort, (unsigned char *)msg, sizeof(LANMessage) /*, 0, 0 */);
- }
- }
- }
- }
- else
- {
- m_transport->queueSend(m_broadcastAddr, lobbyPort, (unsigned char *)msg, sizeof(LANMessage) /*, 0, 0 */);
- }
-}
-
-
-AsciiString GetMessageTypeString(UnsignedInt type)
-{
- AsciiString returnString;
-
- switch (type)
- {
- case LANMessage::MSG_REQUEST_LOCATIONS:
- returnString.format( "Request Locations (%d)",type);
- break;
- case LANMessage::MSG_GAME_ANNOUNCE:
- returnString.format("Game Announce (%d)",type);
- break;
- case LANMessage::MSG_LOBBY_ANNOUNCE:
- returnString.format("Lobby Announce (%d)",type);
- break;
- case LANMessage::MSG_REQUEST_JOIN:
- returnString.format("Request Join (%d)",type);
- break;
- case LANMessage::MSG_JOIN_ACCEPT:
- returnString.format("Join Accept (%d)",type);
- break;
- case LANMessage::MSG_JOIN_DENY:
- returnString.format("Join Deny (%d)",type);
- break;
- case LANMessage::MSG_REQUEST_GAME_LEAVE:
- returnString.format("Request Game Leave (%d)",type);
- break;
- case LANMessage::MSG_REQUEST_LOBBY_LEAVE:
- returnString.format("Request Lobby Leave (%d)",type);
- break;
- case LANMessage::MSG_SET_ACCEPT:
- returnString.format("Set Accept(%d)",type);
- break;
- case LANMessage::MSG_CHAT:
- returnString.format("Chat (%d)",type);
- break;
- case LANMessage::MSG_GAME_START:
- returnString.format("Game Start (%d)",type);
- break;
- case LANMessage::MSG_GAME_START_TIMER:
- returnString.format("Game Start Timer (%d)",type);
- break;
- case LANMessage::MSG_GAME_OPTIONS:
- returnString.format("Game Options (%d)",type);
- break;
- case LANMessage::MSG_REQUEST_GAME_INFO:
- returnString.format("Request GameInfo (%d)", type);
- break;
- case LANMessage::MSG_INACTIVE:
- returnString.format("Inactive (%d)", type);
- break;
- default:
- returnString.format("Unknown Message (%d)",type);
- }
- return returnString;
-}
-
-
-void LANAPI::checkMOTD( void )
-{
-#if defined(RTS_DEBUG)
- if (TheGlobalData->m_useLocalMOTD)
- {
- // for a playtest, let's log some play statistics, eh?
- if (TheGlobalData->m_playStats <= 0)
- TheWritableGlobalData->m_playStats = 30;
-
- static UnsignedInt oldMOTDCRC = 0;
- UnsignedInt newMOTDCRC = 0;
- AsciiString asciiMOTD;
- char buf[4096];
- FILE *fp = fopen(TheGlobalData->m_MOTDPath.str(), "r");
- Int len;
- if (fp)
- {
- while( (len = fread(buf, 1, 4096, fp)) > 0 )
- {
- buf[len] = 0;
- asciiMOTD.concat(buf);
- }
- fclose(fp);
- CRC crcObj;
- crcObj.computeCRC(asciiMOTD.str(), asciiMOTD.getLength());
- newMOTDCRC = crcObj.get();
- }
-
- if (oldMOTDCRC != newMOTDCRC)
- {
- // different MOTD... display it
- oldMOTDCRC = newMOTDCRC;
- AsciiString line;
- while (asciiMOTD.nextToken(&line, "\n"))
- {
- if (line.getCharAt(line.getLength()-1) == '\r')
- line.removeLastChar(); // there is a trailing '\r'
-
- if (line.isEmpty())
- {
- line = " ";
- }
-
- UnicodeString uniLine;
- uniLine.translate(line);
- OnChat( UnicodeString(L"MOTD"), 0, uniLine, LANCHAT_SYSTEM );
- }
- }
- }
-#endif
-}
-
-extern Bool LANbuttonPushed;
-extern Bool LANSocketErrorDetected;
-void LANAPI::update( void )
-{
- if(LANbuttonPushed)
- return;
- static const UnsignedInt LANAPIUpdateDelay = 200;
- UnsignedInt now = timeGetTime();
-
- if( now > m_lastUpdate + LANAPIUpdateDelay)
- {
- m_lastUpdate = now;
- }
- else
- {
- return;
- }
-
- // Let the UDP socket breathe
- if ((m_transport->update() == FALSE) && (LANSocketErrorDetected == FALSE)) {
- if (m_isInLANMenu == TRUE) {
- LANSocketErrorDetected = TRUE;
- }
- }
-
- // Handle any new messages
- int i;
- for (i=0; im_inBuffer[i].length > 0)
- {
- // Process the new message
- UnsignedInt senderIP = m_transport->m_inBuffer[i].addr;
- if (senderIP == m_localIP)
- {
- m_transport->m_inBuffer[i].length = 0;
- continue;
- }
-
- LANMessage *msg = (LANMessage *)(m_transport->m_inBuffer[i].data);
- //DEBUG_LOG(("LAN message type %s from %ls (%s@%s)", GetMessageTypeString(msg->messageType).str(),
- // msg->name, msg->userName, msg->hostName));
- switch (msg->messageType)
- {
- // Location specification
- case LANMessage::MSG_REQUEST_LOCATIONS: // Hey, where is everybody?
- DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_LOCATIONS from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleRequestLocations( msg, senderIP );
- break;
- case LANMessage::MSG_GAME_ANNOUNCE: // Here someone is, and here's his game info!
- DEBUG_LOG(("LANAPI::update - got a MSG_GAME_ANNOUNCE from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleGameAnnounce( msg, senderIP );
- break;
- case LANMessage::MSG_LOBBY_ANNOUNCE: // Hey, I'm in the lobby!
- DEBUG_LOG(("LANAPI::update - got a MSG_LOBBY_ANNOUNCE from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleLobbyAnnounce( msg, senderIP );
- break;
- case LANMessage::MSG_REQUEST_GAME_INFO:
- DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_GAME_INFO from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleRequestGameInfo( msg, senderIP );
- break;
-
- // Joining games
- case LANMessage::MSG_REQUEST_JOIN: // Let me in! Let me in!
- DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_JOIN from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleRequestJoin( msg, senderIP );
- break;
- case LANMessage::MSG_JOIN_ACCEPT: // Okay, you can join.
- DEBUG_LOG(("LANAPI::update - got a MSG_JOIN_ACCEPT from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleJoinAccept( msg, senderIP );
- break;
- case LANMessage::MSG_JOIN_DENY: // Go away! We don't want any!
- DEBUG_LOG(("LANAPI::update - got a MSG_JOIN_DENY from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleJoinDeny( msg, senderIP );
- break;
-
- // Leaving games, lobby
- case LANMessage::MSG_REQUEST_GAME_LEAVE: // I'm outa here!
- DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_GAME_LEAVE from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleRequestGameLeave( msg, senderIP );
- break;
- case LANMessage::MSG_REQUEST_LOBBY_LEAVE: // I'm outa here!
- DEBUG_LOG(("LANAPI::update - got a MSG_REQUEST_LOBBY_LEAVE from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleRequestLobbyLeave( msg, senderIP );
- break;
-
- // Game options, chat, etc
- case LANMessage::MSG_SET_ACCEPT: // I'm cool with everything as is.
- handleSetAccept( msg, senderIP );
- break;
- case LANMessage::MSG_MAP_AVAILABILITY: // Map status
- handleHasMap( msg, senderIP );
- break;
- case LANMessage::MSG_CHAT: // Just spouting my mouth off.
- handleChat( msg, senderIP );
- break;
- case LANMessage::MSG_GAME_START: // Hold on; we're starting!
- handleGameStart( msg, senderIP );
- break;
- case LANMessage::MSG_GAME_START_TIMER:
- handleGameStartTimer( msg, senderIP );
- break;
- case LANMessage::MSG_GAME_OPTIONS: // Here's some info about the game.
- DEBUG_LOG(("LANAPI::update - got a MSG_GAME_OPTIONS from %d.%d.%d.%d", PRINTF_IP_AS_4_INTS(senderIP)));
- handleGameOptions( msg, senderIP );
- break;
- case LANMessage::MSG_INACTIVE: // someone is telling us that we're inactive.
- handleInActive( msg, senderIP );
- break;
-
- default:
- DEBUG_LOG(("Unknown LAN message type %d", msg->messageType));
- }
-
- // Mark it as read
- m_transport->m_inBuffer[i].length = 0;
- }
- }
- if(LANbuttonPushed)
- return;
- // Send out periodic I'm Here messages
- if (now > s_resendDelta + m_lastResendTime)
- {
- m_lastResendTime = now;
-
- if (m_inLobby)
- {
- RequestSetName(m_name);
- }
- else if (m_currentGame && !m_currentGame->isGameInProgress())
- {
- if (AmIHost())
- {
- RequestGameOptions( GenerateGameOptionsString(), true );
- RequestGameAnnounce( );
- }
- else
- {
-#if TELL_COMPUTER_IDENTITY_IN_LAN_LOBBY
- AsciiString text;
- text.format("User=%s", m_userName.str());
- RequestGameOptions( text, true );
- text.format("Host=%s", m_hostName.str());
- RequestGameOptions( text, true );
-#endif
- RequestGameOptions( "HELLO", false );
- }
- }
- else if (m_currentGame)
- {
- // game is in progress - RequestGameAnnounce will check if we should send it
- RequestGameAnnounce();
- }
- }
-
- Bool playerListChanged = false;
- Bool gameListChanged = false;
-
- // Weed out people we haven't heard from in a while
- LANPlayer *player = m_lobbyPlayers;
- while (player)
- {
- if (player->getLastHeard() + s_resendDelta*2 < now)
- {
- // He's gone!
- removePlayer(player);
- LANPlayer *nextPlayer = player->getNext();
- delete player;
- player = nextPlayer;
- playerListChanged = true;
- }
- else
- {
- player = player->getNext();
- }
- }
-
- // Weed out people we haven't heard from in a while
- LANGameInfo *game = m_games;
- while (game)
- {
- if (game != m_currentGame && game->getLastHeard() + s_resendDelta*2 < now)
- {
- // He's gone!
- removeGame(game);
- LANGameInfo *nextGame = game->getNext();
- delete game;
- game = nextGame;
- gameListChanged = true;
- }
- else
- {
- game = game->getNext();
- }
- }
- if ( m_currentGame && !m_currentGame->isGameInProgress() )
- {
- if ( !AmIHost() && (m_currentGame->getLastHeard() + s_resendDelta*16 < now) )
- {
- // We haven't heard from the host in a while. Bail.
- // Actually, fake a host leaving message. :)
- LANMessage msg;
- fillInLANMessage( &msg );
- msg.messageType = LANMessage::MSG_REQUEST_GAME_LEAVE;
- wcslcpy(msg.name, m_currentGame->getPlayerName(0).str(), ARRAY_SIZE(msg.name));
- handleRequestGameLeave(&msg, m_currentGame->getIP(0));
- UnicodeString text;
- text = TheGameText->fetch("LAN:HostNotResponding");
- OnChat(UnicodeString::TheEmptyString, m_localIP, text, LANCHAT_SYSTEM);
- }
- else if ( AmIHost() )
- {
- // Check each player for timeouts
- for (int p=1; pgetIP(p) && m_currentGame->getPlayerLastHeard(p) + s_resendDelta*8 < now)
- {
- LANMessage msg;
- fillInLANMessage( &msg );
- UnicodeString theStr;
- theStr.format(TheGameText->fetch("LAN:PlayerDropped"), m_currentGame->getPlayerName(p).str());
- msg.messageType = LANMessage::MSG_REQUEST_GAME_LEAVE;
- wcslcpy(msg.name, m_currentGame->getPlayerName(p).str(), ARRAY_SIZE(msg.name));
- handleRequestGameLeave(&msg, m_currentGame->getIP(p));
- OnChat(UnicodeString::TheEmptyString, m_localIP, theStr, LANCHAT_SYSTEM);
- }
- }
- }
- }
-
- if (playerListChanged)
- {
- OnPlayerList(m_lobbyPlayers);
- }
-
- if (gameListChanged)
- {
- OnGameList(m_games);
- }
-
- // Time out old actions
- if (m_pendingAction != ACT_NONE && now > m_expiration)
- {
- switch (m_pendingAction)
- {
- case ACT_JOIN:
- OnGameJoin(RET_TIMEOUT, NULL);
- m_pendingAction = ACT_NONE;
- m_currentGame = NULL;
- m_inLobby = true;
- break;
- case ACT_LEAVE:
- OnPlayerLeave(m_name);
- m_pendingAction = ACT_NONE;
- m_currentGame = NULL;
- m_inLobby = true;
- break;
- case ACT_JOINDIRECTCONNECT:
- OnGameJoin(RET_TIMEOUT, NULL);
- m_pendingAction = ACT_NONE;
- m_currentGame = NULL;
- m_inLobby = true;
- break;
- default:
- m_pendingAction = ACT_NONE;
- }
- }
-
- // send out "game starting" messages
- if ( m_gameStartTime && m_gameStartSeconds && m_gameStartTime <= now )
- {
- // m_gameStartTime is when the next message goes out
- // m_gameStartSeconds is how many seconds remain in the message
-
- RequestGameStartTimer( m_gameStartSeconds );
- }
- else if (m_gameStartTime && m_gameStartTime <= now)
- {
-// DEBUG_LOG(("m_gameStartTime=%d, now=%d, m_gameStartSeconds=%d", m_gameStartTime, now, m_gameStartSeconds));
- ResetGameStartTimer();
- RequestGameStart();
- }
-
- // Check for an MOTD every few seconds
- static UnsignedInt lastMOTDCheck = 0;
- static const UnsignedInt motdInterval = 30000;
- if (now > lastMOTDCheck + motdInterval)
- {
- checkMOTD();
- lastMOTDCheck = now;
- }
-}
-
-// Request functions generate network traffic
-void LANAPI::RequestLocations( void )
-{
- LANMessage msg;
- msg.messageType = LANMessage::MSG_REQUEST_LOCATIONS;
- fillInLANMessage( &msg );
- sendMessage(&msg);
-}
-
-void LANAPI::RequestGameJoin( LANGameInfo *game, UnsignedInt ip /* = 0 */ )
-{
- if ((m_pendingAction != ACT_NONE) && (m_pendingAction != ACT_JOINDIRECTCONNECT))
- {
- OnGameJoin( RET_BUSY, NULL );
- return;
- }
-
- if (!game)
- {
- OnGameJoin( RET_GAME_GONE, NULL );
- return;
- }
-
- LANMessage msg;
- msg.messageType = LANMessage::MSG_REQUEST_JOIN;
- fillInLANMessage( &msg );
- msg.GameToJoin.gameIP = game->getSlot(0)->getIP();
- msg.GameToJoin.exeCRC = TheGlobalData->m_exeCRC;
- msg.GameToJoin.iniCRC = TheGlobalData->m_iniCRC;
-
- AsciiString s = "";
- GetStringFromRegistry("\\ergc", "", s);
- strlcpy(msg.GameToJoin.serial, s.str(), ARRAY_SIZE(msg.GameToJoin.serial));
-
- sendMessage(&msg, ip);
-
- m_pendingAction = ACT_JOIN;
- m_expiration = timeGetTime() + m_actionTimeout;
-}
-
-void LANAPI::RequestGameJoinDirectConnect(UnsignedInt ipaddress)
-{
- if (m_pendingAction != ACT_NONE)
- {
- OnGameJoin( RET_BUSY, NULL );
- return;
- }
-
- if (ipaddress == 0)
- {
- OnGameJoin( RET_GAME_GONE, NULL );
- return;
- }
-
- m_directConnectRemoteIP = ipaddress;
-
- LANMessage msg;
- msg.messageType = LANMessage::MSG_REQUEST_GAME_INFO;
- fillInLANMessage(&msg);
- msg.PlayerInfo.ip = GetLocalIP();
- wcslcpy(msg.PlayerInfo.playerName, m_name.str(), ARRAY_SIZE(msg.PlayerInfo.playerName));
-
- sendMessage(&msg, ipaddress);
-
- m_pendingAction = ACT_JOINDIRECTCONNECT;
- m_expiration = timeGetTime() + m_actionTimeout;
-}
-
-void LANAPI::RequestGameLeave( void )
-{
- LANMessage msg;
- msg.messageType = LANMessage::MSG_REQUEST_GAME_LEAVE;
- fillInLANMessage( &msg );
- wcslcpy(msg.PlayerInfo.playerName, m_name.str(), ARRAY_SIZE(msg.PlayerInfo.playerName));
- sendMessage(&msg);
- m_transport->update(); // Send immediately, before OnPlayerLeave below resets everything.
-
- if (m_currentGame && m_currentGame->getIP(0) == m_localIP)
- {
- // Exit out immediately if we're hosting
- OnPlayerLeave(m_name);
- removeGame(m_currentGame);
- m_currentGame = NULL;
- m_inLobby = true;
- }
- else
- {
- m_pendingAction = ACT_LEAVE;
- m_expiration = timeGetTime() + m_actionTimeout;
- }
-}
-
-void LANAPI::RequestGameAnnounce( void )
-{
- // In game - are we a game host?
- if (m_currentGame && !(m_currentGame->getIsDirectConnect()))
- {
- if (m_currentGame->getIP(0) == m_localIP || (m_currentGame->isGameInProgress() && TheNetwork && TheNetwork->isPacketRouter())) // if we're in game we should reply if we're the packet router
- {
- LANMessage reply;
- fillInLANMessage( &reply );
- reply.messageType = LANMessage::MSG_GAME_ANNOUNCE;
-
- AsciiString gameOpts = GameInfoToAsciiString(m_currentGame);
- strlcpy(reply.GameInfo.options,gameOpts.str(), ARRAY_SIZE(reply.GameInfo.options));
- wcslcpy(reply.GameInfo.gameName, m_currentGame->getName().str(), ARRAY_SIZE(reply.GameInfo.gameName));
- reply.GameInfo.inProgress = m_currentGame->isGameInProgress();
- reply.GameInfo.isDirectConnect = m_currentGame->getIsDirectConnect();
-
- sendMessage(&reply);
- }
- }
-}
-
-void LANAPI::RequestAccept( void )
-{
- if (m_inLobby || !m_currentGame)
- return;
-
- LANMessage msg;
- fillInLANMessage( &msg );
- msg.messageType = LANMessage::MSG_SET_ACCEPT;
- msg.Accept.isAccepted = true;
- wcslcpy(msg.Accept.gameName, m_currentGame->getName().str(), ARRAY_SIZE(msg.Accept.gameName));
- sendMessage(&msg);
-}
-
-void LANAPI::RequestHasMap( void )
-{
- if (m_inLobby || !m_currentGame)
- return;
-
- LANMessage msg;
- fillInLANMessage( &msg );
- msg.messageType = LANMessage::MSG_MAP_AVAILABILITY;
- msg.MapStatus.hasMap = m_currentGame->getSlot(m_currentGame->getLocalSlotNum())->hasMap();
- wcslcpy(msg.MapStatus.gameName, m_currentGame->getName().str(), ARRAY_SIZE(msg.MapStatus.gameName));
- CRC mapNameCRC;
-//mapNameCRC.computeCRC(m_currentGame->getMap().str(), m_currentGame->getMap().getLength());
- AsciiString portableMapName = TheGameState->realMapPathToPortableMapPath(m_currentGame->getMap());
- mapNameCRC.computeCRC(portableMapName.str(), portableMapName.getLength());
- msg.MapStatus.mapCRC = mapNameCRC.get();
- sendMessage(&msg);
-
- if (!msg.MapStatus.hasMap)
- {
- UnicodeString text;
- UnicodeString mapDisplayName;
- const MapMetaData *mapData = TheMapCache->findMap( m_currentGame->getMap() );
- Bool willTransfer = TRUE;
- if (mapData)
- {
- mapDisplayName.format(L"%ls", mapData->m_displayName.str());
- if (mapData->m_isOfficial)
- willTransfer = FALSE;
- }
- else
- {
- mapDisplayName.format(L"%hs", TheGameState->getMapLeafName(m_currentGame->getMap()).str());
- willTransfer = WouldMapTransfer(m_currentGame->getMap());
- }
- if (willTransfer)
- text.format(TheGameText->fetch("GUI:LocalPlayerNoMapWillTransfer"), mapDisplayName.str());
- else
- text.format(TheGameText->fetch("GUI:LocalPlayerNoMap"), mapDisplayName.str());
- OnChat(UnicodeString(L"SYSTEM"), m_localIP, text, LANCHAT_SYSTEM);
- }
-}
-
-void LANAPI::RequestChat( UnicodeString message, ChatType format )
-{
- LANMessage msg;
- fillInLANMessage( &msg );
- wcslcpy(msg.Chat.gameName, (m_currentGame) ? m_currentGame->getName().str() : L"", ARRAY_SIZE(msg.Chat.gameName));
- msg.messageType = LANMessage::MSG_CHAT;
- msg.Chat.chatType = format;
- wcslcpy(msg.Chat.message, message.str(), ARRAY_SIZE(msg.Chat.message));
- sendMessage(&msg);
-
- OnChat(m_name, m_localIP, message, format);
-}
-
-void LANAPI::RequestGameStart( void )
-{
- if (m_inLobby || !m_currentGame || m_currentGame->getIP(0) != m_localIP)
- return;
-
- LANMessage msg;
- msg.messageType = LANMessage::MSG_GAME_START;
- fillInLANMessage( &msg );
- sendMessage(&msg);
- m_transport->update(); // force a send
-
- OnGameStart();
-}
-
-void LANAPI::ResetGameStartTimer( void )
-{
- m_gameStartTime = 0;
- m_gameStartSeconds = 0;
-}
-
-void LANAPI::RequestGameStartTimer( Int seconds )
-{
- if (m_inLobby || !m_currentGame || m_currentGame->getIP(0) != m_localIP)
- return;
-
- UnsignedInt now = timeGetTime();
- m_gameStartTime = now + 1000;
- m_gameStartSeconds = (seconds) ? seconds - 1 : 0;
-
- LANMessage msg;
- msg.messageType = LANMessage::MSG_GAME_START_TIMER;
- msg.StartTimer.seconds = seconds;
- fillInLANMessage( &msg );
- sendMessage(&msg);
- m_transport->update(); // force a send
-
- OnGameStartTimer(seconds);
-}
-
-void LANAPI::RequestGameOptions( AsciiString gameOptions, Bool isPublic, UnsignedInt ip /* = 0 */ )
-{
- DEBUG_ASSERTCRASH(gameOptions.getLength() < m_lanMaxOptionsLength, ("Game options string is too long!"));
-
- if (!m_currentGame)
- return;
-
- LANMessage msg;
- fillInLANMessage( &msg );
- msg.messageType = LANMessage::MSG_GAME_OPTIONS;
- strlcpy(msg.GameOptions.options, gameOptions.str(), ARRAY_SIZE(msg.GameOptions.options));
- sendMessage(&msg, ip);
-
- m_lastGameopt = gameOptions;
-
- int player;
- for (player = 0; playergetIP(player) == m_localIP)
- {
- OnGameOptions(m_localIP, player, AsciiString(msg.GameOptions.options));
- break;
- }
- }
-
- // We can request game options (side, color, etc) while we don't have a slot yet. Of course, we don't need to
- // call OnGameOptions for those, so it's okay to silently fail.
- //DEBUG_ASSERTCRASH(player != MAX_SLOTS, ("Requested game options, but we're not in slot list!");
-}
-
-void LANAPI::RequestGameCreate( UnicodeString gameName, Bool isDirectConnect )
-{
- // No games of the same name should exist... Ignore that for now.
- /// @todo: make sure LAN games with identical names don't crash things like in RA2.
-
- if ((!m_inLobby || m_currentGame) && !isDirectConnect)
- {
- DEBUG_ASSERTCRASH(m_inLobby && m_currentGame, ("Can't create a game while in one!"));
- OnGameCreate(LANAPIInterface::RET_BUSY);
- return;
- }
-
- if (m_pendingAction != ACT_NONE)
- {
- OnGameCreate(LANAPIInterface::RET_BUSY);
- return;
- }
-
- // Create the local game object
- m_inLobby = false;
- LANGameInfo *myGame = NEW LANGameInfo;
-
- myGame->setSeed(GetTickCount());
-
-// myGame->setInProgress(false);
- myGame->enterGame();
- UnicodeString s;
- s.format(L"%8.8X%8.8X", m_localIP, myGame->getSeed());
- if (gameName.isEmpty())
- s.concat(m_name);
- else
- s.concat(gameName);
-
- s.truncateTo(g_lanGameNameLength);
-
- DEBUG_LOG(("Setting local game name to '%ls'", s.str()));
-
- myGame->setName(s);
-
- LANGameSlot newSlot;
- newSlot.setState(SLOT_PLAYER, m_name);
- newSlot.setIP(m_localIP);
- newSlot.setPort(NETWORK_BASE_PORT_NUMBER); // LAN game, everyone has a unique IP, so it's ok to use the same port.
- newSlot.setLastHeard(0);
- newSlot.setLogin(m_userName);
- newSlot.setHost(m_hostName);
-
- myGame->setSlot(0,newSlot);
- myGame->setNext(NULL);
- LANPreferences pref;
-
- AsciiString mapName = pref.getPreferredMap();
-
- myGame->setMap(mapName);
- myGame->setIsDirectConnect(isDirectConnect);
-
- myGame->setLastHeard(timeGetTime());
- m_currentGame = myGame;
-
-/// @todo: Need to initialize the players elsewere.
-/* for (int player = 1; player < MAX_SLOTS; ++player)
- {
- myGame->setPlayerName(player, UnicodeString(L""));
- myGame->setIP(player, 0);
- myGame->setAccepted(player, false);
- }*/
-
- // Add the game to the local game list
- addGame(myGame);
-
- // Send an announcement
- //RequestSlotList();
-/*
- LANMessage msg;
- wcslcpy(msg.name, m_name.str(), ARRAY_SIZE(msg.name));
- wcscpy(msg.GameInfo.gameName, myGame->getName().str());
- for (player=0; playergetPlayerName(player).str());
- msg.GameInfo.ip[player] = myGame->getIP(player);
- msg.GameInfo.playerAccepted[player] = myGame->getAccepted(player);
- }
- msg.messageType = LANMessage::MSG_GAME_ANNOUNCE;
-*/
- OnGameCreate(LANAPIInterface::RET_OK);
-}
-
-
-/*static const char slotListID = 'S';
-static const char gameOptionsID = 'G';
-static const char acceptID = 'A';
-static const char wannaStartID = 'W';
-
-AsciiString LANAPI::createSlotString( void )
-{
- AsciiString slotList;
- slotList.concat(slotListID);
- for (int i=0; igetLANSlot(i);
- AsciiString str;
- if (slot->isHuman())
- {
- str = "H";
- LANPlayer *user = slot->getUser();
- DEBUG_ASSERTCRASH(user, ("Human player has no User*!"));
- AsciiString name;
- name.translate(user->getName());
- str.concat(name);
- str.concat(',');
- }
- else if (slot->isAI())
- {
- if (slot->getState() == SLOT_EASY_AI)
- str = "CE,";
- if (slot->getState() == SLOT_MED_AI)
- str = "CM,";
- else
- str = "CB,";
- }
- else if (slot->getState() == SLOT_OPEN)
- {
- str = "O,";
- }
- else if (slot->getState() == SLOT_CLOSED)
- {
- str = "X,";
- }
- else
- {
- DEBUG_ASSERTCRASH(false, ("Bad slot type"));
- str = "X,";
- }
-
- slotList.concat(str);
- }
- return slotList;
-}
-*/
-/*
-void LANAPI::RequestSlotList( void )
-{
-
- LANMessage reply;
- reply.messageType = LANMessage::MSG_GAME_ANNOUNCE;
- wcslcpy(reply.name, m_name.str(), ARRAY_SIZE(reply.name));
- int player;
- for (player = 0; player < MAX_SLOTS; ++player)
- {
- wcslcpy(reply.GameInfo.name[player], m_currentGame->getPlayerName(player).str(), ARRAY_SIZE(reply.GameInfo.name[player]));
- reply.GameInfo.ip[player] = m_currentGame->getIP(player);
- reply.GameInfo.playerAccepted[player] = m_currentGame->getSlot(player)->isAccepted();
- }
- wcslcpy(reply.GameInfo.gameName, m_currentGame->getName().str(), ARRAY_SIZE(reply.GameInfo.gameName));
- reply.GameInfo.inProgress = m_currentGame->isGameInProgress();
-
- sendMessage(&reply);
-
- OnSlotList(LANAPIInterface::RET_OK, m_currentGame);
-}
-*/
-void LANAPI::RequestSetName( UnicodeString newName )
-{
- newName.trim();
- if (m_pendingAction != ACT_NONE)
- {
- // Can't change name while joining games
- OnNameChange(m_localIP, newName);
- return;
- }
-
- // Set up timer
- m_lastResendTime = timeGetTime();
-
- if (m_inLobby && m_pendingAction == ACT_NONE)
- {
- m_name = newName;
- LANMessage msg;
- fillInLANMessage( &msg );
- msg.messageType = LANMessage::MSG_LOBBY_ANNOUNCE;
- sendMessage(&msg);
-
- // Update the interface
- LANPlayer *player = LookupPlayer(m_localIP);
- if (!player)
- {
- player = NEW LANPlayer;
- player->setIP(m_localIP);
- }
- else
- {
- removePlayer(player);
- }
- player->setName(m_name);
- player->setHost(m_hostName);
- player->setLogin(m_userName);
- player->setLastHeard(timeGetTime());
-
- addPlayer(player);
-
- OnNameChange(player->getIP(), player->getName());
- }
-}
-
-void LANAPI::fillInLANMessage( LANMessage *msg )
-{
- if (!msg)
- return;
-
- wcslcpy(msg->name, m_name.str(), ARRAY_SIZE(msg->name));
- strlcpy(msg->userName, m_userName.str(), ARRAY_SIZE(msg->userName));
- strlcpy(msg->hostName, m_hostName.str(), ARRAY_SIZE(msg->hostName));
-}
-
-void LANAPI::RequestLobbyLeave( Bool forced )
-{
- LANMessage msg;
- msg.messageType = LANMessage::MSG_REQUEST_LOBBY_LEAVE;
- fillInLANMessage( &msg );
- sendMessage(&msg);
-
- if (forced)
- m_transport->update();
-}
-
-// Misc utility functions
-LANGameInfo * LANAPI::LookupGame( UnicodeString gameName )
-{
- LANGameInfo *theGame = m_games;
-
- while (theGame && theGame->getName() != gameName)
- {
- theGame = theGame->getNext();
- }
-
- return theGame; // NULL means we didn't find anything.
-}
-
-LANGameInfo * LANAPI::LookupGameByListOffset( Int offset )
-{
- LANGameInfo *theGame = m_games;
-
- if (offset < 0)
- return NULL;
-
- while (offset-- && theGame)
- {
- theGame = theGame->getNext();
- }
-
- return theGame; // NULL means we didn't find anything.
-}
-
-void LANAPI::removeGame( LANGameInfo *game )
-{
- LANGameInfo *g = m_games;
- if (!game)
- {
- return;
- }
- else if (m_games == game)
- {
- m_games = m_games->getNext();
- }
- else
- {
- while (g->getNext() && g->getNext() != game)
- {
- g = g->getNext();
- }
- if (g->getNext() == game)
- {
- g->setNext(game->getNext());
- }
- else
- {
- // Odd. We went the whole way without finding it in the list.
- DEBUG_ASSERTCRASH(false, ("LANGameInfo wasn't in the list"));
- }
- }
-}
-
-LANPlayer * LANAPI::LookupPlayer( UnsignedInt playerIP )
-{
- LANPlayer *thePlayer = m_lobbyPlayers;
-
- while (thePlayer && thePlayer->getIP() != playerIP)
- {
- thePlayer = thePlayer->getNext();
- }
-
- return thePlayer; // NULL means we didn't find anything.
-}
-
-void LANAPI::removePlayer( LANPlayer *player )
-{
- LANPlayer *p = m_lobbyPlayers;
- if (!player)
- {
- return;
- }
- else if (m_lobbyPlayers == player)
- {
- m_lobbyPlayers = m_lobbyPlayers->getNext();
- }
- else
- {
- while (p->getNext() && p->getNext() != player)
- {
- p = p->getNext();
- }
- if (p->getNext() == player)
- {
- p->setNext(player->getNext());
- }
- else
- {
- // Odd. We went the whole way without finding it in the list.
- DEBUG_ASSERTCRASH(false, ("LANPlayer wasn't in the list"));
- }
- }
-}
-
-void LANAPI::addGame( LANGameInfo *game )
-{
- if (!m_games)
- {
- m_games = game;
- game->setNext(NULL);
- return;
- }
- else
- {
- if (game->getName().compareNoCase(m_games->getName()) < 0)
- {
- game->setNext(m_games);
- m_games = game;
- return;
- }
- else
- {
- LANGameInfo *g = m_games;
- while (g->getNext() && g->getNext()->getName().compareNoCase(game->getName()) > 0)
- {
- g = g->getNext();
- }
- game->setNext(g->getNext());
- g->setNext(game);
- return;
- }
- }
-}
-
-void LANAPI::addPlayer( LANPlayer *player )
-{
- if (!m_lobbyPlayers)
- {
- m_lobbyPlayers = player;
- player->setNext(NULL);
- return;
- }
- else
- {
- if (player->getName().compareNoCase(m_lobbyPlayers->getName()) < 0)
- {
- player->setNext(m_lobbyPlayers);
- m_lobbyPlayers = player;
- return;
- }
- else
- {
- LANPlayer *p = m_lobbyPlayers;
- while (p->getNext() && p->getNext()->getName().compareNoCase(player->getName()) > 0)
- {
- p = p->getNext();
- }
- player->setNext(p->getNext());
- p->setNext(player);
- return;
- }
- }
-}
-
-Bool LANAPI::SetLocalIP( UnsignedInt localIP )
-{
- Bool retval = TRUE;
- m_localIP = localIP;
-
- m_transport->reset();
- retval = m_transport->init(m_localIP, lobbyPort);
- m_transport->allowBroadcasts(true);
-
- return retval;
-}
-
-void LANAPI::SetLocalIP( AsciiString localIP )
-{
- UnsignedInt resolvedIP = ResolveIP(localIP);
- SetLocalIP(resolvedIP);
-}
-
-Bool LANAPI::AmIHost( void )
-{
- return m_currentGame && m_currentGame->getIP(0) == m_localIP;
-}
-
-void LANAPI::setIsActive(Bool isActive) {
- DEBUG_LOG(("LANAPI::setIsActive - entering"));
- if (isActive != m_isActive) {
- DEBUG_LOG(("LANAPI::setIsActive - m_isActive changed to %s", isActive ? "TRUE" : "FALSE"));
- if (isActive == FALSE) {
- if ((m_inLobby == FALSE) && (m_currentGame != NULL)) {
- LANMessage msg;
- fillInLANMessage( &msg );
- msg.messageType = LANMessage::MSG_INACTIVE;
- sendMessage(&msg);
- DEBUG_LOG(("LANAPI::setIsActive - sent an IsActive message"));
- }
- }
- }
- m_isActive = isActive;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp b/Generals/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
deleted file mode 100644
index 1c61c6c1443..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: LANAPICallbacks.cpp
-// Author: Chris Huybregts, October 2001
-// Description: LAN API Callbacks
-///////////////////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "strtok_r.h"
-#include "Common/GameEngine.h"
-#include "Common/GlobalData.h"
-#include "Common/MessageStream.h"
-#include "Common/MultiplayerSettings.h"
-#include "Common/PlayerTemplate.h"
-#include "Common/QuotedPrintable.h"
-#include "Common/RandomValue.h"
-#include "Common/UserPreferences.h"
-#include "GameClient/GameText.h"
-#include "GameClient/LanguageFilter.h"
-#include "GameClient/MapUtil.h"
-#include "GameClient/MessageBox.h"
-#include "GameLogic/GameLogic.h"
-#include "GameNetwork/FileTransfer.h"
-#include "GameNetwork/LANAPICallbacks.h"
-#include "GameNetwork/networkutil.h"
-
-LANAPI *TheLAN = NULL;
-extern Bool LANbuttonPushed;
-
-
-//Colors used for the chat dialogs
-const Color playerColor = GameMakeColor(255,255,255,255);
-const Color gameColor = GameMakeColor(255,255,255,255);
-const Color gameInProgressColor = GameMakeColor(128,128,128,255);
-const Color chatNormalColor = GameMakeColor(50,215,230,255);
-const Color chatActionColor = GameMakeColor(255,0,255,255);
-const Color chatLocalNormalColor = GameMakeColor(255,128,0,255);
-const Color chatLocalActionColor = GameMakeColor(128,255,255,255);
-const Color chatSystemColor = GameMakeColor(255,255,255,255);
-const Color acceptTrueColor = GameMakeColor(0,255,0,255);
-const Color acceptFalseColor = GameMakeColor(255,0,0,255);
-
-
-UnicodeString LANAPIInterface::getErrorStringFromReturnType( ReturnType ret )
-{
- switch (ret)
- {
- case RET_OK:
- return TheGameText->fetch("LAN:OK");
- case RET_TIMEOUT:
- return TheGameText->fetch("LAN:ErrorTimeout");
- case RET_GAME_FULL:
- return TheGameText->fetch("LAN:ErrorGameFull");
- case RET_DUPLICATE_NAME:
- return TheGameText->fetch("LAN:ErrorDuplicateName");
- case RET_CRC_MISMATCH:
- return TheGameText->fetch("LAN:ErrorCRCMismatch");
- case RET_GAME_STARTED:
- return TheGameText->fetch("LAN:ErrorGameStarted");
- case RET_GAME_EXISTS:
- return TheGameText->fetch("LAN:ErrorGameExists");
- case RET_GAME_GONE:
- return TheGameText->fetch("LAN:ErrorGameGone");
- case RET_BUSY:
- return TheGameText->fetch("LAN:ErrorBusy");
- case RET_SERIAL_DUPE:
- return TheGameText->fetch("WOL:ChatErrorSerialDup");
- default:
- return TheGameText->fetch("LAN:ErrorUnknown");
- }
-}
-
-// On functions are (generally) the result of network traffic
-
-void LANAPI::OnAccept( UnsignedInt playerIP, Bool status )
-{
- if( AmIHost() )
- {
- Int i = 0;
- for (; i < MAX_SLOTS; i++)
- {
- if (m_currentGame->getIP(i) == playerIP)
- {
- if(status)
- m_currentGame->getLANSlot(i)->setAccept();
- else
- m_currentGame->getLANSlot(i)->unAccept();
- break;
- }
- }
- if (i != MAX_SLOTS )
- {
- RequestGameOptions( GenerateGameOptionsString(), false );
- lanUpdateSlotList();
- }
- }
- else
- {
- //i'm not the host but if the accept came from the host...
- if( m_currentGame->getIP(0) == playerIP )
- {
- UnicodeString text;
- text = TheGameText->fetch("GUI:HostWantsToStart");
- OnChat(UnicodeString(L"SYSTEM"), m_localIP, text, LANCHAT_SYSTEM);
- }
- }
-}
-
-void LANAPI::OnHasMap( UnsignedInt playerIP, Bool status )
-{
- if( AmIHost() )
- {
- Int i = 0;
- for (; i < MAX_SLOTS; i++)
- {
- if (m_currentGame->getIP(i) == playerIP)
- {
- m_currentGame->getLANSlot(i)->setMapAvailability( status );
- break;
- }
- }
- if (i != MAX_SLOTS )
- {
- UnicodeString mapDisplayName;
- const MapMetaData *mapData = TheMapCache->findMap( m_currentGame->getMap() );
- Bool willTransfer = TRUE;
- if (mapData)
- {
- mapDisplayName.format(L"%ls", mapData->m_displayName.str());
- if (mapData->m_isOfficial)
- willTransfer = FALSE;
- }
- else
- {
- mapDisplayName.format(L"%hs", m_currentGame->getMap().str());
- willTransfer = WouldMapTransfer(m_currentGame->getMap());
- }
- if (!status)
- {
- UnicodeString text;
- if (willTransfer)
- text.format(TheGameText->fetch("GUI:PlayerNoMapWillTransfer"), m_currentGame->getLANSlot(i)->getName().str(), mapDisplayName.str());
- else
- text.format(TheGameText->fetch("GUI:PlayerNoMap"), m_currentGame->getLANSlot(i)->getName().str(), mapDisplayName.str());
- OnChat(UnicodeString(L"SYSTEM"), m_localIP, text, LANCHAT_SYSTEM);
- }
- lanUpdateSlotList();
- }
- }
-}
-
-void LANAPI::OnGameStartTimer( Int seconds )
-{
- UnicodeString text;
- if (seconds == 1)
- text.format(TheGameText->fetch("LAN:GameStartTimerSingular"), seconds);
- else
- text.format(TheGameText->fetch("LAN:GameStartTimerPlural"), seconds);
- OnChat(UnicodeString(L"SYSTEM"), m_localIP, text, LANCHAT_SYSTEM);
-}
-
-void LANAPI::OnGameStart( void )
-{
- //DEBUG_LOG(("Map is '%s', preview is '%s'", m_currentGame->getMap().str(), GetPreviewFromMap(m_currentGame->getMap()).str()));
- //DEBUG_LOG(("Map is '%s', INI is '%s'", m_currentGame->getMap().str(), GetINIFromMap(m_currentGame->getMap()).str()));
-
- if (m_currentGame)
- {
- LANPreferences pref;
- AsciiString option;
- option.format("%d", m_currentGame->getLANSlot( m_currentGame->getLocalSlotNum() )->getPlayerTemplate());
- pref["PlayerTemplate"] = option;
- option.format("%d", m_currentGame->getLANSlot( m_currentGame->getLocalSlotNum() )->getColor());
- pref["Color"] = option;
- if (m_currentGame->amIHost())
- {
- pref["Map"] = AsciiStringToQuotedPrintable(m_currentGame->getMap());
- pref.setSuperweaponRestricted( m_currentGame->getSuperweaponRestriction() > 0 );
- pref.setStartingCash( m_currentGame->getStartingCash() );
- }
- pref.write();
-
- m_isInLANMenu = FALSE;
-
- //m_currentGame->startGame(0);
-
- // Set up the game network
- DEBUG_ASSERTCRASH(TheNetwork == NULL, ("For some reason TheNetwork isn't NULL at the start of this game. Better look into that."));
-
- delete TheNetwork;
- TheNetwork = NULL;
-
- // Time to initialize TheNetwork for this game.
- TheNetwork = NetworkInterface::createNetwork();
- TheNetwork->init();
- TheNetwork->setLocalAddress(m_localIP, 8088);
- TheNetwork->initTransport();
-
- TheNetwork->parseUserList(m_currentGame);
-
- if (TheGameLogic->isInGame())
- TheGameLogic->clearGameData();
-
- Bool filesOk = DoAnyMapTransfers(m_currentGame);
-
- // see if we really have the map. if not, back out.
- TheMapCache->updateCache();
- if (!filesOk || TheMapCache->findMap(m_currentGame->getMap()) == NULL)
- {
- DEBUG_LOG(("After transfer, we didn't really have the map. Bailing..."));
- OnPlayerLeave(m_name);
- removeGame(m_currentGame);
- m_currentGame = NULL;
- m_inLobby = TRUE;
-
- delete TheNetwork;
- TheNetwork = NULL;
-
- OnChat(UnicodeString::TheEmptyString, 0, TheGameText->fetch("GUI:CouldNotTransferMap"), LANCHAT_SYSTEM);
- return;
- }
-
- m_currentGame->startGame(0);
-
- // shutdown the top, but do not pop it off the stack
- //TheShell->hideShell();
- // setup the Global Data with the Map and Seed
- TheWritableGlobalData->m_pendingFile = m_currentGame->getMap();
-
- // send a message to the logic for a new game
- GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
- msg->appendIntegerArgument(GAME_LAN);
-
- TheWritableGlobalData->m_useFpsLimit = false;
-
- // Set the random seed
- InitGameLogicRandom( m_currentGame->getSeed() );
- DEBUG_LOG(("InitGameLogicRandom( %d )", m_currentGame->getSeed()));
- }
-}
-
-void LANAPI::OnGameOptions( UnsignedInt playerIP, Int playerSlot, AsciiString options )
-{
- if (!m_currentGame)
- return;
-
- if (m_currentGame->getIP(playerSlot) != playerIP)
- return; // He's not in our game?!?
-
-
- if (m_currentGame->isGameInProgress())
- return; // we don't want to process any game options while in game.
-
- if (playerSlot == 0 && !m_currentGame->amIHost())
- {
- m_currentGame->setLastHeard(timeGetTime());
- AsciiString oldOptions = GameInfoToAsciiString(m_currentGame); // save these off for if we get booted
- if(ParseGameOptionsString(m_currentGame,options))
- {
- lanUpdateSlotList();
- updateGameOptions();
- }
- Bool booted = true;
- for(Int player = 1; player< MAX_SLOTS; player++)
- {
- if(m_currentGame->getIP(player) == m_localIP)
- {
- booted = false;
- break;
- }
- }
- if(booted)
- {
- // restore the options with us in so we can save prefs
- ParseGameOptionsString(m_currentGame, oldOptions);
- OnPlayerLeave(m_name);
- }
-
- }
- else
- {
- // Check for user/host updates
- {
- AsciiString key;
- AsciiString munkee = options;
- munkee.nextToken(&key, "=");
- //DEBUG_LOG(("GameOpt request: key=%s, val=%s from player %d", key.str(), munkee.str(), playerSlot));
-
- LANGameSlot *slot = m_currentGame->getLANSlot(playerSlot);
- if (!slot)
- return;
-
- if (key == "User")
- {
- slot->setLogin(munkee.str()+1);
- return;
- }
- else if (key == "Host")
- {
- slot->setHost(munkee.str()+1);
- return;
- }
- }
-
- // Parse player requests (side, color, etc)
- if( AmIHost() && m_localIP != playerIP)
- {
- if (options.compare("HELLO") == 0)
- {
- m_currentGame->setPlayerLastHeard(playerSlot, timeGetTime());
- }
- else
- {
- m_currentGame->setPlayerLastHeard(playerSlot, timeGetTime());
- Bool change = false;
- Bool shouldUnaccept = false;
- AsciiString key;
- options.nextToken(&key, "=");
- Int val = atoi(options.str()+1);
- DEBUG_LOG(("GameOpt request: key=%s, val=%s from player %d", key.str(), options.str(), playerSlot));
-
- LANGameSlot *slot = m_currentGame->getLANSlot(playerSlot);
- if (!slot)
- return;
-
- if (key == "Color")
- {
- if (val >= -1 && val < TheMultiplayerSettings->getNumColors() && val != slot->getColor() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER)
- {
- Bool colorAvailable = TRUE;
- if(val != -1 )
- {
- for(Int i=0; i getLANSlot(i);
- if(val == checkSlot->getColor() && slot != checkSlot)
- {
- colorAvailable = FALSE;
- break;
- }
- }
- }
- if(colorAvailable)
- slot->setColor(val);
- change = true;
- }
- else
- {
- DEBUG_LOG(("Rejecting invalid color %d", val));
- }
- }
- else if (key == "PlayerTemplate")
- {
- if (val >= PLAYERTEMPLATE_MIN && val < ThePlayerTemplateStore->getPlayerTemplateCount() && val != slot->getPlayerTemplate())
- {
- slot->setPlayerTemplate(val);
- if (val == PLAYERTEMPLATE_OBSERVER)
- {
- slot->setColor(-1);
- slot->setStartPos(-1);
- slot->setTeamNumber(-1);
- }
- change = true;
- shouldUnaccept = true;
- }
- else
- {
- DEBUG_LOG(("Rejecting invalid PlayerTemplate %d", val));
- }
- }
- else if (key == "StartPos" && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER)
- {
-
- if (val >= -1 && val < MAX_SLOTS && val != slot->getStartPos())
- {
- Bool startPosAvailable = TRUE;
- if(val != -1)
- for(Int i=0; i getLANSlot(i);
- if(val == checkSlot->getStartPos() && slot != checkSlot)
- {
- startPosAvailable = FALSE;
- break;
- }
- }
- if(startPosAvailable)
- slot->setStartPos(val);
- change = true;
- shouldUnaccept = true;
- }
- else
- {
- DEBUG_LOG(("Rejecting invalid startPos %d", val));
- }
- }
- else if (key == "Team")
- {
- if (val >= -1 && val < MAX_SLOTS/2 && val != slot->getTeamNumber() && slot->getPlayerTemplate() != PLAYERTEMPLATE_OBSERVER)
- {
- slot->setTeamNumber(val);
- change = true;
- shouldUnaccept = true;
- }
- else
- {
- DEBUG_LOG(("Rejecting invalid team %d", val));
- }
- }
- else if (key == "NAT")
- {
- if ((val >= FirewallHelperClass::FIREWALL_TYPE_SIMPLE) &&
- (val <= FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA))
- {
- slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)val);
- DEBUG_LOG(("NAT behavior set to %d for player %d", val, playerSlot));
- change = true;
- }
- else
- {
- DEBUG_LOG(("Rejecting invalid NAT behavior %d", (Int)val));
- }
- }
-
- if (change)
- {
- if (shouldUnaccept)
- m_currentGame->resetAccepted();
- RequestGameOptions(GenerateGameOptionsString(), true);
- lanUpdateSlotList();
- DEBUG_LOG(("Slot value is color=%d, PlayerTemplate=%d, startPos=%d, team=%d",
- slot->getColor(), slot->getPlayerTemplate(), slot->getStartPos(), slot->getTeamNumber()));
- DEBUG_LOG(("Slot list updated to %s", GenerateGameOptionsString().str()));
- }
- }
- }
- }
-}
-
-
-/*
-void LANAPI::OnSlotList( ReturnType ret, LANGameInfo *theGame )
-{
- if (!theGame || theGame != m_currentGame)
- return;
-
- Bool foundMe = false;
- for (int player = 0; player < MAX_SLOTS; ++player)
- {
- if (m_currentGame->getIP(player) == m_localIP)
- {
- foundMe = true;
- break;
- }
- }
- if (!foundMe)
- {
- // I've been kicked - back to the lobby for me!
- // We're counting on the fact that OnPlayerLeave winds up calling reset on TheLAN.
- OnPlayerLeave(m_name);
- return;
- }
-
- lanUpdateSlotList();
-}
-*/
-void LANAPI::OnPlayerJoin( Int slot, UnicodeString playerName )
-{
- if (m_currentGame && m_currentGame->getIP(0) == m_localIP)
- {
- // Someone New Joined.. lets reset the accepts
- m_currentGame->resetAccepted();
-
- // Send out the game options
- RequestGameOptions(GenerateGameOptionsString(), true);
- }
-
- lanUpdateSlotList();
-}
-
-void LANAPI::OnGameJoin( ReturnType ret, LANGameInfo *theGame )
-{
- if (ret == RET_OK)
- {
- LANbuttonPushed = true;
- TheShell->push( AsciiString("Menus/LanGameOptionsMenu.wnd") );
- //lanUpdateSlotList();
-
- LANPreferences pref;
- AsciiString options;
- options.format("PlayerTemplate=%d", pref.getPreferredFaction());
- RequestGameOptions(options, true);
- options.format("Color=%d", pref.getPreferredColor());
- RequestGameOptions(options, true);
- options.format("User=%s", m_userName.str());
- RequestGameOptions( options, true );
- options.format("Host=%s", m_hostName.str());
- RequestGameOptions( options, true );
- options.format("NAT=%d", FirewallHelperClass::FIREWALL_TYPE_SIMPLE); // BGC: This is a LAN game, so there is no firewall.
- RequestGameOptions( options, true );
- }
- else if (ret != RET_BUSY)
- {
- /// @todo: re-enable lobby controls? Error msgs?
- UnicodeString title, body;
- title = TheGameText->fetch("LAN:JoinFailed");
- body = getErrorStringFromReturnType(ret);
- MessageBoxOk(title, body, NULL);
- }
-}
-
-void LANAPI::OnHostLeave( void )
-{
- DEBUG_ASSERTCRASH(!m_inLobby && m_currentGame, ("Game info is gone!"));
- if (m_inLobby || !m_currentGame)
- return;
- LANbuttonPushed = true;
- DEBUG_LOG(("Host left - popping to lobby"));
- TheShell->pop();
-}
-
-void LANAPI::OnPlayerLeave( UnicodeString player )
-{
- DEBUG_ASSERTCRASH(!m_inLobby && m_currentGame, ("Game info is gone!"));
- if (m_inLobby || !m_currentGame || m_currentGame->isGameInProgress())
- return;
-
- if (m_name.compare(player) == 0)
- {
- // We're leaving. Save options and Pop the shell up a screen.
- //DEBUG_ASSERTCRASH(false, ("Slot is %d", m_currentGame->getLocalSlotNum()));
- if (m_currentGame && m_currentGame->isInGame() && m_currentGame->getLocalSlotNum() >= 0)
- {
- LANPreferences pref;
- AsciiString option;
- option.format("%d", m_currentGame->getLANSlot( m_currentGame->getLocalSlotNum() )->getPlayerTemplate());
- pref["PlayerTemplate"] = option;
- option.format("%d", m_currentGame->getLANSlot( m_currentGame->getLocalSlotNum() )->getColor());
- pref["Color"] = option;
- if (m_currentGame->amIHost())
- pref["Map"] = AsciiStringToQuotedPrintable(m_currentGame->getMap());
- pref.write();
- }
- LANbuttonPushed = true;
- DEBUG_LOG(("OnPlayerLeave says we're leaving! pop away!"));
- TheShell->pop();
- }
- else
- {
- if (m_currentGame && m_currentGame->getIP(0) == m_localIP)
- {
- // Force a new slotlist send
- m_lastResendTime = 0;
-
- lanUpdateSlotList();
- RequestGameOptions( GenerateGameOptionsString(), true );
-
- }
- }
-}
-
-void LANAPI::OnGameList( LANGameInfo *gameList )
-{
-
- if (m_inLobby)
- {
- LANDisplayGameList(listboxGames, gameList);
- }
-}
-
-void LANAPI::OnGameCreate( ReturnType ret )
-{
- if (ret == RET_OK)
- {
-
- LANbuttonPushed = true;
- TheShell->push( AsciiString("Menus/LanGameOptionsMenu.wnd") );
-
- RequestLobbyLeave( false );
- //RequestGameAnnounce( ); // can't do this here, since we don't have a map set
- }
- else
- {
- if(m_inLobby)
- {
- switch( ret )
- {
- case RET_GAME_EXISTS:
- GadgetListBoxAddEntryText(listboxChatWindow, TheGameText->fetch("LAN:ErrorGameExists"), chatSystemColor, -1, -1);
- break;
- case RET_BUSY:
- GadgetListBoxAddEntryText(listboxChatWindow, TheGameText->fetch("LAN:ErrorBusy"), chatSystemColor, -1, -1);
- break;
- default:
- GadgetListBoxAddEntryText(listboxChatWindow, TheGameText->fetch("LAN:ErrorUnknown"), chatSystemColor, -1, -1);
- }
- }
- }
-
-}
-
-void LANAPI::OnPlayerList( LANPlayer *playerList )
-{
- if (m_inLobby)
- {
-
- UnsignedInt selectedIP = 0;
- Int selectedIndex = -1;
- Int indexToSelect = -1;
- GadgetListBoxGetSelected(listboxPlayers, &selectedIndex);
-
- if (selectedIndex != -1 )
- selectedIP = (UnsignedInt) GadgetListBoxGetItemData(listboxPlayers, selectedIndex, 0);
-
- GadgetListBoxReset(listboxPlayers);
-
- LANPlayer *player = m_lobbyPlayers;
- while (player)
- {
- Int addedIndex = GadgetListBoxAddEntryText(listboxPlayers, player->getName(), playerColor, -1, -1);
- GadgetListBoxSetItemData(listboxPlayers, (void *)player->getIP(),addedIndex, 0 );
-
- if (selectedIP == player->getIP())
- indexToSelect = addedIndex;
-
- player = player->getNext();
- }
-
- if (indexToSelect >= 0)
- GadgetListBoxSetSelected(listboxPlayers, indexToSelect);
- }
-}
-
-void LANAPI::OnNameChange( UnsignedInt IP, UnicodeString newName )
-{
- OnPlayerList(m_lobbyPlayers);
-}
-
-void LANAPI::OnInActive(UnsignedInt IP) {
-
-}
-
-void LANAPI::OnChat( UnicodeString player, UnsignedInt ip, UnicodeString message, ChatType format )
-{
- GameWindow *chatWindow = NULL;
-
- if (m_inLobby)
- {
- chatWindow = listboxChatWindow;
- }
- else if( m_currentGame && m_currentGame->isGameInProgress() && TheShell->isShellActive())
- {
- chatWindow = listboxChatWindowScoreScreen;
- }
- else if( m_currentGame && !m_currentGame->isGameInProgress())
- {
- chatWindow = listboxChatWindowLanGame;
- }
- if (chatWindow == NULL)
- return;
- Int index = -1;
- UnicodeString unicodeChat;
- switch (format)
- {
- case LANAPIInterface::LANCHAT_SYSTEM:
- unicodeChat = L"";
- unicodeChat.concat(message);
- unicodeChat.concat(L"");
- index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatSystemColor, -1, -1);
- break;
- case LANAPIInterface::LANCHAT_EMOTE:
- unicodeChat = player;
- unicodeChat.concat(L' ');
- unicodeChat.concat(message);
- if (ip == m_localIP)
- index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatLocalActionColor, -1, -1);
- else
- index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatActionColor, -1, -1);
- break;
- case LANAPIInterface::LANCHAT_NORMAL:
- default:
- {
- // Do the language filtering.
- TheLanguageFilter->filterLine(message);
-
- Color chatColor = GameMakeColor(255, 255, 255, 255);
- if (m_currentGame)
- {
- Int slotNum = m_currentGame->getSlotNum(player);
- // it'll be -1 if its invalid.
- if (slotNum >= 0) {
- GameSlot *gs = m_currentGame->getSlot(slotNum);
- if (gs) {
- Int colorIndex = gs->getColor();
- MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(colorIndex);
- if (def)
- chatColor = def->getColor();
- }
- }
- }
-
- unicodeChat = L"[";
- unicodeChat.concat(player);
- unicodeChat.concat(L"] ");
- unicodeChat.concat(message);
- if (ip == m_localIP)
- index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatColor, -1, -1);
- else
- index =GadgetListBoxAddEntryText(chatWindow, unicodeChat, chatColor, -1, -1);
- break;
- }
- }
- GadgetListBoxSetItemData(chatWindow, (void *)-1, index);
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp b/Generals/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
deleted file mode 100644
index fd505c41297..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////////////
-// FILE: LANAPIHandlers.cpp
-// Author: Matthew D. Campbell, October 2001
-// Description: LAN callback handlers
-///////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/crc.h"
-#include "Common/GameState.h"
-#include "Common/Registry.h"
-#include "Common/GlobalData.h"
-#include "Common/QuotedPrintable.h"
-#include "Common/UserPreferences.h"
-#include "GameNetwork/LANAPI.h"
-#include "GameNetwork/LANAPICallbacks.h"
-#include "GameClient/MapUtil.h"
-
-void LANAPI::handleRequestLocations( LANMessage *msg, UnsignedInt senderIP )
-{
- if (m_inLobby)
- {
- LANMessage reply;
- fillInLANMessage( &reply );
- reply.messageType = LANMessage::MSG_LOBBY_ANNOUNCE;
-
- sendMessage(&reply);
- m_lastResendTime = timeGetTime();
- }
- else
- {
- // In game - are we a game host?
- if (m_currentGame)
- {
- if (m_currentGame->getIP(0) == m_localIP)
- {
- LANMessage reply;
- fillInLANMessage( &reply );
- reply.messageType = LANMessage::MSG_GAME_ANNOUNCE;
- AsciiString gameOpts = GenerateGameOptionsString();
- strlcpy(reply.GameInfo.options, gameOpts.str(), ARRAY_SIZE(reply.GameInfo.options));
- wcslcpy(reply.GameInfo.gameName, m_currentGame->getName().str(), ARRAY_SIZE(reply.GameInfo.gameName));
- reply.GameInfo.inProgress = m_currentGame->isGameInProgress();
-
- sendMessage(&reply);
- }
- else
- {
- // We're a joiner
- }
- }
- }
- // Add the player to the lobby player list
- LANPlayer *player = LookupPlayer(senderIP);
- if (!player)
- {
- player = NEW LANPlayer;
- player->setIP(senderIP);
- }
- else
- {
- removePlayer(player);
- }
- player->setName(UnicodeString(msg->name));
- player->setHost(msg->hostName);
- player->setLogin(msg->userName);
- player->setLastHeard(timeGetTime());
-
- addPlayer(player);
-
- OnNameChange(player->getIP(), player->getName());
-}
-
-void LANAPI::handleGameAnnounce( LANMessage *msg, UnsignedInt senderIP )
-{
- if (senderIP == m_localIP)
- {
- return; // Don't try to update own info
- }
- else if (m_currentGame && m_currentGame->isGameInProgress())
- {
- return; // Don't care about games if we're playing
- }
- else if (senderIP == m_directConnectRemoteIP)
- {
-
- if (m_currentGame == NULL)
- {
- LANGameInfo *game = LookupGame(UnicodeString(msg->GameInfo.gameName));
- if (!game)
- {
- game = NEW LANGameInfo;
- game->setName(UnicodeString(msg->GameInfo.gameName));
- addGame(game);
- }
- Bool success = ParseGameOptionsString(game,AsciiString(msg->GameInfo.options));
- game->setGameInProgress(msg->GameInfo.inProgress);
- game->setIsDirectConnect(msg->GameInfo.isDirectConnect);
- game->setLastHeard(timeGetTime());
- if (!success)
- {
- // remove from list
- removeGame(game);
- delete game;
- return;
- }
- RequestGameJoin(game, m_directConnectRemoteIP);
- }
- }
- else
- {
- LANGameInfo *game = LookupGame(UnicodeString(msg->GameInfo.gameName));
- if (!game)
- {
- game = NEW LANGameInfo;
- game->setName(UnicodeString(msg->GameInfo.gameName));
- addGame(game);
- }
- Bool success = ParseGameOptionsString(game,AsciiString(msg->GameInfo.options));
- game->setGameInProgress(msg->GameInfo.inProgress);
- game->setIsDirectConnect(msg->GameInfo.isDirectConnect);
- game->setLastHeard(timeGetTime());
- if (!success)
- {
- // remove from list
- removeGame(game);
- delete game;
- game = NULL;
- }
-
- OnGameList( m_games );
- // if (game == m_currentGame && !m_inLobby)
- // OnSlotList(RET_OK, game);
- }
-}
-
-void LANAPI::handleLobbyAnnounce( LANMessage *msg, UnsignedInt senderIP )
-{
- LANPlayer *player = LookupPlayer(senderIP);
- if (!player)
- {
- player = NEW LANPlayer;
- player->setIP(senderIP);
- }
- else
- {
- removePlayer(player);
- }
- player->setName(UnicodeString(msg->name));
- player->setHost(msg->hostName);
- player->setLogin(msg->userName);
- player->setLastHeard(timeGetTime());
-
- addPlayer(player);
-
- OnNameChange(player->getIP(), player->getName());
-}
-
-void LANAPI::handleRequestGameInfo( LANMessage *msg, UnsignedInt senderIP )
-{
- // In game - are we a game host?
- if (m_currentGame)
- {
- if (m_currentGame->getIP(0) == m_localIP || (m_currentGame->isGameInProgress() && TheNetwork && TheNetwork->isPacketRouter())) // if we're in game we should reply if we're the packet router
- {
- LANMessage reply;
- fillInLANMessage( &reply );
- reply.messageType = LANMessage::MSG_GAME_ANNOUNCE;
-
- AsciiString gameOpts = GameInfoToAsciiString(m_currentGame);
- strlcpy(reply.GameInfo.options,gameOpts.str(), ARRAY_SIZE(reply.GameInfo.options));
- wcslcpy(reply.GameInfo.gameName, m_currentGame->getName().str(), ARRAY_SIZE(reply.GameInfo.gameName));
- reply.GameInfo.inProgress = m_currentGame->isGameInProgress();
- reply.GameInfo.isDirectConnect = m_currentGame->getIsDirectConnect();
-
- sendMessage(&reply, senderIP);
- }
- }
-}
-
-void LANAPI::handleRequestJoin( LANMessage *msg, UnsignedInt senderIP )
-{
- UnsignedInt responseIP = senderIP; // need this cause the player may or may not be
- // in the player list at the sendMessage.
-
- if (msg->GameToJoin.gameIP != m_localIP)
- {
- return; // Not us. Ignore it.
- }
- LANMessage reply;
- fillInLANMessage( &reply );
- if (!m_inLobby && m_currentGame && m_currentGame->getIP(0) == m_localIP)
- {
- if (m_currentGame->isGameInProgress())
- {
- reply.messageType = LANMessage::MSG_JOIN_DENY;
- reply.GameNotJoined.reason = LANAPIInterface::RET_GAME_STARTED;
- reply.GameNotJoined.gameIP = m_localIP;
- reply.GameNotJoined.playerIP = senderIP;
- DEBUG_LOG(("LANAPI::handleRequestJoin - join denied because game already started."));
- }
- else
- {
- int player;
- Bool canJoin = true;
-
- // see if the CRCs match
-#if defined(RTS_DEBUG)
- if (TheGlobalData->m_netMinPlayers > 0) {
-#endif
-// TheSuperHackers @todo Enable CRC checks!
-#if !RTS_ZEROHOUR
- if (msg->GameToJoin.iniCRC != TheGlobalData->m_iniCRC ||
- msg->GameToJoin.exeCRC != TheGlobalData->m_exeCRC)
- {
- DEBUG_LOG(("LANAPI::handleRequestJoin - join denied because of CRC mismatch. CRCs are them/us INI:%X/%X exe:%X/%X",
- msg->GameToJoin.iniCRC, TheGlobalData->m_iniCRC,
- msg->GameToJoin.exeCRC, TheGlobalData->m_exeCRC));
- reply.messageType = LANMessage::MSG_JOIN_DENY;
- reply.GameNotJoined.reason = LANAPIInterface::RET_CRC_MISMATCH;
- reply.GameNotJoined.gameIP = m_localIP;
- reply.GameNotJoined.playerIP = senderIP;
- canJoin = false;
- }
-#endif
-#if defined(RTS_DEBUG)
- }
-#endif
-
-// TheSuperHackers @tweak Disables the duplicate serial check
-#if 0
- // check for a duplicate serial
- AsciiString s;
- for (player = 0; canJoin && playergetLANSlot(player);
- s.clear();
- if (player == 0)
- {
- GetStringFromRegistry("\\ergc", "", s);
- }
- else if (slot->isHuman())
- {
- s = slot->getSerial();
- if (s.isEmpty())
- s = "";
- }
-
- if (s.isNotEmpty())
- {
- DEBUG_LOG(("Checking serial '%s' in slot %d", s.str(), player));
-
- if (!strncmp(s.str(), msg->GameToJoin.serial, g_maxSerialLength))
- {
- // serials match! kick the punk!
- reply.messageType = LANMessage::MSG_JOIN_DENY;
- reply.GameNotJoined.reason = LANAPIInterface::RET_SERIAL_DUPE;
- reply.GameNotJoined.gameIP = m_localIP;
- reply.GameNotJoined.playerIP = senderIP;
- canJoin = false;
-
- DEBUG_LOG(("LANAPI::handleRequestJoin - join denied because of duplicate serial # (%s).", s.str()));
- break;
- }
- }
- }
-#endif
-
- // We're the host, so see if he has a duplicate name
- for (player = 0; canJoin && playergetLANSlot(player);
- if (slot->isHuman() && slot->getName().compare(msg->name) == 0)
- {
- // just deny duplicates
- reply.messageType = LANMessage::MSG_JOIN_DENY;
- reply.GameNotJoined.reason = LANAPIInterface::RET_DUPLICATE_NAME;
- reply.GameNotJoined.gameIP = m_localIP;
- reply.GameNotJoined.playerIP = senderIP;
- canJoin = false;
-
- DEBUG_LOG(("LANAPI::handleRequestJoin - join denied because of duplicate names."));
- break;
- }
- }
-
- // TheSuperHackers @bugfix Stubbjax 26/09/2025 Players can now join open slots regardless of starting spots on the map.
- for (player = 0; canJoin && playergetLANSlot(player)->isOpen())
- {
- // OK, add him in.
- reply.messageType = LANMessage::MSG_JOIN_ACCEPT;
- wcslcpy(reply.GameJoined.gameName, m_currentGame->getName().str(), ARRAY_SIZE(reply.GameJoined.gameName));
- reply.GameJoined.slotPosition = player;
- reply.GameJoined.gameIP = m_localIP;
- reply.GameJoined.playerIP = senderIP;
-
- LANGameSlot newSlot;
- newSlot.setState(SLOT_PLAYER, UnicodeString(msg->name));
- newSlot.setIP(senderIP);
- newSlot.setPort(NETWORK_BASE_PORT_NUMBER);
- newSlot.setLastHeard(timeGetTime());
- newSlot.setSerial(msg->GameToJoin.serial);
- m_currentGame->setSlot(player,newSlot);
- DEBUG_LOG(("LANAPI::handleRequestJoin - added player %ls at ip 0x%08x to the game", msg->name, senderIP));
-
- OnPlayerJoin(player, UnicodeString(msg->name));
- responseIP = 0;
-
- break;
- }
- }
-
- if (canJoin && player == MAX_SLOTS)
- {
- reply.messageType = LANMessage::MSG_JOIN_DENY;
- wcslcpy(reply.GameNotJoined.gameName, m_currentGame->getName().str(), ARRAY_SIZE(reply.GameNotJoined.gameName));
- reply.GameNotJoined.reason = LANAPIInterface::RET_GAME_FULL;
- reply.GameNotJoined.gameIP = m_localIP;
- reply.GameNotJoined.playerIP = senderIP;
- DEBUG_LOG(("LANAPI::handleRequestJoin - join denied because game is full."));
- }
- }
- }
- else
- {
- reply.messageType = LANMessage::MSG_JOIN_DENY;
- reply.GameNotJoined.reason = LANAPIInterface::RET_GAME_GONE;
- reply.GameNotJoined.gameIP = m_localIP;
- reply.GameNotJoined.playerIP = senderIP;
- }
- sendMessage(&reply, responseIP);
- RequestGameOptions(GenerateGameOptionsString(), true);
-}
-
-void LANAPI::handleJoinAccept( LANMessage *msg, UnsignedInt senderIP )
-{
- if (msg->GameJoined.playerIP == m_localIP) // Is it for us?
- {
- if (m_pendingAction == ACT_JOIN) // Are we trying to join?
- {
- m_currentGame = LookupGame(UnicodeString(msg->GameJoined.gameName));
-
- if (!m_currentGame)
- {
- DEBUG_ASSERTCRASH(false, ("Could not find game to join!"));
- OnGameJoin(RET_UNKNOWN, NULL);
- }
- else
- {
- m_inLobby = false;
- AsciiString options = GameInfoToAsciiString(m_currentGame);
- m_currentGame->enterGame();
- ParseAsciiStringToGameInfo(m_currentGame, options);
-
- Int pos = msg->GameJoined.slotPosition;
-
- LANGameSlot slot;
- slot.setState(SLOT_PLAYER, m_name);
- slot.setIP(m_localIP);
- slot.setPort(NETWORK_BASE_PORT_NUMBER);
- slot.setLastHeard(0);
- slot.setLogin(m_userName);
- slot.setHost(m_hostName);
- m_currentGame->setSlot(pos, slot);
-
- m_currentGame->getLANSlot(0)->setHost(msg->hostName);
- m_currentGame->getLANSlot(0)->setLogin(msg->userName);
-
- LANPreferences prefs;
- AsciiString entry;
- entry.format("%d.%d.%d.%d:%s", PRINTF_IP_AS_4_INTS(senderIP), UnicodeStringToQuotedPrintable(m_currentGame->getSlot(0)->getName()).str());
- prefs["RemoteIP0"] = entry;
- prefs.write();
-
- OnGameJoin(RET_OK, m_currentGame);
- //DEBUG_ASSERTCRASH(false, ("setting host to %ls@%ls", m_currentGame->getLANSlot(0)->getUser()->getLogin().str(),
- // m_currentGame->getLANSlot(0)->getUser()->getHost().str()));
- }
- m_pendingAction = ACT_NONE;
- m_expiration = 0;
- }
- }
-}
-
-void LANAPI::handleJoinDeny( LANMessage *msg, UnsignedInt senderIP )
-{
- if (msg->GameJoined.playerIP == m_localIP) // Is it for us?
- {
- if (m_pendingAction == ACT_JOIN) // Are we trying to join?
- {
- OnGameJoin(msg->GameNotJoined.reason, LookupGame(UnicodeString(msg->GameNotJoined.gameName)));
- m_pendingAction = ACT_NONE;
- m_expiration = 0;
- }
- }
-}
-
-void LANAPI::handleRequestGameLeave( LANMessage *msg, UnsignedInt senderIP )
-{
- if (!m_inLobby && m_currentGame && !m_currentGame->isGameInProgress())
- {
- int player;
- for (player = 0; player < MAX_SLOTS; ++player)
- {
- if (m_currentGame->getIP(player) == senderIP)
- {
- if (player == 0)
- {
- OnHostLeave();
- removeGame(m_currentGame);
- delete m_currentGame;
- m_currentGame = NULL;
-
- /// @todo re-add myself to lobby? Or just keep me there all the time? If we send a LOBBY_ANNOUNCE things'll work out...
- LANPlayer *lanPlayer = LookupPlayer(m_localIP);
- if (!lanPlayer)
- {
- lanPlayer = NEW LANPlayer;
- lanPlayer->setIP(m_localIP);
- }
- else
- {
- removePlayer(lanPlayer);
- }
- lanPlayer->setName(UnicodeString(m_name));
- lanPlayer->setHost(m_hostName);
- lanPlayer->setLogin(m_userName);
- lanPlayer->setLastHeard(timeGetTime());
- addPlayer(lanPlayer);
-
- }
- else
- {
- if (AmIHost())
- {
- // remove the deadbeat
- LANGameSlot slot;
- slot.setState(SLOT_OPEN);
- m_currentGame->setSlot( player, slot );
- }
- OnPlayerLeave(UnicodeString(msg->name));
- m_currentGame->getLANSlot(player)->setState(SLOT_OPEN);
- m_currentGame->resetAccepted();
- RequestGameOptions(GenerateGameOptionsString(), false, senderIP);
- //m_currentGame->endGame();
- }
- break;
- }
- DEBUG_ASSERTCRASH(player < MAX_SLOTS, ("Didn't find player!"));
- }
- }
- else if (m_inLobby)
- {
- // Look for dissappearing games
- LANGameInfo *game = m_games;
- while (game)
- {
- if (game->getName().compare(msg->GameToLeave.gameName) == 0)
- {
- removeGame(game);
- delete game;
- OnGameList(m_games);
- break;
- }
- game = game->getNext();
- }
- }
-}
-
-void LANAPI::handleRequestLobbyLeave( LANMessage *msg, UnsignedInt senderIP )
-{
- if (m_inLobby)
- {
- LANPlayer *player = m_lobbyPlayers;
- while (player)
- {
- if (player->getIP() == senderIP)
- {
- removePlayer(player);
- OnPlayerList(m_lobbyPlayers);
- break;
- }
- player = player->getNext();
- }
- }
-}
-
-void LANAPI::handleSetAccept( LANMessage *msg, UnsignedInt senderIP )
-{
- if (!m_inLobby && m_currentGame && !m_currentGame->isGameInProgress())
- {
- int player;
- for (player = 0; player < MAX_SLOTS; ++player)
- {
- if (m_currentGame->getIP(player) == senderIP)
- {
- OnAccept(senderIP, msg->Accept.isAccepted);
- break;
- }
- }
- }
-}
-
-void LANAPI::handleHasMap( LANMessage *msg, UnsignedInt senderIP )
-{
- if (!m_inLobby && m_currentGame)
- {
- CRC mapNameCRC;
-// mapNameCRC.computeCRC(m_currentGame->getMap().str(), m_currentGame->getMap().getLength());
- AsciiString portableMapName = TheGameState->realMapPathToPortableMapPath(m_currentGame->getMap());
- mapNameCRC.computeCRC(portableMapName.str(), portableMapName.getLength());
- if (mapNameCRC.get() != msg->MapStatus.mapCRC)
- {
- return;
- }
-
- int player;
- for (player = 0; player < MAX_SLOTS; ++player)
- {
- if (m_currentGame->getIP(player) == senderIP)
- {
- OnHasMap(senderIP, msg->MapStatus.hasMap);
- break;
- }
- }
- }
-}
-
-void LANAPI::handleChat( LANMessage *msg, UnsignedInt senderIP )
-{
- if (m_inLobby)
- {
- LANPlayer *player;
- if((player=LookupPlayer(senderIP)) != 0)
- {
- OnChat(UnicodeString(player->getName()), player->getIP(), UnicodeString(msg->Chat.message), msg->Chat.chatType);
- player->setLastHeard(timeGetTime());
- }
- }
- else
- {
- if (LookupGame(UnicodeString(msg->Chat.gameName)) != m_currentGame)
- {
- DEBUG_LOG(("Game '%ls' is not my game", msg->Chat.gameName));
- if (m_currentGame)
- {
- DEBUG_LOG(("Current game is '%ls'", m_currentGame->getName().str()));
- }
- return;
- }
-
- int player;
- for (player = 0; player < MAX_SLOTS; ++player)
- {
- if (m_currentGame && m_currentGame->getIP(player) == senderIP)
- {
- OnChat(UnicodeString(msg->name), m_currentGame->getIP(player), UnicodeString(msg->Chat.message), msg->Chat.chatType);
- break;
- }
- }
- }
-}
-
-void LANAPI::handleGameStart( LANMessage *msg, UnsignedInt senderIP )
-{
- if (!m_inLobby && m_currentGame && m_currentGame->getIP(0) == senderIP && !m_currentGame->isGameInProgress())
- {
- OnGameStart();
- }
-}
-
-void LANAPI::handleGameStartTimer( LANMessage *msg, UnsignedInt senderIP )
-{
- if (!m_inLobby && m_currentGame && m_currentGame->getIP(0) == senderIP && !m_currentGame->isGameInProgress())
- {
- OnGameStartTimer(msg->StartTimer.seconds);
- }
-}
-
-void LANAPI::handleGameOptions( LANMessage *msg, UnsignedInt senderIP )
-{
- if (!m_inLobby && m_currentGame && !m_currentGame->isGameInProgress())
- {
- int player;
- for (player = 0; player < MAX_SLOTS; ++player)
- {
- if (m_currentGame->getIP(player) == senderIP)
- {
- OnGameOptions(senderIP, player, AsciiString(msg->GameOptions.options));
- break;
- }
- }
- }
-}
-
-void LANAPI::handleInActive(LANMessage *msg, UnsignedInt senderIP) {
- if (m_inLobby || (m_currentGame == NULL) || (m_currentGame->isGameInProgress())) {
- return;
- }
-
- // check to see if we are the host of this game.
- if (m_currentGame->amIHost() == FALSE) {
- return;
- }
-
- UnicodeString playerName;
- playerName = msg->name;
-
- Int slotNum = m_currentGame->getSlotNum(playerName);
- if (slotNum < 0)
- return;
- GameSlot *slot = m_currentGame->getSlot(slotNum);
- if (slot == NULL) {
- return;
- }
-
- if (senderIP != slot->getIP()) {
- return;
- }
-
- // don't want to unaccept the host, that's silly. They can't hit start alt-tabbed anyways.
- if (senderIP == TheLAN->GetLocalIP()) {
- return;
- }
-
- // only unaccept if the timer hasn't started yet.
- if (m_gameStartTime != 0) {
- return;
- }
-
- slot->unAccept();
- AsciiString options = GenerateGameOptionsString();
- RequestGameOptions(options, FALSE);
- lanUpdateSlotList();
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp b/Generals/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp
deleted file mode 100644
index 19ac4d52b07..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/LANGameInfo.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: LANGameInfo.cpp //////////////////////////////////////////////////////
-// LAN game setup state info
-// Author: Matthew D. Campbell, December 2001
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/GameInfoWindow.h"
-#include "GameClient/GameText.h"
-#include "GameClient/GadgetListBox.h"
-#include "GameNetwork/LANGameInfo.h"
-#include "GameNetwork/LANAPICallbacks.h"
-#include "Common/MultiplayerSettings.h"
-#include "strtok_r.h"
-/*
-#include "GameNetwork/LAN.h"
-#include "GameNetwork/LANGame.h"
-#include "GameNetwork/LANPing.h"
-#include "GameNetwork/LANusers.h"
-#include "GameNetwork/LANmenus.h"
-*/
-
-// Singleton ------------------------------------------
-
-LANGameInfo *TheLANGameInfo = NULL;
-
-// LANGameSlot ----------------------------------------
-
-LANGameSlot::LANGameSlot()
-{
- m_lastHeard = 0;
-}
-
-
-LANPlayer * LANGameSlot::getUser( void )
-{
- if (isHuman())
- {
- m_user.setIP(getIP());
- m_user.setLastHeard(getLastHeard());
- m_user.setName(getName());
- m_user.setNext(NULL);
- return &m_user;
- }
- return NULL;
-}
-
-// Various tests
-Bool LANGameSlot::isUser( LANPlayer *user )
-{
- return (user && m_state == SLOT_PLAYER && user->getIP() == getIP());
-}
-
-Bool LANGameSlot::isUser( UnicodeString userName )
-{
- return (m_state == SLOT_PLAYER && !userName.compareNoCase(getName()));
-}
-
-Bool LANGameSlot::isLocalPlayer( void ) const
-{
- return isHuman() && TheLAN && TheLAN->GetLocalIP() == getIP();
-}
-
-// LANGameInfo ----------------------------------------
-
-LANGameInfo::LANGameInfo()
-{
- //Added By Sadullah Nader
- //Initializtions missing and needed
- m_lastHeard = 0;
- m_next = NULL;
- //
- for (Int i = 0; i< MAX_SLOTS; ++i)
- setSlotPointer(i, &m_LANSlot[i]);
-
- setLocalIP(TheLAN->GetLocalIP());
-}
-
-void LANGameInfo::setSlot( Int slotNum, LANGameSlot slotInfo )
-{
- DEBUG_ASSERTCRASH( slotNum >= 0 && slotNum < MAX_SLOTS, ("LANGameInfo::setSlot - Invalid slot number"));
- if (slotNum < 0 || slotNum >= MAX_SLOTS)
- return;
-
- m_LANSlot[slotNum] = slotInfo;
-
- if (slotNum == 0)
- {
- m_LANSlot[slotNum].setAccept();
- m_LANSlot[slotNum].setMapAvailability(true);
- }
-}
-
-LANGameSlot* LANGameInfo::getLANSlot( Int slotNum )
-{
- DEBUG_ASSERTCRASH( slotNum >= 0 && slotNum < MAX_SLOTS, ("LANGameInfo::getLANSlot - Invalid slot number"));
- if (slotNum < 0 || slotNum >= MAX_SLOTS)
- return NULL;
-
- return &m_LANSlot[slotNum];
-}
-
-const LANGameSlot* LANGameInfo::getConstLANSlot( Int slotNum ) const
-{
- DEBUG_ASSERTCRASH( slotNum >= 0 && slotNum < MAX_SLOTS, ("LANGameInfo::getConstLANSlot - Invalid slot number"));
- if (slotNum < 0 || slotNum >= MAX_SLOTS)
- return NULL;
-
- return &m_LANSlot[slotNum];
-}
-
-Int LANGameInfo::getLocalSlotNum( void ) const
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for local game slot while not in game"));
- if (!m_inGame)
- return -1;
-
- for (Int i=0; iisLocalPlayer())
- return i;
- }
- return -1;
-}
-
-Int LANGameInfo::getSlotNum( UnicodeString userName )
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for game slot while not in game"));
- if (!m_inGame)
- return -1;
-
- for (Int i=0; iisUser( userName ))
- return i;
- }
- return -1;
-}
-
-Bool LANGameInfo::amIHost( void )
-{
- DEBUG_ASSERTCRASH(m_inGame, ("Looking for game slot while not in game"));
- if (!m_inGame)
- return false;
-
- return getLANSlot(0)->isLocalPlayer();
-}
-
-void LANGameInfo::setMap( AsciiString mapName )
-{
- GameInfo::setMap(mapName);
-}
-
-void LANGameInfo::setSeed( Int seed )
-{
- GameInfo::setSeed(seed);
-}
-
-void LANGameInfo::resetAccepted( void )
-{
- if (TheLAN)
- {
- TheLAN->ResetGameStartTimer();
- if (TheLAN->GetMyGame() == this && TheLAN->AmIHost())
- LANEnableStartButton(true);
- }
- for(int i = 0; i< MAX_SLOTS; i++)
- {
- m_LANSlot[i].unAccept();
- }
-}
-// Misc game-related functionality --------------------
-
-
-void LANDisplayGameList( GameWindow *gameListbox, LANGameInfo *gameList )
-{
- LANGameInfo *selectedPtr = NULL;
- Int selectedIndex = -1;
- Int indexToSelect = -1;
- if (gameListbox)
- {
- GadgetListBoxGetSelected(gameListbox, &selectedIndex);
-
- if (selectedIndex != -1 )
- {
- selectedPtr = (LANGameInfo *)GadgetListBoxGetItemData(gameListbox, selectedIndex, 0);
- }
-
- GadgetListBoxReset(gameListbox);
-
- while (gameList)
- {
- UnicodeString txtGName;
- txtGName = L"";
- if( gameList->isGameInProgress() )
- {
- txtGName.concat(L"[");
- }
- txtGName.concat(gameList->getPlayerName(0));
- if( gameList->isGameInProgress() )
- {
- txtGName.concat(L"]");
- }
- Int addedIndex = GadgetListBoxAddEntryText(gameListbox, txtGName, (gameList->isGameInProgress())?gameInProgressColor:gameColor, -1, -1);
- GadgetListBoxSetItemData(gameListbox, (void *)gameList, addedIndex, 0 );
-
- if (selectedPtr == gameList)
- indexToSelect = addedIndex;
-
- gameList = gameList->getNext();
- }
-
- if (indexToSelect >= 0)
- GadgetListBoxSetSelected(gameListbox, indexToSelect);
- else
- HideGameInfoWindow(TRUE);
- }
-}
-
-AsciiString GenerateGameOptionsString( void )
-{
- if(!TheLAN->GetMyGame() || !TheLAN->GetMyGame()->amIHost())
- return AsciiString::TheEmptyString;
-
- return GameInfoToAsciiString(TheLAN->GetMyGame());
-}
-
-Bool ParseGameOptionsString(LANGameInfo *game, AsciiString options)
-{
- if (!TheLAN || !game)
- return false;
-
- Int oldLocalSlotNum = (game->isInGame()) ? game->getLocalSlotNum() : -1;
- Bool wasInGame = oldLocalSlotNum >= 0;
-// Int hadMap = wasInGame && game->getSlot(oldLocalSlotNum)->hasMap();
- AsciiString oldMap = game->getMap();
- UnsignedInt oldMapCRC, newMapCRC;
- oldMapCRC = game->getMapCRC();
-
- std::map oldLogins, oldMachines;
- std::map::iterator mapIt;
- Int i;
- for (i=0; igetLANSlot(i);
- if (slot && slot->isHuman())
- {
- //DEBUG_LOG(("Saving off %ls@%ls for %ls", slot->getUser()->getLogin().str(), slot->getUser()->getHost().str(), slot->getName().str()));
- oldLogins[slot->getName()] = slot->getUser()->getLogin();
- oldMachines[slot->getName()] = slot->getUser()->getHost();
- }
- }
-
- if (ParseAsciiStringToGameInfo(game, options))
- {
- Int newLocalSlotNum = (game->isInGame()) ? game->getLocalSlotNum() : -1;
- Bool isInGame = newLocalSlotNum >= 0;
- if (!TheLAN->AmIHost() && isInGame)
- {
-// Int hasMap = game->getSlot(newLocalSlotNum)->hasMap();
- newMapCRC = game->getMapCRC();
- //DEBUG_LOG(("wasInGame:%d isInGame:%d hadMap:%d hasMap:%d oldMap:%s newMap:%s", wasInGame, isInGame, hadMap, hasMap, oldMap.str(), game->getMap().str()));
- if ( (oldMapCRC ^ newMapCRC)/*(hasMap ^ hadMap)*/ || (!wasInGame && isInGame) )
- {
- // it changed. send it
- TheLAN->RequestHasMap();
- lanUpdateSlotList();
- updateGameOptions();
- }
- }
- // clean up LAN users, etc.
- UnsignedInt now = timeGetTime();
- for (i=0; igetLANSlot(i);
-
- if (slot->isHuman())
- {
- slot->setLastHeard(now);
- mapIt = oldLogins.find(slot->getName());
- if (mapIt != oldLogins.end())
- slot->setLogin(mapIt->second);
- mapIt = oldMachines.find(slot->getName());
- if (mapIt != oldMachines.end())
- slot->setHost(mapIt->second);
- //DEBUG_LOG(("Restored %ls@%ls for %ls", slot->getUser()->getLogin().str(), slot->getUser()->getHost().str(), slot->getName().str()));
- }
- }
-
- return true;
- }
-
- return false;
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NAT.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NAT.cpp
deleted file mode 100644
index 7b9c63429d4..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NAT.cpp
+++ /dev/null
@@ -1,1294 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: NAT.cpp /////////////////////////////////////////////////////////////////////////////////
-// Author: Bryan Cleveland April 2002
-// Props to Steve Tall for figuring all the NAT and Firewall behavior patterns out, making my job
-// a LOT easier.
-// Desc: Resolves NAT'd IPs and port numbers for the other players in a game.
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/NAT.h"
-#include "GameNetwork/Transport.h"
-#include "GameNetwork/NetworkDefs.h"
-#include "GameClient/EstablishConnectionsMenu.h"
-#include "GameNetwork/NetworkInterface.h"
-#include "GameNetwork/GameInfo.h"
-#include "GameNetwork/GameSpy/PeerThread.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-#include "GameNetwork/GameSpy/GSConfig.h"
-
-
-/*
- * In case you're wondering, we do this weird connection pairing scheme
- * to speed up the negotiation process, especially in cases where there
- * are 4 or more players (nodes). Take for example an 8 player game...
- * In an 8 player game there are 28 connections that need to be negotiated,
- * doing this pairing scheme thing, we can make those 28 connections in the
- * time it would normally take to make 7 connections. Since each connection
- * could potentially take several seconds, this can be a HUGE time savings.
-
- * Right now you're probably wondering who this Bryan Cleveland guy is.
- * He's the network coder that got fired when this didn't work.
-
- * In case you're wondering, this did end up working and Bryan left by
- * his own choice.
- */
-// m_connectionPairs[num nodes] [round] [node index]
-/* static */ Int NAT::m_connectionPairs[MAX_SLOTS-1][MAX_SLOTS-1][MAX_SLOTS] =
-{
- { // 2 nodes
- // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7
- { 1, 0, -1, -1, -1, -1, -1, -1}, // round 0
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 1
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 2
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5
- { -1, -1, -1, -1, -1, -1, -1, -1} // round 6
- },
- { // 3 nodes
- // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7
- { 1, 0, -1, -1, -1, -1, -1, -1}, // round 0
- { 2, -1, 0, -1, -1, -1, -1, -1}, // round 1
- { -1, 2, 1, -1, -1, -1, -1, -1}, // round 2
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5
- { -1, -1, -1, -1, -1, -1, -1, -1} // round 6
- },
- { // 4 nodes
- // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7
- { 1, 0, 3, 2, -1, -1, -1, -1}, // round 0
- { 2, 3, 0, 1, -1, -1, -1, -1}, // round 1
- { 3, 2, 1, 0, -1, -1, -1, -1}, // round 2
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 3
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 4
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5
- { -1, -1, -1, -1, -1, -1, -1, -1} // round 6
- },
- { // 5 nodes
- // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7
- { 2, 4, 0, -1, 1, -1, -1, -1}, // round 0
- { -1, 3, 4, 1, 2, -1, -1, -1}, // round 1
- { 3, 2, 1, 0, -1, -1, -1, -1}, // round 2
- { 4, -1, 3, 2, 0, -1, -1, -1}, // round 3
- { 1, 0, -1, 4, 3, -1, -1, -1}, // round 4
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5
- { -1, -1, -1, -1, -1, -1, -1, -1} // round 6
- },
- { // 6 nodes
- // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7
- { 3, 5, 4, 0, 2, 1, -1, -1}, // round 0
- { 2, 4, 0, 5, 1, 3, -1, -1}, // round 1
- { 4, 3, 5, 1, 0, 2, -1, -1}, // round 2
- { 1, 0, 3, 2, 5, 4, -1, -1}, // round 3
- { 5, 2, 1, 4, 3, 0, -1, -1}, // round 4
- { -1, -1, -1, -1, -1, -1, -1, -1}, // round 5
- { -1, -1, -1, -1, -1, -1, -1, -1} // round 6
- },
- { // 7 nodes
- // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7
- { -1, 6, 5, 4, 3, 2, 1, -1}, // round 0
- { 2, -1, 0, 6, 5, 4, 3, -1}, // round 1
- { 4, 3, -1, 1, 0, 6, 5, -1}, // round 2
- { 6, 5, 4, -1, 2, 1, 0, -1}, // round 3
- { 1, 0, 6, 5, -1, 3, 2, -1}, // round 4
- { 3, 2, 1, 0, 6, -1, 4, -1}, // round 5
- { 5, 4, 3, 2, 1, 0, -1, -1} // round 6
- },
- { // 8 nodes
- // node 0 node 1 node 2 node 3 node 4 node 5 node 6 node 7
- { 4, 5, 6, 7, 0, 1, 2, 3}, // round 0
- { 5, 4, 7, 6, 1, 0, 3, 2}, // round 1
- { 3, 6, 5, 0, 7, 2, 1, 4}, // round 2
- { 2, 7, 0, 5, 6, 3, 4, 1}, // round 3
- { 6, 3, 4, 1, 2, 7, 0, 5}, // round 4
- { 1, 0, 3, 2, 5, 4, 7, 6}, // round 5
- { 7, 2, 1, 4, 3, 6, 5, 0} // round 6
- }
-};
-
-/* static */ Int NAT::m_timeBetweenRetries = 500; // .5 seconds between retries sounds good to me.
-/* static */ time_t NAT::m_manglerRetryTimeInterval = 300; // sounds good to me.
-/* static */ Int NAT::m_maxAllowedManglerRetries = 25; // works for me.
-/* static */ time_t NAT::m_keepaliveInterval = 15000; // 15 seconds between keepalive packets seems good.
-/* static */ time_t NAT::m_timeToWaitForPort = 15000; // wait for 15 seconds for the other player's port number.
-/* static */ time_t NAT::m_timeForRoundTimeout = 15000; // wait for at most 15 seconds for each connection round to finish.
-
-NAT *TheNAT = NULL;
-
-NAT::NAT()
-{
- //Added By Sadullah Nader
- //Initializations inserted
- m_beenProbed = FALSE;
- m_connectionPairIndex = 0;
- m_connectionRound = 0;
- m_localIP = 0;
- m_localNodeNumber = 0;
- m_manglerAddress = 0;
- m_manglerRetries = 0;
- m_numNodes = 0;
- m_numRetries = 0;
- m_previousSourcePort = 0;
- for(Int i = 0; i < MAX_SLOTS; i++)
- m_sourcePorts[i] = 0;
- m_spareSocketPort = 0;
- m_startingPortNumber = 0;
- m_targetNodeNumber = 0;
- //
- m_transport = NULL;
- m_slotList = NULL;
- m_roundTimeout = 0;
-
- m_maxNumRetriesAllowed = 10;
- m_packetID = 0x7f00;
-}
-
-NAT::~NAT() {
-}
-
-// if we're already finished, change to being idle
-// if we are negotiating now, check to see if this round is done
-// if it is, check to see if we're completely done with all rounds.
-// if we are, set state to be done.
-// if not go on to the next connection round.
-// if we are negotiating still, call the connection update
-// check to see if this connection is done for us, or if it has failed.
-enum { MS_TO_WAIT_FOR_STATS = 5000 };
-NATStateType NAT::update() {
- static UnsignedInt s_startStatWaitTime = 0;
- if (m_NATState == NATSTATE_DONE) {
- m_NATState = NATSTATE_IDLE;
- } else if (m_NATState == NATSTATE_WAITFORSTATS) {
- // check for all stats
- Bool gotAllStats = TRUE;
- Bool timedOut = FALSE;
- for (Int i=0; igetGameSpySlot(i);
- if (slot && slot->isHuman())
- {
- PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(slot->getProfileID());
- if (stats.id == 0)
- {
- gotAllStats = FALSE;
- //DEBUG_LOG(("Failed to find stats for %ls(%d)", slot->getName().str(), slot->getProfileID()));
- }
- }
- }
- // check for timeout. Timing out is not a fatal error - it just means we didn't get the other
- // player's stats. We'll see 0/0 as his record, but we can still play him just fine.
- UnsignedInt now = timeGetTime();
- if (now > s_startStatWaitTime + MS_TO_WAIT_FOR_STATS)
- {
- DEBUG_LOG(("Timed out waiting for stats. Let's just start the dang game."));
- timedOut = TRUE;
- }
- if (gotAllStats || timedOut)
- {
- m_NATState = NATSTATE_DONE;
- TheEstablishConnectionsMenu->endMenu();
-
- delete TheFirewallHelper;
- TheFirewallHelper = NULL;
- }
- } else if (m_NATState == NATSTATE_DOCONNECTIONPATHS) {
- if (allConnectionsDoneThisRound() == TRUE) {
- // we finished this round, move on to the next one.
- ++m_connectionRound;
-// m_roundTimeout = timeGetTime() + TheGameSpyConfig->getRoundTimeout();
- m_roundTimeout = timeGetTime() + m_timeForRoundTimeout;
- DEBUG_LOG(("NAT::update - done with connection round, moving on to round %d", m_connectionRound));
-
- // we finished that round, now check to see if we're done, or if there are more rounds to go.
- if (allConnectionsDone() == TRUE) {
- // we're all done, time to go back home.
- m_NATState = NATSTATE_WAITFORSTATS;
-
- // 2/19/03 BGC - we have successfully negotaited a NAT thingy, so our behavior must be correct
- // so therefore we don't need to refresh our NAT even if we previously thought we had to.
- TheFirewallHelper->flagNeedToRefresh(FALSE);
-
- s_startStatWaitTime = timeGetTime();
- DEBUG_LOG(("NAT::update - done with all connections, woohoo!!"));
- /*
- m_NATState = NATSTATE_DONE;
- TheEstablishConnectionsMenu->endMenu();
-
- delete TheFirewallHelper;
- TheFirewallHelper = NULL;
- */
- } else {
- doThisConnectionRound();
- }
- }
- NATConnectionState state = connectionUpdate();
-
- if (timeGetTime() > m_roundTimeout) {
- DEBUG_LOG(("NAT::update - round timeout expired"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- notifyUsersOfConnectionFailed(m_localNodeNumber);
- }
-
- if (state == NATCONNECTIONSTATE_FAILED) {
- // if we fail
- m_NATState = NATSTATE_FAILED;
- TheEstablishConnectionsMenu->endMenu();
- if (TheFirewallHelper != NULL) {
- // we failed NAT negotiation, perhaps we need to redetect our firewall settings.
- // We don't trust the user to do it for themselves so we force them to do it next time
- // the log in.
- // 2/19/03 - ok, we don't want to do this right away, if the user tries to play in another game
- // before they log out and log back in the game won't have a chance at working.
- // so we need to simply flag it so that when they log out the firewall behavior gets blown away.
- TheFirewallHelper->flagNeedToRefresh(TRUE);
-// TheWritableGlobalData->m_firewallBehavior = FirewallHelperClass::FIREWALL_TYPE_UNKNOWN;
-// TheFirewallHelper->writeFirewallBehavior();
-
- delete TheFirewallHelper;
- TheFirewallHelper = NULL;
- }
- // we failed to connect, so we don't have to pass on the transport to the network.
- delete m_transport;
- m_transport = NULL;
- }
- }
- return m_NATState;
-}
-
-
-// update transport, check for PROBE packets from our target.
-// check to see if its time to PROBE our target
-// MANGLER:
-// if we are talking to the mangler, check to see if we got a response
-// if we didn't get a response, check to see if its time to send another packet to it
-NATConnectionState NAT::connectionUpdate() {
-
- GameSlot *targetSlot = NULL;
- if (m_targetNodeNumber >= 0) {
- targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex];
- } else {
- return m_connectionStates[m_localNodeNumber];
- }
-
- if (m_beenProbed == FALSE) {
- if (timeGetTime() >= m_nextPortSendTime) {
-// sendMangledPortNumberToTarget(m_previousSourcePort, targetSlot);
- sendMangledPortNumberToTarget(m_sourcePorts[m_targetNodeNumber], targetSlot);
-// m_nextPortSendTime = timeGetTime() + TheGameSpyConfig->getRetryInterval();
- m_nextPortSendTime = timeGetTime() + m_timeBetweenRetries;
- }
- }
-
- // check to see if its time to send out our keepalives.
- if (timeGetTime() >= m_nextKeepaliveTime) {
- for (UnsignedInt node = 0; node < m_numNodes; ++node) {
- if (m_myConnections[node] == TRUE) {
- // we've made this connection, send a keepalive.
- Int slotIndex = m_connectionNodes[node].m_slotIndex;
- GameSlot *slot = m_slotList[slotIndex];
- DEBUG_ASSERTCRASH(slot != NULL, ("Trying to send keepalive to a NULL slot"));
- if (slot != NULL) {
- UnsignedInt ip = slot->getIP();
- DEBUG_LOG(("NAT::connectionUpdate - sending keep alive to node %d at %d.%d.%d.%d:%d", node,
- PRINTF_IP_AS_4_INTS(ip), slot->getPort()));
- m_transport->queueSend(ip, slot->getPort(), (const unsigned char *)"KEEPALIVE", strlen("KEEPALIVE") + 1);
- }
- }
- }
-// m_nextKeepaliveTime = timeGetTime() + TheGameSpyConfig->getKeepaliveInterval();
- m_nextKeepaliveTime = timeGetTime() + m_keepaliveInterval;
- }
-
- m_transport->update();
-
- // check to see if we've been probed.
- for (Int i = 0; i < MAX_MESSAGES; ++i) {
- if (m_transport->m_inBuffer[i].length > 0) {
-#ifdef DEBUG_LOGGING
- UnsignedInt ip = m_transport->m_inBuffer[i].addr;
-#endif
- DEBUG_LOG(("NAT::connectionUpdate - got a packet from %d.%d.%d.%d:%d, length = %d",
- PRINTF_IP_AS_4_INTS(ip), m_transport->m_inBuffer[i].port, m_transport->m_inBuffer[i].length));
- UnsignedByte *data = m_transport->m_inBuffer[i].data;
- if (memcmp(data, "PROBE", strlen("PROBE")) == 0) {
- Int fromNode = atoi((char *)data + strlen("PROBE"));
- DEBUG_LOG(("NAT::connectionUpdate - we've been probed by node %d.", fromNode));
-
- if (fromNode == m_targetNodeNumber) {
- DEBUG_LOG(("NAT::connectionUpdate - probe was sent by our target, setting connection state %d to done.", m_targetNodeNumber));
- setConnectionState(m_targetNodeNumber, NATCONNECTIONSTATE_DONE);
-
- if (m_transport->m_inBuffer[i].addr != targetSlot->getIP()) {
- UnsignedInt fromIP = m_transport->m_inBuffer[i].addr;
-#ifdef DEBUG_LOGGING
- UnsignedInt slotIP = targetSlot->getIP();
-#endif
- DEBUG_LOG(("NAT::connectionUpdate - incomming packet has different from address than we expected, incoming: %d.%d.%d.%d expected: %d.%d.%d.%d",
- PRINTF_IP_AS_4_INTS(fromIP),
- PRINTF_IP_AS_4_INTS(slotIP)));
- targetSlot->setIP(fromIP);
- }
- if (m_transport->m_inBuffer[i].port != targetSlot->getPort()) {
- DEBUG_LOG(("NAT::connectionUpdate - incoming packet came from a different port than we expected, incoming: %d expected: %d",
- m_transport->m_inBuffer[i].port, targetSlot->getPort()));
- targetSlot->setPort(m_transport->m_inBuffer[i].port);
- m_sourcePorts[m_targetNodeNumber] = m_transport->m_inBuffer[i].port;
- }
- notifyUsersOfConnectionDone(m_targetNodeNumber);
- }
-
- m_transport->m_inBuffer[i].length = 0;
- }
- if (memcmp(data, "KEEPALIVE", strlen("KEEPALIVE")) == 0) {
- // keep alive packet, just toss it.
- DEBUG_LOG(("NAT::connectionUpdate - got keepalive from %d.%d.%d.%d:%d",
- PRINTF_IP_AS_4_INTS(ip), m_transport->m_inBuffer[i].port));
- m_transport->m_inBuffer[i].length = 0;
- }
- }
- }
-
- // we are waiting for our target to tell us that they have received our probe.
- if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORRESPONSE) {
- // check to see if it's time to probe our target.
- if ((m_timeTillNextSend != -1) && (m_timeTillNextSend <= timeGetTime())) {
- if (m_numRetries > m_maxNumRetriesAllowed) {
- DEBUG_LOG(("NAT::connectionUpdate - too many retries, connection failed."));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
-
- notifyUsersOfConnectionFailed(m_localNodeNumber);
- } else {
- DEBUG_LOG(("NAT::connectionUpdate - trying to send another probe (#%d) to our target", m_numRetries+1));
- // Send a probe.
- sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber);
-// m_timeTillNextSend = timeGetTime() + TheGameSpyConfig->getRetryInterval();
- m_timeTillNextSend = timeGetTime() + m_timeBetweenRetries;
-
- // tell the target they've been probed. In other words, our port is open.
- notifyTargetOfProbe(targetSlot);
-
- ++m_numRetries;
- }
- }
- }
-
- // we are waiting for a response from the mangler to tell us what port we're using.
- if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE) {
- UnsignedShort mangledPort = 0;
- if (TheFirewallHelper != NULL) {
- mangledPort = TheFirewallHelper->getManglerResponse(m_packetID);
- }
- if (mangledPort != 0) {
- // we got a response. now we need to start probing (unless of course we have a netgear)
- processManglerResponse(mangledPort);
-
- // we know there is a firewall helper if we got here.
- TheFirewallHelper->closeSpareSocket(m_spareSocketPort);
- m_spareSocketPort = 0;
- } else {
- if (timeGetTime() >= m_manglerRetryTime) {
- ++m_manglerRetries;
-// if (m_manglerRetries > TheGameSpyConfig->getMaxManglerRetries()) {
- if (m_manglerRetries > m_maxAllowedManglerRetries) {
- // we couldn't communicate with the mangler, just use our non-mangled
- // port number and hope that works.
- DEBUG_LOG(("NAT::connectionUpdate - couldn't talk with the mangler using default port number"));
- sendMangledPortNumberToTarget(getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex), targetSlot);
- m_sourcePorts[m_targetNodeNumber] = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex);
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE);
- } else {
- if (TheFirewallHelper != NULL) {
- DEBUG_LOG(("NAT::connectionUpdate - trying to send to the mangler again. mangler address: %d.%d.%d.%d, from port: %d, packet ID:%d",
- PRINTF_IP_AS_4_INTS(m_manglerAddress), m_spareSocketPort, m_packetID));
- TheFirewallHelper->sendToManglerFromPort(m_manglerAddress, m_spareSocketPort, m_packetID);
- }
-// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime();
- m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime();
- }
- }
- }
- }
-
- if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT) {
- if (timeGetTime() > m_timeoutTime) {
- DEBUG_LOG(("NAT::connectionUpdate - waiting too long to get the other player's port number, failed."));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
-
- notifyUsersOfConnectionFailed(m_localNodeNumber);
- }
- }
-
- return m_connectionStates[m_localNodeNumber];
-}
-
-// this is the function that starts the NAT/firewall negotiation process.
-// after calling this, you should call the update function untill it returns
-// NATSTATE_DONE.
-void NAT::establishConnectionPaths() {
- DEBUG_LOG(("NAT::establishConnectionPaths - entering"));
- m_NATState = NATSTATE_DOCONNECTIONPATHS;
- DEBUG_LOG(("NAT::establishConnectionPaths - using %d as our starting port number", m_startingPortNumber));
- if (TheEstablishConnectionsMenu == NULL) {
- TheEstablishConnectionsMenu = NEW EstablishConnectionsMenu;
- }
- TheEstablishConnectionsMenu->initMenu();
-
- if (TheFirewallHelper == NULL) {
- TheFirewallHelper = createFirewallHelper();
- }
-
- DEBUG_ASSERTCRASH(m_slotList != NULL, ("NAT::establishConnectionPaths - don't have a slot list"));
- if (m_slotList == NULL) {
- return;
- }
-
- // determine how many nodes we have.
- m_numNodes = 0;
- Int i = 0;
- for (; i < MAX_SLOTS; ++i) {
- if (m_slotList[i] != NULL) {
- if (m_slotList[i]->isHuman()) {
- DEBUG_LOG(("NAT::establishConnectionPaths - slot %d is %ls", i, m_slotList[i]->getName().str()));
- ++m_numNodes;
- }
- }
- }
- DEBUG_LOG(("NAT::establishConnectionPaths - number of nodes: %d", m_numNodes));
-
- if (m_numNodes < 2)
- {
- // just start the game - there isn't anybody to which to connect. :P
- m_NATState = NATSTATE_DONE;
- return;
- }
-
- m_connectionRound = 0;
- m_connectionPairIndex = m_numNodes - 2;
- Bool connectionAssigned[MAX_SLOTS];
-
- for (i = 0; i < MAX_SLOTS; ++i) {
- m_connectionNodes[i].m_slotIndex = -1;
- connectionAssigned[i] = FALSE;
- m_sourcePorts[i] = 0;
- }
-
- m_previousSourcePort = 0;
-
-// check for netgear bug behavior.
-// as an aside, if there are more than 2 netgear bug firewall's in the game,
-// it probably isn't going to work so well. stupid netgear.
-
-// nodes with a netgear bug behavior need to be matched up first. This prevents
-// the NAT table from being reset for connections to other nodes. This also happens
-// to be the reason why I call them "nodes" rather than "slots" or "players" as the
-// ordering has to be messed with to get the netgears to make love, not war.
- DEBUG_LOG(("NAT::establishConnectionPaths - about to set up the node list"));
- DEBUG_LOG(("NAT::establishConnectionPaths - doing the netgear stuff"));
- UnsignedInt otherNetgearNum = -1;
- for (i = 0; i < MAX_SLOTS; ++i) {
- if ((m_slotList != NULL) && (m_slotList[i] != NULL)) {
- if ((m_slotList[i]->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) {
- if (otherNetgearNum == -1) {
- // this is the start of a new pair, put it in as the first non -1 node connection pair thing.
- Int nodeindex = 0;
- while ((m_connectionPairs[m_connectionPairIndex][0][nodeindex] == -1) || (m_connectionNodes[nodeindex].m_slotIndex != -1)) {
- ++nodeindex;
- }
- m_connectionNodes[nodeindex].m_slotIndex = i;
- m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior();
- connectionAssigned[i] = TRUE;
- otherNetgearNum = nodeindex;
- DEBUG_LOG(("NAT::establishConnectionPaths - first netgear in pair. assigning node %d to slot %d (%ls)", nodeindex, i, m_slotList[i]->getName().str()));
- } else {
- // this is the second in the pair of netgears, pair this up with the other one
- // for the first round.
- Int nodeindex = 0;
- while (m_connectionPairs[m_connectionPairIndex][0][nodeindex] != otherNetgearNum) {
- ++nodeindex;
- }
- m_connectionNodes[nodeindex].m_slotIndex = i;
- m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior();
- connectionAssigned[i] = TRUE;
- otherNetgearNum = -1;
- DEBUG_LOG(("NAT::establishConnectionPaths - second netgear in pair. assigning node %d to slot %d (%ls)", nodeindex, i, m_slotList[i]->getName().str()));
- }
- }
- }
- }
-
- // fill in the rest of the nodes with the remaining slots.
- DEBUG_LOG(("NAT::establishConnectionPaths - doing the non-Netgear nodes"));
- for (i = 0; i < MAX_SLOTS; ++i) {
- if (connectionAssigned[i] == TRUE) {
- continue;
- }
- if (m_slotList[i] == NULL) {
- continue;
- }
- if (!(m_slotList[i]->isHuman())) {
- continue;
- }
- // find the first available connection node for this slot.
- Int nodeindex = 0;
- while (m_connectionNodes[nodeindex].m_slotIndex != -1) {
- ++nodeindex;
- }
- DEBUG_LOG(("NAT::establishConnectionPaths - assigning node %d to slot %d (%ls)", nodeindex, i, m_slotList[i]->getName().str()));
- m_connectionNodes[nodeindex].m_slotIndex = i;
- m_connectionNodes[nodeindex].m_behavior = m_slotList[i]->getNATBehavior();
- connectionAssigned[i] = TRUE;
- }
-
-// sanity check
-#if defined(RTS_DEBUG)
- for (i = 0; i < m_numNodes; ++i) {
- DEBUG_ASSERTCRASH(connectionAssigned[i] == TRUE, ("connection number %d not assigned", i));
- }
-#endif
-
- // find the local node number.
- for (i = 0; i < m_numNodes; ++i) {
- if (m_connectionNodes[i].m_slotIndex == TheGameSpyGame->getLocalSlotNum()) {
- m_localNodeNumber = i;
- DEBUG_LOG(("NAT::establishConnectionPaths - local node is %d", m_localNodeNumber));
- break;
- }
- }
-
- // set up the names in the connection window.
- Int playerNum = 0;
- for (i = 0; i < MAX_SLOTS; ++i) {
- while ((i < MAX_SLOTS) && (m_slotList[i] != NULL) && !(m_slotList[i]->isHuman())) {
- ++i;
- }
- if (i >= MAX_SLOTS) {
- break;
- }
- if (i != TheGameSpyGame->getLocalSlotNum()) {
- TheEstablishConnectionsMenu->setPlayerName(playerNum, m_slotList[i]->getName());
- TheEstablishConnectionsMenu->setPlayerStatus(playerNum, NATCONNECTIONSTATE_WAITINGTOBEGIN);
- ++playerNum;
- }
- }
-
-// m_roundTimeout = timeGetTime() + TheGameSpyConfig->getRoundTimeout();
- m_roundTimeout = timeGetTime() + m_timeForRoundTimeout;
-
- // make the connections for this round.
- // this song is cool.
- doThisConnectionRound();
-}
-
-void NAT::attachSlotList(GameSlot *slotList[], Int localSlot, UnsignedInt localIP) {
- m_slotList = slotList;
- m_localIP = localIP;
- m_transport = new Transport;
- DEBUG_LOG(("NAT::attachSlotList - initting the transport socket with address %d.%d.%d.%d:%d",
- PRINTF_IP_AS_4_INTS(m_localIP), getSlotPort(localSlot)));
-
- m_startingPortNumber = NETWORK_BASE_PORT_NUMBER + ((timeGetTime() / 1000) % 20000);
- DEBUG_LOG(("NAT::attachSlotList - using %d as the starting port number", m_startingPortNumber));
- generatePortNumbers(slotList, localSlot);
- m_transport->init(m_localIP, getSlotPort(localSlot));
-}
-
-Int NAT::getSlotPort(Int slot) {
-// return (slot + m_startingPortNumber);
- if (m_slotList[slot] != NULL) {
- return m_slotList[slot]->getPort();
- }
- return 0;
-}
-
-void NAT::generatePortNumbers(GameSlot *slotList[], Int localSlot) {
- for (UnsignedInt i = 0; i < (UnsignedInt)MAX_SLOTS; ++i) {
- if (slotList[i] != NULL) {
- if ((i == localSlot) && (TheWritableGlobalData->m_firewallPortOverride != 0)) {
- slotList[i]->setPort(TheWritableGlobalData->m_firewallPortOverride);
- } else {
- slotList[i]->setPort(i + m_startingPortNumber);
- }
- }
- }
-}
-
-Transport * NAT::getTransport() {
- return m_transport;
-}
-
-// figure out which port I'll be using.
-// send the port number to our target for this round.
-// init the m_connectionStates for all players.
-void NAT::doThisConnectionRound() {
- DEBUG_LOG(("NAT::doThisConnectionRound - starting process for connection round %d", m_connectionRound));
- // clear out the states from the last round.
- m_targetNodeNumber = -1;
-
- Int i = 0;
- for (; i < MAX_SLOTS; ++i) {
- setConnectionState(i, NATCONNECTIONSTATE_NOSTATE);
- }
-
- m_beenProbed = FALSE;
- m_numRetries = 0;
-
- for (i = 0; i < m_numNodes; ++i) {
- Int targetNodeNumber = m_connectionPairs[m_connectionPairIndex][m_connectionRound][i];
- DEBUG_LOG(("NAT::doThisConnectionRound - node %d needs to connect to node %d", i, targetNodeNumber));
- if (targetNodeNumber != -1) {
- if (i == m_localNodeNumber) {
- m_targetNodeNumber = targetNodeNumber;
- DEBUG_LOG(("NAT::doThisConnectionRound - Local node is connecting to node %d", m_targetNodeNumber));
- UnsignedInt targetSlotIndex = m_connectionNodes[(m_connectionPairs[m_connectionPairIndex][m_connectionRound][i])].m_slotIndex;
- GameSlot *targetSlot = m_slotList[targetSlotIndex];
- GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex];
-
- DEBUG_ASSERTCRASH(localSlot != NULL, ("local slot is NULL"));
- DEBUG_ASSERTCRASH(targetSlot != NULL, ("trying to negotiate with a NULL target slot, slot is %d", m_connectionPairs[m_connectionPairIndex][m_connectionRound][i]));
- DEBUG_LOG(("NAT::doThisConnectionRound - Target slot index = %d (%ls)", targetSlotIndex, m_slotList[targetSlotIndex]->getName().str()));
- DEBUG_LOG(("NAT::doThisConnectionRound - Target slot has NAT behavior 0x%8X, local slot has NAT behavior 0x%8X", targetSlot->getNATBehavior(), localSlot->getNATBehavior()));
-
-#if defined(DEBUG_LOGGING)
- UnsignedInt targetIP = targetSlot->getIP();
- UnsignedInt localIP = localSlot->getIP();
-#endif
-
- DEBUG_LOG(("NAT::doThisConnectionRound - Target slot has IP %d.%d.%d.%d Local slot has IP %d.%d.%d.%d",
- PRINTF_IP_AS_4_INTS(targetIP),
- PRINTF_IP_AS_4_INTS(localIP)));
-
- if (((targetSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) == 0) &&
- ((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0)) {
-
- // we have a netgear bug type behavior and the target does not, so we need them to send to us
- // first to avoid having our NAT table reset.
-
- DEBUG_LOG(("NAT::doThisConnectionRound - Local node has a netgear and the target node does not, need to delay our probe."));
- m_timeTillNextSend = -1;
- }
-
- // figure out which port number I'm using for this connection
- // this merely starts to talk to the mangler server, we have to keep calling
- // the update function till we get a response.
- DEBUG_LOG(("NAT::doThisConnectionRound - About to attempt to get the next mangled source port"));
- sendMangledSourcePort();
-// m_nextPortSendTime = timeGetTime() + TheGameSpyConfig->getRetryInterval();
- m_nextPortSendTime = timeGetTime() + m_timeBetweenRetries;
-// m_timeoutTime = timeGetTime() + TheGameSpyConfig->getPortTimeout();
- m_timeoutTime = timeGetTime() + m_timeToWaitForPort;
- } else {
- // this is someone else that needs to connect to someone, so wait till they tell us
- // that they're done.
- setConnectionState(i, NATCONNECTIONSTATE_WAITINGFORRESPONSE);
- }
- } else {
- // no one to connect to, so this one is done.
- DEBUG_LOG(("NAT::doThisConnectionRound - node %d has no one to connect to, so they're done", i));
- setConnectionState(i, NATCONNECTIONSTATE_DONE);
- }
- }
-}
-
-void NAT::sendAProbe(UnsignedInt ip, UnsignedShort port, Int fromNode) {
- DEBUG_LOG(("NAT::sendAProbe - sending a probe from port %d to %d.%d.%d.%d:%d", getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex),
- PRINTF_IP_AS_4_INTS(ip), port));
- AsciiString str;
- str.format("PROBE%d", fromNode);
- m_transport->queueSend(ip, port, (unsigned char *)str.str(), str.getLength() + 1);
- m_transport->doSend();
-}
-
-// find the next mangled source port, and then send it to the other player.
-// if this requires talking to the mangler, we'll have to wait till a later update
-// to send our port out.
-void NAT::sendMangledSourcePort() {
- UnsignedShort sourcePort = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex);
-
- FirewallHelperClass::tFirewallBehaviorType fwType = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]->getNATBehavior();
- GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::sendMangledSourcePort - targetSlot is NULL"));
- if (targetSlot == NULL) {
- DEBUG_LOG(("NAT::sendMangledSourcePort - targetSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::sendMangledSourcePort - localSlot is NULL, WTF?"));
- if (localSlot == NULL) {
- DEBUG_LOG(("NAT::sendMangledSourcePort - localSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- // check to see if the target and I are behind the same NAT
- if (targetSlot->getIP() == localSlot->getIP()) {
-#if defined(DEBUG_LOGGING)
- UnsignedInt localip = localSlot->getIP();
- UnsignedInt targetip = targetSlot->getIP();
-#endif
- DEBUG_LOG(("NAT::sendMangledSourcePort - target and I are behind the same NAT, no mangling"));
- DEBUG_LOG(("NAT::sendMangledSourcePort - I am %ls, target is %ls, my IP is %d.%d.%d.%d, target IP is %d.%d.%d.%d", localSlot->getName().str(), targetSlot->getName().str(),
- PRINTF_IP_AS_4_INTS(localip),
- PRINTF_IP_AS_4_INTS(targetip)));
-
- sendMangledPortNumberToTarget(sourcePort, targetSlot);
- m_sourcePorts[m_targetNodeNumber] = sourcePort;
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT);
- // In case you're wondering, we don't set the m_previousSourcePort here because this will be a different source
- // address than what other nodes will likely see (unless of course there are more than
- // two of us behind the same NAT, but we won't worry about that cause theres no mangling
- // in that case anyways)
- return;
- }
-
- // check to see if we are NAT'd at all.
- if ((fwType == 0) || (fwType == FirewallHelperClass::FIREWALL_TYPE_SIMPLE)) {
- // no mangling, just return the source port
- DEBUG_LOG(("NAT::sendMangledSourcePort - no mangling, just using the source port"));
- sendMangledPortNumberToTarget(sourcePort, targetSlot);
- m_previousSourcePort = sourcePort;
- m_sourcePorts[m_targetNodeNumber] = sourcePort;
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT);
- return;
- }
-
- // check to see if our NAT keeps the same source port for different destinations.
- // if this is the case, and we've already worked out what our mangled port number is
- // then we don't have to figure it out again.
- if (((fwType & FirewallHelperClass::FIREWALL_TYPE_DESTINATION_PORT_DELTA) == 0) &&
- ((fwType & FirewallHelperClass::FIREWALL_TYPE_SMART_MANGLING) == 0)) {
- DEBUG_LOG(("NAT::sendMangledSourcePort - our firewall doesn't NAT based on destination address, checking for old connections from this address"));
- if (m_previousSourcePort != 0) {
- DEBUG_LOG(("NAT::sendMangledSourcePort - Previous source port was %d, using that one", m_previousSourcePort));
- sendMangledPortNumberToTarget(m_previousSourcePort, targetSlot);
- m_sourcePorts[m_targetNodeNumber] = m_previousSourcePort;
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT);
- return;
- } else {
- DEBUG_LOG(("NAT::sendMangledSourcePort - Previous source port not found"));
- }
- }
-
- // At this point we know that our NAT uses some kind of relative port mapping scheme, so we
- // need to talk to the mangler to find out where we are now so we can find out where we'll be on the
- // next port allocation.
-
- // get the address of the mangler we need to talk to.
- Char manglerName[256];
- FirewallHelperClass::getManglerName(1, manglerName);
- DEBUG_LOG(("NAT::sendMangledSourcePort - about to call gethostbyname for mangler at %s", manglerName));
- struct hostent *hostInfo = gethostbyname(manglerName);
-
- if (hostInfo == NULL) {
- DEBUG_LOG(("NAT::sendMangledSourcePort - gethostbyname failed for mangler address %s", manglerName));
- // can't find the mangler, we're screwed so just send the source port.
- sendMangledPortNumberToTarget(sourcePort, targetSlot);
- m_sourcePorts[m_targetNodeNumber] = sourcePort;
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT);
- return;
- }
-
- memcpy(&m_manglerAddress, &(hostInfo->h_addr_list[0][0]), 4);
- m_manglerAddress = ntohl(m_manglerAddress);
- DEBUG_LOG(("NAT::sendMangledSourcePort - mangler %s address is %d.%d.%d.%d", manglerName,
- PRINTF_IP_AS_4_INTS(m_manglerAddress)));
-
- DEBUG_LOG(("NAT::sendMangledSourcePort - NAT behavior = 0x%08x", fwType));
-
-// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime();
- m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime();
- m_manglerRetries = 0;
-
- if (TheFirewallHelper != NULL) {
- m_spareSocketPort = TheFirewallHelper->getNextTemporarySourcePort(0);
- TheFirewallHelper->openSpareSocket(m_spareSocketPort);
- TheFirewallHelper->sendToManglerFromPort(m_manglerAddress, m_spareSocketPort, m_packetID);
-// m_manglerRetryTime = TheGameSpyConfig->getRetryInterval() + timeGetTime();
- m_manglerRetryTime = m_manglerRetryTimeInterval + timeGetTime();
- }
-
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE);
-}
-
-void NAT::processManglerResponse(UnsignedShort mangledPort) {
- DEBUG_LOG(("NAT::processManglerResponse - Work out what my NAT'd port will be"));
-
- GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::processManglerResponse - targetSlot is NULL"));
- if (targetSlot == NULL) {
- DEBUG_LOG(("NAT::processManglerResponse - targetSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- Short delta = TheGlobalData->m_firewallPortAllocationDelta;
- UnsignedShort sourcePort = getSlotPort(m_connectionNodes[m_localNodeNumber].m_slotIndex);
- UnsignedShort returnPort = 0;
-
- FirewallHelperClass::tFirewallBehaviorType fwType = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex]->getNATBehavior();
-
- if ((fwType & FirewallHelperClass::FIREWALL_TYPE_SIMPLE_PORT_ALLOCATION) != 0) {
- returnPort = mangledPort + delta;
- } else {
- // to steal a line from Steve Tall...
- // Rats. It's a relative mangler. This is much harder. Damn NAT32 guy.
- if (delta == 100) {
- // Special NAT32 section.
- // NAT32 mangles source UDP port by ading 1700 + 100*NAT table index.
- returnPort = mangledPort - m_spareSocketPort;
- returnPort -= 1700;
-
- returnPort += delta;
- returnPort += sourcePort;
- returnPort += 1700;
-
- } else if (delta == 0) {
- returnPort = sourcePort;
- } else {
- returnPort = mangledPort / delta;
- returnPort = returnPort * delta;
-
- returnPort += (sourcePort % delta);
- returnPort += delta;
- }
- }
-
- // This bit is probably doomed.
- if (returnPort > 65535) {
- returnPort -= 65535;
- }
- if (returnPort < 1024) {
- returnPort += 1024;
- }
-
- DEBUG_LOG(("NAT::processManglerResponse - mangled port is %d", returnPort));
- m_previousSourcePort = returnPort;
-
- sendMangledPortNumberToTarget(returnPort, targetSlot);
- m_sourcePorts[m_targetNodeNumber] = returnPort;
- if (targetSlot->getPort() == 0) {
- // we haven't got the target's mangled port number yet, wait for it.
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT);
- } else {
- // in this case we should have already sent a PROBE, so we'll just change the state
- // and leave it at that.
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE);
- }
-}
-
-// check to see if we've completed all the rounds
-// this is kind of a cheesy way to check, but it works.
-Bool NAT::allConnectionsDone() {
- if (m_numNodes < 2) {
- return FALSE;
- }
- const Int requiredRounds = (m_numNodes & 1) ? m_numNodes : m_numNodes - 1;
- return m_connectionRound >= requiredRounds;
-}
-
-Bool NAT::allConnectionsDoneThisRound() {
- Bool retval = TRUE;
- for (UnsignedInt i = 0; (i < m_numNodes) && (retval == TRUE); ++i) {
- if ((m_connectionStates[i] != NATCONNECTIONSTATE_DONE) && (m_connectionStates[i] != NATCONNECTIONSTATE_FAILED)) {
- retval = FALSE;
- }
- }
- return retval;
-}
-
-// this node's connection for this round has been completed.
-void NAT::connectionComplete(Int slotIndex) {
-}
-
-// this node's connection for this round has failed.
-void NAT::connectionFailed(Int slotIndex) {
-}
-
-// I have been probed by the target.
-void NAT::probed(Int nodeNumber) {
- GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::probed - localSlot is NULL, WTF?"));
- if (localSlot == NULL) {
- DEBUG_LOG(("NAT::probed - localSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- if (m_beenProbed == FALSE) {
- m_beenProbed = TRUE;
- DEBUG_LOG(("NAT::probed - just got probed for the first time."));
- if ((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) {
- DEBUG_LOG(("NAT::probed - we have a NETGEAR and we were just probed for the first time"));
- GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::probed - targetSlot is NULL"));
- if (targetSlot == NULL) {
- DEBUG_LOG(("NAT::probed - targetSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- if (targetSlot->getPort() == 0) {
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT);
- DEBUG_LOG(("NAT::probed - still waiting for mangled port"));
- } else {
- DEBUG_LOG(("NAT::probed - sending a probe to %ls", targetSlot->getName().str()));
- sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber);
- notifyTargetOfProbe(targetSlot);
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE);
- }
- }
- }
-}
-
-// got the mangled port for our target for this round.
-void NAT::gotMangledPort(Int nodeNumber, UnsignedShort mangledPort) {
-
- // if we've already finished the connection, then we don't need to process this.
- if (m_connectionStates[m_localNodeNumber] == NATCONNECTIONSTATE_DONE) {
- DEBUG_LOG(("NAT::gotMangledPort - got a mangled port, but we've already finished this connection, ignoring."));
- return;
- }
-
- GameSlot *targetSlot = m_slotList[m_connectionNodes[m_targetNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::gotMangledPort - targetSlot is NULL"));
- if (targetSlot == NULL) {
- DEBUG_LOG(("NAT::gotMangledPort - targetSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::gotMangledPort - localSlot is NULL, WTF?"));
- if (localSlot == NULL) {
- DEBUG_LOG(("NAT::gotMangledPort - localSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- if (nodeNumber != m_targetNodeNumber) {
- DEBUG_LOG(("NAT::gotMangledPort - got a mangled port number for someone that isn't my target. node = %d, target node = %d", nodeNumber, m_targetNodeNumber));
- return;
- }
-
- targetSlot->setPort(mangledPort);
- DEBUG_LOG(("NAT::gotMangledPort - got mangled port number %d from our target node (%ls)", mangledPort, targetSlot->getName().str()));
- if (((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) == 0) || (m_beenProbed == TRUE) ||
- (((localSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0) && ((targetSlot->getNATBehavior() & FirewallHelperClass::FIREWALL_TYPE_NETGEAR_BUG) != 0))) {
-#ifdef DEBUG_LOGGING
- UnsignedInt ip = targetSlot->getIP();
-#endif
- DEBUG_LOG(("NAT::gotMangledPort - don't have a netgear or we have already been probed, or both my target and I have a netgear, send a PROBE. Sending to %d.%d.%d.%d:%d",
- PRINTF_IP_AS_4_INTS(ip), targetSlot->getPort()));
-
- sendAProbe(targetSlot->getIP(), targetSlot->getPort(), m_localNodeNumber);
- notifyTargetOfProbe(targetSlot);
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_WAITINGFORRESPONSE);
- } else {
- DEBUG_LOG(("NAT::gotMangledPort - we are a netgear, not sending a PROBE yet."));
- }
-}
-
-void NAT::gotInternalAddress(Int nodeNumber, UnsignedInt address) {
- GameSlot *targetSlot = m_slotList[m_connectionNodes[nodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(targetSlot != NULL, ("NAT::gotInternalAddress - targetSlot is NULL"));
- if (targetSlot == NULL) {
- return;
- }
-
- GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::gotInternalAddress - localSlot is NULL, WTF?"));
- if (localSlot == NULL) {
- return;
- }
-
- if (nodeNumber != m_targetNodeNumber) {
- DEBUG_LOG(("NAT::gotInternalAddress - got a internal address for someone that isn't my target. node = %d, target node = %d", nodeNumber, m_targetNodeNumber));
- return;
- }
-
- if (localSlot->getIP() == targetSlot->getIP()) {
- // we have the same IP address, i.e. we are behind the same NAT.
- // I need to talk directly to his internal address.
- DEBUG_LOG(("NAT::gotInternalAddress - target and local players have same external address, using internal address."));
- targetSlot->setIP(address); // use the slot's internal address from now on
- }
-}
-
-void NAT::notifyTargetOfProbe(GameSlot *targetSlot) {
- PeerRequest req;
- AsciiString options;
- options.format("PROBED%d", m_localNodeNumber);
- req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER;
- req.UTM.isStagingRoom = TRUE;
- req.id = "NAT/";
- AsciiString hostName;
- hostName.translate(targetSlot->getName());
- req.nick = hostName.str();
- req.options = options.str();
- TheGameSpyPeerMessageQueue->addRequest(req);
- DEBUG_LOG(("NAT::notifyTargetOfProbe - notifying %ls that we have probed them.", targetSlot->getName().str()));
-}
-
-void NAT::notifyUsersOfConnectionDone(Int nodeIndex) {
- GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::notifyUsersOfConnectionDone - localSlot is NULL, WTF?"));
- if (localSlot == NULL) {
- DEBUG_LOG(("NAT::notifyUsersOfConnectionDone - localSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- PeerRequest req;
- AsciiString options;
- options.format("CONNDONE%d %d", nodeIndex, m_localNodeNumber);
-
- req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER;
- req.UTM.isStagingRoom = TRUE;
- req.id = "NAT";
- AsciiString names;
- for (Int i=0; iisHuman() == FALSE)) {
- continue;
- }
-
- AsciiString name;
- name.translate(m_slotList[i]->getName());
- if (names.isNotEmpty())
- {
- names.concat(',');
- }
- names.concat(name);
- }
- req.nick = names.str();
- req.options = options.str();
-
- DEBUG_LOG(("NAT::notifyUsersOfConnectionDone - sending %s to %s", options.str(), names.str()));
- TheGameSpyPeerMessageQueue->addRequest(req);
-}
-
-void NAT::notifyUsersOfConnectionFailed(Int nodeIndex) {
- GameSlot *localSlot = m_slotList[m_connectionNodes[m_localNodeNumber].m_slotIndex];
- DEBUG_ASSERTCRASH(localSlot != NULL, ("NAT::notifyUsersOfConnectionFailed - localSlot is NULL, WTF?"));
- if (localSlot == NULL) {
- DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - localSlot is NULL, failed this connection"));
- setConnectionState(m_localNodeNumber, NATCONNECTIONSTATE_FAILED);
- return;
- }
-
- PeerRequest req;
- AsciiString options;
- options.format("CONNFAILED%d", nodeIndex);
-/*
- req.peerRequestType = PeerRequest::PEERREQUEST_UTMROOM;
- req.UTM.isStagingRoom = TRUE;
- req.id = "NAT/";
- req.options = options.str();
-
- DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - sending %s to room", options.str()));
-*/
-
- req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER;
- req.UTM.isStagingRoom = TRUE;
- req.id = "NAT";
- AsciiString names;
- for (Int i=0; iisHuman() == FALSE)) {
- continue;
- }
-
- AsciiString name;
- name.translate(m_slotList[i]->getName());
- if (names.isNotEmpty())
- {
- names.concat(',');
- }
- names.concat(name);
- }
- req.nick = names.str();
- req.options = options.str();
-
- DEBUG_LOG(("NAT::notifyUsersOfConnectionFailed - sending %s to %s", options.str(), names.str()));
-
- TheGameSpyPeerMessageQueue->addRequest(req);
-}
-
-void NAT::sendMangledPortNumberToTarget(UnsignedShort mangledPort, GameSlot *targetSlot) {
- PeerRequest req;
- AsciiString options;
- options.format("PORT%d %d %08X", m_localNodeNumber, mangledPort, m_localIP);
-
- req.peerRequestType = PeerRequest::PEERREQUEST_UTMPLAYER;
- req.UTM.isStagingRoom = TRUE;
- req.id = "NAT/";
- AsciiString hostName;
- hostName.translate(targetSlot->getName());
- req.nick = hostName.str();
- req.options = options.str();
- DEBUG_LOG(("NAT::sendMangledPortNumberToTarget - sending \"%s\" to %s", options.str(), hostName.str()));
- TheGameSpyPeerMessageQueue->addRequest(req);
-}
-
-void NAT::processGlobalMessage(Int slotNum, const char *options) {
- const char *ptr = options;
- // skip preceding whitespace.
- while (isspace(*ptr)) {
- ++ptr;
- }
- DEBUG_LOG(("NAT::processGlobalMessage - got message from slot %d, message is \"%s\"", slotNum, ptr));
- if (!strncmp(ptr, "PROBED", strlen("PROBED"))) {
- // format: PROBED
- // a probe has been sent at us, if we are waiting because of a netgear or something, we
- // should start sending our own probes.
- Int node = atoi(ptr + strlen("PROBED"));
- if (node == m_targetNodeNumber) {
- // make sure we're being probed by who we're supposed to be probed by.
- probed(node);
- } else {
- DEBUG_LOG(("NAT::processGlobalMessage - probed by node %d, not our target", node));
- }
- } else if (!strncmp(ptr, "CONNDONE", strlen("CONNDONE"))) {
- // format: CONNDONE
- // we should get the node number of the player who's connection is done from the options
- // and mark that down as part of the connectionStates.
- const char *c = ptr + strlen("CONNDONE");
-/* while (*c != ' ') {
- ++c;
- }
- while (*c == ' ') {
- ++c;
- }
-*/ Int node;
- Int sendingNode;
- sscanf(c, "%d %d\n", &node, &sendingNode);
-
- if (m_connectionPairs[m_connectionPairIndex][m_connectionRound][node] == sendingNode) {
-// Int node = atoi(ptr + strlen("CONNDONE"));
- DEBUG_LOG(("NAT::processGlobalMessage - got a CONNDONE message for node %d", node));
- if ((node >= 0) && (node <= m_numNodes)) {
- DEBUG_LOG(("NAT::processGlobalMessage - node %d's connection is complete, setting connection state to done", node));
- setConnectionState(node, NATCONNECTIONSTATE_DONE);
- }
- } else {
- DEBUG_LOG(("NAT::processGlobalMessage - got a connection done message that isn't from this round. node: %d sending node: %d", node, sendingNode));
- }
- } else if (!strncmp(ptr, "CONNFAILED", strlen("CONNFAILED"))) {
- // format: CONNFAILED
- // we should get the node number of the player who's connection failed from the options
- // and mark that down as part of the connectionStates.
- Int node = atoi(ptr + strlen("CONNFAILED"));
- if ((node >= 0) && (node < m_numNodes)) {
- DEBUG_LOG(("NAT::processGlobalMessage - node %d's connection failed, setting connection state to failed", node));
- setConnectionState(node, NATCONNECTIONSTATE_FAILED);
- }
- } else if (!strncmp(ptr, "PORT", strlen("PORT"))) {
- // format: PORT
- // we should get the node number and the mangled port number of the client we
- // are supposed to be communicating with and start probing them. No, that was not
- // meant to be a phallic reference, you sicko.
- const char *c = ptr + strlen("PORT");
- Int node = atoi(c);
- while (*c != ' ') {
- ++c;
- }
- while (*c == ' ') {
- ++c;
- }
- UnsignedInt intport = 0;
- UnsignedInt addr = 0;
- sscanf(c, "%d %X", &intport, &addr);
- UnsignedShort port = (UnsignedShort)intport;
-
- DEBUG_LOG(("NAT::processGlobalMessage - got port message from node %d, port: %d, internal address: %d.%d.%d.%d", node, port,
- PRINTF_IP_AS_4_INTS(addr)));
-
- if ((node >= 0) && (node < m_numNodes)) {
- if (port < 1024) {
- // it has to be less than 65535 cause its a short duh.
- DEBUG_ASSERTCRASH(port >= 1024, ("Was passed an invalid port number"));
- port += 1024;
- }
- gotInternalAddress(node, addr);
- gotMangledPort(node, port);
- }
- }
-}
-
-void NAT::setConnectionState(Int nodeNumber, NATConnectionState state) {
- m_connectionStates[nodeNumber] = state;
-
- if (nodeNumber != m_localNodeNumber) {
- return;
- }
-
- // if this is the case we are starting a new round and we don't know
- // who we're connecting to yet.
- if (m_localNodeNumber == m_targetNodeNumber) {
- return;
- }
-
- // if this is the start of a new connection round we don't have a
- // target yet.
- if (m_targetNodeNumber == -1) {
- return;
- }
-
- // find the menu slot of the target node.
- Int slotIndex = m_connectionNodes[m_targetNodeNumber].m_slotIndex;
- Int slot = 0;
- Int i = 0;
- for (; i < MAX_SLOTS; ++i) {
- if (m_slotList[i] != NULL) {
- if (m_slotList[i]->isHuman()) {
- if (i != m_connectionNodes[m_localNodeNumber].m_slotIndex) {
- if (i == slotIndex) {
- break;
- }
- ++slot;
- }
- }
- }
- }
- if (i == MAX_SLOTS) {
- DEBUG_ASSERTCRASH(i < MAX_SLOTS, ("Didn't find the node number in the slot list"));
- return;
- }
- TheEstablishConnectionsMenu->setPlayerStatus(slot, state);
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandList.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NetCommandList.cpp
deleted file mode 100644
index a7b005fcb96..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandList.cpp
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/NetCommandList.h"
-#include "GameNetwork/networkutil.h"
-
-/**
- * Constructor.
- */
-NetCommandList::NetCommandList() {
- m_first = NULL;
- m_last = NULL;
- m_lastMessageInserted = NULL;
-}
-
-/**
- * Destructor.
- */
-NetCommandList::~NetCommandList() {
- reset();
-}
-
-/**
- * Append the given list of commands to this list.
- */
-void NetCommandList::appendList(NetCommandList *list) {
- if (list == NULL) {
- return;
- }
-
- // Need to do it this way because of the reference counting that needs to happen in appendMessage.
- NetCommandRef *msg = list->getFirstMessage();
- NetCommandRef *next = NULL;
- while (msg != NULL) {
- next = msg->getNext();
- NetCommandRef *temp = addMessage(msg->getCommand());
- if (temp != NULL) {
- temp->setRelay(msg->getRelay());
- }
-
- msg = next;
- }
-}
-
-/**
- * Return the first message in this list.
- */
-NetCommandRef *NetCommandList::getFirstMessage() {
- return m_first;
-}
-
-/**
- * Remove the given message from this list.
- */
-void NetCommandList::removeMessage(NetCommandRef *msg) {
- if (m_lastMessageInserted == msg) {
- m_lastMessageInserted = msg->getNext();
- }
-
- if (msg->getPrev() != NULL) {
- msg->getPrev()->setNext(msg->getNext());
- }
- if (msg->getNext() != NULL) {
- msg->getNext()->setPrev(msg->getPrev());
- }
-
- if (msg == m_first) {
- m_first = msg->getNext();
- }
- if (msg == m_last) {
- m_last = msg->getPrev();
- }
-
- msg->setNext(NULL);
- msg->setPrev(NULL);
-}
-
-/**
- * Initialize the list.
- */
-void NetCommandList::init() {
- reset();
-}
-
-/**
- * Reset the contents of this list.
- */
-void NetCommandList::reset() {
- NetCommandRef *temp = m_first;
- while (m_first != NULL) {
- temp = m_first->getNext();
- m_first->setNext(NULL);
- m_first->setPrev(NULL);
- deleteInstance(m_first);
- m_first = temp;
- }
- m_last = NULL;
- m_lastMessageInserted = NULL;
-}
-
-/**
- * Insert sorts msg. Assumes that all the previous message inserts were done using this function.
- * The message is sorted in based first on command type, then player id, and then command id.
- */
-NetCommandRef * NetCommandList::addMessage(NetCommandMsg *cmdMsg) {
- if (cmdMsg == NULL) {
- DEBUG_ASSERTCRASH(cmdMsg != NULL, ("NetCommandList::addMessage - command message was NULL"));
- return NULL;
- }
-
-// UnsignedInt id = cmdMsg->getID();
-
- NetCommandRef *msg = NEW_NETCOMMANDREF(cmdMsg);
-
- if (m_first == NULL) {
- // this is the first node, so we don't have to worry about ordering it.
- m_first = msg;
- m_last = msg;
- m_lastMessageInserted = msg;
- return msg;
- }
-
- if (m_lastMessageInserted != NULL) {
- // Messages that are inserted in order should just be put in one right after the other.
- // So saving the placement of the last message inserted can give us a huge boost in
- // efficiency.
- NetCommandRef *theNext = m_lastMessageInserted->getNext();
- if ((m_lastMessageInserted->getCommand()->getNetCommandType() == msg->getCommand()->getNetCommandType()) &&
- (m_lastMessageInserted->getCommand()->getPlayerID() == msg->getCommand()->getPlayerID()) &&
- (m_lastMessageInserted->getCommand()->getID() < msg->getCommand()->getID()) &&
- ((theNext == NULL) || ((theNext->getCommand()->getNetCommandType() > msg->getCommand()->getNetCommandType()) ||
- (theNext->getCommand()->getPlayerID() > msg->getCommand()->getPlayerID()) ||
- (theNext->getCommand()->getID() > msg->getCommand()->getID())))) {
-
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(m_lastMessageInserted->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- msg = NULL;
- return NULL;
- }
-
- if (theNext == NULL) {
- // this means that m_lastMessageInserted == m_last, so m_last should point to the msg that is being inserted.
- msg->setNext(m_lastMessageInserted->getNext());
- msg->setPrev(m_lastMessageInserted);
- m_lastMessageInserted->setNext(msg);
- m_lastMessageInserted = msg;
- m_last = msg;
- } else {
- msg->setNext(m_lastMessageInserted->getNext());
- msg->setPrev(m_lastMessageInserted);
- m_lastMessageInserted->setNext(msg);
- msg->getNext()->setPrev(msg);
- m_lastMessageInserted = msg;
- }
- return msg;
- }
- }
-
- if (msg->getCommand()->getNetCommandType() > m_last->getCommand()->getNetCommandType()) {
- // easy optimization for a command that goes at the end of the list
- // since they are likely to be added in order.
-
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(m_last->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- msg = NULL;
- return NULL;
- }
-
- msg->setPrev(m_last);
- msg->setNext(NULL);
- m_last->setNext(msg);
- m_last = msg;
- m_lastMessageInserted = msg;
- return msg;
- }
-
- if (msg->getCommand()->getNetCommandType() < m_first->getCommand()->getNetCommandType()) {
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(m_first->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- msg = NULL;
- return NULL;
- }
-
- // The command goes at the head of the list.
- msg->setNext(m_first);
- msg->setPrev(NULL);
- m_first->setPrev(msg);
- m_first = msg;
- m_lastMessageInserted = msg;
- return msg;
- }
-
-
- // Find the start of the command type we're looking for.
- NetCommandRef *tempmsg = m_first;
- while ((tempmsg != NULL) && (msg->getCommand()->getNetCommandType() > tempmsg->getCommand()->getNetCommandType())) {
- tempmsg = tempmsg->getNext();
- }
-
- if (tempmsg == NULL) {
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(m_last->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- msg = NULL;
- return NULL;
- }
-
- // message goes at the end of the list.
- msg->setPrev(m_last);
- msg->setNext(NULL);
- m_last->setNext(msg);
- m_last = msg;
- m_lastMessageInserted = msg;
- return msg;
- }
-
- // Now find the player position. munkee.
- while ((tempmsg != NULL) && (msg->getCommand()->getNetCommandType() == tempmsg->getCommand()->getNetCommandType()) && (msg->getCommand()->getPlayerID() > tempmsg->getCommand()->getPlayerID())) {
- tempmsg = tempmsg->getNext();
- }
-
- if (tempmsg == NULL) {
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(m_last->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- msg = NULL;
- return NULL;
- }
-
- // message goes at the end of the list.
- msg->setPrev(m_last);
- msg->setNext(NULL);
- m_last->setNext(msg);
- m_last = msg;
- m_lastMessageInserted = msg;
- return msg;
- }
-
- // Find the position within the player's section based on the command ID.
- // If the command type doesn't require a command ID, sort by whatever it should be sorted by.
- while ((tempmsg != NULL) && (msg->getCommand()->getNetCommandType() == tempmsg->getCommand()->getNetCommandType()) && (msg->getCommand()->getPlayerID() == tempmsg->getCommand()->getPlayerID()) && (msg->getCommand()->getSortNumber() > tempmsg->getCommand()->getSortNumber())) {
- tempmsg = tempmsg->getNext();
- }
-
- if (tempmsg == NULL) {
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(m_last->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- msg = NULL;
- return NULL;
- }
-
- // This message goes at the end of the list.
- msg->setPrev(m_last);
- msg->setNext(NULL);
- m_last->setNext(msg);
- m_last = msg;
- m_lastMessageInserted = msg;
- return msg;
- }
-
- if (tempmsg == m_first) {
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(m_first->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- return NULL;
- }
-
- // This message goes at the head of the list.
- msg->setNext(m_first);
- msg->setPrev(NULL);
- m_first->setPrev(msg);
- m_first = msg;
- m_lastMessageInserted = msg;
- return msg;
- }
-
- // Make sure this command isn't already in the list.
- if (isEqualCommandMsg(tempmsg->getCommand(), msg->getCommand())) {
-
- // This command is already in the list, don't duplicate it.
- deleteInstance(msg);
- msg = NULL;
- return NULL;
- }
-
- // Insert message before tempmsg.
- msg->setNext(tempmsg);
- msg->setPrev(tempmsg->getPrev());
- msg->getPrev()->setNext(msg);
- tempmsg->setPrev(msg);
- m_lastMessageInserted = msg;
-
- return msg;
-}
-
-Int NetCommandList::length() {
- Int retval = 0;
- NetCommandRef *temp = m_first;
- while (temp != NULL) {
- ++retval;
- temp = temp->getNext();
- }
- return retval;
-}
-
-/**
- * This is really inefficient, but we can probably get away with it because
- * there shouldn't be too many messages for any given frame.
- */
-NetCommandRef * NetCommandList::findMessage(NetCommandMsg *msg) {
- NetCommandRef *retval = m_first;
- while ((retval != NULL) && (isEqualCommandMsg(retval->getCommand(), msg) == FALSE)) {
- retval = retval->getNext();
- }
- return retval;
-}
-
-NetCommandRef * NetCommandList::findMessage(UnsignedShort commandID, UnsignedByte playerID) {
- NetCommandRef *retval = m_first;
- while (retval != NULL) {
- if (DoesCommandRequireACommandID(retval->getCommand()->getNetCommandType())) {
- if ((retval->getCommand()->getID() == commandID) && (retval->getCommand()->getPlayerID() == playerID)) {
- return retval;
- }
- }
- retval = retval->getNext();
- }
- return retval;
-}
-
-Bool NetCommandList::isEqualCommandMsg(NetCommandMsg *msg1, NetCommandMsg *msg2) {
- if (DoesCommandRequireACommandID(msg1->getNetCommandType()) != DoesCommandRequireACommandID(msg2->getNetCommandType())) {
- return FALSE;
- }
-
- // At this point we know that the commands both do or do not require a command id.
- // Do or do not, there is no try.
- if (DoesCommandRequireACommandID(msg1->getNetCommandType())) {
- // Are the commands from the same player?
- if (msg1->getPlayerID() != msg2->getPlayerID()) {
- return FALSE;
- }
-
- // Do they have the same command ID?
- if (msg1->getID() != msg2->getID()) {
- return FALSE;
- }
- return TRUE;
- }
-
- // If we've gotten this far, we know that the commands do not require a command id.
- // So now our equality checking becomes type-specific.
-
- // Are they the same type?
- if (msg1->getNetCommandType() != msg2->getNetCommandType()) {
- return FALSE;
- }
-
- // Are they from the same player?
- if (msg1->getPlayerID() != msg2->getPlayerID()) {
- return FALSE;
- }
-
- // They are the same type and from the same player.
- // Time for the type specific stuff.
- if (msg1->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE1) {
- NetAckStage1CommandMsg *ack1 = (NetAckStage1CommandMsg *)msg1;
- NetAckStage1CommandMsg *ack2 = (NetAckStage1CommandMsg *)msg2;
-
- if (ack1->getOriginalPlayerID() != ack2->getOriginalPlayerID()) {
- return FALSE;
- }
-
- if (ack1->getCommandID() != ack2->getCommandID()) {
- return FALSE;
- }
- return TRUE;
- }
-
- // They are the same type and from the same player.
- // Time for the type specific stuff.
- if (msg1->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE2) {
- NetAckStage2CommandMsg *ack1 = (NetAckStage2CommandMsg *)msg1;
- NetAckStage2CommandMsg *ack2 = (NetAckStage2CommandMsg *)msg2;
-
- if (ack1->getOriginalPlayerID() != ack2->getOriginalPlayerID()) {
- return FALSE;
- }
-
- if (ack1->getCommandID() != ack2->getCommandID()) {
- return FALSE;
- }
- return TRUE;
- }
-
- // They are the same type and from the same player.
- // Time for the type specific stuff.
- if (msg1->getNetCommandType() == NETCOMMANDTYPE_ACKBOTH) {
- NetAckBothCommandMsg *ack1 = (NetAckBothCommandMsg *)msg1;
- NetAckBothCommandMsg *ack2 = (NetAckBothCommandMsg *)msg2;
-
- if (ack1->getOriginalPlayerID() != ack2->getOriginalPlayerID()) {
- return FALSE;
- }
-
- if (ack1->getCommandID() != ack2->getCommandID()) {
- return FALSE;
- }
- return TRUE;
- }
-
- return FALSE;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandMsg.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NetCommandMsg.cpp
deleted file mode 100644
index e2fd54682df..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandMsg.cpp
+++ /dev/null
@@ -1,1066 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/NetCommandMsg.h"
-#include "Common/GameState.h"
-#include "Common/PlayerList.h"
-#include "Common/Player.h"
-
-/**
- * Base constructor
- */
-NetCommandMsg::NetCommandMsg()
-{
- //Added By Sadullah Nader
- //Initializations inserted
- m_executionFrame = 0;
- m_id = 0;
- m_playerID = 0;
-
- //
- m_timestamp = 0;
- m_referenceCount = 1; // start this off as 1. This means that an "attach" is implied by creating a NetCommandMsg object.
- m_commandType = NETCOMMANDTYPE_UNKNOWN;
-}
-
-/**
- * Destructor
- */
-NetCommandMsg::~NetCommandMsg() {
-}
-
-/**
- * Adds one to the reference count.
- */
-void NetCommandMsg::attach() {
- ++m_referenceCount;
-}
-
-/**
- * Subtracts one from the reference count. If the reference count is 0, the this object is destroyed.
- */
-void NetCommandMsg::detach() {
- --m_referenceCount;
- if (m_referenceCount == 0) {
- deleteInstance(this);
- return;
- }
- DEBUG_ASSERTCRASH(m_referenceCount > 0, ("Invalid reference count for NetCommandMsg")); // Just to make sure...
- if (m_referenceCount < 0) {
- deleteInstance(this);
- }
-}
-
-/**
- * Returns the value by which this type of message should be sorted.
- */
-Int NetCommandMsg::getSortNumber() {
- return m_id;
-}
-
-//-------------------------------
-// NetGameCommandMsg
-//-------------------------------
-
-/**
- * Constructor with no argument, sets everything to default values.
- */
-NetGameCommandMsg::NetGameCommandMsg() : NetCommandMsg() {
- //Added By Sadullah Nader
- //Initializations inserted
- m_argSize = 0;
- m_numArgs = 0;
- //
-
- m_type = (GameMessage::Type)0;
- m_commandType = NETCOMMANDTYPE_GAMECOMMAND;
- m_argList = NULL;
- m_argTail = NULL;
-}
-
-/**
- * Constructor with a GameMessage argument. Sets member variables appropriately for this GameMessage.
- * Also copies all the arguments.
- */
-NetGameCommandMsg::NetGameCommandMsg(GameMessage *msg) : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_GAMECOMMAND;
-
- m_type = msg->getType();
- Int count = msg->getArgumentCount();
- for (Int i = 0; i < count; ++i) {
- addArgument(msg->getArgumentDataType(i), *(msg->getArgument(i)));
- }
-}
-
-/**
- * Destructor
- */
-NetGameCommandMsg::~NetGameCommandMsg() {
- GameMessageArgument *arg = m_argList;
- while (arg != NULL) {
- m_argList = m_argList->m_next;
- deleteInstance(arg);
- arg = m_argList;
- }
-}
-
-/**
- * Add an argument to this command.
- */
-void NetGameCommandMsg::addArgument(const GameMessageArgumentDataType type, GameMessageArgumentType arg)
-{
- if (m_argTail == NULL) {
- m_argList = newInstance(GameMessageArgument);
- m_argTail = m_argList;
- m_argList->m_data = arg;
- m_argList->m_type = type;
- m_argList->m_next = NULL;
- return;
- }
-
- GameMessageArgument *newArg = newInstance(GameMessageArgument);
- newArg->m_data = arg;
- newArg->m_type = type;
- newArg->m_next = NULL;
- m_argTail->m_next = newArg;
- m_argTail = newArg;
-}
-
-// here's where we figure out which slot corresponds to which player
-static Int indexFromMask(UnsignedInt mask)
-{
- Player *player = NULL;
- Int i;
-
- for( i = 0; i < MAX_PLAYER_COUNT; i++ )
- {
- player = ThePlayerList->getNthPlayer( i );
- if( player && player->getPlayerMask() == mask )
- return i;
- }
-
- return -1;
-}
-
-/**
- * Construct a new GameMessage object from the data in this object.
- */
-GameMessage *NetGameCommandMsg::constructGameMessage()
-{
- GameMessage *retval = newInstance(GameMessage)(m_type);
-
- AsciiString name;
- name.format("player%d", getPlayerID());
- retval->friend_setPlayerIndex( ThePlayerList->findPlayerWithNameKey(TheNameKeyGenerator->nameToKey(name))->getPlayerIndex());
-
- GameMessageArgument *arg = m_argList;
- while (arg != NULL) {
-
- switch (arg->m_type) {
-
- case ARGUMENTDATATYPE_INTEGER:
- retval->appendIntegerArgument(arg->m_data.integer);
- break;
- case ARGUMENTDATATYPE_REAL:
- retval->appendRealArgument(arg->m_data.real);
- break;
- case ARGUMENTDATATYPE_BOOLEAN:
- retval->appendBooleanArgument(arg->m_data.boolean);
- break;
- case ARGUMENTDATATYPE_OBJECTID:
- retval->appendObjectIDArgument(arg->m_data.objectID);
- break;
- case ARGUMENTDATATYPE_DRAWABLEID:
- retval->appendDrawableIDArgument(arg->m_data.drawableID);
- break;
- case ARGUMENTDATATYPE_TEAMID:
- retval->appendTeamIDArgument(arg->m_data.teamID);
- break;
- case ARGUMENTDATATYPE_LOCATION:
- retval->appendLocationArgument(arg->m_data.location);
- break;
- case ARGUMENTDATATYPE_PIXEL:
- retval->appendPixelArgument(arg->m_data.pixel);
- break;
- case ARGUMENTDATATYPE_PIXELREGION:
- retval->appendPixelRegionArgument(arg->m_data.pixelRegion);
- break;
- case ARGUMENTDATATYPE_TIMESTAMP:
- retval->appendTimestampArgument(arg->m_data.timestamp);
- break;
- case ARGUMENTDATATYPE_WIDECHAR:
- retval->appendWideCharArgument(arg->m_data.wChar);
- break;
-
- }
-
- arg = arg->m_next;
- }
- return retval;
-}
-
-/**
- * Sets the type of game message
- */
-void NetGameCommandMsg::setGameMessageType(GameMessage::Type type) {
- m_type = type;
-}
-
-//-------------------------
-// NetAckBothCommandMsg
-//-------------------------
-/**
- * Constructor. Sets the member variables according to the given message.
- */
-NetAckBothCommandMsg::NetAckBothCommandMsg(NetCommandMsg *msg) : NetCommandMsg() {
- m_commandID = msg->getID();
- m_commandType = NETCOMMANDTYPE_ACKBOTH;
- m_originalPlayerID = msg->getPlayerID();
-}
-
-/**
- * Constructor. Sets the member variables to default values.
- */
-NetAckBothCommandMsg::NetAckBothCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_ACKBOTH;
-}
-
-/**
- * Destructor.
- */
-NetAckBothCommandMsg::~NetAckBothCommandMsg() {
-}
-
-/**
- * Returns the command ID of the command being ack'd.
- */
-UnsignedShort NetAckBothCommandMsg::getCommandID() {
- return m_commandID;
-}
-
-/**
- * Set the command ID of the command being ack'd.
- */
-void NetAckBothCommandMsg::setCommandID(UnsignedShort commandID) {
- m_commandID = commandID;
-}
-
-/**
- * Get the player id of the player who originally sent the command.
- */
-UnsignedByte NetAckBothCommandMsg::getOriginalPlayerID() {
- return m_originalPlayerID;
-}
-
-/**
- * Set the player id of the player who originally sent the command.
- */
-void NetAckBothCommandMsg::setOriginalPlayerID(UnsignedByte originalPlayerID) {
- m_originalPlayerID = originalPlayerID;
-}
-
-Int NetAckBothCommandMsg::getSortNumber() {
- return m_commandID;
-}
-
-//-------------------------
-// NetAckStage1CommandMsg
-//-------------------------
-/**
- * Constructor. Sets the member variables according to the given message.
- */
-NetAckStage1CommandMsg::NetAckStage1CommandMsg(NetCommandMsg *msg) : NetCommandMsg() {
- m_commandID = msg->getID();
- m_commandType = NETCOMMANDTYPE_ACKSTAGE1;
- m_originalPlayerID = msg->getPlayerID();
-}
-
-/**
- * Constructor. Sets the member variables to default values.
- */
-NetAckStage1CommandMsg::NetAckStage1CommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_ACKSTAGE1;
-}
-
-/**
- * Destructor.
- */
-NetAckStage1CommandMsg::~NetAckStage1CommandMsg() {
-}
-
-/**
- * Returns the command ID of the command being ack'd.
- */
-UnsignedShort NetAckStage1CommandMsg::getCommandID() {
- return m_commandID;
-}
-
-/**
- * Set the command ID of the command being ack'd.
- */
-void NetAckStage1CommandMsg::setCommandID(UnsignedShort commandID) {
- m_commandID = commandID;
-}
-
-/**
- * Get the player id of the player who originally sent the command.
- */
-UnsignedByte NetAckStage1CommandMsg::getOriginalPlayerID() {
- return m_originalPlayerID;
-}
-
-/**
- * Set the player id of the player who originally sent the command.
- */
-void NetAckStage1CommandMsg::setOriginalPlayerID(UnsignedByte originalPlayerID) {
- m_originalPlayerID = originalPlayerID;
-}
-
-Int NetAckStage1CommandMsg::getSortNumber() {
- return m_commandID;
-}
-
-//-------------------------
-// NetAckStage2CommandMsg
-//-------------------------
-/**
- * Constructor. Sets the member variables according to the given message.
- */
-NetAckStage2CommandMsg::NetAckStage2CommandMsg(NetCommandMsg *msg) : NetCommandMsg() {
- m_commandID = msg->getID();
- m_commandType = NETCOMMANDTYPE_ACKSTAGE2;
- m_originalPlayerID = msg->getPlayerID();
-}
-
-/**
- * Constructor. Sets the member variables to default values.
- */
-NetAckStage2CommandMsg::NetAckStage2CommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_ACKSTAGE2;
-}
-
-/**
- * Destructor.
- */
-NetAckStage2CommandMsg::~NetAckStage2CommandMsg() {
-}
-
-/**
- * Returns the command ID of the command being ack'd.
- */
-UnsignedShort NetAckStage2CommandMsg::getCommandID() {
- return m_commandID;
-}
-
-/**
- * Set the command ID of the command being ack'd.
- */
-void NetAckStage2CommandMsg::setCommandID(UnsignedShort commandID) {
- m_commandID = commandID;
-}
-
-/**
- * Get the player id of the player who originally sent the command.
- */
-UnsignedByte NetAckStage2CommandMsg::getOriginalPlayerID() {
- return m_originalPlayerID;
-}
-
-/**
- * Set the player id of the player who originally sent the command.
- */
-void NetAckStage2CommandMsg::setOriginalPlayerID(UnsignedByte originalPlayerID) {
- m_originalPlayerID = originalPlayerID;
-}
-
-Int NetAckStage2CommandMsg::getSortNumber() {
- return m_commandID;
-}
-
-//-------------------------
-// NetFrameCommandMsg
-//-------------------------
-/**
- * Constructor.
- */
-NetFrameCommandMsg::NetFrameCommandMsg() : NetCommandMsg() {
- m_commandCount = 0;
- m_commandType = NETCOMMANDTYPE_FRAMEINFO;
-}
-
-/**
- * Destructor
- */
-NetFrameCommandMsg::~NetFrameCommandMsg() {
-}
-
-/**
- * Set the command count of this frame.
- */
-void NetFrameCommandMsg::setCommandCount(UnsignedShort commandCount) {
- m_commandCount = commandCount;
-}
-
-/**
- * Return the command count of this frame.
- */
-UnsignedShort NetFrameCommandMsg::getCommandCount() {
- return m_commandCount;
-}
-
-//-------------------------
-// NetPlayerLeaveCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetPlayerLeaveCommandMsg::NetPlayerLeaveCommandMsg() : NetCommandMsg() {
- m_leavingPlayerID = 0;
- m_commandType = NETCOMMANDTYPE_PLAYERLEAVE;
-}
-
-/**
- * Destructor
- */
-NetPlayerLeaveCommandMsg::~NetPlayerLeaveCommandMsg() {
-}
-
-/**
- * Get the id of the player leaving the game.
- */
-UnsignedByte NetPlayerLeaveCommandMsg::getLeavingPlayerID() {
- return m_leavingPlayerID;
-}
-
-/**
- * Set the id of the player leaving the game.
- */
-void NetPlayerLeaveCommandMsg::setLeavingPlayerID(UnsignedByte id) {
- m_leavingPlayerID = id;
-}
-
-//-------------------------
-// NetRunAheadMetricsCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetRunAheadMetricsCommandMsg::NetRunAheadMetricsCommandMsg() : NetCommandMsg() {
- m_averageLatency = 0.0;
- m_averageFps = 0;
- m_commandType = NETCOMMANDTYPE_RUNAHEADMETRICS;
-}
-
-/**
- * Destructor
- */
-NetRunAheadMetricsCommandMsg::~NetRunAheadMetricsCommandMsg() {
-}
-
-/**
- * set the average latency
- */
-void NetRunAheadMetricsCommandMsg::setAverageLatency(Real avgLat) {
- m_averageLatency = avgLat;
-}
-
-/**
- * get the average latency
- */
-Real NetRunAheadMetricsCommandMsg::getAverageLatency() {
- return m_averageLatency;
-}
-
-/**
- * set the average fps
- */
-void NetRunAheadMetricsCommandMsg::setAverageFps(Int fps) {
- m_averageFps = fps;
-}
-
-/**
- * get the average fps
- */
-Int NetRunAheadMetricsCommandMsg::getAverageFps() {
- return m_averageFps;
-}
-
-//-------------------------
-// NetRunAheadCommandMsg
-//-------------------------
-NetRunAheadCommandMsg::NetRunAheadCommandMsg() : NetCommandMsg() {
- m_runAhead = min(max(20, MIN_RUNAHEAD), MAX_FRAMES_AHEAD/2);
- m_frameRate = 30;
- m_commandType = NETCOMMANDTYPE_RUNAHEAD;
-}
-
-NetRunAheadCommandMsg::~NetRunAheadCommandMsg() {
-}
-
-UnsignedShort NetRunAheadCommandMsg::getRunAhead() {
- return m_runAhead;
-}
-
-void NetRunAheadCommandMsg::setRunAhead(UnsignedShort runAhead) {
- m_runAhead = runAhead;
-}
-
-UnsignedByte NetRunAheadCommandMsg::getFrameRate() {
- return m_frameRate;
-}
-
-void NetRunAheadCommandMsg::setFrameRate(UnsignedByte frameRate) {
- m_frameRate = frameRate;
-}
-
-//-------------------------
-// NetDestroyPlayerCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetDestroyPlayerCommandMsg::NetDestroyPlayerCommandMsg() : NetCommandMsg()
-{
- m_playerIndex = 0;
- m_commandType = NETCOMMANDTYPE_DESTROYPLAYER;
-}
-
-/**
- * Destructor
- */
-NetDestroyPlayerCommandMsg::~NetDestroyPlayerCommandMsg()
-{
-}
-
-/**
- * set the CRC
- */
-void NetDestroyPlayerCommandMsg::setPlayerIndex( UnsignedInt playerIndex )
-{
- m_playerIndex = playerIndex;
-}
-
-/**
- * get the average CRC
- */
-UnsignedInt NetDestroyPlayerCommandMsg::getPlayerIndex( void )
-{
- return m_playerIndex;
-}
-
-//-------------------------
-// NetKeepAliveCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetKeepAliveCommandMsg::NetKeepAliveCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_KEEPALIVE;
-}
-
-NetKeepAliveCommandMsg::~NetKeepAliveCommandMsg() {
-}
-
-//-------------------------
-// NetDisconnectKeepAliveCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetDisconnectKeepAliveCommandMsg::NetDisconnectKeepAliveCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_DISCONNECTKEEPALIVE;
-}
-
-NetDisconnectKeepAliveCommandMsg::~NetDisconnectKeepAliveCommandMsg() {
-}
-
-//-------------------------
-// NetDisconnectPlayerCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetDisconnectPlayerCommandMsg::NetDisconnectPlayerCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_DISCONNECTPLAYER;
- m_disconnectSlot = 0;
-}
-
-/**
- * Destructor
- */
-NetDisconnectPlayerCommandMsg::~NetDisconnectPlayerCommandMsg() {
-}
-
-/**
- * Returns the disconnecting slot number
- */
-UnsignedByte NetDisconnectPlayerCommandMsg::getDisconnectSlot() {
- return m_disconnectSlot;
-}
-
-/**
- * Sets the disconnecting slot number
- */
-void NetDisconnectPlayerCommandMsg::setDisconnectSlot(UnsignedByte slot) {
- m_disconnectSlot = slot;
-}
-
-/**
- * Sets the disconnect frame
- */
-void NetDisconnectPlayerCommandMsg::setDisconnectFrame(UnsignedInt frame) {
- m_disconnectFrame = frame;
-}
-
-/**
- * returns the disconnect frame
- */
-UnsignedInt NetDisconnectPlayerCommandMsg::getDisconnectFrame() {
- return m_disconnectFrame;
-}
-
-//-------------------------
-// NetPacketRouterQueryCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetPacketRouterQueryCommandMsg::NetPacketRouterQueryCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_PACKETROUTERQUERY;
-}
-
-/**
- * Destructor
- */
-NetPacketRouterQueryCommandMsg::~NetPacketRouterQueryCommandMsg() {
-}
-
-//-------------------------
-// NetPacketRouterAckCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetPacketRouterAckCommandMsg::NetPacketRouterAckCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_PACKETROUTERACK;
-}
-
-/**
- * Destructor
- */
-NetPacketRouterAckCommandMsg::~NetPacketRouterAckCommandMsg() {
-}
-
-//-------------------------
-// NetDisconnectChatCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetDisconnectChatCommandMsg::NetDisconnectChatCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_DISCONNECTCHAT;
-}
-
-/**
- * Destructor
- */
-NetDisconnectChatCommandMsg::~NetDisconnectChatCommandMsg() {
-}
-
-/**
- * Set the chat text for this message.
- */
-void NetDisconnectChatCommandMsg::setText(UnicodeString text) {
- m_text = text;
-}
-
-/**
- * Get the chat text for this message.
- */
-UnicodeString NetDisconnectChatCommandMsg::getText() {
- return m_text;
-}
-
-//-------------------------
-// NetChatCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetChatCommandMsg::NetChatCommandMsg() : NetCommandMsg()
-{
- m_commandType = NETCOMMANDTYPE_CHAT;
- //added by Sadullah Nader
- //Initializations inserted
- m_playerMask = 0;
- //
-}
-
-/**
- * Destructor
- */
-NetChatCommandMsg::~NetChatCommandMsg()
-{
-}
-
-/**
- * Set the chat text for this message.
- */
-void NetChatCommandMsg::setText(UnicodeString text)
-{
- m_text = text;
-}
-
-/**
- * Get the chat text for this message.
- */
-UnicodeString NetChatCommandMsg::getText()
-{
- return m_text;
-}
-
-/**
- * Get the bitmask of chat recipients from this message.
- */
-Int NetChatCommandMsg::getPlayerMask()
-{
- return m_playerMask;
-}
-
-/**
- * Set a bitmask of chat recipients in this message.
- */
-void NetChatCommandMsg::setPlayerMask( Int playerMask )
-{
- m_playerMask = playerMask;
-}
-
-//-------------------------
-// NetDisconnectVoteCommandMsg
-//-------------------------
-/**
- * Constructor
- */
-NetDisconnectVoteCommandMsg::NetDisconnectVoteCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_DISCONNECTVOTE;
- m_slot = 0;
-}
-
-/**
- * Destructor
- */
-NetDisconnectVoteCommandMsg::~NetDisconnectVoteCommandMsg() {
-}
-
-/**
- * Set the slot that is being voted for.
- */
-void NetDisconnectVoteCommandMsg::setSlot(UnsignedByte slot) {
- m_slot = slot;
-}
-
-/**
- * Get the slot that is being voted for.
- */
-UnsignedByte NetDisconnectVoteCommandMsg::getSlot() {
- return m_slot;
-}
-
-/**
- * Get the vote frame.
- */
-UnsignedInt NetDisconnectVoteCommandMsg::getVoteFrame() {
- return m_voteFrame;
-}
-
-/**
- * Set the vote frame.
- */
-void NetDisconnectVoteCommandMsg::setVoteFrame(UnsignedInt voteFrame) {
- m_voteFrame = voteFrame;
-}
-
-//-------------------------
-// NetProgressCommandMsg
-//-------------------------
-NetProgressCommandMsg::NetProgressCommandMsg( void ) : NetCommandMsg()
-{
- m_commandType = NETCOMMANDTYPE_PROGRESS;
- m_percent = 0;
-}
-
-NetProgressCommandMsg::~NetProgressCommandMsg( void ) {}
-
-UnsignedByte NetProgressCommandMsg::getPercentage()
-{
- return m_percent;
-}
-
-void NetProgressCommandMsg::setPercentage( UnsignedByte percent )
-{
- m_percent = percent;
-}
-
-//-------------------------
-// NetWrapperCommandMsg
-//-------------------------
-NetWrapperCommandMsg::NetWrapperCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_WRAPPER;
- m_numChunks = 0;
- m_data = NULL;
- m_totalDataLength = 0;
- m_chunkNumber = 0;
- m_dataLength = 0;
- m_dataOffset = 0;
- m_wrappedCommandID = 0;
-}
-
-NetWrapperCommandMsg::~NetWrapperCommandMsg() {
- delete m_data;
- m_data = NULL;
-}
-
-UnsignedByte * NetWrapperCommandMsg::getData() {
- return m_data;
-}
-
-void NetWrapperCommandMsg::setData(UnsignedByte *data, UnsignedInt dataLength)
-{
- delete m_data;
- m_data = NEW UnsignedByte[dataLength]; // pool[]ify
- memcpy(m_data, data, dataLength);
- m_dataLength = dataLength;
-}
-
-UnsignedInt NetWrapperCommandMsg::getDataLength() {
- return m_dataLength;
-}
-
-UnsignedInt NetWrapperCommandMsg::getDataOffset() {
- return m_dataOffset;
-}
-
-void NetWrapperCommandMsg::setDataOffset(UnsignedInt offset) {
- m_dataOffset = offset;
-}
-
-UnsignedInt NetWrapperCommandMsg::getChunkNumber() {
- return m_chunkNumber;
-}
-
-void NetWrapperCommandMsg::setChunkNumber(UnsignedInt chunkNumber) {
- m_chunkNumber = chunkNumber;
-}
-
-UnsignedInt NetWrapperCommandMsg::getNumChunks() {
- return m_numChunks;
-}
-
-void NetWrapperCommandMsg::setNumChunks(UnsignedInt numChunks) {
- m_numChunks = numChunks;
-}
-
-UnsignedInt NetWrapperCommandMsg::getTotalDataLength() {
- return m_totalDataLength;
-}
-
-void NetWrapperCommandMsg::setTotalDataLength(UnsignedInt totalDataLength) {
- m_totalDataLength = totalDataLength;
-}
-
-UnsignedShort NetWrapperCommandMsg::getWrappedCommandID() {
- return m_wrappedCommandID;
-}
-
-void NetWrapperCommandMsg::setWrappedCommandID(UnsignedShort wrappedCommandID) {
- m_wrappedCommandID = wrappedCommandID;
-}
-
-//-------------------------
-// NetFileCommandMsg
-//-------------------------
-NetFileCommandMsg::NetFileCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_FILE;
- m_data = NULL;
- m_portableFilename.clear();
- m_dataLength = 0;
-}
-
-NetFileCommandMsg::~NetFileCommandMsg() {
- delete[] m_data;
- m_data = NULL;
-}
-
-AsciiString NetFileCommandMsg::getRealFilename()
-{
- return TheGameState->portableMapPathToRealMapPath(m_portableFilename);
-}
-
-void NetFileCommandMsg::setRealFilename(AsciiString filename)
-{
- m_portableFilename = TheGameState->realMapPathToPortableMapPath(filename);
-}
-
-UnsignedInt NetFileCommandMsg::getFileLength() {
- return m_dataLength;
-}
-
-UnsignedByte * NetFileCommandMsg::getFileData() {
- return m_data;
-}
-
-void NetFileCommandMsg::setFileData(UnsignedByte *data, UnsignedInt dataLength)
-{
- m_dataLength = dataLength;
- m_data = NEW UnsignedByte[dataLength]; // pool[]ify
- memcpy(m_data, data, dataLength);
-}
-
-//-------------------------
-// NetFileAnnounceCommandMsg
-//-------------------------
-NetFileAnnounceCommandMsg::NetFileAnnounceCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_FILEANNOUNCE;
- m_portableFilename.clear();
- m_fileID = 0;
- m_playerMask = 0;
-}
-
-NetFileAnnounceCommandMsg::~NetFileAnnounceCommandMsg() {
-}
-
-AsciiString NetFileAnnounceCommandMsg::getRealFilename()
-{
- return TheGameState->portableMapPathToRealMapPath(m_portableFilename);
-}
-
-void NetFileAnnounceCommandMsg::setRealFilename(AsciiString filename)
-{
- m_portableFilename = TheGameState->realMapPathToPortableMapPath(filename);
-}
-
-UnsignedShort NetFileAnnounceCommandMsg::getFileID() {
- return m_fileID;
-}
-
-void NetFileAnnounceCommandMsg::setFileID(UnsignedShort fileID) {
- m_fileID = fileID;
-}
-
-UnsignedByte NetFileAnnounceCommandMsg::getPlayerMask(void) {
- return m_playerMask;
-}
-
-void NetFileAnnounceCommandMsg::setPlayerMask(UnsignedByte playerMask) {
- m_playerMask = playerMask;
-}
-
-
-//-------------------------
-// NetFileProgressCommandMsg
-//-------------------------
-NetFileProgressCommandMsg::NetFileProgressCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_FILEPROGRESS;
- m_fileID = 0;
- m_progress = 0;
-}
-
-NetFileProgressCommandMsg::~NetFileProgressCommandMsg() {
-}
-
-UnsignedShort NetFileProgressCommandMsg::getFileID() {
- return m_fileID;
-}
-
-void NetFileProgressCommandMsg::setFileID(UnsignedShort val) {
- m_fileID = val;
-}
-
-Int NetFileProgressCommandMsg::getProgress() {
- return m_progress;
-}
-
-void NetFileProgressCommandMsg::setProgress(Int val) {
- m_progress = val;
-}
-
-//-------------------------
-// NetDisconnectFrameCommandMsg
-//-------------------------
-NetDisconnectFrameCommandMsg::NetDisconnectFrameCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_DISCONNECTFRAME;
- m_disconnectFrame = 0;
-}
-
-NetDisconnectFrameCommandMsg::~NetDisconnectFrameCommandMsg() {
-}
-
-UnsignedInt NetDisconnectFrameCommandMsg::getDisconnectFrame() {
- return m_disconnectFrame;
-}
-
-void NetDisconnectFrameCommandMsg::setDisconnectFrame(UnsignedInt disconnectFrame) {
- m_disconnectFrame = disconnectFrame;
-}
-
-//-------------------------
-// NetDisconnectScreenOffCommandMsg
-//-------------------------
-NetDisconnectScreenOffCommandMsg::NetDisconnectScreenOffCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_DISCONNECTSCREENOFF;
- m_newFrame = 0;
-}
-
-NetDisconnectScreenOffCommandMsg::~NetDisconnectScreenOffCommandMsg() {
-}
-
-UnsignedInt NetDisconnectScreenOffCommandMsg::getNewFrame() {
- return m_newFrame;
-}
-
-void NetDisconnectScreenOffCommandMsg::setNewFrame(UnsignedInt newFrame) {
- m_newFrame = newFrame;
-}
-
-//-------------------------
-// NetFrameResendRequestCommandMsg
-//-------------------------
-NetFrameResendRequestCommandMsg::NetFrameResendRequestCommandMsg() : NetCommandMsg() {
- m_commandType = NETCOMMANDTYPE_FRAMERESENDREQUEST;
- m_frameToResend = 0;
-}
-
-NetFrameResendRequestCommandMsg::~NetFrameResendRequestCommandMsg() {
-}
-
-UnsignedInt NetFrameResendRequestCommandMsg::getFrameToResend() {
- return m_frameToResend;
-}
-
-void NetFrameResendRequestCommandMsg::setFrameToResend(UnsignedInt frame) {
- m_frameToResend = frame;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandRef.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NetCommandRef.cpp
deleted file mode 100644
index 66b004c09f4..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandRef.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/NetCommandRef.h"
-
-#ifdef DEBUG_NETCOMMANDREF
-static UnsignedInt refNum = 0;
-#endif
-
-/**
- * Constructor. Attach to the given network command.
- */
-#ifdef DEBUG_NETCOMMANDREF
-NetCommandRef::NetCommandRef(NetCommandMsg *msg, char *filename, int line)
-#else
-NetCommandRef::NetCommandRef(NetCommandMsg *msg)
-#endif
-{
- m_msg = msg;
- m_next = NULL;
- m_prev = NULL;
- m_msg->attach();
- m_timeLastSent = -1;
-
-#ifdef DEBUG_NETCOMMANDREF
- m_id = ++refNum;
- DEBUG_LOG(("NetCommandRef %d allocated in file %s line %d", m_id, filename, line));
-#endif
-}
-
-/**
- * Destructor. Detach from the network command.
- */
-NetCommandRef::~NetCommandRef()
-{
- if (m_msg != NULL)
- {
- m_msg->detach();
- }
- DEBUG_ASSERTCRASH(m_next == NULL, ("NetCommandRef::~NetCommandRef - m_next != NULL"));
- DEBUG_ASSERTCRASH(m_prev == NULL, ("NetCommandRef::~NetCommandRef - m_prev != NULL"));
-
-#ifdef DEBUG_NETCOMMANDREF
- DEBUG_LOG(("NetCommandRef %d deleted", m_id));
-#endif
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandWrapperList.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NetCommandWrapperList.cpp
deleted file mode 100644
index 99c297c6168..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NetCommandWrapperList.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-////// NetCommandWrapperList.cpp ////////////////////////////////
-// Bryan Cleveland
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/NetCommandWrapperList.h"
-#include "GameNetwork/NetPacket.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-////// NetCommandWrapperListNode ///////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-NetCommandWrapperListNode::NetCommandWrapperListNode(NetWrapperCommandMsg *msg)
-{
- //Added By Sadullah Nader
- //Initializations inserted
- m_next = NULL;
-
- //
-
- m_numChunks = msg->getNumChunks();
- m_chunksPresent = NEW Bool[m_numChunks]; // pool[]ify
- m_numChunksPresent = 0;
-
- for (UnsignedInt i = 0; i < m_numChunks; ++i) {
- m_chunksPresent[i] = FALSE;
- }
-
- m_dataLength = msg->getTotalDataLength();
- m_data = NEW UnsignedByte[m_dataLength]; // pool[]ify
-
- m_commandID = msg->getWrappedCommandID();
-}
-
-NetCommandWrapperListNode::~NetCommandWrapperListNode() {
- delete[] m_chunksPresent;
- m_chunksPresent = NULL;
-
- delete[] m_data;
- m_data = NULL;
-}
-
-Bool NetCommandWrapperListNode::isComplete() {
- return m_numChunksPresent == m_numChunks;
-}
-
-Int NetCommandWrapperListNode::getPercentComplete(void) {
- if (isComplete())
- return 100;
- else
- return min(99, REAL_TO_INT( ((Real)m_numChunksPresent)/((Real)m_numChunks)*100.0f ));
-}
-
-UnsignedShort NetCommandWrapperListNode::getCommandID() {
- return m_commandID;
-}
-
-UnsignedInt NetCommandWrapperListNode::getRawDataLength() {
- return m_dataLength;
-}
-
-void NetCommandWrapperListNode::copyChunkData(NetWrapperCommandMsg *msg) {
- if (msg == NULL) {
- DEBUG_CRASH(("Trying to copy data from a non-existent wrapper command message"));
- return;
- }
-
- DEBUG_ASSERTCRASH(msg->getChunkNumber() < m_numChunks, ("MunkeeChunk %d of %d",
- msg->getChunkNumber(), m_numChunks));
- if (msg->getChunkNumber() >= m_numChunks)
- return;
-
- DEBUG_LOG(("NetCommandWrapperListNode::copyChunkData() - copying chunk %d",
- msg->getChunkNumber()));
-
- if (m_chunksPresent[msg->getChunkNumber()] == TRUE) {
- // we already received this chunk, no need to recopy it.
- return;
- }
-
- m_chunksPresent[msg->getChunkNumber()] = TRUE;
- UnsignedInt offset = msg->getDataOffset();
- memcpy(m_data + offset, msg->getData(), msg->getDataLength());
- ++m_numChunksPresent;
-}
-
-UnsignedByte * NetCommandWrapperListNode::getRawData() {
- return m_data;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-////// NetCommandWrapperList ///////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-NetCommandWrapperList::NetCommandWrapperList() {
- m_list = NULL;
-}
-
-NetCommandWrapperList::~NetCommandWrapperList() {
- NetCommandWrapperListNode *temp;
- while (m_list != NULL) {
- temp = m_list->m_next;
- deleteInstance(m_list);
- m_list = temp;
- }
-}
-
-void NetCommandWrapperList::init() {
- m_list = NULL;
-}
-
-void NetCommandWrapperList::reset() {
- NetCommandWrapperListNode *temp;
- while (m_list != NULL) {
- temp = m_list->m_next;
- deleteInstance(m_list);
- m_list = temp;
- }
-}
-
-Int NetCommandWrapperList::getPercentComplete(UnsignedShort wrappedCommandID)
-{
- NetCommandWrapperListNode *temp = m_list;
-
- while ((temp != NULL) && (temp->getCommandID() != wrappedCommandID)) {
- temp = temp->m_next;
- }
-
- if (!temp)
- return 0;
-
- return temp->getPercentComplete();
-}
-
-void NetCommandWrapperList::processWrapper(NetCommandRef *ref) {
- NetCommandWrapperListNode *temp = m_list;
- NetWrapperCommandMsg *msg = (NetWrapperCommandMsg *)(ref->getCommand());
-
- while ((temp != NULL) && (temp->getCommandID() != msg->getWrappedCommandID())) {
- temp = temp->m_next;
- }
-
- if (temp == NULL) {
- temp = newInstance(NetCommandWrapperListNode)(msg);
- temp->m_next = m_list;
- m_list = temp;
- }
-
- temp->copyChunkData(msg);
-}
-
-NetCommandList * NetCommandWrapperList::getReadyCommands()
-{
- NetCommandList *retlist = newInstance(NetCommandList);
- retlist->init();
-
- NetCommandWrapperListNode *temp = m_list;
- NetCommandWrapperListNode *next = NULL;
-
- while (temp != NULL) {
- next = temp->m_next;
- if (temp->isComplete()) {
- NetCommandRef *msg = NetPacket::ConstructNetCommandMsgFromRawData(temp->getRawData(), temp->getRawDataLength());
- NetCommandRef *ret = retlist->addMessage(msg->getCommand());
- ret->setRelay(msg->getRelay());
-
- deleteInstance(msg);
- msg = NULL;
-
- removeFromList(temp);
- temp = NULL;
- }
- temp = next;
- }
-
- return retlist;
-}
-
-void NetCommandWrapperList::removeFromList(NetCommandWrapperListNode *node) {
- if (node == NULL) {
- return;
- }
-
- NetCommandWrapperListNode *temp = m_list;
- NetCommandWrapperListNode *prev = NULL;
-
- while ((temp != NULL) && (temp->getCommandID() != node->getCommandID())) {
- prev = temp;
- temp = temp->m_next;
- }
-
- if (temp == NULL) {
- return;
- }
-
- if (prev == NULL) {
- m_list = temp->m_next;
- deleteInstance(temp);
- temp = NULL;
- } else {
- prev->m_next = temp->m_next;
- deleteInstance(temp);
- temp = NULL;
- }
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NetMessageStream.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NetMessageStream.cpp
deleted file mode 100644
index 8aa55eafe34..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NetMessageStream.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in 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!"));
- 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", 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!", 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", 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; igetArgumentCount(); ++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;
-}
-
-//====================================================================================
-
-*/
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NetPacket.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NetPacket.cpp
deleted file mode 100644
index 56f4bed686e..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NetPacket.cpp
+++ /dev/null
@@ -1,5964 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-////////// NetPacket.cpp ///////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/NetPacket.h"
-#include "GameNetwork/NetCommandMsg.h"
-#include "GameNetwork/NetworkDefs.h"
-#include "GameNetwork/networkutil.h"
-#include "GameNetwork/GameMessageParser.h"
-
-// TheSuperHackers @refactor BobTista 10/06/2025 Extract magic character literals into named constants for improved readability
-typedef UnsignedByte NetPacketFieldType;
-
-namespace NetPacketFieldTypes {
- constexpr const NetPacketFieldType CommandType = 'T'; // NetCommandType field
- constexpr const NetPacketFieldType Relay = 'R'; // Relay field
- constexpr const NetPacketFieldType PlayerId = 'P'; // Player ID field
- constexpr const NetPacketFieldType CommandId = 'C'; // Command ID field
- constexpr const NetPacketFieldType Frame = 'F'; // Frame field
- constexpr const NetPacketFieldType Data = 'D'; // Data payload field
-}
-
-// This function assumes that all of the fields are either of default value or are
-// present in the raw data.
-NetCommandRef * NetPacket::ConstructNetCommandMsgFromRawData(UnsignedByte *data, UnsignedShort dataLength) {
- NetCommandType commandType = NETCOMMANDTYPE_GAMECOMMAND;
- UnsignedShort commandID = 0;
- UnsignedInt frame = 0;
- UnsignedByte playerID = 0;
- UnsignedByte relay = 0;
-
- Int offset = 0;
- NetCommandRef *ref = NULL;
- NetCommandMsg *msg = NULL;
-
- while (offset < (Int)dataLength) {
-
- switch (data[offset]) {
-
- case NetPacketFieldTypes::CommandType:
- ++offset;
- memcpy(&commandType, data + offset, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
- break;
-
- case NetPacketFieldTypes::Relay:
- ++offset;
- memcpy(&relay, data + offset, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
- break;
-
- case NetPacketFieldTypes::PlayerId:
- ++offset;
- memcpy(&playerID, data + offset, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
- break;
-
- case NetPacketFieldTypes::CommandId:
- ++offset;
- memcpy(&commandID, data + offset, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
- break;
-
- case NetPacketFieldTypes::Frame:
- ++offset;
- memcpy(&frame, data + offset, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
- break;
-
- case NetPacketFieldTypes::Data:
- ++offset;
-
- switch (commandType) {
-
- case NETCOMMANDTYPE_GAMECOMMAND:
- msg = readGameMessage(data, offset);
- break;
- case NETCOMMANDTYPE_ACKBOTH:
- msg = readAckBothMessage(data, offset);
- break;
- case NETCOMMANDTYPE_ACKSTAGE1:
- msg = readAckStage1Message(data, offset);
- break;
- case NETCOMMANDTYPE_ACKSTAGE2:
- msg = readAckStage2Message(data, offset);
- break;
- case NETCOMMANDTYPE_FRAMEINFO:
- msg = readFrameMessage(data, offset);
- break;
- case NETCOMMANDTYPE_PLAYERLEAVE:
- msg = readPlayerLeaveMessage(data, offset);
- break;
- case NETCOMMANDTYPE_RUNAHEADMETRICS:
- msg = readRunAheadMetricsMessage(data, offset);
- break;
- case NETCOMMANDTYPE_RUNAHEAD:
- msg = readRunAheadMessage(data, offset);
- break;
- case NETCOMMANDTYPE_DESTROYPLAYER:
- msg = readDestroyPlayerMessage(data, offset);
- break;
- case NETCOMMANDTYPE_KEEPALIVE:
- msg = readKeepAliveMessage(data, offset);
- break;
- case NETCOMMANDTYPE_DISCONNECTKEEPALIVE:
- msg = readDisconnectKeepAliveMessage(data, offset);
- break;
- case NETCOMMANDTYPE_DISCONNECTPLAYER:
- msg = readDisconnectPlayerMessage(data, offset);
- break;
- case NETCOMMANDTYPE_PACKETROUTERQUERY:
- msg = readPacketRouterQueryMessage(data, offset);
- break;
- case NETCOMMANDTYPE_PACKETROUTERACK:
- msg = readPacketRouterAckMessage(data, offset);
- break;
- case NETCOMMANDTYPE_DISCONNECTCHAT:
- msg = readDisconnectChatMessage(data, offset);
- break;
- case NETCOMMANDTYPE_DISCONNECTVOTE:
- msg = readDisconnectVoteMessage(data, offset);
- break;
- case NETCOMMANDTYPE_CHAT:
- msg = readChatMessage(data, offset);
- break;
- case NETCOMMANDTYPE_PROGRESS:
- msg = readProgressMessage(data, offset);
- break;
- case NETCOMMANDTYPE_LOADCOMPLETE:
- msg = readLoadCompleteMessage(data, offset);
- break;
- case NETCOMMANDTYPE_TIMEOUTSTART:
- msg = readTimeOutGameStartMessage(data, offset);
- break;
- case NETCOMMANDTYPE_WRAPPER:
- msg = readWrapperMessage(data, offset);
- break;
- case NETCOMMANDTYPE_FILE:
- msg = readFileMessage(data, offset);
- break;
- case NETCOMMANDTYPE_FILEANNOUNCE:
- msg = readFileAnnounceMessage(data, offset);
- break;
- case NETCOMMANDTYPE_FILEPROGRESS:
- msg = readFileProgressMessage(data, offset);
- break;
- case NETCOMMANDTYPE_DISCONNECTFRAME:
- msg = readDisconnectFrameMessage(data, offset);
- break;
- case NETCOMMANDTYPE_DISCONNECTSCREENOFF:
- msg = readDisconnectScreenOffMessage(data, offset);
- break;
- case NETCOMMANDTYPE_FRAMERESENDREQUEST:
- msg = readFrameResendRequestMessage(data, offset);
- break;
-
- }
-
- msg->setExecutionFrame(frame);
- msg->setID(commandID);
- msg->setPlayerID(playerID);
- msg->setNetCommandType(commandType);
-
- ref = NEW_NETCOMMANDREF(msg);
-
- ref->setRelay(relay);
-
- msg->detach();
- msg = NULL;
-
- return ref;
-
- }
-
- }
-
- return ref;
-}
-
-NetPacketList NetPacket::ConstructBigCommandPacketList(NetCommandRef *ref) {
- // if we don't have a unique command ID, then the wrapped command cannot
- // be identified. Therefore don't allow commands without a unique ID to
- // be wrapped.
- NetCommandMsg *msg = ref->getCommand();
-
- if (!DoesCommandRequireACommandID(msg->getNetCommandType())) {
- DEBUG_CRASH(("Trying to wrap a command that doesn't have a unique command ID"));
- return NetPacketList();
- }
-
- UnsignedInt bufferSize = GetBufferSizeNeededForCommand(msg); // need to implement. I have a drinking problem.
- UnsignedByte *bigPacketData = NULL;
-
- NetPacketList packetList;
-
- // create the buffer for the huge message and fill the buffer with that message.
- UnsignedInt bigPacketCurrentOffset = 0;
- bigPacketData = NEW UnsignedByte[bufferSize];
- FillBufferWithCommand(bigPacketData, ref);
-
- // create the wrapper command message we'll be using.
- NetWrapperCommandMsg *wrapperMsg = newInstance(NetWrapperCommandMsg);
- // get the amount of space needed for the wrapper message, not including the wrapped command data.
- UnsignedInt wrapperSize = GetBufferSizeNeededForCommand(wrapperMsg);
- UnsignedInt commandSizePerPacket = MAX_PACKET_SIZE - wrapperSize;
-
- UnsignedInt numChunks = bufferSize / commandSizePerPacket;
- if ((bufferSize % commandSizePerPacket) > 0) {
- ++numChunks;
- }
- UnsignedInt currentChunk = 0;
-
- // create the packets and the wrapper messages.
- while (currentChunk < numChunks) {
- NetPacket *packet = newInstance(NetPacket);
-
- UnsignedShort dataSizeThisPacket = commandSizePerPacket;
- if ((bufferSize - bigPacketCurrentOffset) < dataSizeThisPacket) {
- dataSizeThisPacket = bufferSize - bigPacketCurrentOffset;
- }
-
- if (DoesCommandRequireACommandID(wrapperMsg->getNetCommandType())) {
- wrapperMsg->setID(GenerateNextCommandID());
- }
- wrapperMsg->setPlayerID(msg->getPlayerID());
- wrapperMsg->setExecutionFrame(msg->getExecutionFrame());
-
- wrapperMsg->setChunkNumber(currentChunk);
- wrapperMsg->setNumChunks(numChunks);
- wrapperMsg->setDataOffset(bigPacketCurrentOffset);
- wrapperMsg->setData(bigPacketData + bigPacketCurrentOffset, dataSizeThisPacket);
- wrapperMsg->setTotalDataLength(bufferSize);
- wrapperMsg->setWrappedCommandID(msg->getID());
-
- bigPacketCurrentOffset += dataSizeThisPacket;
-
- NetCommandRef * ref = NEW_NETCOMMANDREF(wrapperMsg);
- ref->setRelay(ref->getRelay());
-
- if (packet->addCommand(ref) == FALSE) {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::BeginBigCommandPacketList - failed to add a wrapper command to the packet")); // I still have a drinking problem.
- }
-
- packetList.push_back(packet);
-
- deleteInstance(ref);
- ref = NULL;
-
- ++currentChunk;
- }
- wrapperMsg->detach();
- wrapperMsg = NULL;
-
- delete[] bigPacketData;
- bigPacketData = NULL;
-
- return packetList;
-}
-
-UnsignedInt NetPacket::GetBufferSizeNeededForCommand(NetCommandMsg *msg) {
- // This is where the fun begins...
-
- if (msg == NULL) {
- return TRUE; // There was nothing to add, so it was successful.
- }
-
- switch(msg->getNetCommandType())
- {
- case NETCOMMANDTYPE_GAMECOMMAND:
- return GetGameCommandSize(msg);
- case NETCOMMANDTYPE_ACKSTAGE1:
- case NETCOMMANDTYPE_ACKSTAGE2:
- case NETCOMMANDTYPE_ACKBOTH:
- return GetAckCommandSize(msg);
- case NETCOMMANDTYPE_FRAMEINFO:
- return GetFrameCommandSize(msg);
- case NETCOMMANDTYPE_PLAYERLEAVE:
- return GetPlayerLeaveCommandSize(msg);
- case NETCOMMANDTYPE_RUNAHEADMETRICS:
- return GetRunAheadMetricsCommandSize(msg);
- case NETCOMMANDTYPE_RUNAHEAD:
- return GetRunAheadCommandSize(msg);
- case NETCOMMANDTYPE_DESTROYPLAYER:
- return GetDestroyPlayerCommandSize(msg);
- case NETCOMMANDTYPE_KEEPALIVE:
- return GetKeepAliveCommandSize(msg);
- case NETCOMMANDTYPE_DISCONNECTKEEPALIVE:
- return GetDisconnectKeepAliveCommandSize(msg);
- case NETCOMMANDTYPE_DISCONNECTPLAYER:
- return GetDisconnectPlayerCommandSize(msg);
- case NETCOMMANDTYPE_PACKETROUTERQUERY:
- return GetPacketRouterQueryCommandSize(msg);
- case NETCOMMANDTYPE_PACKETROUTERACK:
- return GetPacketRouterAckCommandSize(msg);
- case NETCOMMANDTYPE_DISCONNECTCHAT:
- return GetDisconnectChatCommandSize(msg);
- case NETCOMMANDTYPE_DISCONNECTVOTE:
- return GetDisconnectVoteCommandSize(msg);
- case NETCOMMANDTYPE_CHAT:
- return GetChatCommandSize(msg);
- case NETCOMMANDTYPE_PROGRESS:
- return GetProgressMessageSize(msg);
- case NETCOMMANDTYPE_LOADCOMPLETE:
- return GetLoadCompleteMessageSize(msg);
- case NETCOMMANDTYPE_TIMEOUTSTART:
- return GetTimeOutGameStartMessageSize(msg);
- case NETCOMMANDTYPE_WRAPPER:
- return GetWrapperCommandSize(msg);
- case NETCOMMANDTYPE_FILE:
- return GetFileCommandSize(msg);
- case NETCOMMANDTYPE_FILEANNOUNCE:
- return GetFileAnnounceCommandSize(msg);
- case NETCOMMANDTYPE_FILEPROGRESS:
- return GetFileProgressCommandSize(msg);
- case NETCOMMANDTYPE_DISCONNECTFRAME:
- return GetDisconnectFrameCommandSize(msg);
- case NETCOMMANDTYPE_DISCONNECTSCREENOFF:
- return GetDisconnectScreenOffCommandSize(msg);
- case NETCOMMANDTYPE_FRAMERESENDREQUEST:
- return GetFrameResendRequestCommandSize(msg);
- default:
- DEBUG_CRASH(("Unknown NETCOMMANDTYPE %d", msg->getNetCommandType()));
- break;
- }
-
- return 0;
-}
-
-UnsignedInt NetPacket::GetGameCommandSize(NetCommandMsg *msg) {
- NetGameCommandMsg *cmdMsg = (NetGameCommandMsg *)msg;
-
- UnsignedShort msglen = 0;
- msglen += sizeof(UnsignedInt) + sizeof(UnsignedByte); // frame number
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // relay
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // command type
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte); // command ID
- msglen += sizeof(UnsignedByte); // the NetPacketFieldTypes::Data for the data section.
-
- GameMessage *gmsg = cmdMsg->constructGameMessage();
- GameMessageParser *parser = newInstance(GameMessageParser)(gmsg);
-
- msglen += sizeof(GameMessage::Type);
- msglen += sizeof(UnsignedByte);
-// Int numTypes = parser->getNumTypes();
- GameMessageParserArgumentType *arg = parser->getFirstArgumentType();
- while (arg != NULL) {
- msglen += 2 * sizeof(UnsignedByte); // for the type and number of args of that type declaration.
- GameMessageArgumentDataType type = arg->getType();
-
- switch (type) {
-
- case ARGUMENTDATATYPE_INTEGER:
- msglen += arg->getArgCount() * sizeof(Int);
- break;
- case ARGUMENTDATATYPE_REAL:
- msglen += arg->getArgCount() * sizeof(Real);
- break;
- case ARGUMENTDATATYPE_BOOLEAN:
- msglen += arg->getArgCount() * sizeof(Bool);
- break;
- case ARGUMENTDATATYPE_OBJECTID:
- msglen += arg->getArgCount() * sizeof(ObjectID);
- break;
- case ARGUMENTDATATYPE_DRAWABLEID:
- msglen += arg->getArgCount() * sizeof(DrawableID);
- break;
- case ARGUMENTDATATYPE_TEAMID:
- msglen += arg->getArgCount() * sizeof(UnsignedInt);
- break;
- case ARGUMENTDATATYPE_LOCATION:
- msglen += arg->getArgCount() * sizeof(Coord3D);
- break;
- case ARGUMENTDATATYPE_PIXEL:
- msglen += arg->getArgCount() * sizeof(ICoord2D);
- break;
- case ARGUMENTDATATYPE_PIXELREGION:
- msglen += arg->getArgCount() * sizeof(IRegion2D);
- break;
- case ARGUMENTDATATYPE_TIMESTAMP:
- msglen += arg->getArgCount() * sizeof(UnsignedInt);
- break;
- case ARGUMENTDATATYPE_WIDECHAR:
- msglen += arg->getArgCount() * sizeof(WideChar);
- break;
-
- }
-
- arg = arg->getNext();
- }
-
- deleteInstance(parser);
- parser = NULL;
-
- deleteInstance(gmsg);
- gmsg = NULL;
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetAckCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
- ++msglen;
- msglen += sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen;
- msglen += sizeof(UnsignedShort);
- msglen += sizeof(UnsignedByte);
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetFrameCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen;
- msglen += sizeof(UnsignedShort);
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetPlayerLeaveCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- msglen += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetRunAheadMetricsCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(Real);
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetRunAheadCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- msglen += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen;
- msglen += sizeof(UnsignedShort);
- msglen += sizeof(UnsignedByte);
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetDestroyPlayerCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- msglen += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen;
- msglen += sizeof(UnsignedInt);
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetKeepAliveCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // For the NetPacketFieldTypes::Data
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetDisconnectKeepAliveCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // For the NetPacketFieldTypes::Data
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetDisconnectPlayerCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen; // the NetPacketFieldTypes::Data
- msglen += sizeof(UnsignedByte); // slot number
- msglen += sizeof(UnsignedInt); // disconnect frame
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetPacketRouterQueryCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // the NetPacketFieldTypes::Data
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetPacketRouterAckCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // the NetPacketFieldTypes::Data
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetDisconnectChatCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
- NetDisconnectChatCommandMsg *cmdMsg = (NetDisconnectChatCommandMsg *)(msg);
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // the NetPacketFieldTypes::Data
- msglen += sizeof(UnsignedByte); // string msglength
- UnsignedByte textmsglen = cmdMsg->getText().getLength();
- msglen += textmsglen * sizeof(UnsignedShort);
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetDisconnectVoteCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen; // the NetPacketFieldTypes::Data
- msglen += sizeof(UnsignedByte); // slot number
- msglen += sizeof(UnsignedInt); // vote frame.
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetChatCommandSize(NetCommandMsg *msg) {
- Int msglen = 0;
- NetChatCommandMsg *cmdMsg = (NetChatCommandMsg *)(msg);
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
-
- ++msglen; // the NetPacketFieldTypes::Data
- msglen += sizeof(UnsignedByte); // string msglength
- UnsignedByte textmsglen = cmdMsg->getText().getLength();
- msglen += textmsglen * sizeof(UnsignedShort);
- msglen += sizeof(Int); // playerMask
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetProgressMessageSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // For the NetPacketFieldTypes::Data
- ++msglen; // percentage
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetLoadCompleteMessageSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // For the NetPacketFieldTypes::Data
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetTimeOutGameStartMessageSize(NetCommandMsg *msg) {
- Int msglen = 0;
-
- ++msglen;
- msglen += sizeof(UnsignedByte);
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- ++msglen;
- msglen += sizeof(UnsignedByte);
-
- ++msglen; // For the NetPacketFieldTypes::Data
-
- return msglen;
-}
-
-// type, player, ID, relay, Data
-UnsignedInt NetPacket::GetWrapperCommandSize(NetCommandMsg *msg) {
- UnsignedInt msglen = 0;
-
- ++msglen; // NetPacketFieldTypes::CommandType
- msglen += sizeof(UnsignedByte); // command type
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::PlayerId and player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedShort); // NetPacketFieldTypes::CommandId and command ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::Relay and relay
- ++msglen; // NetPacketFieldTypes::Data
-
- msglen += sizeof(UnsignedShort); // m_wrappedCommandID
- msglen += sizeof(UnsignedInt); // m_chunkNumber
- msglen += sizeof(UnsignedInt); // m_numChunks
- msglen += sizeof(UnsignedInt); // m_totalDataLength
- msglen += sizeof(UnsignedInt); // m_dataLength
- msglen += sizeof(UnsignedInt); // m_dataOffset
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetFileCommandSize(NetCommandMsg *msg) {
- NetFileCommandMsg *filemsg = (NetFileCommandMsg *)msg;
- UnsignedInt msglen = 0;
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::CommandType and command type
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::PlayerId and player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedShort); // NetPacketFieldTypes::CommandId and command ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::Relay and relay
-
- ++msglen; // NetPacketFieldTypes::Data
-
- msglen += filemsg->getPortableFilename().getLength() + 1; // PORTABLE filename and the terminating 0
- msglen += sizeof(UnsignedInt); // file data length
- msglen += filemsg->getFileLength(); // the file data
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetFileAnnounceCommandSize(NetCommandMsg *msg) {
- NetFileAnnounceCommandMsg *filemsg = (NetFileAnnounceCommandMsg *)msg;
- UnsignedInt msglen = 0;
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::CommandType and command type
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::PlayerId and player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedShort); // NetPacketFieldTypes::CommandId and command ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::Relay and relay
-
- ++msglen; // NetPacketFieldTypes::Data
-
- msglen += filemsg->getPortableFilename().getLength() + 1; // PORTABLE filename and the terminating 0
- msglen += sizeof(UnsignedShort); // m_fileID
- msglen += sizeof(UnsignedByte); // m_playerMask
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetFileProgressCommandSize(NetCommandMsg *msg) {
- UnsignedInt msglen = 0;
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::CommandType and command type
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::PlayerId and player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedShort); // NetPacketFieldTypes::CommandId and command ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::Relay and relay
-
- ++msglen; // NetPacketFieldTypes::Data
-
- msglen += sizeof(UnsignedShort); // m_fileID
- msglen += sizeof(Int); // m_progress
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetDisconnectFrameCommandSize(NetCommandMsg *msg) {
- UnsignedInt msglen = 0;
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::CommandType and command type
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::PlayerId and player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedShort); // NetPacketFieldTypes::CommandId and command ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::Relay and relay
-
- ++msglen; // NetPacketFieldTypes::Data
- msglen += sizeof(UnsignedInt); // disconnect frame
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetDisconnectScreenOffCommandSize(NetCommandMsg *msg) {
- UnsignedInt msglen = 0;
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::CommandType and command type
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::PlayerId and player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedShort); // NetPacketFieldTypes::CommandId and command ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::Relay and relay
-
- ++msglen; // NetPacketFieldTypes::Data
- msglen += sizeof(UnsignedInt); // new frame
-
- return msglen;
-}
-
-UnsignedInt NetPacket::GetFrameResendRequestCommandSize(NetCommandMsg *msg) {
- UnsignedInt msglen = 0;
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::CommandType and command type
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::PlayerId and player ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedShort); // NetPacketFieldTypes::CommandId and command ID
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte); // NetPacketFieldTypes::Relay and relay
-
- ++msglen; // NetPacketFieldTypes::Data
- msglen += sizeof(UnsignedInt); // frame to resend
-
- return msglen;
-}
-
-// this function assumes that buffer is already the correct size.
-void NetPacket::FillBufferWithCommand(UnsignedByte *buffer, NetCommandRef *ref) {
- NetCommandMsg *msg = ref->getCommand();
-
- switch(msg->getNetCommandType())
- {
- case NETCOMMANDTYPE_GAMECOMMAND:
- FillBufferWithGameCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_ACKSTAGE1:
- case NETCOMMANDTYPE_ACKSTAGE2:
- case NETCOMMANDTYPE_ACKBOTH:
- FillBufferWithAckCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_FRAMEINFO:
- FillBufferWithFrameCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_PLAYERLEAVE:
- FillBufferWithPlayerLeaveCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_RUNAHEADMETRICS:
- FillBufferWithRunAheadMetricsCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_RUNAHEAD:
- FillBufferWithRunAheadCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_DESTROYPLAYER:
- FillBufferWithDestroyPlayerCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_KEEPALIVE:
- FillBufferWithKeepAliveCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_DISCONNECTKEEPALIVE:
- FillBufferWithDisconnectKeepAliveCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_DISCONNECTPLAYER:
- FillBufferWithDisconnectPlayerCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_PACKETROUTERQUERY:
- FillBufferWithPacketRouterQueryCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_PACKETROUTERACK:
- FillBufferWithPacketRouterAckCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_DISCONNECTCHAT:
- FillBufferWithDisconnectChatCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_DISCONNECTVOTE:
- FillBufferWithDisconnectVoteCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_CHAT:
- FillBufferWithChatCommand(buffer, ref);
- break;
- case NETCOMMANDTYPE_PROGRESS:
- FillBufferWithProgressMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_LOADCOMPLETE:
- FillBufferWithLoadCompleteMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_TIMEOUTSTART:
- FillBufferWithTimeOutGameStartMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_FILE:
- FillBufferWithFileMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_FILEANNOUNCE:
- FillBufferWithFileAnnounceMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_FILEPROGRESS:
- FillBufferWithFileProgressMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_DISCONNECTFRAME:
- FillBufferWithDisconnectFrameMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_DISCONNECTSCREENOFF:
- FillBufferWithDisconnectScreenOffMessage(buffer, ref);
- break;
- case NETCOMMANDTYPE_FRAMERESENDREQUEST:
- FillBufferWithFrameResendRequestMessage(buffer, ref);
- break;
- default:
- DEBUG_CRASH(("Unknown NETCOMMANDTYPE %d", msg->getNetCommandType()));
- break;
- }
-}
-
-void NetPacket::FillBufferWithGameCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetGameCommandMsg *cmdMsg = (NetGameCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
- // get the game message from the NetCommandMsg
- GameMessage *gmsg = cmdMsg->constructGameMessage();
-
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::FillBufferWithGameCommand for command ID %d", cmdMsg->getID()));
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // If necessary, put the execution frame into the packet.
- buffer[offset] = NetPacketFieldTypes::Frame;
- ++offset;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(buffer+offset, &newframe, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
-
- // If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- // If necessary, put the playerID into the packet.
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- // Now copy the GameMessage type into the packet.
- GameMessage::Type newType = gmsg->getType();
- memcpy(buffer + offset, &newType, sizeof(GameMessage::Type));
- offset += sizeof(GameMessage::Type);
-
-
- GameMessageParser *parser = newInstance(GameMessageParser)(gmsg);
- UnsignedByte numTypes = parser->getNumTypes();
- memcpy(buffer + offset, &numTypes, sizeof(numTypes));
- offset += sizeof(numTypes);
-
- GameMessageParserArgumentType *argType = parser->getFirstArgumentType();
- while (argType != NULL) {
- UnsignedByte type = (UnsignedByte)(argType->getType());
- memcpy(buffer + offset, &type, sizeof(type));
- offset += sizeof(type);
-
- UnsignedByte argTypeCount = argType->getArgCount();
- memcpy(buffer + offset, &argTypeCount, sizeof(argTypeCount));
- offset += sizeof(argTypeCount);
-
- argType = argType->getNext();
- }
-
- Int numArgs = gmsg->getArgumentCount();
- for (Int i = 0; i < numArgs; ++i) {
- GameMessageArgumentDataType type = gmsg->getArgumentDataType(i);
- GameMessageArgumentType arg = *(gmsg->getArgument(i));
-
- switch (type) {
-
- case ARGUMENTDATATYPE_INTEGER:
- memcpy(buffer + offset, &(arg.integer), sizeof(arg.integer));
- offset += sizeof(arg.integer);
- break;
- case ARGUMENTDATATYPE_REAL:
- memcpy(buffer + offset, &(arg.real), sizeof(arg.real));
- offset += sizeof(arg.real);
- break;
- case ARGUMENTDATATYPE_BOOLEAN:
- memcpy(buffer + offset, &(arg.boolean), sizeof(arg.boolean));
- offset += sizeof(arg.boolean);
- break;
- case ARGUMENTDATATYPE_OBJECTID:
- memcpy(buffer + offset, &(arg.objectID), sizeof(arg.objectID));
- offset += sizeof(arg.objectID);
- break;
- case ARGUMENTDATATYPE_DRAWABLEID:
- memcpy(buffer + offset, &(arg.drawableID), sizeof(arg.drawableID));
- offset += sizeof(arg.drawableID);
- break;
- case ARGUMENTDATATYPE_TEAMID:
- memcpy(buffer + offset, &(arg.teamID), sizeof(arg.teamID));
- offset += sizeof(arg.teamID);
- break;
- case ARGUMENTDATATYPE_LOCATION:
- memcpy(buffer + offset, &(arg.location), sizeof(arg.location));
- offset += sizeof(arg.location);
- break;
- case ARGUMENTDATATYPE_PIXEL:
- memcpy(buffer + offset, &(arg.pixel), sizeof(arg.pixel));
- offset += sizeof(arg.pixel);
- break;
- case ARGUMENTDATATYPE_PIXELREGION:
- memcpy(buffer + offset, &(arg.pixelRegion), sizeof(arg.pixelRegion));
- offset += sizeof(arg.pixelRegion);
- break;
- case ARGUMENTDATATYPE_TIMESTAMP:
- memcpy(buffer + offset, &(arg.timestamp), sizeof(arg.timestamp));
- offset += sizeof(arg.timestamp);
- break;
- case ARGUMENTDATATYPE_WIDECHAR:
- memcpy(buffer + offset, &(arg.wChar), sizeof(arg.wChar));
- offset += sizeof(arg.wChar);
- break;
- }
-
- }
-
- deleteInstance(parser);
- parser = NULL;
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addGameMessage - added game message, frame %d, player %d, command ID %d", m_lastFrame, m_lastPlayerID, m_lastCommandID));
-
- deleteInstance(gmsg);
- gmsg = NULL;
-}
-
-void NetPacket::FillBufferWithAckCommand(UnsignedByte *buffer, NetCommandRef *msg) {
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::FillBufferWithAckCommand - adding ack for command %d for player %d", cmdMsg->getCommandID(), msg->getCommand()->getPlayerID()));
-
- NetCommandMsg *cmdMsg = msg->getCommand();
- UnsignedShort offset = 0;
-
- UnsignedShort commandID = 0;
- UnsignedByte originalPlayerID = 0;
-
- NetCommandType type = cmdMsg->getNetCommandType();
-
- switch (type) {
-
- case NETCOMMANDTYPE_ACKBOTH: {
- NetAckBothCommandMsg* ackbothmsg = (NetAckBothCommandMsg*)msg;
- commandID = ackbothmsg->getCommandID();
- originalPlayerID = ackbothmsg->getOriginalPlayerID();
- break;
- }
-
- case NETCOMMANDTYPE_ACKSTAGE1: {
- NetAckStage1CommandMsg* ackstageonemsg = (NetAckStage1CommandMsg*)msg;
- commandID = ackstageonemsg->getCommandID();
- originalPlayerID = ackstageonemsg->getOriginalPlayerID();
- break;
- }
-
- case NETCOMMANDTYPE_ACKSTAGE2: {
- NetAckStage2CommandMsg* ackstagetwomsg = (NetAckStage2CommandMsg*)msg;
- commandID = ackstagetwomsg->getCommandID();
- originalPlayerID = ackstagetwomsg->getOriginalPlayerID();
- break;
- }
-
- }
-
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = type;
- offset += sizeof(UnsignedByte);
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // Put in the command id of the command we are acking.
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- memcpy(buffer + offset, &commandID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
- memcpy(buffer + offset, &originalPlayerID, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- // DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("outgoing - added ACK, original player %d, command id %d", origPlayerID, cmdID));
-}
-
-void NetPacket::FillBufferWithFrameCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetFrameCommandMsg *cmdMsg = (NetFrameCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
- // DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addFrameCommand - adding frame command for frame %d, command count = %d, command id = %d", cmdMsg->getExecutionFrame(), cmdMsg->getCommandCount(), cmdMsg->getID()));
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the execution frame into the packet.
- buffer[offset] = NetPacketFieldTypes::Frame;
- ++offset;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(buffer+offset, &newframe, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnsignedShort cmdCount = cmdMsg->getCommandCount();
- memcpy(buffer + offset, &cmdCount, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
- // frameinfodebug
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("outgoing - added frame %d, player %d, command count = %d, command id = %d", cmdMsg->getExecutionFrame(), cmdMsg->getPlayerID(), cmdMsg->getCommandCount(), cmdMsg->getID()));
-}
-
-void NetPacket::FillBufferWithPlayerLeaveCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetPlayerLeaveCommandMsg *cmdMsg = (NetPlayerLeaveCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addPlayerLeaveCommand - adding player leave command for player %d", cmdMsg->getLeavingPlayerID()));
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the execution frame into the packet.
- buffer[offset] = NetPacketFieldTypes::Frame;
- ++offset;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(buffer+offset, &newframe, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnsignedByte leavingPlayerID = cmdMsg->getLeavingPlayerID();
- memcpy(buffer + offset, &leavingPlayerID, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-}
-
-void NetPacket::FillBufferWithRunAheadMetricsCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetRunAheadMetricsCommandMsg *cmdMsg = (NetRunAheadMetricsCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addRunAheadMetricsCommand - adding run ahead metrics for player %d, fps = %d, latency = %f", cmdMsg->getPlayerID(), cmdMsg->getAverageFps(), cmdMsg->getAverageLatency()));
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- // write the average latency
- Real averageLatency = cmdMsg->getAverageLatency();
- memcpy(buffer + offset, &averageLatency, sizeof(averageLatency));
- offset += sizeof(averageLatency);
- // write the average fps
- UnsignedShort averageFps = (UnsignedShort)(cmdMsg->getAverageFps());
- memcpy(buffer + offset, &averageFps, sizeof(averageFps));
- offset += sizeof(averageFps);
-}
-
-void NetPacket::FillBufferWithRunAheadCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetRunAheadCommandMsg *cmdMsg = (NetRunAheadCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::FillBufferWithRunAheadCommand - adding run ahead command"));
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- // If necessary, put the execution frame into the packet.
- buffer[offset] = NetPacketFieldTypes::Frame;
- ++offset;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(buffer+offset, &newframe, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnsignedShort newRunAhead = cmdMsg->getRunAhead();
- memcpy(buffer + offset, &newRunAhead, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
- UnsignedByte newFrameRate = cmdMsg->getFrameRate();
- memcpy(buffer + offset, &newFrameRate, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket - added run ahead command, frame %d, player id %d command id %d", m_lastFrame, m_lastPlayerID, m_lastCommandID));
-}
-
-void NetPacket::FillBufferWithDestroyPlayerCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetDestroyPlayerCommandMsg *cmdMsg = (NetDestroyPlayerCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addRunAheadCommand - adding run ahead command"));
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the execution frame into the packet.
- buffer[offset] = NetPacketFieldTypes::Frame;
- ++offset;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(buffer+offset, &newframe, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnsignedInt newVal = cmdMsg->getPlayerIndex();
- memcpy(buffer + offset, &newVal, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
-}
-
-void NetPacket::FillBufferWithKeepAliveCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetKeepAliveCommandMsg *cmdMsg = (NetKeepAliveCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-}
-
-void NetPacket::FillBufferWithDisconnectKeepAliveCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetDisconnectKeepAliveCommandMsg *cmdMsg = (NetDisconnectKeepAliveCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-
- // Put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // Put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- // Put the player ID into the packet.
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-}
-
-void NetPacket::FillBufferWithDisconnectPlayerCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetDisconnectPlayerCommandMsg *cmdMsg = (NetDisconnectPlayerCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectPlayerCommand - adding run ahead command"));
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
- // DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnsignedByte slot = cmdMsg->getDisconnectSlot();
- memcpy(buffer + offset, &slot, sizeof(slot));
- offset += sizeof(slot);
-
- UnsignedInt disconnectFrame = cmdMsg->getDisconnectFrame();
- memcpy(buffer + offset, &disconnectFrame, sizeof(disconnectFrame));
- offset += sizeof(disconnectFrame);
-}
-
-void NetPacket::FillBufferWithPacketRouterQueryCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetPacketRouterQueryCommandMsg *cmdMsg = (NetPacketRouterQueryCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addPacketRouterQueryCommand - adding packet router query command"));
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-}
-
-void NetPacket::FillBufferWithPacketRouterAckCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetPacketRouterAckCommandMsg *cmdMsg = (NetPacketRouterAckCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addPacketRouterAckCommand - adding packet router query command"));
-
- // If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-}
-
-void NetPacket::FillBufferWithDisconnectChatCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetDisconnectChatCommandMsg *cmdMsg = (NetDisconnectChatCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectChatCommand - adding run ahead command"));
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnicodeString unitext = cmdMsg->getText();
- UnsignedByte length = unitext.getLength();
- memcpy(buffer + offset, &length, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- memcpy(buffer + offset, unitext.str(), length * sizeof(UnsignedShort));
- offset += length * sizeof(UnsignedShort);
-}
-
-void NetPacket::FillBufferWithDisconnectVoteCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetDisconnectVoteCommandMsg *cmdMsg = (NetDisconnectVoteCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectVoteCommand - adding run ahead command"));
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnsignedByte slot = cmdMsg->getSlot();
- memcpy(buffer + offset, &slot, sizeof(slot));
- offset += sizeof(slot);
-
- UnsignedInt voteFrame = cmdMsg->getVoteFrame();
- memcpy(buffer + offset, &voteFrame, sizeof(voteFrame));
- offset += sizeof(voteFrame);
-}
-
-void NetPacket::FillBufferWithChatCommand(UnsignedByte *buffer, NetCommandRef *msg) {
- NetChatCommandMsg *cmdMsg = (NetChatCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectChatCommand - adding run ahead command"));
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the execution frame into the packet.
- buffer[offset] = NetPacketFieldTypes::Frame;
- ++offset;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(buffer+offset, &newframe, sizeof(UnsignedInt));
- offset += sizeof(UnsignedInt);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
- UnicodeString unitext = cmdMsg->getText();
- UnsignedByte length = unitext.getLength();
- Int playerMask = cmdMsg->getPlayerMask();
- memcpy(buffer + offset, &length, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- memcpy(buffer + offset, unitext.str(), length * sizeof(UnsignedShort));
- offset += length * sizeof(UnsignedShort);
-
- memcpy(buffer + offset, &playerMask, sizeof(Int));
- offset += sizeof(Int);
-}
-
-void NetPacket::FillBufferWithProgressMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetProgressCommandMsg *cmdMsg = (NetProgressCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
-// Put the player ID into the packet.
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- buffer[offset] = cmdMsg->getPercentage();
- ++offset;
-}
-
-void NetPacket::FillBufferWithLoadCompleteMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetCommandMsg *cmdMsg = (NetCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
-
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-}
-
-void NetPacket::FillBufferWithTimeOutGameStartMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetCommandMsg *cmdMsg = (NetCommandMsg *)(msg->getCommand());
- UnsignedShort offset = 0;
-
-// If necessary, put the NetCommandType into the packet.
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
-// If necessary, put the relay into the packet.
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(buffer+offset, &newRelay, sizeof(UnsignedByte));
- offset += sizeof(UnsignedByte);
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
-// If necessary, specify the command ID of this command.
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(UnsignedShort));
- offset += sizeof(UnsignedShort);
-
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-}
-
-void NetPacket::FillBufferWithFileMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetFileCommandMsg *cmdMsg = (NetFileCommandMsg *)(msg->getCommand());
- UnsignedInt offset = 0;
-
- // command type
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // relay
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- buffer[offset] = msg->getRelay();
- offset += sizeof(UnsignedByte);
-
- // player ID
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // command ID
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(newID));
- offset += sizeof(newID);
-
- // data
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- AsciiString filename = cmdMsg->getPortableFilename(); // PORTABLE
- for (Int i = 0; i < filename.getLength(); ++i) {
- buffer[offset] = filename.getCharAt(i);
- ++offset;
- }
- buffer[offset] = 0;
- ++offset;
-
- UnsignedInt newInt = cmdMsg->getFileLength();
- memcpy(buffer + offset, &newInt, sizeof(newInt));
- offset += sizeof(newInt);
-
- memcpy(buffer + offset, cmdMsg->getFileData(), cmdMsg->getFileLength());
- offset += cmdMsg->getFileLength();
-}
-
-void NetPacket::FillBufferWithFileAnnounceMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetFileAnnounceCommandMsg *cmdMsg = (NetFileAnnounceCommandMsg *)(msg->getCommand());
- UnsignedInt offset = 0;
-
- // command type
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // relay
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- buffer[offset] = msg->getRelay();
- offset += sizeof(UnsignedByte);
-
- // player ID
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // command ID
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(newID));
- offset += sizeof(newID);
-
- // data
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- AsciiString filename = cmdMsg->getPortableFilename(); // PORTABLE
- for (Int i = 0; i < filename.getLength(); ++i) {
- buffer[offset] = filename.getCharAt(i);
- ++offset;
- }
- buffer[offset] = 0;
- ++offset;
-
- UnsignedShort fileID = cmdMsg->getFileID();
- memcpy(buffer + offset, &fileID, sizeof(fileID));
- offset += sizeof(fileID);
-
- UnsignedByte playerMask = cmdMsg->getPlayerMask();
- memcpy(buffer + offset, &playerMask, sizeof(playerMask));
- offset += sizeof(playerMask);
-}
-
-void NetPacket::FillBufferWithFileProgressMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetFileProgressCommandMsg *cmdMsg = (NetFileProgressCommandMsg *)(msg->getCommand());
- UnsignedInt offset = 0;
-
- // command type
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // relay
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- buffer[offset] = msg->getRelay();
- offset += sizeof(UnsignedByte);
-
- // player ID
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // command ID
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(newID));
- offset += sizeof(newID);
-
- // data
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- UnsignedShort fileID = cmdMsg->getFileID();
- memcpy(buffer + offset, &fileID, sizeof(fileID));
- offset += sizeof(fileID);
-
- Int progress = cmdMsg->getProgress();
- memcpy(buffer + offset, &progress, sizeof(progress));
- offset += sizeof(progress);
-}
-
-void NetPacket::FillBufferWithDisconnectFrameMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetDisconnectFrameCommandMsg *cmdMsg = (NetDisconnectFrameCommandMsg *)(msg->getCommand());
- UnsignedInt offset = 0;
-
- // command type
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // relay
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- buffer[offset] = msg->getRelay();
- offset += sizeof(UnsignedByte);
-
- // player ID
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // command ID
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(newID));
- offset += sizeof(newID);
-
- // data
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- UnsignedInt disconnectFrame = cmdMsg->getDisconnectFrame();
- memcpy(buffer + offset, &disconnectFrame, sizeof(disconnectFrame));
- offset += sizeof(disconnectFrame);
-}
-
-void NetPacket::FillBufferWithDisconnectScreenOffMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetDisconnectScreenOffCommandMsg *cmdMsg = (NetDisconnectScreenOffCommandMsg *)(msg->getCommand());
- UnsignedInt offset = 0;
-
- // command type
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // relay
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- buffer[offset] = msg->getRelay();
- offset += sizeof(UnsignedByte);
-
- // player ID
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // command ID
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(newID));
- offset += sizeof(newID);
-
- // data
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- UnsignedInt newFrame = cmdMsg->getNewFrame();
- memcpy(buffer + offset, &newFrame, sizeof(newFrame));
- offset += sizeof(newFrame);
-}
-
-void NetPacket::FillBufferWithFrameResendRequestMessage(UnsignedByte *buffer, NetCommandRef *msg) {
- NetFrameResendRequestCommandMsg *cmdMsg = (NetFrameResendRequestCommandMsg *)(msg->getCommand());
- UnsignedInt offset = 0;
-
- // command type
- buffer[offset] = NetPacketFieldTypes::CommandType;
- ++offset;
- buffer[offset] = cmdMsg->getNetCommandType();
- offset += sizeof(UnsignedByte);
-
- // relay
- buffer[offset] = NetPacketFieldTypes::Relay;
- ++offset;
- buffer[offset] = msg->getRelay();
- offset += sizeof(UnsignedByte);
-
- // player ID
- buffer[offset] = NetPacketFieldTypes::PlayerId;
- ++offset;
- buffer[offset] = cmdMsg->getPlayerID();
- offset += sizeof(UnsignedByte);
-
- // command ID
- buffer[offset] = NetPacketFieldTypes::CommandId;
- ++offset;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(buffer + offset, &newID, sizeof(newID));
- offset += sizeof(newID);
-
- // data
- buffer[offset] = NetPacketFieldTypes::Data;
- ++offset;
-
- UnsignedInt frameToResend = cmdMsg->getFrameToResend();
- memcpy(buffer + offset, &frameToResend, sizeof(frameToResend));
- offset += sizeof(frameToResend);
-}
-
-
-/**
- * Constructor
- */
-NetPacket::NetPacket() {
- init();
-}
-
-/**
- * Constructor given raw transport data.
- */
-NetPacket::NetPacket(TransportMessage *msg) {
- init();
- m_packetLen = msg->length;
- memcpy(m_packet, msg->data, MAX_PACKET_SIZE);
- m_numCommands = -1;
- m_addr = msg->addr;
- m_port = msg->port;
-}
-
-/**
- * Destructor
- */
-NetPacket::~NetPacket() {
- deleteInstance(m_lastCommand);
- m_lastCommand = NULL;
-}
-
-/**
- * Initialize all the member variable values.
- */
-void NetPacket::init() {
- m_addr = 0;
- m_port = 0;
- m_numCommands = 0;
- m_packetLen = 0;
- m_packet[0] = 0;
-
- m_lastPlayerID = 0;
- m_lastFrame = 0;
- m_lastCommandID = 0;
- m_lastCommandType = 0;
- m_lastRelay = 0;
-
- m_lastCommand = NULL;
-}
-
-void NetPacket::reset() {
- deleteInstance(m_lastCommand);
- m_lastCommand = NULL;
-
- init();
-}
-
-/**
- * Set the address to which this packet is to be sent.
- */
-void NetPacket::setAddress(Int addr, Int port) {
- m_addr = addr;
- m_port = port;
-}
-
-/**
- * Adds this command to the packet. Returns false if there wasn't enough room
- * in the packet for this message, true otherwise.
- */
-Bool NetPacket::addCommand(NetCommandRef *msg) {
- // This is where the fun begins...
-
- NetCommandMsg *cmdMsg = msg->getCommand();
-
- if (msg == NULL) {
- return TRUE; // There was nothing to add, so it was successful.
- }
-
- switch(cmdMsg->getNetCommandType())
- {
- case NETCOMMANDTYPE_GAMECOMMAND:
- return addGameCommand(msg);
- case NETCOMMANDTYPE_ACKSTAGE1:
- return addAckStage1Command(msg);
- case NETCOMMANDTYPE_ACKSTAGE2:
- return addAckStage2Command(msg);
- case NETCOMMANDTYPE_ACKBOTH:
- return addAckBothCommand(msg);
- case NETCOMMANDTYPE_FRAMEINFO:
- return addFrameCommand(msg);
- case NETCOMMANDTYPE_PLAYERLEAVE:
- return addPlayerLeaveCommand(msg);
- case NETCOMMANDTYPE_RUNAHEADMETRICS:
- return addRunAheadMetricsCommand(msg);
- case NETCOMMANDTYPE_RUNAHEAD:
- return addRunAheadCommand(msg);
- case NETCOMMANDTYPE_DESTROYPLAYER:
- return addDestroyPlayerCommand(msg);
- case NETCOMMANDTYPE_KEEPALIVE:
- return addKeepAliveCommand(msg);
- case NETCOMMANDTYPE_DISCONNECTKEEPALIVE:
- return addDisconnectKeepAliveCommand(msg);
- case NETCOMMANDTYPE_DISCONNECTPLAYER:
- return addDisconnectPlayerCommand(msg);
- case NETCOMMANDTYPE_PACKETROUTERQUERY:
- return addPacketRouterQueryCommand(msg);
- case NETCOMMANDTYPE_PACKETROUTERACK:
- return addPacketRouterAckCommand(msg);
- case NETCOMMANDTYPE_DISCONNECTCHAT:
- return addDisconnectChatCommand(msg);
- case NETCOMMANDTYPE_DISCONNECTVOTE:
- return addDisconnectVoteCommand(msg);
- case NETCOMMANDTYPE_CHAT:
- return addChatCommand(msg);
- case NETCOMMANDTYPE_PROGRESS:
- return addProgressMessage(msg);
- case NETCOMMANDTYPE_LOADCOMPLETE:
- return addLoadCompleteMessage(msg);
- case NETCOMMANDTYPE_TIMEOUTSTART:
- return addTimeOutGameStartMessage(msg);
- case NETCOMMANDTYPE_WRAPPER:
- return addWrapperCommand(msg);
- case NETCOMMANDTYPE_FILE:
- return addFileCommand(msg);
- case NETCOMMANDTYPE_FILEANNOUNCE:
- return addFileAnnounceCommand(msg);
- case NETCOMMANDTYPE_FILEPROGRESS:
- return addFileProgressCommand(msg);
- case NETCOMMANDTYPE_DISCONNECTFRAME:
- return addDisconnectFrameCommand(msg);
- case NETCOMMANDTYPE_DISCONNECTSCREENOFF:
- return addDisconnectScreenOffCommand(msg);
- case NETCOMMANDTYPE_FRAMERESENDREQUEST:
- return addFrameResendRequestCommand(msg);
- default:
- DEBUG_CRASH(("Unknown NETCOMMANDTYPE %d", cmdMsg->getNetCommandType()));
- break;
- }
-
- return TRUE;
-}
-
-/*
-T = Net command type
-F = Execution frame
-P = Player ID
-C = Command ID
-R = Relay
-D = Command Data
-Z = Repeat last command
-*/
-Bool NetPacket::addFrameResendRequestCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForFrameResendRequestMessage(msg)) {
- NetFrameResendRequestCommandMsg *cmdMsg = (NetFrameResendRequestCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet + m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary put the player ID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- UnsignedInt frameToResend = cmdMsg->getFrameToResend();
- memcpy(m_packet + m_packetLen, &frameToResend, sizeof(frameToResend));
- m_packetLen += sizeof(frameToResend);
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addFrameResendRequest - added frame resend request command from player %d for frame %d, command id = %d", m_lastPlayerID, frameToResend, m_lastCommandID));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForFrameResendRequestMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetFrameResendRequestCommandMsg *cmdMsg = (NetFrameResendRequestCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedInt); // for the frame to be resent
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addDisconnectScreenOffCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForDisconnectScreenOffMessage(msg)) {
- NetDisconnectScreenOffCommandMsg *cmdMsg = (NetDisconnectScreenOffCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet + m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary put the player ID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- UnsignedInt newFrame = cmdMsg->getNewFrame();
- memcpy(m_packet + m_packetLen, &newFrame, sizeof(newFrame));
- m_packetLen += sizeof(newFrame);
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectScreenOff - added disconnect screen off command from player %d for frame %d, command id = %d", m_lastPlayerID, newFrame, m_lastCommandID));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForDisconnectScreenOffMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetDisconnectScreenOffCommandMsg *cmdMsg = (NetDisconnectScreenOffCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedInt); // for the disconnect frame
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addDisconnectFrameCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForDisconnectFrameMessage(msg)) {
- NetDisconnectFrameCommandMsg *cmdMsg = (NetDisconnectFrameCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet + m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary put the player ID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- UnsignedInt disconnectFrame = cmdMsg->getDisconnectFrame();
- memcpy(m_packet + m_packetLen, &disconnectFrame, sizeof(disconnectFrame));
- m_packetLen += sizeof(disconnectFrame);
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectFrame - added disconnect frame command from player %d for frame %d, command id = %d", m_lastPlayerID, disconnectFrame, m_lastCommandID));
-
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForDisconnectFrameMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetDisconnectFrameCommandMsg *cmdMsg = (NetDisconnectFrameCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedInt); // for the disconnect frame
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addFileCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForFileMessage(msg)) {
- NetFileCommandMsg *cmdMsg = (NetFileCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet + m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary put the player ID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- AsciiString filename = cmdMsg->getPortableFilename(); // PORTABLE
- strcpy((char *)(m_packet + m_packetLen), filename.str());
- m_packetLen += filename.getLength() + 1;
-
- UnsignedInt fileLength = cmdMsg->getFileLength();
- memcpy(m_packet + m_packetLen, &fileLength, sizeof(fileLength));
- m_packetLen += sizeof(fileLength);
-
- memcpy(m_packet + m_packetLen, cmdMsg->getFileData(), fileLength);
- m_packetLen += fileLength;
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForFileMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetFileCommandMsg *cmdMsg = (NetFileCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedShort);
- }
-
- ++len; // NetPacketFieldTypes::Data
- len += cmdMsg->getPortableFilename().getLength() + 1; // PORTABLE filename + the terminating 0
- len += sizeof(UnsignedInt); // filedata length
- len += cmdMsg->getFileLength();
-
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-Bool NetPacket::addFileAnnounceCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForFileAnnounceMessage(msg)) {
- NetFileAnnounceCommandMsg *cmdMsg = (NetFileAnnounceCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet + m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary put the player ID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- AsciiString filename = cmdMsg->getPortableFilename(); // PORTABLE
- strcpy((char *)(m_packet + m_packetLen), filename.str());
- m_packetLen += filename.getLength() + 1;
-
- UnsignedShort fileID = cmdMsg->getFileID();
- memcpy(m_packet + m_packetLen, &fileID, sizeof(fileID));
- m_packetLen += sizeof(fileID);
-
- UnsignedByte playerMask = cmdMsg->getPlayerMask();
- memcpy(m_packet + m_packetLen, &playerMask, sizeof(playerMask));
- m_packetLen += sizeof(playerMask);
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Adding file announce message for fileID %d, ID %d to packet",
- cmdMsg->getFileID(), cmdMsg->getID()));
- return TRUE;
- }
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("No room to add file announce message to packet"));
- return FALSE;
-}
-
-Bool NetPacket::isRoomForFileAnnounceMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetFileAnnounceCommandMsg *cmdMsg = (NetFileAnnounceCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedShort);
- }
-
- ++len; // NetPacketFieldTypes::Data
- len += cmdMsg->getPortableFilename().getLength() + 1; // PORTABLE filename + the terminating 0
- len += sizeof(UnsignedShort); // m_fileID
- len += sizeof(UnsignedByte); // m_playerMask
-
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-Bool NetPacket::addFileProgressCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForFileProgressMessage(msg)) {
- NetFileProgressCommandMsg *cmdMsg = (NetFileProgressCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet + m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary put the player ID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- UnsignedShort fileID = cmdMsg->getFileID();
- memcpy(m_packet + m_packetLen, &fileID, sizeof(fileID));
- m_packetLen += sizeof(fileID);
-
- Int progress = cmdMsg->getProgress();
- memcpy(m_packet + m_packetLen, &progress, sizeof(progress));
- m_packetLen += sizeof(progress);
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForFileProgressMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetFileProgressCommandMsg *cmdMsg = (NetFileProgressCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedShort);
- }
-
- ++len; // NetPacketFieldTypes::Data
- len += sizeof(UnsignedShort); // m_fileID
- len += sizeof(Int); // m_progress
-
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-Bool NetPacket::addWrapperCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForWrapperMessage(msg)) {
- NetWrapperCommandMsg *cmdMsg = (NetWrapperCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet + m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary put the player ID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- // wrapped command ID
- UnsignedShort wrappedCommandID = cmdMsg->getWrappedCommandID();
- memcpy(m_packet + m_packetLen, &wrappedCommandID, sizeof(wrappedCommandID));
- m_packetLen += sizeof(wrappedCommandID);
-
- // chunk number
-// m_packet[m_packetLen] = cmdMsg->getChunkNumber();
-// ++m_packetLen;
- UnsignedInt chunkNumber = cmdMsg->getChunkNumber();
- memcpy(m_packet + m_packetLen, &chunkNumber, sizeof(chunkNumber));
- m_packetLen += sizeof(chunkNumber);
-
- // number of chunks
-// m_packet[m_packetLen] = cmdMsg->getNumChunks();
-// ++m_packetLen;
- UnsignedInt numChunks = cmdMsg->getNumChunks();
- memcpy(m_packet + m_packetLen, &numChunks, sizeof(numChunks));
- m_packetLen += sizeof(numChunks);
-
- // total length of data for all chunks
- UnsignedInt totalDataLength = cmdMsg->getTotalDataLength();
- memcpy(m_packet + m_packetLen, &totalDataLength, sizeof(totalDataLength));
- m_packetLen += sizeof(totalDataLength);
-
- // data length for this chunk
- UnsignedInt dataLength = cmdMsg->getDataLength();
- memcpy(m_packet + m_packetLen, &dataLength, sizeof(dataLength));
- m_packetLen += sizeof(dataLength);
-
- // the offset into the data of this chunk
- UnsignedInt dataOffset = cmdMsg->getDataOffset();
- memcpy(m_packet + m_packetLen, &dataOffset, sizeof(dataOffset));
- m_packetLen += sizeof(dataOffset);
-
- // the data for this chunk
- UnsignedByte *data = cmdMsg->getData();
- memcpy(m_packet + m_packetLen, data, dataLength);
- m_packetLen += dataLength;
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForWrapperMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetWrapperCommandMsg *cmdMsg = (NetWrapperCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedShort);
- }
-
- ++len; // NetPacketFieldTypes::Data
- len += sizeof(UnsignedShort); // wrapped command ID
- len += sizeof(UnsignedInt); // chunk number
- len += sizeof(UnsignedInt); // number of chunks
- len += sizeof(UnsignedInt); // total data length
- len += sizeof(UnsignedInt); // data length of this chunk
- len += sizeof(UnsignedInt); // offset of this chunk
- len += cmdMsg->getDataLength(); // for the data of this chunk
-
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Add a TimeOutGameStart to the packet. Returns true if successful.
- */
-Bool NetPacket::addTimeOutGameStartMessage(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForLoadCompleteMessage(msg)) {
- NetCommandMsg *cmdMsg = (NetCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Added keep alive command to packet."));
-
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room in the packet for this command.
- */
-Bool NetPacket::isRoomForTimeOutGameStartMessage(NetCommandRef *msg) {
- Int len = 0;
- NetCommandMsg *cmdMsg = (NetCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // For the NetPacketFieldTypes::Data
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-
-
-/**
- * Add a Progress command to the packet. Returns true if successful.
- */
-Bool NetPacket::addLoadCompleteMessage(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForLoadCompleteMessage(msg)) {
- NetCommandMsg *cmdMsg = (NetCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Added keep alive command to packet."));
-
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room in the packet for this command.
- */
-Bool NetPacket::isRoomForLoadCompleteMessage(NetCommandRef *msg) {
- Int len = 0;
- NetCommandMsg *cmdMsg = (NetCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // For the NetPacketFieldTypes::Data
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-
-
-
-/**
- * Add a Progress command to the packet. Returns true if successful.
- */
-Bool NetPacket::addProgressMessage(NetCommandRef *msg) {
- if (isRoomForProgressMessage(msg)) {
- NetProgressCommandMsg *cmdMsg = (NetProgressCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- m_packet[m_packetLen] = cmdMsg->getPercentage();
- ++m_packetLen;
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Added keep alive command to packet."));
-
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room in the packet for this command.
- */
-Bool NetPacket::isRoomForProgressMessage(NetCommandRef *msg) {
- Int len = 0;
- NetProgressCommandMsg *cmdMsg = (NetProgressCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // For the NetPacketFieldTypes::Data
- ++len; // percentage
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-
-
-Bool NetPacket::addDisconnectVoteCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectVoteCommand - entering..."));
- // need type, player id, relay, command id, slot number
- if (isRoomForDisconnectVoteMessage(msg)) {
- NetDisconnectVoteCommandMsg *cmdMsg = (NetDisconnectVoteCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectVoteCommand - adding run ahead command"));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnsignedByte slot = cmdMsg->getSlot();
- memcpy(m_packet + m_packetLen, &slot, sizeof(slot));
- m_packetLen += sizeof(slot);
-
- UnsignedInt voteFrame = cmdMsg->getVoteFrame();
- memcpy(m_packet + m_packetLen, &voteFrame, sizeof(voteFrame));
- m_packetLen += sizeof(voteFrame);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectVoteCommand - added disconnect vote command, player id %d command id %d, voted slot %d", m_lastPlayerID, m_lastCommandID, slot));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room for this player disconnect command in this packet.
- */
-Bool NetPacket::isRoomForDisconnectVoteMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetDisconnectVoteCommandMsg *cmdMsg = (NetDisconnectVoteCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // the NetPacketFieldTypes::Data
- len += sizeof(UnsignedByte); // slot number
- len += sizeof(UnsignedInt); // vote frame
-
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addDisconnectChatCommand(NetCommandRef *msg) {
- // type, player, id, relay, data
- // data format: 1 byte string length, string (two bytes per character)
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectChatCommand - Entering..."));
- if (isRoomForDisconnectChatMessage(msg)) {
- NetDisconnectChatCommandMsg *cmdMsg = (NetDisconnectChatCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectChatCommand - adding run ahead command"));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnicodeString unitext = cmdMsg->getText();
- UnsignedByte length = unitext.getLength();
- memcpy(m_packet + m_packetLen, &length, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- memcpy(m_packet + m_packetLen, unitext.str(), length * sizeof(UnsignedShort));
- m_packetLen += length * sizeof(UnsignedShort);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket - added disconnect chat command"));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForDisconnectChatMessage(NetCommandRef *msg) {
- Int len = 0;
- NetDisconnectChatCommandMsg *cmdMsg = (NetDisconnectChatCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // the NetPacketFieldTypes::Data
- len += sizeof(UnsignedByte); // string length
- UnsignedByte textLen = cmdMsg->getText().getLength();
- len += textLen * sizeof(UnsignedShort);
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addChatCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForChatMessage(msg)) {
- NetChatCommandMsg *cmdMsg = (NetChatCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectChatCommand - adding run ahead command"));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnicodeString unitext = cmdMsg->getText();
- UnsignedByte length = unitext.getLength();
- Int playerMask = cmdMsg->getPlayerMask();
- memcpy(m_packet + m_packetLen, &length, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- memcpy(m_packet + m_packetLen, unitext.str(), length * sizeof(UnsignedShort));
- m_packetLen += length * sizeof(UnsignedShort);
-
- memcpy(m_packet + m_packetLen, &playerMask, sizeof(Int));
- m_packetLen += sizeof(Int);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket - added chat command"));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-Bool NetPacket::isRoomForChatMessage(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- Int len = 0;
- NetChatCommandMsg *cmdMsg = (NetChatCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // the NetPacketFieldTypes::Data
- len += sizeof(UnsignedByte); // string length
- UnsignedByte textLen = cmdMsg->getText().getLength();
- len += textLen * sizeof(UnsignedShort);
- len += sizeof(Int); // playerMask
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addPacketRouterAckCommand(NetCommandRef *msg) {
- // need type, player id, relay, command id, slot number
- if (isRoomForPacketRouterAckMessage(msg)) {
- NetPacketRouterAckCommandMsg *cmdMsg = (NetPacketRouterAckCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addPacketRouterAckCommand - adding packet router query command"));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket - added packet router ack command, player id %d", m_lastPlayerID));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room for this packet router ack command in this packet.
- */
-Bool NetPacket::isRoomForPacketRouterAckMessage(NetCommandRef *msg) {
- Int len = 0;
- NetPacketRouterAckCommandMsg *cmdMsg = (NetPacketRouterAckCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // the NetPacketFieldTypes::Data
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addPacketRouterQueryCommand(NetCommandRef *msg) {
- // need type, player id, relay, command id, slot number
- if (isRoomForPacketRouterQueryMessage(msg)) {
- NetPacketRouterQueryCommandMsg *cmdMsg = (NetPacketRouterQueryCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addPacketRouterQueryCommand - adding packet router query command"));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket - added packet router query command, player id %d", m_lastPlayerID));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room for this packet router query command in this packet.
- */
-Bool NetPacket::isRoomForPacketRouterQueryMessage(NetCommandRef *msg) {
- Int len = 0;
- NetPacketRouterQueryCommandMsg *cmdMsg = (NetPacketRouterQueryCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // the NetPacketFieldTypes::Data
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::addDisconnectPlayerCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectPlayerCommand - entering..."));
- // need type, player id, relay, command id, slot number
- if (isRoomForDisconnectPlayerMessage(msg)) {
- NetDisconnectPlayerCommandMsg *cmdMsg = (NetDisconnectPlayerCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectPlayerCommand - adding run ahead command"));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnsignedByte slot = cmdMsg->getDisconnectSlot();
- memcpy(m_packet + m_packetLen, &slot, sizeof(slot));
- m_packetLen += sizeof(slot);
-
- UnsignedInt disconnectFrame = cmdMsg->getDisconnectFrame();
- memcpy(m_packet + m_packetLen, &disconnectFrame, sizeof(disconnectFrame));
- m_packetLen += sizeof(disconnectFrame);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addDisconnectPlayerCommand - added disconnect player command, player id %d command id %d, disconnecting slot %d", m_lastPlayerID, m_lastCommandID, slot));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room for this player disconnect command in this packet.
- */
-Bool NetPacket::isRoomForDisconnectPlayerMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetDisconnectPlayerCommandMsg *cmdMsg = (NetDisconnectPlayerCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // the NetPacketFieldTypes::Data
- len += sizeof(UnsignedByte); // slot number
- len += sizeof(UnsignedInt); // disconnectFrame
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-
-/**
- * Add a keep alive command to the packet. Returns true if successful.
- */
-Bool NetPacket::addDisconnectKeepAliveCommand(NetCommandRef *msg) {
- if (isRoomForDisconnectKeepAliveMessage(msg)) {
- NetDisconnectKeepAliveCommandMsg *cmdMsg = (NetDisconnectKeepAliveCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Added keep alive command to packet."));
-
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room in the packet for this command.
- */
-Bool NetPacket::isRoomForDisconnectKeepAliveMessage(NetCommandRef *msg) {
- Int len = 0;
- NetDisconnectKeepAliveCommandMsg *cmdMsg = (NetDisconnectKeepAliveCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // For the NetPacketFieldTypes::Data
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Add a keep alive command to the packet. Returns true if successful.
- */
-Bool NetPacket::addKeepAliveCommand(NetCommandRef *msg) {
- if (isRoomForKeepAliveMessage(msg)) {
- NetKeepAliveCommandMsg *cmdMsg = (NetKeepAliveCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Added keep alive command to packet."));
-
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room in the packet for this command.
- */
-Bool NetPacket::isRoomForKeepAliveMessage(NetCommandRef *msg) {
- Int len = 0;
- NetKeepAliveCommandMsg *cmdMsg = (NetKeepAliveCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // For the NetPacketFieldTypes::Data
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Add a run ahead command to the packet. Returns true if successful.
- */
-Bool NetPacket::addRunAheadCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForRunAheadMessage(msg)) {
- NetRunAheadCommandMsg *cmdMsg = (NetRunAheadCommandMsg *)(msg->getCommand());
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addRunAheadCommand - adding run ahead command"));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnsignedShort newRunAhead = cmdMsg->getRunAhead();
- memcpy(m_packet + m_packetLen, &newRunAhead, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
-
- UnsignedByte newFrameRate = cmdMsg->getFrameRate();
- memcpy(m_packet + m_packetLen, &newFrameRate, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket - added run ahead command, frame %d, player id %d command id %d", m_lastFrame, m_lastPlayerID, m_lastCommandID));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room for this run ahead command in this packet.
- */
-Bool NetPacket::isRoomForRunAheadMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetRunAheadCommandMsg *cmdMsg = (NetRunAheadCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedShort);
- len += sizeof(UnsignedByte);
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Add a DestroyPlayer command to the packet. Returns true if successful.
- */
-Bool NetPacket::addDestroyPlayerCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForDestroyPlayerMessage(msg)) {
- NetDestroyPlayerCommandMsg *cmdMsg = (NetDestroyPlayerCommandMsg *)(msg->getCommand());
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnsignedInt newVal = cmdMsg->getPlayerIndex();
- memcpy(m_packet + m_packetLen, &newVal, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket - added CRC:0x%8.8X info command, frame %d, player id %d command id %d", newCRC, m_lastFrame, m_lastPlayerID, m_lastCommandID));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is room for this DestroyPlayer command in this packet.
- */
-Bool NetPacket::isRoomForDestroyPlayerMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetDestroyPlayerCommandMsg *cmdMsg = (NetDestroyPlayerCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedInt);
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Add a run ahead metrics command to the packet. Returns true if successful.
- */
-Bool NetPacket::addRunAheadMetricsCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForRunAheadMetricsMessage(msg)) {
- NetRunAheadMetricsCommandMsg *cmdMsg = (NetRunAheadMetricsCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addRunAheadMetricsCommand - adding run ahead metrics for player %d, fps = %d, latency = %f", cmdMsg->getPlayerID(), cmdMsg->getAverageFps(), cmdMsg->getAverageLatency()));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- // write the average latency
- Real averageLatency = cmdMsg->getAverageLatency();
- memcpy(m_packet + m_packetLen, &averageLatency, sizeof(averageLatency));
- m_packetLen += sizeof(averageLatency);
- // write the average fps
- UnsignedShort averageFps = (UnsignedShort)(cmdMsg->getAverageFps());
- memcpy(m_packet + m_packetLen, &averageFps, sizeof(averageFps));
- m_packetLen += sizeof(averageFps);
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- ++m_numCommands;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is enough room in the packet to fit this message.
- */
-Bool NetPacket::isRoomForRunAheadMetricsMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetRunAheadMetricsCommandMsg *cmdMsg = (NetRunAheadMetricsCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // NetPacketFieldTypes::Data
- len += sizeof(UnsignedShort);
- len += sizeof(Real);
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-
-/**
- * Add a player leave command to the packet. Returns true if successful.
- */
-Bool NetPacket::addPlayerLeaveCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isRoomForPlayerLeaveMessage(msg)) {
- NetPlayerLeaveCommandMsg *cmdMsg = (NetPlayerLeaveCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addPlayerLeaveCommand - adding player leave command for player %d", cmdMsg->getLeavingPlayerID()));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnsignedByte leavingPlayerID = cmdMsg->getLeavingPlayerID();
- memcpy(m_packet + m_packetLen, &leavingPlayerID, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- ++m_numCommands;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is enough room in the packet to fit this message.
- */
-Bool NetPacket::isRoomForPlayerLeaveMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetPlayerLeaveCommandMsg *cmdMsg = (NetPlayerLeaveCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedByte);
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Add this frame command message. Returns true if successful.
- */
-Bool NetPacket::addFrameCommand(NetCommandRef *msg) {
- Bool needNewCommandID = FALSE;
- if (isFrameRepeat(msg)) {
- if (m_packetLen >= MAX_PACKET_SIZE) {
- return FALSE;
- }
- m_packet[m_packetLen] = 'Z';
- ++m_packetLen;
- m_lastCommandID = msg->getCommand()->getID();
- deleteInstance(m_lastCommand);
- m_lastCommand = newInstance(NetCommandRef)(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- ++m_lastFrame; // need this cause we're actually advancing to the next frame by adding this command.
- ++m_numCommands;
- // frameinfodebug
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("outgoing - added frame %d, player %d, command count = %d, command id = %d, repeat", m_lastFrame, m_lastPlayerID, 0, m_lastCommandID));
- return TRUE;
- }
- if (isRoomForFrameMessage(msg)) {
- NetFrameCommandMsg *cmdMsg = (NetFrameCommandMsg *)(msg->getCommand());
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addFrameCommand - adding frame command for frame %d, command count = %d, command id = %d", cmdMsg->getExecutionFrame(), cmdMsg->getCommandCount(), cmdMsg->getID()));
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("relay = %d, ", m_lastRelay));
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- needNewCommandID = TRUE;
- }
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("player = %d", m_lastPlayerID));
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command id = %d", m_lastCommandID));
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- UnsignedShort cmdCount = cmdMsg->getCommandCount();
- memcpy(m_packet + m_packetLen, &cmdCount, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
-
- // frameinfodebug
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("outgoing - added frame %d, player %d, command count = %d, command id = %d", cmdMsg->getExecutionFrame(), cmdMsg->getPlayerID(), cmdMsg->getCommandCount(), cmdMsg->getID()));
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- ++m_numCommands;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is enough room in this packet for this frame message.
- */
-Bool NetPacket::isRoomForFrameMessage(NetCommandRef *msg) {
- Int len = 0;
- Bool needNewCommandID = FALSE;
- NetFrameCommandMsg *cmdMsg = (NetFrameCommandMsg *)(msg->getCommand());
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- len += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastRelay != msg->getRelay()) {
- len += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- len += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedShort);
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::isFrameRepeat(NetCommandRef *msg) {
- if (m_lastCommand == NULL) {
- return FALSE;
- }
- if (m_lastCommand->getCommand()->getNetCommandType() != NETCOMMANDTYPE_FRAMEINFO) {
- return FALSE;
- }
- NetFrameCommandMsg *framemsg = (NetFrameCommandMsg *)(msg->getCommand());
- NetFrameCommandMsg *lastmsg = (NetFrameCommandMsg *)(m_lastCommand->getCommand());
- if (framemsg->getCommandCount() != 0) {
- return FALSE;
- }
- if (framemsg->getExecutionFrame() != (lastmsg->getExecutionFrame() + 1)) {
- return FALSE;
- }
- if (msg->getRelay() != m_lastCommand->getRelay()) {
- return FALSE;
- }
- if (framemsg->getID() != (lastmsg->getID() + 1)) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Add an ack "both" command.
- */
-Bool NetPacket::addAckBothCommand(NetCommandRef *msg) {
- NetAckBothCommandMsg *ackmsg = (NetAckBothCommandMsg *)(msg->getCommand());
- return addAckCommand(msg, ackmsg->getCommandID(), ackmsg->getOriginalPlayerID());
-}
-
-/**
- * Add an ack stage 1 command.
- */
-Bool NetPacket::addAckStage1Command(NetCommandRef *msg) {
- NetAckStage1CommandMsg *ackmsg = (NetAckStage1CommandMsg *)(msg->getCommand());
- return addAckCommand(msg, ackmsg->getCommandID(), ackmsg->getOriginalPlayerID());
-}
-
-/**
- * Add an ack stage 2 command.
- */
-Bool NetPacket::addAckStage2Command(NetCommandRef *msg) {
- NetAckStage2CommandMsg *ackmsg = (NetAckStage2CommandMsg *)(msg->getCommand());
- return addAckCommand(msg, ackmsg->getCommandID(), ackmsg->getOriginalPlayerID());
-}
-
-/**
- * Add this ack command to the packet. Returns true if successful.
- */
-Bool NetPacket::addAckCommand(NetCommandRef *msg, UnsignedShort commandID, UnsignedByte originalPlayerID) {
- if (isAckRepeat(msg)) {
- if (m_packetLen >= MAX_PACKET_SIZE) {
- return FALSE;
- }
- m_packet[m_packetLen] = 'Z';
- ++m_packetLen;
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
- return TRUE;
- }
- if (isRoomForAckMessage(msg)) {
- NetCommandMsg *cmdMsg = msg->getCommand();
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addAckCommand - adding ack for command %d for player %d", cmdMsg->getCommandID(), msg->getCommand()->getPlayerID()));
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
- // Put in the command id of the command we are acking.
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
- memcpy(m_packet + m_packetLen, &commandID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- memcpy(m_packet + m_packetLen, &originalPlayerID, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("outgoing - added ACK, original player %d, command id %d", origPlayerID, cmdID));
- ++m_numCommands;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if there is enough room in the packet for this ack message.
- */
-Bool NetPacket::isRoomForAckMessage(NetCommandRef *msg) {
- Int len = 0;
- NetCommandMsg *cmdMsg = msg->getCommand();
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- ++len;
- len += sizeof(UnsignedByte);
- }
-
- ++len; // for NetPacketFieldTypes::Data
- len += sizeof(UnsignedShort);
- len += sizeof(UnsignedByte);
- if ((len + m_packetLen) > MAX_PACKET_SIZE) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::isAckRepeat(NetCommandRef *msg) {
- if (m_lastCommand == NULL) {
- return FALSE;
- }
- if (m_lastCommand->getCommand()->getNetCommandType() != msg->getCommand()->getNetCommandType()) {
- return FALSE;
- }
- if (msg->getCommand()->getNetCommandType() == NETCOMMANDTYPE_ACKBOTH) {
- return isAckBothRepeat(msg);
- }
- if (msg->getCommand()->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE1) {
- return isAckStage1Repeat(msg);
- }
- if (msg->getCommand()->getNetCommandType() == NETCOMMANDTYPE_ACKSTAGE2) {
- return isAckStage2Repeat(msg);
- }
- return FALSE;
-}
-
-Bool NetPacket::isAckBothRepeat(NetCommandRef *msg) {
- NetAckBothCommandMsg *ack = (NetAckBothCommandMsg *)(msg->getCommand());
- NetAckBothCommandMsg *lastAck = (NetAckBothCommandMsg *)(m_lastCommand->getCommand());
- if (lastAck->getCommandID() != (ack->getCommandID() - 1)) {
- return FALSE;
- }
- if (lastAck->getOriginalPlayerID() != ack->getOriginalPlayerID()) {
- return FALSE;
- }
- if (msg->getRelay() != m_lastCommand->getRelay()) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::isAckStage1Repeat(NetCommandRef *msg) {
- NetAckStage2CommandMsg *ack = (NetAckStage2CommandMsg *)(msg->getCommand());
- NetAckStage2CommandMsg *lastAck = (NetAckStage2CommandMsg *)(m_lastCommand->getCommand());
- if (lastAck->getCommandID() != (ack->getCommandID() - 1)) {
- return FALSE;
- }
- if (lastAck->getOriginalPlayerID() != ack->getOriginalPlayerID()) {
- return FALSE;
- }
- if (msg->getRelay() != m_lastCommand->getRelay()) {
- return FALSE;
- }
- return TRUE;
-}
-
-Bool NetPacket::isAckStage2Repeat(NetCommandRef *msg) {
- NetAckStage2CommandMsg *ack = (NetAckStage2CommandMsg *)(msg->getCommand());
- NetAckStage2CommandMsg *lastAck = (NetAckStage2CommandMsg *)(m_lastCommand->getCommand());
- if (lastAck->getCommandID() != (ack->getCommandID() - 1)) {
- return FALSE;
- }
- if (lastAck->getOriginalPlayerID() != ack->getOriginalPlayerID()) {
- return FALSE;
- }
- if (msg->getRelay() != m_lastCommand->getRelay()) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Adds this game command to the packet. Returns true if successful.
- */
-Bool NetPacket::addGameCommand(NetCommandRef *msg) {
- Bool retval = FALSE;
- NetGameCommandMsg *cmdMsg = (NetGameCommandMsg *)(msg->getCommand());
- // get the game message from the NetCommandMsg
- GameMessage *gmsg = cmdMsg->constructGameMessage();
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addGameCommand for command ID %d", cmdMsg->getID()));
-
- if (isRoomForGameMessage(msg, gmsg)) {
- // Now we know there is enough room, put the new game message into the packet.
-
- Bool needNewCommandID = FALSE; // this is to allow us to force the starting command ID to be respecified with this command.
-
- // If necessary, put the NetCommandType into the packet.
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandType;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getNetCommandType();
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastCommandType = cmdMsg->getNetCommandType();
- }
-
- // If necessary, put the execution frame into the packet.
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Frame;
- ++m_packetLen;
- UnsignedInt newframe = cmdMsg->getExecutionFrame();
- memcpy(m_packet+m_packetLen, &newframe, sizeof(UnsignedInt));
- m_packetLen += sizeof(UnsignedInt);
-
- m_lastFrame = newframe;
- }
-
- // If necessary, put the relay into the packet.
- if (m_lastRelay != msg->getRelay()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::Relay;
- ++m_packetLen;
- UnsignedByte newRelay = msg->getRelay();
- memcpy(m_packet+m_packetLen, &newRelay, sizeof(UnsignedByte));
- m_packetLen += sizeof(UnsignedByte);
-
- m_lastRelay = newRelay;
- }
-
- // If necessary, put the playerID into the packet.
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- m_packet[m_packetLen] = NetPacketFieldTypes::PlayerId;
- ++m_packetLen;
- m_packet[m_packetLen] = cmdMsg->getPlayerID();
- m_packetLen += sizeof(UnsignedByte);
- //since if we have a new player we need to respecify the starting command ID, lets force the command id to be different.
- needNewCommandID = TRUE;
-
- m_lastPlayerID = cmdMsg->getPlayerID();
- }
-
- // If necessary, specify the command ID of this command.
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- m_packet[m_packetLen] = NetPacketFieldTypes::CommandId;
- ++m_packetLen;
- UnsignedShort newID = cmdMsg->getID();
- memcpy(m_packet + m_packetLen, &newID, sizeof(UnsignedShort));
- m_packetLen += sizeof(UnsignedShort);
- }
- m_lastCommandID = cmdMsg->getID();
-
- m_packet[m_packetLen] = NetPacketFieldTypes::Data;
- ++m_packetLen;
-
- // Now copy the GameMessage type into the packet.
- GameMessage::Type newType = gmsg->getType();
- memcpy(m_packet + m_packetLen, &newType, sizeof(GameMessage::Type));
- m_packetLen += sizeof(GameMessage::Type);
-
-
- GameMessageParser *parser = newInstance(GameMessageParser)(gmsg);
- UnsignedByte numTypes = parser->getNumTypes();
- memcpy(m_packet + m_packetLen, &numTypes, sizeof(numTypes));
- m_packetLen += sizeof(numTypes);
-
- GameMessageParserArgumentType *argType = parser->getFirstArgumentType();
- while (argType != NULL) {
- UnsignedByte type = (UnsignedByte)(argType->getType());
- memcpy(m_packet + m_packetLen, &type, sizeof(type));
- m_packetLen += sizeof(type);
-
- UnsignedByte argTypeCount = argType->getArgCount();
- memcpy(m_packet + m_packetLen, &argTypeCount, sizeof(argTypeCount));
- m_packetLen += sizeof(argTypeCount);
-
- argType = argType->getNext();
- }
-
- Int numArgs = gmsg->getArgumentCount();
- for (Int i = 0; i < numArgs; ++i) {
- GameMessageArgumentDataType type = gmsg->getArgumentDataType(i);
- GameMessageArgumentType arg = *(gmsg->getArgument(i));
- writeGameMessageArgumentToPacket(type, arg);
- }
-
- deleteInstance(parser);
- parser = NULL;
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::addGameMessage - added game message, frame %d, player %d, command ID %d", m_lastFrame, m_lastPlayerID, m_lastCommandID));
-
- ++m_numCommands;
-
- deleteInstance(m_lastCommand);
- m_lastCommand = NEW_NETCOMMANDREF(msg->getCommand());
- m_lastCommand->setRelay(msg->getRelay());
-
- retval = TRUE;
- }
-
- deleteInstance(gmsg);
- gmsg = NULL;
-
- return retval;
-}
-
-void NetPacket::writeGameMessageArgumentToPacket(GameMessageArgumentDataType type, GameMessageArgumentType arg) {
-
- switch(type) {
-
- case ARGUMENTDATATYPE_INTEGER:
- memcpy(m_packet + m_packetLen, &(arg.integer), sizeof(arg.integer));
- m_packetLen += sizeof(arg.integer);
- break;
- case ARGUMENTDATATYPE_REAL:
- memcpy(m_packet + m_packetLen, &(arg.real), sizeof(arg.real));
- m_packetLen += sizeof(arg.real);
- break;
- case ARGUMENTDATATYPE_BOOLEAN:
- memcpy(m_packet + m_packetLen, &(arg.boolean), sizeof(arg.boolean));
- m_packetLen += sizeof(arg.boolean);
- break;
- case ARGUMENTDATATYPE_OBJECTID:
- memcpy(m_packet + m_packetLen, &(arg.objectID), sizeof(arg.objectID));
- m_packetLen += sizeof(arg.objectID);
- break;
- case ARGUMENTDATATYPE_DRAWABLEID:
- memcpy(m_packet + m_packetLen, &(arg.drawableID), sizeof(arg.drawableID));
- m_packetLen += sizeof(arg.drawableID);
- break;
- case ARGUMENTDATATYPE_TEAMID:
- memcpy(m_packet + m_packetLen, &(arg.teamID), sizeof(arg.teamID));
- m_packetLen += sizeof(arg.teamID);
- break;
- case ARGUMENTDATATYPE_LOCATION:
- memcpy(m_packet + m_packetLen, &(arg.location), sizeof(arg.location));
- m_packetLen += sizeof(arg.location);
- break;
- case ARGUMENTDATATYPE_PIXEL:
- memcpy(m_packet + m_packetLen, &(arg.pixel), sizeof(arg.pixel));
- m_packetLen += sizeof(arg.pixel);
- break;
- case ARGUMENTDATATYPE_PIXELREGION:
- memcpy(m_packet + m_packetLen, &(arg.pixelRegion), sizeof(arg.pixelRegion));
- m_packetLen += sizeof(arg.pixelRegion);
- break;
- case ARGUMENTDATATYPE_TIMESTAMP:
- memcpy(m_packet + m_packetLen, &(arg.timestamp), sizeof(arg.timestamp));
- m_packetLen += sizeof(arg.timestamp);
- break;
- case ARGUMENTDATATYPE_WIDECHAR:
- memcpy(m_packet + m_packetLen, &(arg.wChar), sizeof(arg.wChar));
- m_packetLen += sizeof(arg.wChar);
- break;
-
- }
-}
-
-/**
- * Returns true if there is enough room in this packet for this message.
- */
-Bool NetPacket::isRoomForGameMessage(NetCommandRef *msg, GameMessage *gmsg) {
- // Calculate how much space the NetCommandMsg will take in this packet.
- Int msglen = 0;
-
- NetGameCommandMsg *cmdMsg = (NetGameCommandMsg *)(msg->getCommand());
-
- Bool needNewCommandID = FALSE;
-
- if (m_lastFrame != cmdMsg->getExecutionFrame()) {
- msglen += sizeof(UnsignedInt) + sizeof(UnsignedByte);
- }
- if (m_lastPlayerID != cmdMsg->getPlayerID()) {
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- needNewCommandID = TRUE;
- }
- if (m_lastRelay != msg->getRelay()) {
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (m_lastCommandType != cmdMsg->getNetCommandType()) {
- msglen += sizeof(UnsignedByte) + sizeof(UnsignedByte);
- }
- if (((m_lastCommandID + 1) != (UnsignedShort)(cmdMsg->getID())) || (needNewCommandID == TRUE)) {
- msglen += sizeof(UnsignedShort) + sizeof(UnsignedByte);
- }
-
- GameMessageParser *parser = newInstance(GameMessageParser)(gmsg);
-
- ++msglen; // for NetPacketFieldTypes::Data
- msglen += sizeof(GameMessage::Type);
- msglen += sizeof(UnsignedByte);
-// Int numTypes = parser->getNumTypes();
- GameMessageParserArgumentType *arg = parser->getFirstArgumentType();
- while (arg != NULL) {
- msglen += 2 * sizeof(UnsignedByte); // for the type and number of args of that type declaration.
- GameMessageArgumentDataType type = arg->getType();
-
- switch (type) {
-
- case ARGUMENTDATATYPE_INTEGER:
- msglen += arg->getArgCount() * sizeof(Int);
- break;
- case ARGUMENTDATATYPE_REAL:
- msglen += arg->getArgCount() * sizeof(Real);
- break;
- case ARGUMENTDATATYPE_BOOLEAN:
- msglen += arg->getArgCount() * sizeof(Bool);
- break;
- case ARGUMENTDATATYPE_OBJECTID:
- msglen += arg->getArgCount() * sizeof(ObjectID);
- break;
- case ARGUMENTDATATYPE_DRAWABLEID:
- msglen += arg->getArgCount() * sizeof(DrawableID);
- break;
- case ARGUMENTDATATYPE_TEAMID:
- msglen += arg->getArgCount() * sizeof(UnsignedInt);
- break;
- case ARGUMENTDATATYPE_LOCATION:
- msglen += arg->getArgCount() * sizeof(Coord3D);
- break;
- case ARGUMENTDATATYPE_PIXEL:
- msglen += arg->getArgCount() * sizeof(ICoord2D);
- break;
- case ARGUMENTDATATYPE_PIXELREGION:
- msglen += arg->getArgCount() * sizeof(IRegion2D);
- break;
- case ARGUMENTDATATYPE_TIMESTAMP:
- msglen += arg->getArgCount() * sizeof(UnsignedInt);
- break;
- case ARGUMENTDATATYPE_WIDECHAR:
- msglen += arg->getArgCount() * sizeof(WideChar);
- break;
-
- }
-
- arg = arg->getNext();
-
- }
-
- deleteInstance(parser);
- parser = NULL;
-
- // Is there enough room in the packet for this message?
- if (msglen > (MAX_PACKET_SIZE - m_packetLen)) {
- return FALSE; // there isn't enough room in this packet for this new message.
- }
- return TRUE;
-}
-
-/**
- * Returns the list of commands that are in this packet.
- */
-NetCommandList * NetPacket::getCommandList() {
- NetCommandList *retval = newInstance(NetCommandList);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList, packet length = %d", m_packetLen));
- retval->init();
-
- // These need to be the same as the default values for m_lastPlayerID, m_lastFrame, etc.
- UnsignedByte playerID = 0;
- UnsignedInt frame = 0;
- UnsignedShort commandID = 1; // The first command is going to be
- UnsignedByte commandType = 0;
- UnsignedByte relay = 0;
- NetCommandRef *lastCommand = NULL;
-
- Int i = 0;
- while (i < m_packetLen) {
-
- switch(m_packet[i]) {
-
- case NetPacketFieldTypes::CommandType:
- ++i;
- memcpy(&commandType, m_packet + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- break;
- case NetPacketFieldTypes::Frame:
- ++i;
- memcpy(&frame, m_packet + i, sizeof(UnsignedInt));
- i += sizeof(UnsignedInt);
- break;
- case NetPacketFieldTypes::PlayerId:
- ++i;
- memcpy(&playerID, m_packet + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- break;
- case NetPacketFieldTypes::Relay:
- ++i;
- memcpy(&relay, m_packet + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- break;
- case NetPacketFieldTypes::CommandId:
- ++i;
- memcpy(&commandID, m_packet + i, sizeof(UnsignedShort));
- i += sizeof(UnsignedShort);
- break;
- case NetPacketFieldTypes::Data: {
- ++i;
-
- NetCommandMsg *msg = NULL;
-
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList() - command of type %d(%s)", commandType, GetNetCommandTypeAsString((NetCommandType)commandType)));
-
- switch((NetCommandType)commandType)
- {
- case NETCOMMANDTYPE_GAMECOMMAND:
- msg = readGameMessage(m_packet, i);
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read game command from player %d for frame %d", playerID, frame));
- break;
- case NETCOMMANDTYPE_ACKBOTH:
- msg = readAckBothMessage(m_packet, i);
- break;
- case NETCOMMANDTYPE_ACKSTAGE1:
- msg = readAckStage1Message(m_packet, i);
- break;
- case NETCOMMANDTYPE_ACKSTAGE2:
- msg = readAckStage2Message(m_packet, i);
- break;
- case NETCOMMANDTYPE_FRAMEINFO:
- msg = readFrameMessage(m_packet, i);
- // frameinfodebug
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read frame %d from player %d, command count = %d, relay = 0x%X", frame, playerID, ((NetFrameCommandMsg *)msg)->getCommandCount(), relay));
- break;
- case NETCOMMANDTYPE_PLAYERLEAVE:
- msg = readPlayerLeaveMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read player leave message from player %d for execution on frame %d", playerID, frame));
- break;
- case NETCOMMANDTYPE_RUNAHEADMETRICS:
- msg = readRunAheadMetricsMessage(m_packet, i);
- break;
- case NETCOMMANDTYPE_RUNAHEAD:
- msg = readRunAheadMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read run ahead message from player %d for execution on frame %d", playerID, frame));
- break;
- case NETCOMMANDTYPE_DESTROYPLAYER:
- msg = readDestroyPlayerMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read CRC info message from player %d for execution on frame %d", playerID, frame));
- break;
- case NETCOMMANDTYPE_KEEPALIVE:
- msg = readKeepAliveMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read keep alive message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_DISCONNECTKEEPALIVE:
- msg = readDisconnectKeepAliveMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read keep alive message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_DISCONNECTPLAYER:
- msg = readDisconnectPlayerMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect player message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_PACKETROUTERQUERY:
- msg = readPacketRouterQueryMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read packet router query message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_PACKETROUTERACK:
- msg = readPacketRouterAckMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read packet router ack message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_DISCONNECTCHAT:
- msg = readDisconnectChatMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect chat message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_DISCONNECTVOTE:
- msg = readDisconnectVoteMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect vote message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_CHAT:
- msg = readChatMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read chat message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_PROGRESS:
- msg = readProgressMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read Progress message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_LOADCOMPLETE:
- msg = readLoadCompleteMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read LoadComplete message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_TIMEOUTSTART:
- msg = readTimeOutGameStartMessage(m_packet, i);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read TimeOutGameStart message from player %d", playerID));
- break;
- case NETCOMMANDTYPE_WRAPPER:
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read Wrapper message from player %d", playerID));
- msg = readWrapperMessage(m_packet, i);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Done reading Wrapper message from player %d - wrapped command was %d", playerID,
- ((NetWrapperCommandMsg *)msg)->getWrappedCommandID()));
- break;
- case NETCOMMANDTYPE_FILE:
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read file message from player %d", playerID));
- msg = readFileMessage(m_packet, i);
- break;
- case NETCOMMANDTYPE_FILEANNOUNCE:
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read file announce message from player %d", playerID));
- msg = readFileAnnounceMessage(m_packet, i);
- break;
- case NETCOMMANDTYPE_FILEPROGRESS:
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read file progress message from player %d", playerID));
- msg = readFileProgressMessage(m_packet, i);
- break;
- case NETCOMMANDTYPE_DISCONNECTFRAME:
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect frame message from player %d", playerID));
- msg = readDisconnectFrameMessage(m_packet, i);
- break;
- case NETCOMMANDTYPE_DISCONNECTSCREENOFF:
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read disconnect screen off message from player %d", playerID));
- msg = readDisconnectScreenOffMessage(m_packet, i);
- break;
- case NETCOMMANDTYPE_FRAMERESENDREQUEST:
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("read frame resend request message from player %d", playerID));
- msg = readFrameResendRequestMessage(m_packet, i);
- break;
- }
-
- if (msg == NULL) {
- DEBUG_CRASH(("Didn't read a message from the packet. Things are about to go wrong."));
- continue;
- }
-
- // set the info
- msg->setExecutionFrame(frame);
- msg->setPlayerID(playerID);
- msg->setNetCommandType((NetCommandType)commandType);
- msg->setID(commandID);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("frame = %d, player = %d, command type = %d, id = %d", frame, playerID, commandType, commandID));
-
- // increment to the next command ID.
- if (DoesCommandRequireACommandID((NetCommandType)commandType)) {
- ++commandID;
- }
-
- // add the message to the list.
- NetCommandRef *ref = retval->addMessage(msg);
- if (ref != NULL) {
- ref->setRelay(relay);
- } else {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList - failed to set relay for message %d", msg->getID()));
- }
-
- deleteInstance(lastCommand);
- lastCommand = newInstance(NetCommandRef)(msg);
-
- msg->detach(); // Need to detach from new NetCommandMsg created by the "readXMessage" above.
-
- // since the message is part of the list now, we don't have to keep track of it. So we'll just set it to NULL.
- msg = NULL;
- break;
- }
-
- case 'Z': {
-
- ++i;
- // Repeat the last command, doing some funky cool byte-saving stuff
- if (lastCommand == NULL) {
- DEBUG_CRASH(("Got a repeat command with no command to repeat."));
- }
-
- NetCommandMsg *msg = NULL;
-
- switch(commandType) {
-
- case NETCOMMANDTYPE_ACKSTAGE1: {
- msg = newInstance(NetAckStage1CommandMsg)();
- NetAckStage1CommandMsg* laststageone = (NetAckStage1CommandMsg*)(lastCommand->getCommand());
- ((NetAckStage1CommandMsg*)msg)->setCommandID(laststageone->getCommandID() + 1);
- ((NetAckStage1CommandMsg*)msg)->setOriginalPlayerID(laststageone->getOriginalPlayerID());
- break;
- }
- case NETCOMMANDTYPE_ACKSTAGE2: {
- msg = newInstance(NetAckStage2CommandMsg)();
- NetAckStage2CommandMsg* laststagetwo = (NetAckStage2CommandMsg*)(lastCommand->getCommand());
- ((NetAckStage2CommandMsg*)msg)->setCommandID(laststagetwo->getCommandID() + 1);
- ((NetAckStage2CommandMsg*)msg)->setOriginalPlayerID(laststagetwo->getOriginalPlayerID());
- break;
- }
- case NETCOMMANDTYPE_ACKBOTH: {
- msg = newInstance(NetAckBothCommandMsg)();
- NetAckBothCommandMsg* lastboth = (NetAckBothCommandMsg*)(lastCommand->getCommand());
- ((NetAckBothCommandMsg*)msg)->setCommandID(lastboth->getCommandID() + 1);
- ((NetAckBothCommandMsg*)msg)->setOriginalPlayerID(lastboth->getOriginalPlayerID());
- break;
- }
- case NETCOMMANDTYPE_FRAMEINFO: {
- msg = newInstance(NetFrameCommandMsg)();
- ++frame; // this is set below.
- ((NetFrameCommandMsg*)msg)->setCommandCount(0);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Read a repeated frame command, frame = %d, player = %d, commandID = %d", frame, playerID, commandID));
- break;
- }
- default:
- DEBUG_CRASH(("Trying to repeat a command that shouldn't be repeated."));
- continue;
-
- }
-
- msg->setExecutionFrame(frame);
- msg->setPlayerID(playerID);
- msg->setNetCommandType((NetCommandType)commandType);
- msg->setID(commandID);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("frame = %d, player = %d, command type = %d, id = %d", frame, playerID, commandType, commandID));
-
- // increment to the next command ID.
- if (DoesCommandRequireACommandID((NetCommandType)commandType)) {
- ++commandID;
- }
-
- // add the message to the list.
- NetCommandRef *ref = retval->addMessage(msg);
- if (ref != NULL) {
- ref->setRelay(relay);
- }
-
- deleteInstance(lastCommand);
-// lastCommand = newInstance(NetCommandRef)(msg);
- lastCommand = NEW_NETCOMMANDREF(msg);
-
- msg->detach(); // Need to detach from new NetCommandMsg created by the "readXMessage" above.
-
- // since the message is part of the list now, we don't have to keep track of it. So we'll just set it to NULL.
- msg = NULL;
- break;
- }
-
- default:
- // we don't recognize this command, but we have to increment i so we don't fall into an infinite loop.
- DEBUG_CRASH(("Unrecognized packet entry, ignoring."));
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::getCommandList - Unrecognized packet entry at index %d", i));
- dumpPacketToLog();
- ++i;
- break;
-
- }
-
- }
-
- deleteInstance(lastCommand);
- lastCommand = NULL;
-
- return retval;
-}
-
-/**
- * Reads the data portion of a game message from the given position in the packet.
- */
-NetCommandMsg * NetPacket::readGameMessage(UnsignedByte *data, Int &i)
-{
- NetGameCommandMsg *msg = newInstance(NetGameCommandMsg);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readGameMessage"));
-
- // Get the GameMessage command type.
- GameMessage::Type newType;
- memcpy(&newType, data + i, sizeof(GameMessage::Type));
- i += sizeof(GameMessage::Type);
- msg->setGameMessageType(newType);
-
- // Get the number of argument types
- UnsignedByte numArgTypes = 0;
- memcpy(&numArgTypes, data + i, sizeof(numArgTypes));
- i += sizeof(numArgTypes);
-
- // Get the types and the number of arguments of those types.
- Int totalArgCount = 0;
- GameMessageParser *parser = newInstance(GameMessageParser)();
- Int j = 0;
- for (; j < numArgTypes; ++j) {
- UnsignedByte type = (UnsignedByte)ARGUMENTDATATYPE_UNKNOWN;
- memcpy(&type, data + i, sizeof(type));
- i += sizeof(type);
-
- UnsignedByte argCount = 0;
- memcpy(&argCount, data + i, sizeof(argCount));
- i += sizeof(argCount);
-
- parser->addArgType((GameMessageArgumentDataType)type, argCount);
- totalArgCount += argCount;
- }
-
- GameMessageParserArgumentType *parserArgType = parser->getFirstArgumentType();
- GameMessageArgumentDataType lasttype = ARGUMENTDATATYPE_UNKNOWN;
- Int argsLeftForType = 0;
- if (parserArgType != NULL) {
- lasttype = parserArgType->getType();
- argsLeftForType = parserArgType->getArgCount();
- }
- for (j = 0; j < totalArgCount; ++j) {
- readGameMessageArgumentFromPacket(lasttype, msg, data, i);
-
- --argsLeftForType;
- if (argsLeftForType == 0) {
- DEBUG_ASSERTCRASH(parserArgType != NULL, ("parserArgType was NULL when it shouldn't have been."));
- if (parserArgType == NULL) {
- return NULL;
- }
-
- parserArgType = parserArgType->getNext();
- // parserArgType is allowed to be NULL here
- if (parserArgType != NULL) {
- argsLeftForType = parserArgType->getArgCount();
- lasttype = parserArgType->getType();
- }
- }
- }
-
- deleteInstance(parser);
- parser = NULL;
-
- return (NetCommandMsg *)msg;
-}
-
-void NetPacket::readGameMessageArgumentFromPacket(GameMessageArgumentDataType type, NetGameCommandMsg *msg, UnsignedByte *data, Int &i) {
-
- GameMessageArgumentType arg;
-
- switch (type) {
-
- case ARGUMENTDATATYPE_INTEGER:
- Int theint;
- memcpy(&theint, data + i, sizeof(theint));
- i += sizeof(theint);
- arg.integer = theint;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_REAL:
- Real thereal;
- memcpy(&thereal, data + i, sizeof(thereal));
- i += sizeof(thereal);
- arg.real = thereal;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_BOOLEAN:
- Bool thebool;
- memcpy(&thebool, data + i, sizeof(thebool));
- i += sizeof(thebool);
- arg.boolean = thebool;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_OBJECTID:
- ObjectID theobjectid;
- memcpy(&theobjectid, data + i, sizeof(theobjectid));
- i += sizeof(theobjectid);
- arg.objectID = theobjectid;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_DRAWABLEID:
- DrawableID thedrawableid;
- memcpy(&thedrawableid, data + i, sizeof(thedrawableid));
- i += sizeof(thedrawableid);
- arg.drawableID = thedrawableid;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_TEAMID:
- UnsignedInt theunsignedint;
- memcpy(&theunsignedint, data + i, sizeof(theunsignedint));
- i += sizeof(theunsignedint);
- arg.teamID = theunsignedint;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_LOCATION:
- Coord3D coord;
- memcpy(&coord, data + i, sizeof(coord));
- i += sizeof(coord);
- arg.location = coord;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_PIXEL:
- ICoord2D pixel;
- memcpy(&pixel, data + i, sizeof(pixel));
- i += sizeof(pixel);
- arg.pixel = pixel;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_PIXELREGION:
- IRegion2D reg;
- memcpy(®, data + i, sizeof(reg));
- i += sizeof(reg);
- arg.pixelRegion = reg;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_TIMESTAMP:
- UnsignedInt stamp;
- memcpy(&stamp, data + i, sizeof(stamp));
- i += sizeof(stamp);
- arg.timestamp = stamp;
- msg->addArgument(type, arg);
- break;
-
- case ARGUMENTDATATYPE_WIDECHAR:
- WideChar c;
- memcpy(&c, data + i, sizeof(c));
- i += sizeof(c);
- arg.wChar = c;
- msg->addArgument(type, arg);
- break;
-
- }
-
-}
-
-/**
- * Reads the data portion of the ack message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readAckBothMessage(UnsignedByte *data, Int &i) {
- NetAckBothCommandMsg *msg = newInstance(NetAckBothCommandMsg);
-
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readAckMessage, "));
- UnsignedShort cmdID = 0;
-
- memcpy(&cmdID, data + i, sizeof(UnsignedShort));
- i += sizeof(UnsignedShort);
- msg->setCommandID(cmdID);
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("commandID = %d, ", cmdID));
-
- UnsignedByte origPlayerID = 0;
- memcpy(&origPlayerID, data + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- msg->setOriginalPlayerID(origPlayerID);
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("original player id = %d", origPlayerID));
-
- return msg;
-}
-
-/**
- * Reads the data portion of the ack message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readAckStage1Message(UnsignedByte *data, Int &i) {
- NetAckStage1CommandMsg *msg = newInstance(NetAckStage1CommandMsg);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readAckMessage, "));
- UnsignedShort cmdID = 0;
-
- memcpy(&cmdID, data + i, sizeof(UnsignedShort));
- i += sizeof(UnsignedShort);
- msg->setCommandID(cmdID);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("commandID = %d, ", cmdID));
-
- UnsignedByte origPlayerID = 0;
- memcpy(&origPlayerID, data + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- msg->setOriginalPlayerID(origPlayerID);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("original player id = %d", origPlayerID));
-
- return msg;
-}
-
-/**
- * Reads the data portion of the ack message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readAckStage2Message(UnsignedByte *data, Int &i) {
- NetAckStage2CommandMsg *msg = newInstance(NetAckStage2CommandMsg);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readAckMessage, "));
- UnsignedShort cmdID = 0;
-
- memcpy(&cmdID, data + i, sizeof(UnsignedShort));
- i += sizeof(UnsignedShort);
- msg->setCommandID(cmdID);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("commandID = %d, ", cmdID));
-
- UnsignedByte origPlayerID = 0;
- memcpy(&origPlayerID, data + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- msg->setOriginalPlayerID(origPlayerID);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("original player id = %d", origPlayerID));
-
- return msg;
-}
-
-/**
- * Reads the data portion of the frame message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readFrameMessage(UnsignedByte *data, Int &i) {
- NetFrameCommandMsg *msg = newInstance(NetFrameCommandMsg);
-
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readFrameMessage, "));
- UnsignedShort cmdCount = 0;
-
- memcpy(&cmdCount, data + i, sizeof(UnsignedShort));
- i += sizeof(UnsignedShort);
- msg->setCommandCount(cmdCount);
-// DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command count = %d, ", cmdCount));
-
- return msg;
-}
-
-/**
- * Reads the player leave message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readPlayerLeaveMessage(UnsignedByte *data, Int &i) {
- NetPlayerLeaveCommandMsg *msg = newInstance(NetPlayerLeaveCommandMsg);
-
- UnsignedByte leavingPlayerID = 0;
-
- memcpy(&leavingPlayerID, data + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- msg->setLeavingPlayerID(leavingPlayerID);
-
- return msg;
-}
-
-/**
- * Reads the run ahead metrics message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readRunAheadMetricsMessage(UnsignedByte *data, Int &i) {
- NetRunAheadMetricsCommandMsg *msg = newInstance(NetRunAheadMetricsCommandMsg);
-
- Real averageLatency = (Real)0.2;
- UnsignedShort averageFps = 30;
-
- memcpy(&averageLatency, data + i, sizeof(Real));
- i += sizeof(Real);
- msg->setAverageLatency(averageLatency);
-
- memcpy(&averageFps, data + i, sizeof(UnsignedShort));
- i += sizeof(UnsignedShort);
- msg->setAverageFps((Int)averageFps);
- return msg;
-}
-
-/**
- * Reads the run ahead message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readRunAheadMessage(UnsignedByte *data, Int &i) {
- NetRunAheadCommandMsg *msg = newInstance(NetRunAheadCommandMsg);
-
- UnsignedShort newRunAhead = 20;
- memcpy(&newRunAhead, data + i, sizeof(UnsignedShort));
- i += sizeof(UnsignedShort);
- msg->setRunAhead(newRunAhead);
-
- UnsignedByte newFrameRate = 30;
- memcpy(&newFrameRate, data + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- msg->setFrameRate(newFrameRate);
-
- return msg;
-}
-
-/**
- * Reads the CRC info message at this position in the packet.
- */
-NetCommandMsg * NetPacket::readDestroyPlayerMessage(UnsignedByte *data, Int &i) {
- NetDestroyPlayerCommandMsg *msg = newInstance(NetDestroyPlayerCommandMsg);
-
- UnsignedInt newVal = 0;
- memcpy(&newVal, data + i, sizeof(UnsignedInt));
- i += sizeof(UnsignedInt);
- msg->setPlayerIndex(newVal);
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("Saw CRC of 0x%8.8X", newCRC));
-
- return msg;
-}
-
-/**
- * Reads the keep alive data, of which there is none.
- */
-NetCommandMsg * NetPacket::readKeepAliveMessage(UnsignedByte *data, Int &i) {
- NetKeepAliveCommandMsg *msg = newInstance(NetKeepAliveCommandMsg);
-
- return msg;
-}
-
-/**
- * Reads the disconnect keep alive data, of which there is none.
- */
-NetCommandMsg * NetPacket::readDisconnectKeepAliveMessage(UnsignedByte *data, Int &i) {
- NetDisconnectKeepAliveCommandMsg *msg = newInstance(NetDisconnectKeepAliveCommandMsg);
-
- return msg;
-}
-
-/**
- * Reads the disconnect player data. Which is the slot number of the player being disconnected.
- */
-NetCommandMsg * NetPacket::readDisconnectPlayerMessage(UnsignedByte *data, Int &i) {
- NetDisconnectPlayerCommandMsg *msg = newInstance(NetDisconnectPlayerCommandMsg);
-
- UnsignedByte slot = 0;
- memcpy(&slot, data + i, sizeof(slot));
- i += sizeof(slot);
- msg->setDisconnectSlot(slot);
-
- UnsignedInt disconnectFrame = 0;
- memcpy(&disconnectFrame, data + i, sizeof(disconnectFrame));
- i += sizeof(disconnectFrame);
- msg->setDisconnectFrame(disconnectFrame);
-
- return msg;
-}
-
-/**
- * Reads the packet router query data, of which there is none.
- */
-NetCommandMsg * NetPacket::readPacketRouterQueryMessage(UnsignedByte *data, Int &i) {
- NetPacketRouterQueryCommandMsg *msg = newInstance(NetPacketRouterQueryCommandMsg);
-
- return msg;
-}
-
-/**
- * Reads the packet router ack data, of which there is none.
- */
-NetCommandMsg * NetPacket::readPacketRouterAckMessage(UnsignedByte *data, Int &i) {
- NetPacketRouterAckCommandMsg *msg = newInstance(NetPacketRouterAckCommandMsg);
-
- return msg;
-}
-
-/**
- * Reads the disconnect chat data, which is just the string.
- */
-NetCommandMsg * NetPacket::readDisconnectChatMessage(UnsignedByte *data, Int &i) {
- NetDisconnectChatCommandMsg *msg = newInstance(NetDisconnectChatCommandMsg);
-
- WideChar text[256];
- UnsignedByte length;
- memcpy(&length, data + i, sizeof(UnsignedByte));
- ++i;
- memcpy(text, data + i, length * sizeof(WideChar));
- i += length * sizeof(WideChar);
- text[length] = 0;
-
- UnicodeString unitext;
- unitext.set(text);
-
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readDisconnectChatMessage - read message, message is %ls", unitext.str()));
-
- msg->setText(unitext);
- return msg;
-}
-
-/**
- * Reads the chat data, which is just the string.
- */
-NetCommandMsg * NetPacket::readChatMessage(UnsignedByte *data, Int &i) {
- NetChatCommandMsg *msg = newInstance(NetChatCommandMsg);
-
- WideChar text[256];
- UnsignedByte length;
- Int playerMask;
- memcpy(&length, data + i, sizeof(UnsignedByte));
- ++i;
- memcpy(text, data + i, length * sizeof(WideChar));
- i += length * sizeof(WideChar);
- text[length] = 0;
- memcpy(&playerMask, data + i, sizeof(Int));
- i += sizeof(Int);
-
-
- UnicodeString unitext;
- unitext.set(text);
-
- //DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readChatMessage - read message, message is %ls", unitext.str()));
-
- msg->setText(unitext);
- msg->setPlayerMask(playerMask);
- return msg;
-}
-
-/**
- * Reads the disconnect vote data. Which is the slot number of the player being disconnected.
- */
-NetCommandMsg * NetPacket::readDisconnectVoteMessage(UnsignedByte *data, Int &i) {
- NetDisconnectVoteCommandMsg *msg = newInstance(NetDisconnectVoteCommandMsg);
-
- UnsignedByte slot = 0;
- memcpy(&slot, data + i, sizeof(slot));
- i += sizeof(slot);
- msg->setSlot(slot);
-
- UnsignedInt voteFrame = 0;
- memcpy(&voteFrame, data + i, sizeof(voteFrame));
- i += sizeof(voteFrame);
- msg->setVoteFrame(voteFrame);
-
- return msg;
-}
-
-/**
- * Reads the Progress data. Which is the slot number of the player being disconnected.
- */
-NetCommandMsg * NetPacket::readProgressMessage(UnsignedByte *data, Int &i) {
- NetProgressCommandMsg *msg = newInstance(NetProgressCommandMsg);
-
- UnsignedByte percentage = 0;
- memcpy(&percentage, data + i, sizeof(UnsignedByte));
- i += sizeof(UnsignedByte);
- msg->setPercentage(percentage);
-
- return msg;
-}
-
-NetCommandMsg * NetPacket::readLoadCompleteMessage(UnsignedByte *data, Int &i) {
- NetCommandMsg *msg = newInstance(NetCommandMsg);
- return msg;
-}
-
-NetCommandMsg * NetPacket::readTimeOutGameStartMessage(UnsignedByte *data, Int &i) {
- NetCommandMsg *msg = newInstance(NetCommandMsg);
- return msg;
-}
-
-NetCommandMsg * NetPacket::readWrapperMessage(UnsignedByte *data, Int &i) {
- NetWrapperCommandMsg *msg = newInstance(NetWrapperCommandMsg);
-
- // get the wrapped command ID
- UnsignedShort wrappedCommandID = 0;
- memcpy(&wrappedCommandID, data + i, sizeof(wrappedCommandID));
- msg->setWrappedCommandID(wrappedCommandID);
- i += sizeof(wrappedCommandID);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - wrapped command ID == %d", wrappedCommandID));
-
- // get the chunk number.
- UnsignedInt chunkNumber = 0;
- memcpy(&chunkNumber, data + i, sizeof(chunkNumber));
- msg->setChunkNumber(chunkNumber);
- i += sizeof(chunkNumber);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - chunk number = %d", chunkNumber));
-
- // get the number of chunks
- UnsignedInt numChunks = 0;
- memcpy(&numChunks, data + i, sizeof(numChunks));
- msg->setNumChunks(numChunks);
- i += sizeof(numChunks);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - number of chunks = %d", numChunks));
-
- // get the total data length
- UnsignedInt totalDataLength = 0;
- memcpy(&totalDataLength, data + i, sizeof(totalDataLength));
- msg->setTotalDataLength(totalDataLength);
- i += sizeof(totalDataLength);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - total data length = %d", totalDataLength));
-
- // get the data length for this chunk
- UnsignedInt dataLength = 0;
- memcpy(&dataLength, data + i, sizeof(dataLength));
- i += sizeof(dataLength);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - data length = %d", dataLength));
-
- UnsignedInt dataOffset = 0;
- memcpy(&dataOffset, data + i, sizeof(dataOffset));
- msg->setDataOffset(dataOffset);
- i += sizeof(dataOffset);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readWrapperMessage - data offset = %d", dataOffset));
-
- msg->setData(data + i, dataLength);
- i += dataLength;
-
- return msg;
-}
-
-NetCommandMsg * NetPacket::readFileMessage(UnsignedByte *data, Int &i) {
- NetFileCommandMsg *msg = newInstance(NetFileCommandMsg);
- char filename[_MAX_PATH];
- char *c = filename;
-
- while (data[i] != 0) {
- *c = data[i];
- ++c;
- ++i;
- }
- *c = 0;
- ++i;
- msg->setPortableFilename(AsciiString(filename)); // it's transferred as a portable filename
-
- UnsignedInt dataLength = 0;
- memcpy(&dataLength, data + i, sizeof(dataLength));
- i += sizeof(dataLength);
-
- UnsignedByte *buf = NEW UnsignedByte[dataLength];
- memcpy(buf, data + i, dataLength);
- i += dataLength;
-
- msg->setFileData(buf, dataLength);
-
- return msg;
-}
-
-NetCommandMsg * NetPacket::readFileAnnounceMessage(UnsignedByte *data, Int &i) {
- NetFileAnnounceCommandMsg *msg = newInstance(NetFileAnnounceCommandMsg);
- char filename[_MAX_PATH];
- char *c = filename;
-
- while (data[i] != 0) {
- *c = data[i];
- ++c;
- ++i;
- }
- *c = 0;
- ++i;
- msg->setPortableFilename(AsciiString(filename)); // it's transferred as a portable filename
-
- UnsignedShort fileID = 0;
- memcpy(&fileID, data + i, sizeof(fileID));
- i += sizeof(fileID);
- msg->setFileID(fileID);
-
- UnsignedByte playerMask = 0;
- memcpy(&playerMask, data + i, sizeof(playerMask));
- i += sizeof(playerMask);
- msg->setPlayerMask(playerMask);
-
- return msg;
-}
-
-NetCommandMsg * NetPacket::readFileProgressMessage(UnsignedByte *data, Int &i) {
- NetFileProgressCommandMsg *msg = newInstance(NetFileProgressCommandMsg);
-
- UnsignedShort fileID = 0;
- memcpy(&fileID, data + i, sizeof(fileID));
- i += sizeof(fileID);
- msg->setFileID(fileID);
-
- Int progress = 0;
- memcpy(&progress, data + i, sizeof(progress));
- i += sizeof(progress);
- msg->setProgress(progress);
-
- return msg;
-}
-
-NetCommandMsg * NetPacket::readDisconnectFrameMessage(UnsignedByte *data, Int &i) {
- NetDisconnectFrameCommandMsg *msg = newInstance(NetDisconnectFrameCommandMsg);
-
- UnsignedInt disconnectFrame = 0;
- memcpy(&disconnectFrame, data + i, sizeof(disconnectFrame));
- i += sizeof(disconnectFrame);
- msg->setDisconnectFrame(disconnectFrame);
-
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::readDisconnectFrameMessage - read disconnect frame for frame %d", disconnectFrame));
-
- return msg;
-}
-
-NetCommandMsg * NetPacket::readDisconnectScreenOffMessage(UnsignedByte *data, Int &i) {
- NetDisconnectScreenOffCommandMsg *msg = newInstance(NetDisconnectScreenOffCommandMsg);
-
- UnsignedInt newFrame = 0;
- memcpy(&newFrame, data + i, sizeof(newFrame));
- i += sizeof(newFrame);
- msg->setNewFrame(newFrame);
-
- return msg;
-}
-
-NetCommandMsg * NetPacket::readFrameResendRequestMessage(UnsignedByte *data, Int &i) {
- NetFrameResendRequestCommandMsg *msg = newInstance(NetFrameResendRequestCommandMsg);
-
- UnsignedInt frameToResend = 0;
- memcpy(&frameToResend, data + i, sizeof(frameToResend));
- i += sizeof(frameToResend);
- msg->setFrameToResend(frameToResend);
-
- return msg;
-}
-
-/**
- * Returns the number of commands in this packet. Only valid if the packet is locally constructed.
- */
-Int NetPacket::getNumCommands() {
- return m_numCommands;
-}
-
-/**
- * Returns the address that this packet is to be sent to. Only valid if the packet is locally constructed.
- */
-UnsignedInt NetPacket::getAddr() {
- return m_addr;
-}
-
-/**
- * Returns the port that this packet is to be sent to. Only valid if the packet is locally constructed.
- */
-UnsignedShort NetPacket::getPort() {
- return m_port;
-}
-
-/**
- * Returns the data of this packet.
- */
-UnsignedByte * NetPacket::getData() {
- return m_packet;
-}
-
-/**
- * Returns the length of the packet.
- */
-Int NetPacket::getLength() {
- return m_packetLen;
-}
-
-/**
- * Dumps the packet to the debug log file
- */
-void NetPacket::dumpPacketToLog() {
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("NetPacket::dumpPacketToLog() - packet is %d bytes", m_packetLen));
- Int numLines = m_packetLen / 8;
- if ((m_packetLen % 8) != 0) {
- ++numLines;
- }
- for (Int dumpindex = 0; dumpindex < numLines; ++dumpindex) {
- DEBUG_LOG_LEVEL_RAW(DEBUG_LEVEL_NET, ("\t%d\t", dumpindex*8));
- for (Int dumpindex2 = 0; (dumpindex2 < 8) && ((dumpindex*8 + dumpindex2) < m_packetLen); ++dumpindex2) {
- DEBUG_LOG_LEVEL_RAW(DEBUG_LEVEL_NET, ("%02x '%c' ", m_packet[dumpindex*8 + dumpindex2], m_packet[dumpindex*8 + dumpindex2]));
- }
- DEBUG_LOG_LEVEL_RAW(DEBUG_LEVEL_NET, ("\n"));
- }
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("End of packet dump"));
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/Network.cpp b/Generals/Code/GameEngine/Source/GameNetwork/Network.cpp
deleted file mode 100644
index 84fd67182a7..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/Network.cpp
+++ /dev/null
@@ -1,1056 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Network.cpp ////////////////////////////////////////////////////
-// Implementation of Network singleton
-// Author: Matthew D. Campbell, July 2001
-///////////////////////////////////////////////////////////////////////////////
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/GameEngine.h"
-#include "Common/MessageStream.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "GameNetwork/NetworkInterface.h"
-#include "GameNetwork/udp.h"
-#include "GameNetwork/Transport.h"
-#include "strtok_r.h"
-#include "GameClient/Shell.h"
-#include "Common/CRCDebug.h"
-#include "GameLogic/GameLogic.h"
-
-#include "Common/RandomValue.h"
-
-
-#include "GameLogic/ScriptActions.h"
-#include "GameLogic/ScriptEngine.h"
-#include "Common/Recorder.h"
-#include "GameClient/MessageBox.h"
-
-
-#if defined(DEBUG_CRC)
-Int NET_CRC_INTERVAL = 1;
-#else
-Int NET_CRC_INTERVAL = 100;
-#endif
-
-// DEFINES ////////////////////////////////////////////////////////////////////
-
-#define RESEND_INTERVAL 1
-
-// PRIVATE TYPES //////////////////////////////////////////////////////////////
-
-/**
- * Connection message - encapsulating info kept by the connection layer about each
- * packet. These structs make up the in/out buffers at the connection layer.
- */
-#pragma pack(push, 1)
-struct ConnectionMessage
-{
- Int id;
- NetMessageFlags flags;
- UnsignedByte data[MAX_MESSAGE_LEN];
- time_t lastSendTime;
- Int retries;
- Int length;
-};
-#pragma pack(pop)
-
-static const int CmdMsgLen = 6; //< Minimum size of a command packet (Int + Unsigned Short)
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////
-
-
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////
-
-/// The Network singleton instance
-NetworkInterface *TheNetwork = NULL;
-
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
-
-/**
- * The Network class is used to instantiate a singleton which
- * implements the interface to all Network operations such as message stream processing and network communications.
- */
-class Network : public NetworkInterface
-{
-public:
- //---------------------------------------------------------------------------------------
- // Setup / Teardown functions
- Network();
- ~Network();
- void init( void ); ///< Initialize or re-initialize the instance
- void reset( void ); ///< Reinitialize the network
- void update( void ); ///< Process command list
- void liteupdate( void ); ///< Do a lightweight update to send packets and pass messages.
- Bool deinit( void ); ///< Shutdown connections, release memory
-
- void setLocalAddress(UnsignedInt ip, UnsignedInt port);
- inline UnsignedInt getRunAhead(void) { return m_runAhead; }
- inline UnsignedInt getFrameRate(void) { return m_frameRate; }
- UnsignedInt getPacketArrivalCushion(void); ///< Returns the smallest packet arrival cushion since this was last called.
- Bool isFrameDataReady( void );
- virtual Bool isStalling();
- void parseUserList( const GameInfo *game );
- void startGame(void); ///< Sets the network game frame counter to -1
-
- void sendChat(UnicodeString text, Int playerMask);
- void sendDisconnectChat(UnicodeString text);
-
- void sendFile(AsciiString path, UnsignedByte playerMask, UnsignedShort commandID);
- UnsignedShort sendFileAnnounce(AsciiString path, UnsignedByte playerMask);
- Int getFileTransferProgress(Int playerID, AsciiString path);
- Bool areAllQueuesEmpty(void);
-
- void quitGame();
- virtual void selfDestructPlayer(Int index);
-
-
- void voteForPlayerDisconnect(Int slot);
- virtual Bool isPacketRouter( void );
-
- // Bandwidth metrics
- Real getIncomingBytesPerSecond( void );
- Real getIncomingPacketsPerSecond( void );
- Real getOutgoingBytesPerSecond( void );
- Real getOutgoingPacketsPerSecond( void );
- Real getUnknownBytesPerSecond( void );
- Real getUnknownPacketsPerSecond( void );
-
- // Multiplayer Load Progress Functions
- void updateLoadProgress( Int percent );
- void loadProgressComplete( void );
- void sendTimeOutGameStart( void );
-
-#if defined(RTS_DEBUG)
- // Disconnect screen testing
- virtual void toggleNetworkOn();
-#endif
-
- // Exposing some info contained in the Connection Manager
- UnsignedInt getLocalPlayerID( void );
- UnicodeString getPlayerName(Int playerNum);
- Int getNumPlayers(void );
-
- Int getAverageFPS() { return m_conMgr->getAverageFPS(); }
- Int getSlotAverageFPS(Int slot);
-
- void attachTransport(Transport *transport);
- void initTransport();
-
- void setSawCRCMismatch( void );
- Bool sawCRCMismatch( void ) { return m_sawCRCMismatch; }
- Bool isPlayerConnected( Int playerID );
-
- void notifyOthersOfCurrentFrame(); ///< Tells all the other players what frame we are on.
- void notifyOthersOfNewFrame(UnsignedInt frame); ///< Tells all the other players that we are on a new frame.
-
- Int getExecutionFrame(); ///< Returns the next valid frame for simultaneous command execution.
-
- // For disconnect blame assignment
- UnsignedInt getPingFrame();
- Int getPingsSent();
- Int getPingsRecieved();
-
-protected:
- void GetCommandsFromCommandList(); ///< Remove commands from TheCommandList and put them on the Network command list.
- void SendCommandsToConnectionManager(); ///< Send the new commands to the ConnectionManager
- Bool AllCommandsReady(UnsignedInt frame); ///< Do we have all the commands for the given frame?
- void RelayCommandsToCommandList(UnsignedInt frame); ///< Put the commands for the given frame onto TheCommandList.
- Bool isTransferCommand(GameMessage *msg); ///< Is this a command that needs to be transfered to the other clients?
- Bool processCommand(GameMessage *msg); ///< Whatever needs to be done as a result of this command, do it now.
- void processFrameSynchronizedNetCommand(NetCommandRef *msg); ///< If there is a network command that needs to be executed at the same frame number on all clients, it happens here.
- void processRunAheadCommand(NetRunAheadCommandMsg *msg); ///< Do what needs to be done when we get a new run ahead command.
- void processDestroyPlayerCommand(NetDestroyPlayerCommandMsg *msg); ///< Do what needs to be done when we need to destroy a player.
- void endOfGameCheck(); ///< Checks to see if its ok to leave this game. If it is, send the apropriate command to the game logic.
- Bool timeForNewFrame();
-
- ConnectionManager *m_conMgr; ///< The connection manager object
-
- UnsignedInt m_lastFrame; ///< The last game logic frame that was processed.
-
- NetLocalStatus m_localStatus; ///< My local status as a player in this game.
-
- Int m_runAhead; ///< The current run ahead of the game.
- Int m_frameRate;
- Int m_lastExecutionFrame; ///< The highest frame number that a command could have been executed on.
- Int m_lastFrameCompleted;
- Bool m_didSelfSlug;
- __int64 m_perfCountFreq; ///< The frequency of the performance counter.
-
- __int64 m_nextFrameTime; ///< When did we execute the last frame? For slugging the GameLogic...
-
- Bool m_frameDataReady; ///< Is the frame data for the next frame ready to be executed by TheGameLogic?
- Bool m_isStalling;
-
- // CRC info
- Bool m_checkCRCsThisFrame;
- Bool m_sawCRCMismatch;
- std::vector m_CRC[MAX_SLOTS];
- std::list m_playersToDisconnect;
- GameWindow *m_messageWindow;
-
-#if defined(RTS_DEBUG)
- Bool m_networkOn;
-#endif
-};
-
-UnsignedInt Network::getPingFrame()
-{
- return (m_conMgr)?m_conMgr->getPingFrame():0;
-}
-
-Int Network::getPingsSent()
-{
- return (m_conMgr)?m_conMgr->getPingsSent():0;
-}
-
-Int Network::getPingsRecieved()
-{
- return (m_conMgr)?m_conMgr->getPingsRecieved():0;
-}
-
-Bool Network::isPlayerConnected( Int playerID ) {
- if (playerID == getLocalPlayerID()) {
- return m_localStatus == NETLOCALSTATUS_INGAME || m_localStatus == NETLOCALSTATUS_LEAVING;
- }
- return m_conMgr->isPlayerConnected(playerID);
-}
-
-
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * This creates a network object and returns it.
- */
-NetworkInterface *NetworkInterface::createNetwork()
-{
- return NEW Network;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * The constructor.
- */
-Network::Network()
-{
- //Added By Sadullah Nader
- //Initializations inserted
- m_checkCRCsThisFrame = FALSE;
- m_didSelfSlug = FALSE;
- m_frameDataReady = FALSE;
- m_isStalling = FALSE;
- m_sawCRCMismatch = FALSE;
- //
-
- m_conMgr = NULL;
- m_messageWindow = NULL;
-
-#if defined(RTS_DEBUG)
- m_networkOn = TRUE;
-#endif
-}
-
-/**
- * The destructor.
- */
-Network::~Network()
-{
- deinit();
-}
-
-/**
- * This basically releases all the memory.
- */
-Bool Network::deinit( void )
-{
- if (m_conMgr)
- {
- m_conMgr->destroyGameMessages();
- delete m_conMgr;
- m_conMgr = NULL;
- }
- if (m_messageWindow) {
- TheWindowManager->winDestroy(m_messageWindow);
- m_messageWindow = NULL;
- }
-
- return true;
-}
-
-/**
- * Takes the network back to the initial state.
- */
-void Network::reset() {
- init();
-}
-
-/**
- * Initializes all the network subsystems.
- */
-void Network::init()
-{
- if (!deinit())
- {
- DEBUG_LOG(("Could not deinit network prior to init!"));
- return;
- }
-
- m_conMgr = NEW ConnectionManager;
- m_conMgr->init();
-
- m_lastFrame = 0;
- m_runAhead = min(max(30, MIN_RUNAHEAD), MAX_FRAMES_AHEAD/2); ///< @todo: don't hard-code the run-ahead.
- m_frameRate = 30;
- m_lastExecutionFrame = m_runAhead - 1; // subtract 1 since we're starting on frame 0
- m_lastFrameCompleted = m_runAhead - 1; // subtract 1 since we're starting on frame 0
- m_frameDataReady = FALSE;
- m_isStalling = FALSE;
- m_didSelfSlug = FALSE;
-
- m_localStatus = NETLOCALSTATUS_PREGAME;
-
- QueryPerformanceFrequency((LARGE_INTEGER *)&m_perfCountFreq);
- m_nextFrameTime = 0;
- m_sawCRCMismatch = FALSE;
- m_checkCRCsThisFrame = FALSE;
-
- DEBUG_LOG(("Network timing values:"));
- DEBUG_LOG(("NetworkFPSHistoryLength: %d", TheGlobalData->m_networkFPSHistoryLength));
- DEBUG_LOG(("NetworkLatencyHistoryLength: %d", TheGlobalData->m_networkLatencyHistoryLength));
- DEBUG_LOG(("NetworkRunAheadMetricsTime: %d", TheGlobalData->m_networkRunAheadMetricsTime));
- DEBUG_LOG(("NetworkCushionHistoryLength: %d", TheGlobalData->m_networkCushionHistoryLength));
- DEBUG_LOG(("NetworkRunAheadSlack: %d", TheGlobalData->m_networkRunAheadSlack));
- DEBUG_LOG(("NetworkKeepAliveDelay: %d", TheGlobalData->m_networkKeepAliveDelay));
- DEBUG_LOG(("NetworkDisconnectTime: %d", TheGlobalData->m_networkDisconnectTime));
- DEBUG_LOG(("NetworkPlayerTimeoutTime: %d", TheGlobalData->m_networkPlayerTimeoutTime));
- DEBUG_LOG(("NetworkDisconnectScreenNotifyTime: %d", TheGlobalData->m_networkDisconnectScreenNotifyTime));
- DEBUG_LOG(("Other network stuff:"));
- DEBUG_LOG(("FRAME_DATA_LENGTH = %d", FRAME_DATA_LENGTH));
- DEBUG_LOG(("FRAMES_TO_KEEP = %d", FRAMES_TO_KEEP));
-
-
-#if defined(RTS_DEBUG)
- m_networkOn = TRUE;
-#endif
-
- return;
-}
-
-void Network::setSawCRCMismatch( void )
-{
- m_sawCRCMismatch = TRUE;
-
- TheScriptActions->closeWindows( TRUE );
- m_messageWindow = TheWindowManager->winCreateFromScript("Menus/CRCMismatch.wnd");
- TheScriptEngine->startEndGameTimer();
-
- TheRecorder->logCRCMismatch();
-
- // dump GameLogic random seed
- DEBUG_LOG(("Latest frame for mismatch = %d GameLogic frame = %d",
- TheGameLogic->getFrame()-m_runAhead-1, TheGameLogic->getFrame()));
- DEBUG_LOG(("GetGameLogicRandomSeedCRC() = %d", GetGameLogicRandomSeedCRC()));
-
- // dump CRCs
- {
- DEBUG_LOG(("--- GameState Dump ---"));
-#ifdef DEBUG_CRC
- outputCRCDumpLines();
-#endif
- DEBUG_LOG(("------ End Dump ------"));
- }
- {
- DEBUG_LOG(("--- DebugInfo Dump ---"));
-#ifdef DEBUG_CRC
- outputCRCDebugLines();
-#endif
- DEBUG_LOG(("------ End Dump ------"));
- }
-}
-
-/**
- * Take a user list and build the connection queues and player lists and stuff like that.
- */
-void Network::parseUserList( const GameInfo *game )
-{
- if (!game)
- {
- DEBUG_LOG(("FAILED parseUserList with a NULL game"));
- return;
- }
-
- m_conMgr->parseUserList(game);
-
- // Now that we have the players in this game, we need to reset the FrameData stuff.
- m_conMgr->destroyGameMessages();
- m_conMgr->zeroFrames(1, m_runAhead-1); ///< we zero out m_runAhead frames +1 because the game actually starts at frame 1.
-}
-
-/**
- * Guess what, we're starting a game!
- */
-void Network::startGame() {
-}
-
-/**
- * Tell the network which ip address the user has chosen to use. Well ok, they probably didn't choose
- * it explicitly, but regardless, this is the one we're going to use.
- */
-void Network::setLocalAddress(UnsignedInt ip, UnsignedInt port) {
- DEBUG_ASSERTCRASH(m_conMgr != NULL, ("Connection manager does not exist."));
- if (m_conMgr != NULL) {
- m_conMgr->setLocalAddress(ip, port);
- }
-}
-
-/**
- * Tell the network to initialize the transport object
- */
-void Network::initTransport() {
- DEBUG_ASSERTCRASH(m_conMgr != NULL, ("Connection manager does not exist."));
- if (m_conMgr != NULL) {
- m_conMgr->initTransport();
- }
-}
-
-void Network::attachTransport(Transport *transport) {
- DEBUG_ASSERTCRASH(m_conMgr != NULL, ("Connection manager does not exist."));
- if (m_conMgr != NULL) {
- m_conMgr->attachTransport(transport);
- }
-}
-
-/**
- * Does this command need to be transfered to the other game clients?
- */
-Bool Network::isTransferCommand(GameMessage *msg) {
- if ((msg != NULL) && ((msg->getType() > GameMessage::MSG_BEGIN_NETWORK_MESSAGES) && (msg->getType() < GameMessage::MSG_END_NETWORK_MESSAGES))) {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Take commands from TheCommandList and give them to the connection manager for transport.
- */
-void Network::GetCommandsFromCommandList() {
- GameMessage *msg = TheCommandList->getFirstMessage();
- GameMessage *next = NULL;
- while (msg != NULL) {
- next = msg->next();
- if (isTransferCommand(msg)) { // Is this something we should be sending to the other players?
- if (m_localStatus == NETLOCALSTATUS_INGAME) {
- m_conMgr->sendLocalGameMessage(msg, getExecutionFrame());
- }
- TheCommandList->removeMessage(msg); // This does not destroy msg's prev and next pointers, so they should still be valid.
- deleteInstance(msg);
- } else {
- if (processCommand(msg)) {
- TheCommandList->removeMessage(msg);
- deleteInstance(msg);
- }
- }
- msg = next;
- }
-}
-
-Int Network::getExecutionFrame() {
- Int logicFrame = TheGameLogic->getFrame() + m_runAhead;
- if (logicFrame > m_lastExecutionFrame) {
- m_lastExecutionFrame = logicFrame;
- return (logicFrame);
- }
- return m_lastExecutionFrame;
-}
-
-/**
- * This is where any processing that needs to be done for specific game messages.
- * Also check here to see if the logic frame number has changed to see if we need to
- * send our info for the last frame to the other players.
- * Return true if the message should be "eaten" by the network.
- */
-Bool Network::processCommand(GameMessage *msg)
-{
- if ((m_lastFrame != TheGameLogic->getFrame()) || (m_localStatus == NETLOCALSTATUS_PREGAME)) {
- // If this is the start of a new game logic frame, then tell the connection manager that the last
- // frame is over and that it should now produce a frame info packet for the other players.
-
- if (m_localStatus == NETLOCALSTATUS_PREGAME) {
- // a sort-of-hack that prevents extraneous frames from being executed before the game actually starts.
- // Idealy this shouldn't be necessary, but I don't think its hurting anything by being here.
- if (TheGameLogic->getFrame() == 1) {
- m_localStatus = NETLOCALSTATUS_INGAME;
- NetCommandList *netcmdlist = m_conMgr->getFrameCommandList(0); // clear out frame 0 since we skipped it
- deleteInstance(netcmdlist);
- } else {
- return FALSE;
- }
- }
-
- // Only send frame info packets for frames where we are actually going to be in the game.
- // The reason is so we don't have to wait for frame info packets to be sent that aren't going to
- // matter anyways when we actually try to leave the game ourselves.
- if (m_localStatus == NETLOCALSTATUS_INGAME) {
- Int executionFrame = getExecutionFrame();
-
- // Send command counts for all the frames we can.
- for (Int i = m_lastFrameCompleted + 1; i < executionFrame; ++i) {
- m_conMgr->processFrameTick(i);
- //DEBUG_LOG(("Network::processCommand - calling processFrameTick for frame %d", i));
- m_lastFrameCompleted = i;
- }
- }
-
- //DEBUG_LOG(("Next Execution Frame - %d, last frame completed - %d", getExecutionFrame(), m_lastFrameCompleted));
- m_lastFrame = TheGameLogic->getFrame();
- }
-
- // Are we leaving the game?
- // This has to happen after the check to see if this is the start of a new logic frame.
- // The reason is that we have to send all the frame info packets necessary to get to the
- // frame where everyone else is going to see that we left.
- if ((msg->getType() == GameMessage::MSG_CLEAR_GAME_DATA) && (m_localStatus == NETLOCALSTATUS_INGAME)) {
- Int executionFrame = getExecutionFrame();
- DEBUG_LOG(("Network::processCommand - local player leaving, executionFrame = %d, player leaving on frame %d", executionFrame, executionFrame+1));
-
- m_conMgr->handleLocalPlayerLeaving(executionFrame+1);
- m_conMgr->processFrameTick(executionFrame); // This is the last command we will execute, so send the command count.
- // Also, we are guaranteed not to send any more commands for this frame
- // since the local status will change to "Leaving" so we don't have to
- // worry about messing up the other players.
- m_conMgr->processFrameTick(executionFrame+1); // since we send it for executionFrame+1, we need to process both ticks
- m_lastFrameCompleted = executionFrame;
- DEBUG_LOG(("Network::processCommand - player leaving on frame %d", executionFrame));
- m_localStatus = NETLOCALSTATUS_LEAVING;
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * returns true if all the commands are ready for the given frame.
- */
-Bool Network::AllCommandsReady(UnsignedInt frame) {
- if (m_conMgr == NULL) {
- return TRUE;
- }
-
- if (m_localStatus == NETLOCALSTATUS_PREGAME) {
- return TRUE;
- }
-
- if (m_localStatus == NETLOCALSTATUS_POSTGAME) {
- return TRUE;
- }
-
- return m_conMgr->allCommandsReady(frame);// && m_conMgr->allCRCsReady(frame);
-}
-
-/**
- * Take commands from the connection manager and put them on TheCommandList.
- * The commands need to be put on in the same order across all clients.
- */
-void Network::RelayCommandsToCommandList(UnsignedInt frame) {
- if ((m_conMgr == NULL) || (m_localStatus == NETLOCALSTATUS_PREGAME)) {
- return;
- }
- m_checkCRCsThisFrame = FALSE;
- NetCommandList *netcmdlist = m_conMgr->getFrameCommandList(frame);
- NetCommandRef *msg = netcmdlist->getFirstMessage();
- while (msg != NULL) {
- NetCommandType cmdType = msg->getCommand()->getNetCommandType();
- if (cmdType == NETCOMMANDTYPE_GAMECOMMAND) {
- //DEBUG_LOG(("Network::RelayCommandsToCommandList - appending command %d of type %s to command list on frame %d", msg->getCommand()->getID(), ((NetGameCommandMsg *)msg->getCommand())->constructGameMessage()->getCommandAsString(), TheGameLogic->getFrame()));
- TheCommandList->appendMessage(((NetGameCommandMsg *)msg->getCommand())->constructGameMessage());
- } else {
- processFrameSynchronizedNetCommand(msg);
- }
- msg = msg->getNext();
- }
-
- for (std::list::iterator selfDestructIt = m_playersToDisconnect.begin(); selfDestructIt != m_playersToDisconnect.end(); ++selfDestructIt)
- {
- //Int playerToDisconnect = *selfDestructIt;
- //GameMessage *msg = newInstance(GameMessage)( GameMessage::MSG_SELF_DESTRUCT );
- //msg->friend_setPlayerIndex(playerToDisconnect);
- //msg->appendBooleanArgument(TRUE);
- //TheCommandList->appendMessage(msg);
- }
- m_playersToDisconnect.clear();
-
- deleteInstance(netcmdlist);
-}
-
-/**
- * This is where network commands that need to be executed on the same frame should be executed.
- */
-void Network::processFrameSynchronizedNetCommand(NetCommandRef *msg) {
- NetCommandMsg *cmdMsg = msg->getCommand();
- if (cmdMsg->getNetCommandType() == NETCOMMANDTYPE_PLAYERLEAVE) {
- PlayerLeaveCode retval = m_conMgr->processPlayerLeave((NetPlayerLeaveCommandMsg *)cmdMsg);
- if (retval == PLAYERLEAVECODE_LOCAL) {
- DEBUG_LOG(("Network::processFrameSynchronizedNetCommand - Local player left the game on frame %d.", TheGameLogic->getFrame()));
- m_localStatus = NETLOCALSTATUS_LEFT;
- } else if (retval == PLAYERLEAVECODE_PACKETROUTER) {
- DEBUG_LOG(("Network::processFrameSynchronizedNetCommand - Packet router left the game on frame %d", TheGameLogic->getFrame()));
- } else {
- DEBUG_LOG(("Network::processFrameSynchronizedNetCommand - Client left the game on frame %d", TheGameLogic->getFrame()));
- }
- }
- else if (cmdMsg->getNetCommandType() == NETCOMMANDTYPE_RUNAHEAD) {
- NetRunAheadCommandMsg *netmsg = (NetRunAheadCommandMsg *)cmdMsg;
- processRunAheadCommand(netmsg);
- DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("command to set run ahead to %d and frame rate to %d on frame %d actually executed on frame %d", netmsg->getRunAhead(), netmsg->getFrameRate(), netmsg->getExecutionFrame(), TheGameLogic->getFrame()));
- }
- else if (cmdMsg->getNetCommandType() == NETCOMMANDTYPE_DESTROYPLAYER) {
- NetDestroyPlayerCommandMsg *netmsg = (NetDestroyPlayerCommandMsg *)cmdMsg;
- processDestroyPlayerCommand(netmsg);
- //DEBUG_LOG(("CRC command (%8.8X) on frame %d actually executed on frame %d", netmsg->getCRC(), netmsg->getExecutionFrame(), TheGameLogic->getFrame()));
- }
-}
-
-void Network::processRunAheadCommand(NetRunAheadCommandMsg *msg) {
- m_runAhead = msg->getRunAhead();
- m_frameRate = msg->getFrameRate();
- time_t frameGrouping = (1000 * m_runAhead) / m_frameRate; // number of miliseconds between packet sends
- frameGrouping = frameGrouping / 2; // since we only want the latency for one way to be a factor.
-// DEBUG_LOG(("Network::processRunAheadCommand - trying to set frame grouping to %d. run ahead = %d, m_frameRate = %d", frameGrouping, m_runAhead, m_frameRate));
- if (frameGrouping < 1) {
- frameGrouping = 1; // Having a value less than 1 doesn't make sense.
- }
- if (frameGrouping > 500) {
- frameGrouping = 500; // Max of a half a second.
- }
- m_conMgr->setFrameGrouping(frameGrouping);
-}
-
-void Network::processDestroyPlayerCommand(NetDestroyPlayerCommandMsg *msg)
-{
- UnsignedInt playerIndex = msg->getPlayerIndex();
- DEBUG_ASSERTCRASH(playerIndex < MAX_SLOTS, ("Bad player index"));
- if (playerIndex >= MAX_SLOTS)
- return;
-
- AsciiString playerName;
- playerName.format("player%d", playerIndex);
- Player *pPlayer = ThePlayerList->findPlayerWithNameKey(NAMEKEY(playerName));
- if (pPlayer)
- {
- GameMessage *msg = newInstance(GameMessage)(GameMessage::MSG_SELF_DESTRUCT);
-#if RETAIL_COMPATIBLE_CRC
- const Bool transferAssets = FALSE;
-#else
- const Bool transferAssets = TRUE;
-#endif
- msg->appendBooleanArgument(transferAssets);
- msg->friend_setPlayerIndex(pPlayer->getPlayerIndex());
- TheCommandList->appendMessage(msg);
- }
-
- DEBUG_LOG(("Saw DestroyPlayer from %d about %d for frame %d on frame %d", msg->getPlayerID(), msg->getPlayerIndex(),
- msg->getExecutionFrame(), TheGameLogic->getFrame()));
-}
-
-/**
- * Service queues, process message stream, etc
- */
-void Network::update( void )
-{
-//
-// 1. Take Commands off TheCommandList, hand them off to the ConnectionManager.
-// 2. Call ConnectionManager->update;
-// 3. Check to see if all the commands for the next frame are there.
-// 4. If all commands are there, put that frame's commands on TheCommandList.
-//
- m_frameDataReady = FALSE;
- m_isStalling = FALSE;
-
-#if defined(RTS_DEBUG)
- if (m_networkOn == FALSE) {
- return;
- }
-#endif
-
- GetCommandsFromCommandList(); // Remove commands from TheCommandList and send them to the connection manager.
- if (m_conMgr != NULL) {
- if (m_localStatus == NETLOCALSTATUS_INGAME) {
- m_conMgr->updateRunAhead(m_runAhead, m_frameRate, m_didSelfSlug, getExecutionFrame());
- m_didSelfSlug = FALSE;
- }
- //m_conMgr->update(); // Do the priority thing, packetize thing. This also calls the Transport::update function.
- // depacketizes the incoming packets and puts them on the Network command list.
- }
-
- liteupdate();
-
- if (m_localStatus == NETLOCALSTATUS_LEFT) {// || (m_localStatus == NETLOCALSTATUS_LEAVING)) {
- endOfGameCheck();
- }
-
- if (AllCommandsReady(TheGameLogic->getFrame())) { // If all the commands are ready for the next frame...
- m_conMgr->handleAllCommandsReady();
-// DEBUG_LOG(("Network::update - frame %d is ready", TheGameLogic->getFrame()));
- if (timeForNewFrame()) { // This needs to come after any other pre-frame execution checks as this changes the timing variables.
- RelayCommandsToCommandList(TheGameLogic->getFrame()); // Put the commands for the next frame on TheCommandList.
- m_frameDataReady = TRUE; // Tell the GameEngine to run the commands for the new frame.
- }
- }
- else {
- __int64 curTime;
- QueryPerformanceCounter((LARGE_INTEGER *)&curTime);
- m_isStalling = curTime >= m_nextFrameTime;
- }
-}
-
-void Network::liteupdate() {
-
-#if defined(RTS_DEBUG)
- if (m_networkOn == FALSE) {
- return;
- }
-#endif
-
- if (m_conMgr != NULL) {
- if (m_localStatus == NETLOCALSTATUS_PREGAME) {
- m_conMgr->update(FALSE);
- } else {
- m_conMgr->update(TRUE);
- }
- }
-}
-
-void Network::endOfGameCheck() {
- if (m_conMgr != NULL) {
- if (m_conMgr->canILeave()) {
- m_conMgr->disconnectLocalPlayer();
- TheGameLogic->exitGame();
- m_localStatus = NETLOCALSTATUS_POSTGAME;
-
- DEBUG_LOG(("Network::endOfGameCheck - about to show the shell"));
- }
-#if defined(RTS_DEBUG)
- else {
- m_conMgr->debugPrintConnectionCommands();
- }
-#endif
- }
-}
-
-Bool Network::timeForNewFrame() {
- __int64 curTime;
- QueryPerformanceCounter((LARGE_INTEGER *)&curTime);
- __int64 frameDelay = m_perfCountFreq / m_frameRate;
-
- /*
- * If we're pushing up against the edge of our run ahead, we should slow the framerate down a bit
- * to avoid being frozen by spikes in network lag. This will happen if another user's computer is
- * running too far behind us, so we need to slow down to let them catch up.
- */
- if (m_conMgr != NULL) {
- Real cushion = m_conMgr->getMinimumCushion();
- Real runAheadPercentage = m_runAhead * (TheGlobalData->m_networkRunAheadSlack / (Real)100.0); // If we are at least 50% into our slack, we need to slow down.
- if (cushion < runAheadPercentage) {
- __int64 oldFrameDelay = frameDelay;
- frameDelay += oldFrameDelay / 10; // temporarily decrease the frame rate by 20%.
-// DEBUG_LOG(("Average cushion = %f, run ahead percentage = %f. Adjusting frameDelay from %I64d to %I64d", cushion, runAheadPercentage, oldFrameDelay, frameDelay));
- m_didSelfSlug = TRUE;
-// } else {
-// DEBUG_LOG(("Average cushion = %f, run ahead percentage = %f", cushion, runAheadPercentage));
- }
- }
-
- // Check to see if we can run another frame.
- if (curTime >= m_nextFrameTime) {
-// DEBUG_LOG(("Allowing a new frame, frameDelay = %I64d, curTime - m_nextFrameTime = %I64d", frameDelay, curTime - m_nextFrameTime));
-
-// if (m_nextFrameTime + frameDelay < curTime) {
- if ((m_nextFrameTime + (2 * frameDelay)) < curTime) {
- // If we get too far behind on our framerate we need to reset the nextFrameTime thing.
- m_nextFrameTime = curTime;
-// DEBUG_LOG(("Initializing m_nextFrameTime to %I64d", m_nextFrameTime));
- } else {
- // Set the soonest possible starting time for the next frame.
- m_nextFrameTime += frameDelay;
-// DEBUG_LOG(("m_nextFrameTime = %I64d", m_nextFrameTime));
- }
-
- return TRUE;
- }
-// DEBUG_LOG(("Slowing down frame rate. frame rate = %d, frame delay = %I64d, curTime - m_nextFrameTime = %I64d", m_frameRate, frameDelay, curTime - m_nextFrameTime));
- return FALSE;
-}
-
-/**
- * Returns true if the game commands for the next frame have been put on the command list.
- */
-Bool Network::isFrameDataReady() {
- return (m_frameDataReady || (m_localStatus == NETLOCALSTATUS_LEFT));
-}
-
-Bool Network::isStalling()
-{
- return m_isStalling;
-}
-
-/**
- * returns the number of incoming bytes per second averaged over the last 30 sec.
- */
-Real Network::getIncomingBytesPerSecond( void )
-{
- if (m_conMgr)
- return m_conMgr->getIncomingBytesPerSecond();
- else
- return 0.0;
-}
-
-/**
- * returns the number of incoming packets per second averaged over the last 30 sec.
- */
-Real Network::getIncomingPacketsPerSecond( void )
-{
- if (m_conMgr)
- return m_conMgr->getIncomingPacketsPerSecond();
- else
- return 0.0;
-}
-
-/**
- * returns the number of outgoing bytes per second averaged over the last 30 sec.
- */
-Real Network::getOutgoingBytesPerSecond( void )
-{
- if (m_conMgr)
- return m_conMgr->getOutgoingBytesPerSecond();
- else
- return 0.0;
-}
-
-/**
- * returns the number of outgoing packets per second averaged over the last 30 sec.
- */
-Real Network::getOutgoingPacketsPerSecond( void )
-{
- if (m_conMgr)
- return m_conMgr->getOutgoingPacketsPerSecond();
- else
- return 0.0;
-}
-
-/**
- * returns the number of bytes received per second that are not from a generals client averaged over 30 sec.
- */
-Real Network::getUnknownBytesPerSecond( void )
-{
- if (m_conMgr)
- return m_conMgr->getUnknownBytesPerSecond();
- else
- return 0.0;
-}
-
-/**
- * returns the number of packets received per second that are not from a generals client averaged over 30 sec.
- */
-Real Network::getUnknownPacketsPerSecond( void )
-{
- if (m_conMgr)
- return m_conMgr->getUnknownPacketsPerSecond();
- else
- return 0.0;
-}
-
-/**
- * returns the smallest packet arrival cushion since this was last called.
- */
-UnsignedInt Network::getPacketArrivalCushion( void )
-{
- if (m_conMgr)
- return m_conMgr->getPacketArrivalCushion();
- else
- return 0;
-}
-
-/**
- * Sends a line of chat to the other players
- */
-void Network::sendChat(UnicodeString text, Int playerMask) {
- Int executionFrame = getExecutionFrame();
- m_conMgr->sendChat(text, playerMask, executionFrame);
-}
-
-/**
- * Sends a line of chat to the other players using the disconnect manager.
- */
-void Network::sendDisconnectChat(UnicodeString text) {
- m_conMgr->sendDisconnectChat(text);
-}
-
-// send a file. woohoo.
-void Network::sendFile(AsciiString path, UnsignedByte playerMask, UnsignedShort commandID)
-{
- m_conMgr->sendFile(path, playerMask, commandID);
-}
-
-// send a file. woohoo.
-UnsignedShort Network::sendFileAnnounce(AsciiString path, UnsignedByte playerMask)
-{
- return m_conMgr->sendFileAnnounce(path, playerMask);
-}
-
-Int Network::getFileTransferProgress(Int playerID, AsciiString path)
-{
- return m_conMgr->getFileTransferProgress(playerID, path);
-}
-
-Bool Network::areAllQueuesEmpty(void)
-{
- return m_conMgr->canILeave();
-}
-
-/**
- * Quit the game now. This should only be called from the disconnect screen.
- */
-void Network::quitGame() {
- if (m_conMgr != NULL) {
- m_conMgr->quitGame();
- }
-
-#if !RTS_GENERALS || !RETAIL_COMPATIBLE_CRC
- // Blow up / Transfer your units when you quit. Like a normal quit menu quit.
- GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_SELF_DESTRUCT);
- msg->appendBooleanArgument(TRUE);
-#endif
-
- TheGameLogic->exitGame();
- m_localStatus = NETLOCALSTATUS_POSTGAME;
- DEBUG_LOG(("Network::quitGame - quitting game..."));
-}
-
-void Network::selfDestructPlayer(Int index)
-{
- m_playersToDisconnect.push_back(index);
-}
-
-
-Bool Network::isPacketRouter( void )
-{
- return m_conMgr && m_conMgr->isPacketRouter();
-}
-
-/**
- * Register a vote towards a player being disconnected.
- */
-void Network::voteForPlayerDisconnect(Int slot) {
- if (m_conMgr != NULL) {
- m_conMgr->voteForPlayerDisconnect(slot);
- }
-}
-
-void Network::updateLoadProgress( Int percent )
-{
- if (m_conMgr != NULL) {
- m_conMgr->updateLoadProgress( percent );
- }
-}
-
-void Network::loadProgressComplete( void )
-{
- if (m_conMgr != NULL) {
- m_conMgr->loadProgressComplete();
- }
-}
-
-void Network::sendTimeOutGameStart( void )
-{
- if (m_conMgr != NULL) {
- m_conMgr->sendTimeOutGameStart();
- }
-}
-
-
-UnsignedInt Network::getLocalPlayerID()
-{
-if (m_conMgr != NULL) {
- return m_conMgr->getLocalPlayerID();
- }
- return 49;
-}
-UnicodeString Network::getPlayerName(Int playerNum)
-{
- if (playerNum == m_conMgr->getLocalPlayerID()) {
- if (m_localStatus != NETLOCALSTATUS_INGAME) {
- return UnicodeString::TheEmptyString;
- }
- }
- if (m_conMgr != NULL) {
- return m_conMgr->getPlayerName( playerNum );
- }
- return UnicodeString::TheEmptyString;
-}
-Int Network::getNumPlayers()
-{
- if (m_conMgr != NULL) {
- return m_conMgr->getNumPlayers();
- }
- return -1;
-}
-
-Int Network::getSlotAverageFPS(Int slot) {
- if (m_conMgr != NULL) {
- return m_conMgr->getSlotAverageFPS(slot);
- }
- return -1;
-}
-
-#if defined(RTS_DEBUG)
-void Network::toggleNetworkOn() {
- if (m_networkOn == TRUE) {
- m_networkOn = FALSE;
- } else {
- m_networkOn = TRUE;
- }
-}
-#endif
-
-void Network::notifyOthersOfCurrentFrame() {
- if (m_conMgr != NULL) {
- m_conMgr->notifyOthersOfCurrentFrame(TheGameLogic->getFrame());
- }
-}
-
-void Network::notifyOthersOfNewFrame(UnsignedInt frame) {
- if (m_conMgr != NULL) {
- m_conMgr->notifyOthersOfNewFrame(frame);
- }
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/NetworkUtil.cpp b/Generals/Code/GameEngine/Source/GameNetwork/NetworkUtil.cpp
deleted file mode 100644
index 332c2d8f01a..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/NetworkUtil.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/networkutil.h"
-
-// TheSuperHackers @tweak Mauller 26/08/2025 reduce the minimum runahead from 10
-// This lets network games run at latencies down to 133ms when the network conditions allow
-Int MIN_LOGIC_FRAMES = 5;
-Int MAX_FRAMES_AHEAD = 128;
-Int MIN_RUNAHEAD = 4;
-Int FRAME_DATA_LENGTH = (MAX_FRAMES_AHEAD+1)*2;
-Int FRAMES_TO_KEEP = (MAX_FRAMES_AHEAD/2) + 1;
-
-#ifdef DEBUG_LOGGING
-
-void dumpBufferToLog(const void *vBuf, Int len, const char *fname, Int line)
-{
- DEBUG_LOG(("======= dumpBufferToLog() %d bytes =======", len));
- DEBUG_LOG(("Source: %s:%d", fname, line));
- const char *buf = (const char *)vBuf;
- Int numLines = len / 8;
- if ((len % 8) != 0)
- {
- ++numLines;
- }
- for (Int dumpindex = 0; dumpindex < numLines; ++dumpindex)
- {
- Int offset = dumpindex*8;
- DEBUG_LOG_RAW(("\t%5.5d\t", offset));
- Int dumpindex2;
- Int numBytesThisLine = min(8, len - offset);
- for (dumpindex2 = 0; dumpindex2 < numBytesThisLine; ++dumpindex2)
- {
- Int c = (buf[offset + dumpindex2] & 0xff);
- DEBUG_LOG_RAW(("%02X ", c));
- }
- for (; dumpindex2 < 8; ++dumpindex2)
- {
- DEBUG_LOG_RAW((" "));
- }
- DEBUG_LOG_RAW((" | "));
- for (dumpindex2 = 0; dumpindex2 < numBytesThisLine; ++dumpindex2)
- {
- char c = buf[offset + dumpindex2];
- DEBUG_LOG_RAW(("%c", (isprint(c)?c:'.')));
- }
- DEBUG_LOG_RAW(("\n"));
- }
- DEBUG_LOG(("End of packet dump"));
-}
-
-#endif // DEBUG_LOGGING
-
-/**
- * ResolveIP turns a string ("games2.westwood.com", or "192.168.0.1") into
- * a 32-bit unsigned integer.
- */
-UnsignedInt ResolveIP(AsciiString host)
-{
- struct hostent *hostStruct;
- struct in_addr *hostNode;
-
- if (host.getLength() == 0)
- {
- DEBUG_LOG(("ResolveIP(): Can't resolve NULL"));
- return 0;
- }
-
- // String such as "127.0.0.1"
- if (isdigit(host.getCharAt(0)))
- {
- return ( ntohl(inet_addr(host.str())) );
- }
-
- // String such as "localhost"
- hostStruct = gethostbyname(host.str());
- if (hostStruct == NULL)
- {
- DEBUG_LOG(("ResolveIP(): Can't resolve %s", host.str()));
- return 0;
- }
- hostNode = (struct in_addr *) hostStruct->h_addr;
- return ( ntohl(hostNode->s_addr) );
-}
-
-/**
- * Returns the next network command ID.
- */
-UnsignedShort GenerateNextCommandID() {
- static UnsignedShort commandID = 64000;
- ++commandID;
- return commandID;
-}
-
-/**
- * Returns true if this type of command requires a unique command ID.
- */
-Bool DoesCommandRequireACommandID(NetCommandType type) {
- if ((type == NETCOMMANDTYPE_GAMECOMMAND) ||
- (type == NETCOMMANDTYPE_FRAMEINFO) ||
- (type == NETCOMMANDTYPE_PLAYERLEAVE) ||
- (type == NETCOMMANDTYPE_DESTROYPLAYER) ||
- (type == NETCOMMANDTYPE_RUNAHEADMETRICS) ||
- (type == NETCOMMANDTYPE_RUNAHEAD) ||
- (type == NETCOMMANDTYPE_CHAT) ||
- (type == NETCOMMANDTYPE_DISCONNECTVOTE) ||
- (type == NETCOMMANDTYPE_LOADCOMPLETE) ||
- (type == NETCOMMANDTYPE_TIMEOUTSTART) ||
- (type == NETCOMMANDTYPE_WRAPPER) ||
- (type == NETCOMMANDTYPE_FILE) ||
- (type == NETCOMMANDTYPE_FILEANNOUNCE) ||
- (type == NETCOMMANDTYPE_FILEPROGRESS) ||
- (type == NETCOMMANDTYPE_DISCONNECTPLAYER) ||
- (type == NETCOMMANDTYPE_DISCONNECTFRAME) ||
- (type == NETCOMMANDTYPE_DISCONNECTSCREENOFF) ||
- (type == NETCOMMANDTYPE_FRAMERESENDREQUEST))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if this type of network command requires an ack.
- */
-Bool CommandRequiresAck(NetCommandMsg *msg) {
- if ((msg->getNetCommandType() == NETCOMMANDTYPE_GAMECOMMAND) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FRAMEINFO) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_PLAYERLEAVE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DESTROYPLAYER) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_RUNAHEADMETRICS) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_RUNAHEAD) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_CHAT) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTVOTE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTPLAYER) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_LOADCOMPLETE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_TIMEOUTSTART) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_WRAPPER) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FILE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FILEANNOUNCE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FILEPROGRESS) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTPLAYER) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTSCREENOFF) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FRAMERESENDREQUEST))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool IsCommandSynchronized(NetCommandType type) {
- if ((type == NETCOMMANDTYPE_GAMECOMMAND) ||
- (type == NETCOMMANDTYPE_FRAMEINFO) ||
- (type == NETCOMMANDTYPE_PLAYERLEAVE) ||
- (type == NETCOMMANDTYPE_DESTROYPLAYER) ||
- (type == NETCOMMANDTYPE_RUNAHEAD))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Returns true if this type of network command requires the ack to be sent directly to the player
- * rather than going through the packet router. This should really only be used by commands
- * used on the disconnect screen.
- */
-Bool CommandRequiresDirectSend(NetCommandMsg *msg) {
- if ((msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTVOTE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTPLAYER) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_LOADCOMPLETE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_TIMEOUTSTART) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FILE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FILEANNOUNCE) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FILEPROGRESS) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTSCREENOFF) ||
- (msg->getNetCommandType() == NETCOMMANDTYPE_FRAMERESENDREQUEST)) {
- return TRUE;
- }
- return FALSE;
-}
-
-const char* GetNetCommandTypeAsString(NetCommandType type) {
-
- switch (type) {
- case NETCOMMANDTYPE_ACKBOTH:
- return "NETCOMMANDTYPE_ACKBOTH";
- case NETCOMMANDTYPE_ACKSTAGE1:
- return "NETCOMMANDTYPE_ACKSTAGE1";
- case NETCOMMANDTYPE_ACKSTAGE2:
- return "NETCOMMANDTYPE_ACKSTAGE2";
- case NETCOMMANDTYPE_FRAMEINFO:
- return "NETCOMMANDTYPE_FRAMEINFO";
- case NETCOMMANDTYPE_GAMECOMMAND:
- return "NETCOMMANDTYPE_GAMECOMMAND";
- case NETCOMMANDTYPE_PLAYERLEAVE:
- return "NETCOMMANDTYPE_PLAYERLEAVE";
- case NETCOMMANDTYPE_RUNAHEADMETRICS:
- return "NETCOMMANDTYPE_RUNAHEADMETRICS";
- case NETCOMMANDTYPE_RUNAHEAD:
- return "NETCOMMANDTYPE_RUNAHEAD";
- case NETCOMMANDTYPE_DESTROYPLAYER:
- return "NETCOMMANDTYPE_DESTROYPLAYER";
- case NETCOMMANDTYPE_KEEPALIVE:
- return "NETCOMMANDTYPE_KEEPALIVE";
- case NETCOMMANDTYPE_DISCONNECTCHAT:
- return "NETCOMMANDTYPE_DISCONNECTCHAT";
- case NETCOMMANDTYPE_CHAT:
- return "NETCOMMANDTYPE_CHAT";
- case NETCOMMANDTYPE_MANGLERQUERY:
- return "NETCOMMANDTYPE_MANGLERQUERY";
- case NETCOMMANDTYPE_MANGLERRESPONSE:
- return "NETCOMMANDTYPE_MANGLERRESPONSE";
- case NETCOMMANDTYPE_PROGRESS:
- return "NETCOMMANDTYPE_PROGRESS";
- case NETCOMMANDTYPE_LOADCOMPLETE:
- return "NETCOMMANDTYPE_LOADCOMPLETE";
- case NETCOMMANDTYPE_TIMEOUTSTART:
- return "NETCOMMANDTYPE_TIMEOUTSTART";
- case NETCOMMANDTYPE_WRAPPER:
- return "NETCOMMANDTYPE_WRAPPER";
- case NETCOMMANDTYPE_FILE:
- return "NETCOMMANDTYPE_FILE";
- case NETCOMMANDTYPE_FILEANNOUNCE:
- return "NETCOMMANDTYPE_FILEANNOUNCE";
- case NETCOMMANDTYPE_FILEPROGRESS:
- return "NETCOMMANDTYPE_FILEPROGRESS";
- case NETCOMMANDTYPE_DISCONNECTKEEPALIVE:
- return "NETCOMMANDTYPE_DISCONNECTKEEPALIVE";
- case NETCOMMANDTYPE_DISCONNECTPLAYER:
- return "NETCOMMANDTYPE_DISCONNECTPLAYER";
- case NETCOMMANDTYPE_PACKETROUTERQUERY:
- return "NETCOMMANDTYPE_PACKETROUTERQUERY";
- case NETCOMMANDTYPE_PACKETROUTERACK:
- return "NETCOMMANDTYPE_PACKETROUTERACK";
- case NETCOMMANDTYPE_DISCONNECTVOTE:
- return "NETCOMMANDTYPE_DISCONNECTVOTE";
- case NETCOMMANDTYPE_DISCONNECTFRAME:
- return "NETCOMMANDTYPE_DISCONNECTFRAME";
- case NETCOMMANDTYPE_DISCONNECTSCREENOFF:
- return "NETCOMMANDTYPE_DISCONNECTSCREENOFF";
- case NETCOMMANDTYPE_FRAMERESENDREQUEST:
- return "NETCOMMANDTYPE_FRAMERESENDREQUEST";
- default:
- DEBUG_CRASH(("Unknown NetCommandType in GetNetCommandTypeAsString"));
- return "UNKNOWN";
- }
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/Transport.cpp b/Generals/Code/GameEngine/Source/GameNetwork/Transport.cpp
deleted file mode 100644
index eedbe729c82..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/Transport.cpp
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/crc.h"
-#include "GameNetwork/Transport.h"
-#include "GameNetwork/NetworkInterface.h"
-
-
-//--------------------------------------------------------------------------
-// Packet-level encryption is an XOR operation, for speed reasons. To get
-// the max throughput, we only XOR whole 4-byte words, so the last bytes
-// can be non-XOR'd.
-
-// This assumes the buf is a multiple of 4 bytes. Extra is not encrypted.
-static inline void encryptBuf( unsigned char *buf, Int len )
-{
- UnsignedInt mask = 0x0000Fade;
-
- UnsignedInt *uintPtr = (UnsignedInt *) (buf);
-
- for (int i=0 ; iBind(ip, port);
- }
-
- if (retval != 0) {
- DEBUG_CRASH(("Could not bind to 0x%8.8X:%d", ip, port));
- DEBUG_LOG(("Transport::init - Failure to bind socket with error code %x", retval));
- delete m_udpsock;
- m_udpsock = NULL;
- return false;
- }
-
- // ------- Clear buffers --------
- int i=0;
- for (; im_latencyAverage > 0 || TheGlobalData->m_latencyNoise)
- m_useLatency = true;
-
- if (TheGlobalData->m_packetLoss)
- m_usePacketLoss = true;
-#endif
-
- return true;
-}
-
-void Transport::reset( void )
-{
- delete m_udpsock;
- m_udpsock = NULL;
-
- if (m_winsockInit)
- {
- WSACleanup();
- m_winsockInit = false;
- }
-}
-
-Bool Transport::update( void )
-{
- Bool retval = TRUE;
- if (doRecv() == FALSE && m_udpsock && m_udpsock->GetStatus() == UDP::ADDRNOTAVAIL)
- {
- retval = FALSE;
- }
- DEBUG_ASSERTLOG(retval, ("WSA error is %s", GetWSAErrorString(WSAGetLastError()).str()));
- if (doSend() == FALSE && m_udpsock && m_udpsock->GetStatus() == UDP::ADDRNOTAVAIL)
- {
- retval = FALSE;
- }
- DEBUG_ASSERTLOG(retval, ("WSA error is %s", GetWSAErrorString(WSAGetLastError()).str()));
- return retval;
-}
-
-Bool Transport::doSend() {
- if (!m_udpsock)
- {
- DEBUG_LOG(("Transport::doSend() - m_udpSock is NULL!"));
- return FALSE;
- }
-
- Bool retval = TRUE;
-
- // Statistics gathering
- UnsignedInt now = timeGetTime();
- if (m_lastSecond + 1000 < now)
- {
- m_lastSecond = now;
- m_statisticsSlot = (m_statisticsSlot + 1) % MAX_TRANSPORT_STATISTICS_SECONDS;
- m_outgoingPackets[m_statisticsSlot] = 0;
- m_outgoingBytes[m_statisticsSlot] = 0;
- m_incomingPackets[m_statisticsSlot] = 0;
- m_incomingBytes[m_statisticsSlot] = 0;
- m_unknownPackets[m_statisticsSlot] = 0;
- m_unknownBytes[m_statisticsSlot] = 0;
- }
-
- // Send all messages
- int i;
- for (i=0; iWrite((unsigned char *)(&m_outBuffer[i]), bytesToSend, m_outBuffer[i].addr, m_outBuffer[i].port)) > 0)
- {
- //DEBUG_LOG(("Sending %d bytes to %d.%d.%d.%d:%d", bytesToSend, PRINTF_IP_AS_4_INTS(m_outBuffer[i].addr), m_outBuffer[i].port));
- m_outgoingPackets[m_statisticsSlot]++;
- m_outgoingBytes[m_statisticsSlot] += m_outBuffer[i].length + sizeof(TransportMessageHeader);
- m_outBuffer[i].length = 0; // Remove from queue
- if (bytesSent != bytesToSend)
- {
- DEBUG_LOG(("Transport::doSend - wanted to send %d bytes, only sent %d bytes to %d.%d.%d.%d:%d",
- bytesToSend, bytesSent,
- PRINTF_IP_AS_4_INTS(m_outBuffer[i].addr), m_outBuffer[i].port));
- }
- }
- else
- {
- //DEBUG_LOG(("Could not write to socket!!! Not discarding message!"));
- retval = FALSE;
- //DEBUG_LOG(("Transport::doSend returning FALSE"));
- }
- }
- }
-
-#if defined(RTS_DEBUG)
- // Latency simulation - deliver anything we're holding on to that is ready
- if (m_useLatency)
- {
- for (i=0; iRead(buf, MAX_MESSAGE_LEN, &from)) > 0 )
- {
-#if defined(RTS_DEBUG)
- // Packet loss simulation
- if (m_usePacketLoss)
- {
- if ( TheGlobalData->m_packetLoss >= GameClientRandomValue(0, 100) )
- {
- continue;
- }
- }
-#endif
-
-// DEBUG_LOG(("Transport::doRecv - Got something! len = %d", len));
- // Decrypt the packet
-// DEBUG_LOG_RAW(("buffer = "));
-// for (Int munkee = 0; munkee < len; ++munkee) {
-// DEBUG_LOG_RAW(("%02x", *(buf + munkee)));
-// }
-// DEBUG_LOG_RAW(("\n"));
- decryptBuf(buf, len);
-
- incomingMessage.length = len - sizeof(TransportMessageHeader);
-
- if (len <= sizeof(TransportMessageHeader) || !isGeneralsPacket( &incomingMessage ))
- {
- DEBUG_LOG(("Transport::doRecv - unknownPacket! len = %d", len));
- m_unknownPackets[m_statisticsSlot]++;
- m_unknownBytes[m_statisticsSlot] += len;
- continue;
- }
-
- // Something there; stick it somewhere
-// DEBUG_LOG(("Saw %d bytes from %d:%d", len, ntohl(from.sin_addr.S_un.S_addr), ntohs(from.sin_port)));
- m_incomingPackets[m_statisticsSlot]++;
- m_incomingBytes[m_statisticsSlot] += len;
-
- for (int i=0; im_latencyAverage +
- (Int)(TheGlobalData->m_latencyAmplitude * sin(now * TheGlobalData->m_latencyPeriod)) +
- GameClientRandomValue(-TheGlobalData->m_latencyNoise, TheGlobalData->m_latencyNoise);
- m_delayedInBuffer[i].message.length = incomingMessage.length;
- m_delayedInBuffer[i].message.addr = ntohl(from.sin_addr.S_un.S_addr);
- m_delayedInBuffer[i].message.port = ntohs(from.sin_port);
- memcpy(&m_delayedInBuffer[i].message, buf, len);
- break;
- }
- }
- else
- {
-#endif
- if (m_inBuffer[i].length == 0)
- {
- // Empty slot; use it
- m_inBuffer[i].length = incomingMessage.length;
- m_inBuffer[i].addr = ntohl(from.sin_addr.S_un.S_addr);
- m_inBuffer[i].port = ntohs(from.sin_port);
- memcpy(&m_inBuffer[i], buf, len);
- break;
- }
-#if defined(RTS_DEBUG)
- }
-#endif
- }
- //DEBUG_ASSERTCRASH(i MAX_PACKET_SIZE)
- {
- DEBUG_LOG(("Transport::queueSend - Invalid Packet size"));
- return false;
- }
-
- for (i=0; ilength < 0 || msg->length > MAX_MESSAGE_LEN)
- return false;
-
- CRC crc;
-// crc.computeCRC( (unsigned char *)msg->data, msg->length );
- crc.computeCRC( (unsigned char *)(&(msg->header.magic)), msg->length + sizeof(TransportMessageHeader) - sizeof(UnsignedInt) );
-
- if (crc.get() != msg->header.crc)
- return false;
-
- if (msg->header.magic != GENERALS_MAGIC_NUMBER)
- return false;
-
- return true;
-}
-
-// Statistics ---------------------------------------------------
-Real Transport::getIncomingBytesPerSecond( void )
-{
- Real val = 0.0;
- for (int i=0; i.
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////////
-// User class copy and comparisons
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameNetwork/User.h"
-
-/**
- * Constructor. Sets up the member variables with the appropriate values.
- */
-User::User(UnicodeString name, UnsignedInt addr, UnsignedInt port) {
- m_name.set(name);
- m_ipaddr = addr;
- m_port = port;
-}
-
-/**
- * The assignment operator.
- */
-User & User::operator= (const User *other)
-{
- m_name = other->m_name;
- m_ipaddr = other->m_ipaddr;
- m_port = other->m_port;
-
- return *this;
-}
-
-/**
- * The equality operator.
- */
-Bool User::operator== (const User *other)
-{
- return (m_name.compare(other->m_name) == 0);
-}
-
-/**
- * The inequality operator.
- */
-Bool User::operator!= (const User *other)
-{
- return (m_name.compare(other->m_name) != 0);
-}
-
-/**
- * Set the name of this user.
- */
-void User::setName(UnicodeString name) {
- m_name.set(name);
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/WOLBrowser/WebBrowser.cpp b/Generals/Code/GameEngine/Source/GameNetwork/WOLBrowser/WebBrowser.cpp
deleted file mode 100644
index c3b0bf2e463..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/WOLBrowser/WebBrowser.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-/******************************************************************************
-*
-* NAME
-* $Archive: $
-*
-* DESCRIPTION
-*
-* PROGRAMMER
-* Bryan Cleveland
-* $Author: $
-*
-* VERSION INFO
-* $Revision: $
-* $Modtime: $
-*
-******************************************************************************/
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-//#include "WinMain.h"
-#include "GameNetwork/WOLBrowser/WebBrowser.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/Display.h"
-
-
-/**
- * OLEInitializer class - Init and shutdown OLE & COM as a global
- * object. Scary, nasty stuff, COM. /me shivers.
- */
-class OLEInitializer
-{
-public:
- OLEInitializer()
- {
- // Initialize this instance
- OleInitialize(NULL);
- }
- ~OLEInitializer()
- {
- OleUninitialize();
- }
-};
-OLEInitializer g_OLEInitializer;
-CComModule _Module;
-
-CComObject * TheWebBrowser = NULL;
-
-
-/******************************************************************************
-*
-* NAME
-* WebBrowser::WebBrowser
-*
-* DESCRIPTION
-* Default constructor
-*
-* INPUTS
-* NONE
-*
-* RESULT
-* NONE
-*
-******************************************************************************/
-
-WebBrowser::WebBrowser() :
- mRefCount(1)
-{
- DEBUG_LOG(("Instantiating embedded WebBrowser"));
- m_urlList = NULL;
-}
-
-
-/******************************************************************************
-*
-* NAME
-* WebBrowser::~WebBrowser
-*
-* DESCRIPTION
-* Destructor
-*
-* INPUTS
-* NONE
-*
-* RESULT
-* NONE
-*
-******************************************************************************/
-
-WebBrowser::~WebBrowser()
-{
- DEBUG_LOG(("Destructing embedded WebBrowser"));
- if (this == TheWebBrowser) {
- DEBUG_LOG(("WebBrowser::~WebBrowser - setting TheWebBrowser to NULL"));
- TheWebBrowser = NULL;
- }
- WebBrowserURL *url = m_urlList;
- while (url != NULL) {
- WebBrowserURL *temp = url;
- url = url->m_next;
- deleteInstance(temp);
- temp = NULL;
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/** The INI data fields for Webpage URL's */
-//-------------------------------------------------------------------------------------------------
-const FieldParse WebBrowserURL::m_URLFieldParseTable[] =
-{
-
- { "URL", INI::parseAsciiString, NULL, offsetof( WebBrowserURL, m_url ) },
- { NULL, NULL, NULL, 0 },
-
-};
-
-WebBrowserURL::WebBrowserURL()
-{
- m_next = NULL;
- m_tag.clear();
- m_url.clear();
-}
-
-WebBrowserURL::~WebBrowserURL()
-{
-}
-/******************************************************************************
-*
-* NAME
-* WebBrowser::init
-*
-* DESCRIPTION
-* Perform post creation initialization.
-*
-* INPUTS
-* NONE
-*
-* RESULT
-* NONE
-*
-******************************************************************************/
-
-void WebBrowser::init()
-{
- m_urlList = NULL;
- INI ini;
- ini.loadFileDirectory( AsciiString( "Data\\INI\\Webpages" ), INI_LOAD_OVERWRITE, NULL );
-}
-
-/******************************************************************************
-*
-* NAME
-* WebBrowser::reset
-*
-* DESCRIPTION
-* Perform post creation initialization.
-*
-* INPUTS
-* NONE
-*
-* RESULT
-* NONE
-*
-******************************************************************************/
-
-void WebBrowser::reset()
-{
-}
-
-void WebBrowser::update( void )
-{
-}
-
-WebBrowserURL * WebBrowser::findURL(AsciiString tag)
-{
- WebBrowserURL *retval = m_urlList;
-
- while ((retval != NULL) && tag.compareNoCase(retval->m_tag.str()))
- {
- retval = retval->m_next;
- }
-
- return retval;
-}
-
-WebBrowserURL * WebBrowser::makeNewURL(AsciiString tag)
-{
- WebBrowserURL *newURL = newInstance(WebBrowserURL);
-
- newURL->m_tag = tag;
-
- newURL->m_next = m_urlList;
- m_urlList = newURL;
-
- return newURL;
-}
-
-/******************************************************************************
-*
-* NAME
-* IUnknown::QueryInterface
-*
-* DESCRIPTION
-*
-* INPUTS
-* IID - Interface ID
-*
-* RESULT
-*
-******************************************************************************/
-
-STDMETHODIMP WebBrowser::QueryInterface(REFIID iid, void** ppv) IUNKNOWN_NOEXCEPT
-{
- *ppv = NULL;
-
- if ((iid == IID_IUnknown) || (iid == IID_IBrowserDispatch))
- {
- *ppv = static_cast(this);
- }
- else
- {
- return E_NOINTERFACE;
- }
-
- static_cast(*ppv)->AddRef();
-
- return S_OK;
-}
-
-
-/******************************************************************************
-*
-* NAME
-* IUnknown::AddRef
-*
-* DESCRIPTION
-*
-* INPUTS
-* NONE
-*
-* RESULT
-*
-******************************************************************************/
-
-ULONG STDMETHODCALLTYPE WebBrowser::AddRef(void) IUNKNOWN_NOEXCEPT
-{
- return ++mRefCount;
-}
-
-
-/******************************************************************************
-*
-* NAME
-* IUnknown::Release
-*
-* DESCRIPTION
-*
-* INPUTS
-* NONE
-*
-* RESULT
-*
-******************************************************************************/
-
-ULONG STDMETHODCALLTYPE WebBrowser::Release(void) IUNKNOWN_NOEXCEPT
-{
- DEBUG_ASSERTCRASH(mRefCount > 0, ("Negative reference count"));
- --mRefCount;
-
- if (mRefCount == 0)
- {
- DEBUG_LOG(("WebBrowser::Release - all references released, deleting the object."));
- if (this == TheWebBrowser) {
- TheWebBrowser = NULL;
- }
- delete this;
- return 0;
- }
-
- return mRefCount;
-}
-
-STDMETHODIMP WebBrowser::TestMethod(Int num1)
-{
- DEBUG_LOG(("WebBrowser::TestMethod - num1 = %d", num1));
- return S_OK;
-}
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/udp.cpp b/Generals/Code/GameEngine/Source/GameNetwork/udp.cpp
deleted file mode 100644
index 469e6f1c38d..00000000000
--- a/Generals/Code/GameEngine/Source/GameNetwork/udp.cpp
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
-** Command & Conquer Generals(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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Udp.cpp //////////////////////////////////////////////////////////////
-// Implementation of UDP socket wrapper class (taken from wnet lib)
-// Author: Matthew D. Campbell, July 2001
-///////////////////////////////////////////////////////////////////////////////
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Common/GameEngine.h"
-//#include "GameNetwork/NetworkInterface.h"
-#include "GameNetwork/udp.h"
-
-
-//-------------------------------------------------------------------------
-
-#ifdef DEBUG_LOGGING
-
-#define CASE(x) case (x): return #x;
-
-AsciiString GetWSAErrorString( Int error )
-{
- switch (error)
- {
- CASE(WSABASEERR)
- CASE(WSAEINTR)
- CASE(WSAEBADF)
- CASE(WSAEACCES)
- CASE(WSAEFAULT)
- CASE(WSAEINVAL)
- CASE(WSAEMFILE)
- CASE(WSAEWOULDBLOCK)
- CASE(WSAEINPROGRESS)
- CASE(WSAEALREADY)
- CASE(WSAENOTSOCK)
- CASE(WSAEDESTADDRREQ)
- CASE(WSAEMSGSIZE)
- CASE(WSAEPROTOTYPE)
- CASE(WSAENOPROTOOPT)
- CASE(WSAEPROTONOSUPPORT)
- CASE(WSAESOCKTNOSUPPORT)
- CASE(WSAEOPNOTSUPP)
- CASE(WSAEPFNOSUPPORT)
- CASE(WSAEAFNOSUPPORT)
- CASE(WSAEADDRINUSE)
- CASE(WSAEADDRNOTAVAIL)
- CASE(WSAENETDOWN)
- CASE(WSAENETUNREACH)
- CASE(WSAENETRESET)
- CASE(WSAECONNABORTED)
- CASE(WSAECONNRESET)
- CASE(WSAENOBUFS)
- CASE(WSAEISCONN)
- CASE(WSAENOTCONN)
- CASE(WSAESHUTDOWN)
- CASE(WSAETOOMANYREFS)
- CASE(WSAETIMEDOUT)
- CASE(WSAECONNREFUSED)
- CASE(WSAELOOP)
- CASE(WSAENAMETOOLONG)
- CASE(WSAEHOSTDOWN)
- CASE(WSAEHOSTUNREACH)
- CASE(WSAENOTEMPTY)
- CASE(WSAEPROCLIM)
- CASE(WSAEUSERS)
- CASE(WSAEDQUOT)
- CASE(WSAESTALE)
- CASE(WSAEREMOTE)
- CASE(WSAEDISCON)
- CASE(WSASYSNOTREADY)
- CASE(WSAVERNOTSUPPORTED)
- CASE(WSANOTINITIALISED)
- CASE(WSAHOST_NOT_FOUND)
- CASE(WSATRY_AGAIN)
- CASE(WSANO_RECOVERY)
- CASE(WSANO_DATA)
- default:
- {
- AsciiString ret;
- ret.format("Not a Winsock error (%d)", error);
- return ret;
- }
- }
- return AsciiString::TheEmptyString; // will not be hit, ever.
-}
-
-#undef CASE
-
-#endif // defined(RTS_DEBUG)
-
-//-------------------------------------------------------------------------
-
-UDP::UDP()
-{
- fd=0;
-}
-
-UDP::~UDP()
-{
- if (fd)
- closesocket(fd);
-}
-
-Int UDP::Bind(const char *Host,UnsignedShort port)
-{
- struct hostent *hostStruct;
- struct in_addr *hostNode;
-
- if (isdigit(Host[0]))
- return ( Bind( ntohl(inet_addr(Host)), port) );
-
- hostStruct = gethostbyname(Host);
- if (hostStruct == NULL)
- return (0);
- hostNode = (struct in_addr *) hostStruct->h_addr;
- return ( Bind(ntohl(hostNode->s_addr),port) );
-}
-
-// You must call bind, implicit binding is for sissies
-// Well... you can get implicit binding if you pass 0 for either arg
-Int UDP::Bind(UnsignedInt IP,UnsignedShort Port)
-{
- int retval;
- int status;
-
- IP=htonl(IP);
- Port=htons(Port);
-
- addr.sin_family=AF_INET;
- addr.sin_port=Port;
- addr.sin_addr.s_addr=IP;
- fd=socket(AF_INET,SOCK_DGRAM,DEFAULT_PROTOCOL);
- #ifdef _WINDOWS
- if (fd==SOCKET_ERROR)
- fd=-1;
- #endif
- if (fd==-1)
- return(UNKNOWN);
-
- retval=bind(fd,(struct sockaddr *)&addr,sizeof(addr));
-
- #ifdef _WINDOWS
- if (retval==SOCKET_ERROR)
- {
- retval=-1;
- m_lastError = WSAGetLastError();
- }
- #endif
- if (retval==-1)
- {
- status=GetStatus();
- //CERR("Bind failure (" << status << ") IP " << IP << " PORT " << Port )
- return(status);
- }
-
- int namelen=sizeof(addr);
- getsockname(fd, (struct sockaddr *)&addr, &namelen);
-
- myIP=ntohl(addr.sin_addr.s_addr);
- myPort=ntohs(addr.sin_port);
-
- retval=SetBlocking(FALSE);
- if (retval==-1)
- fprintf(stderr,"Couldn't set nonblocking mode!\n");
-
- return(OK);
-}
-
-Int UDP::getLocalAddr(UnsignedInt &ip, UnsignedShort &port)
-{
- ip=myIP;
- port=myPort;
- return(OK);
-}
-
-
-// private function
-Int UDP::SetBlocking(Int block)
-{
- #ifdef _WINDOWS
- unsigned long flag=1;
- if (block)
- flag=0;
- int retval;
- retval=ioctlsocket(fd,FIONBIO,&flag);
- if (retval==SOCKET_ERROR)
- return(UNKNOWN);
- else
- return(OK);
- #else // UNIX
- int flags = fcntl(fd, F_GETFL, 0);
- if (block==FALSE) // set nonblocking
- flags |= O_NONBLOCK;
- else // set blocking
- flags &= ~(O_NONBLOCK);
-
- if (fcntl(fd, F_SETFL, flags) < 0)
- {
- return(UNKNOWN);
- }
- return(OK);
- #endif
-}
-
-
-Int UDP::Write(const unsigned char *msg,UnsignedInt len,UnsignedInt IP,UnsignedShort port)
-{
- Int retval;
- struct sockaddr_in to;
-
- // This happens frequently
- if ((IP==0)||(port==0)) return(ADDRNOTAVAIL);
-
-#ifdef _UNIX
- errno=0;
-#endif
- to.sin_port=htons(port);
- to.sin_addr.s_addr=htonl(IP);
- to.sin_family=AF_INET;
-
- ClearStatus();
- retval=sendto(fd,(const char *)msg,len,0,(struct sockaddr *)&to,sizeof(to));
- #ifdef _WINDOWS
- if (retval==SOCKET_ERROR)
- {
- retval=-1;
- m_lastError = WSAGetLastError();
-#ifdef DEBUG_LOGGING
- static Int errCount = 0;
-#endif
- DEBUG_ASSERTLOG(errCount++ > 100, ("UDP::Write() - WSA error is %s", GetWSAErrorString(WSAGetLastError()).str()));
- }
- #endif
-
- return(retval);
-}
-
-Int UDP::Read(unsigned char *msg,UnsignedInt len,sockaddr_in *from)
-{
- Int retval;
- int alen=sizeof(sockaddr_in);
-
- if (from!=NULL)
- {
- retval=recvfrom(fd,(char *)msg,len,0,(struct sockaddr *)from,&alen);
- #ifdef _WINDOWS
- if (retval == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- {
- // failing because of a blocking error isn't really such a bad thing.
- m_lastError = WSAGetLastError();
-#ifdef DEBUG_LOGGING
- static Int errCount = 0;
-#endif
- DEBUG_ASSERTLOG(errCount++ > 100, ("UDP::Read() - WSA error is %s", GetWSAErrorString(WSAGetLastError()).str()));
- retval = -1;
- } else {
- retval = 0;
- }
- }
- #endif
- }
- else
- {
- retval=recvfrom(fd,(char *)msg,len,0,NULL,NULL);
- #ifdef _WINDOWS
- if (retval==SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- {
- // failing because of a blocking error isn't really such a bad thing.
- m_lastError = WSAGetLastError();
-#ifdef DEBUG_LOGGING
- static Int errCount = 0;
-#endif
- DEBUG_ASSERTLOG(errCount++ > 100, ("UDP::Read() - WSA error is %s", GetWSAErrorString(WSAGetLastError()).str()));
- retval = -1;
- } else {
- retval = 0;
- }
- }
- #endif
- }
- return(retval);
-}
-
-
-void UDP::ClearStatus(void)
-{
- #ifndef _WINDOWS
- errno=0;
- #endif
-
- m_lastError = 0;
-}
-
-UDP::sockStat UDP::GetStatus(void)
-{
- Int status = m_lastError;
- #ifdef _WINDOWS
- //int status=WSAGetLastError();
- switch (status) {
- case NO_ERROR:
- return OK;
- case WSAEINTR:
- return INTR;
- case WSAEINPROGRESS:
- return INPROGRESS;
- case WSAECONNREFUSED:
- return CONNREFUSED;
- case WSAEINVAL:
- return INVAL;
- case WSAEISCONN:
- return ISCONN;
- case WSAENOTSOCK:
- return NOTSOCK;
- case WSAETIMEDOUT:
- return TIMEDOUT;
- case WSAEALREADY:
- return ALREADY;
- case WSAEWOULDBLOCK:
- return WOULDBLOCK;
- case WSAEBADF:
- return BADF;
- default:
- return (UDP::sockStat)status;
- }
- #else
- //int status=errno;
- switch (status) {
- case 0:
- return OK;
- case EINTR:
- return INTR;
- case EINPROGRESS:
- return INPROGRESS;
- case ECONNREFUSED:
- return CONNREFUSED;
- case EINVAL:
- return INVAL;
- case EISCONN:
- return ISCONN;
- case ENOTSOCK:
- return NOTSOCK;
- case ETIMEDOUT:
- return TIMEDOUT;
- case EALREADY:
- return ALREADY;
- case EAGAIN:
- return AGAIN;
- case EWOULDBLOCK:
- return WOULDBLOCK;
- case EBADF:
- return BADF;
- default:
- return UNKNOWN;
- }
- #endif
-}
-
-
-
-/*
-//
-// Wait for net activity on this socket
-//
-int UDP::Wait(Int sec,Int usec,fd_set &returnSet)
-{
- fd_set inputSet;
-
- FD_ZERO(&inputSet);
- FD_SET(fd,&inputSet);
-
- return(Wait(sec,usec,inputSet,returnSet));
-}
-*/
-
-/*
-//
-// Wait for net activity on a list of sockets
-//
-int UDP::Wait(Int sec,Int usec,fd_set &givenSet,fd_set &returnSet)
-{
- Wtime timeout,timenow,timethen;
- fd_set backupSet;
- int retval=0,done,givenMax;
- Bool noTimeout=FALSE;
- timeval tv;
-
- returnSet=givenSet;
- backupSet=returnSet;
-
- if ((sec==-1)&&(usec==-1))
- noTimeout=TRUE;
-
- timeout.SetSec(sec);
- timeout.SetUsec(usec);
- timethen+=timeout;
-
- givenMax=fd;
- for (UnsignedInt i=0; i<(sizeof(fd_set)*8); i++) // i=maxFD+1
- {
- if (FD_ISSET(i,&givenSet))
- givenMax=i;
- }
- ///DBGMSG("WAIT fd="<