forked from electronicarts/CnC_Generals_Zero_Hour
-
Notifications
You must be signed in to change notification settings - Fork 188
Expand file tree
/
Copy pathGameClient.h
More file actions
276 lines (223 loc) · 12.2 KB
/
GameClient.h
File metadata and controls
276 lines (223 loc) · 12.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*
** 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 <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// GameClient.h ///////////////////////////////////////////////////////////////
// GameClient singleton class - defines interface to GameClient methods and drawables
// Author: Michael S. Booth, March 2001
#pragma once
#include "Common/GameType.h"
#include "Common/MessageStream.h" // for GameMessageTranslator
#include "Common/Snapshot.h"
#include "Common/STLTypedefs.h"
#include "Common/SubsystemInterface.h"
#include "GameClient/CommandXlat.h"
#include "GameClient/Drawable.h"
// forward declarations
class AsciiString;
class Display;
class DisplayStringManager;
class Drawable;
class FontLibrary;
class GameWindowManager;
class InGameUI;
class Keyboard;
class Mouse;
class ParticleSystemManager;
class TerrainVisual;
class ThingTemplate;
class VideoPlayerInterface;
struct RayEffectData;
/// Function pointers for use by GameClient callback functions.
typedef void (*GameClientFuncPtr)( Drawable *draw, void *userData );
typedef std::hash_map<DrawableID, Drawable *, rts::hash<DrawableID>, rts::equal_to<DrawableID> > DrawablePtrHash;
typedef DrawablePtrHash::iterator DrawablePtrHashIt;
//-----------------------------------------------------------------------------
/** The Client message dispatcher, this is the last "translator" on the message
* stream before the messages go to the network for processing. It gives
* the client itself the opportunity to respond to any messages on the stream
* or create new ones to pass along to the network and logic */
class GameClientMessageDispatcher : public GameMessageTranslator
{
public:
virtual GameMessageDisposition translateGameMessage(const GameMessage *msg);
virtual ~GameClientMessageDispatcher() { }
};
//-----------------------------------------------------------------------------
/**
* The GameClient class is used to instantiate a singleton which
* implements the interface to all GameClient operations such as Drawable access and user-interface functions.
*/
class GameClient : public SubsystemInterface,
public Snapshot
{
public:
GameClient();
virtual ~GameClient();
// subsystem methods
virtual void init(); ///< Initialize resources
virtual void update(); ///< Updates the GUI, display, audio, etc
virtual void reset(); ///< reset system
virtual void setFrame( UnsignedInt frame ) { m_frame = frame; } ///< Set the GameClient's internal frame number
virtual void registerDrawable( Drawable *draw ); ///< Given a drawable, register it with the GameClient and give it a unique ID
void step(); ///< Do one fixed time step
void updateHeadless();
void addDrawableToLookupTable( Drawable *draw ); ///< add drawable ID to hash lookup table
void removeDrawableFromLookupTable( Drawable *draw ); ///< remove drawable ID from hash lookup table
virtual Drawable *findDrawableByID( const DrawableID id ); ///< Given an ID, return the associated drawable
void setDrawableIDCounter( DrawableID nextDrawableID ) { m_nextDrawableID = nextDrawableID; }
DrawableID getDrawableIDCounter() { return m_nextDrawableID; }
virtual Drawable *firstDrawable() { return m_drawableList; }
virtual GameMessage::Type evaluateContextCommand( Drawable *draw,
const Coord3D *pos,
CommandTranslator::CommandEvaluateType cmdType );
void addTextBearingDrawable( Drawable *tbd );
void flushTextBearingDrawables();
void updateFakeDrawables();
virtual void removeFromRayEffects( Drawable *draw ); ///< remove the drawable from the ray effect system if present
virtual void getRayEffectData( Drawable *draw, RayEffectData *effectData ); ///< get ray effect data for a drawable
virtual void createRayEffectByTemplate( const Coord3D *start, const Coord3D *end, const ThingTemplate* tmpl ) = 0; ///< create effect needing start and end location
virtual void addScorch(const Coord3D *pos, Real radius, Scorches type) = 0;
virtual Bool loadMap( AsciiString mapName ); ///< load a map into our scene
virtual void unloadMap( AsciiString mapName ); ///< unload the specified map from our scene
virtual void iterateDrawablesInRegion( Region3D *region, GameClientFuncPtr userFunc, void *userData ); ///< Calls userFunc for each drawable contained within the region
virtual Drawable *friend_createDrawable( const ThingTemplate *thing, DrawableStatusBits statusBits = DRAWABLE_STATUS_DEFAULT ) = 0;
virtual void destroyDrawable( Drawable *draw ); ///< Destroy the given drawable
virtual void setTimeOfDay( TimeOfDay tod ); ///< Tell all the drawables what time of day it is now
virtual void selectDrawablesInGroup( Int group ); ///< select all drawables belong to the specifies group
virtual void assignSelectedDrawablesToGroup( Int group ); ///< assign all selected drawables to the specified group
//---------------------------------------------------------------------------------------
virtual UnsignedInt getFrame() { return m_frame; } ///< Returns the current simulation frame number
//---------------------------------------------------------------------------
virtual void setTeamColor( Int red, Int green, Int blue ) = 0; ///< @todo superhack for demo, remove!!!
virtual void setTextureLOD( Int level ) = 0;
virtual void releaseShadows(); ///< frees all shadow resources used by this module - used by Options screen.
virtual void allocateShadows(); ///< create shadow resources if not already present. Used by Options screen.
virtual void preloadAssets( TimeOfDay timeOfDay ); ///< preload assets
virtual Drawable *getDrawableList() { return m_drawableList; }
void resetRenderedObjectCount() { m_renderedObjectCount = 0; }
UnsignedInt getRenderedObjectCount() const { return m_renderedObjectCount; }
void incrementRenderedObjectCount() { m_renderedObjectCount++; }
static Bool isMovieAbortRequested();
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess();
// @todo Should there be a separate GameClient frame counter?
UnsignedInt m_frame; ///< Simulation frame number from server
Drawable *m_drawableList; ///< All of the drawables in the world
DrawablePtrHash m_drawableHash; ///< Used for DrawableID lookups
DrawableID m_nextDrawableID; ///< For allocating drawable id's
DrawableID allocDrawableID(); ///< Returns a new unique drawable id
enum { MAX_CLIENT_TRANSLATORS = 32 };
TranslatorID m_translators[ MAX_CLIENT_TRANSLATORS ]; ///< translators we have used
UnsignedInt m_numTranslators; ///< number of translators in m_translators[]
CommandTranslator *m_commandTranslator; ///< the command translator on the message stream
private:
UnsignedInt m_renderedObjectCount; ///< Keeps track of the number of rendered objects -- resets each frame.
//---------------------------------------------------------------------------
virtual Display *createGameDisplay() = 0; ///< Factory for Display classes. Called during init to instantiate TheDisplay.
virtual InGameUI *createInGameUI() = 0; ///< Factory for InGameUI classes. Called during init to instantiate TheInGameUI
virtual GameWindowManager *createWindowManager() = 0; ///< Factory to window manager
virtual FontLibrary *createFontLibrary() = 0; ///< Factory for font library
virtual DisplayStringManager *createDisplayStringManager() = 0; ///< Factory for display strings
virtual VideoPlayerInterface *createVideoPlayer() = 0;///< Factory for video device
virtual TerrainVisual *createTerrainVisual() = 0; ///< Factory for TerrainVisual classes. Called during init to instance TheTerrainVisual
virtual Keyboard *createKeyboard() = 0; ///< factory for the keyboard
virtual Mouse *createMouse() = 0; ///< factory for the mouse
virtual void setFrameRate(Real msecsPerFrame) = 0;
// ----------------------------------------------------------------------------------------------
struct DrawableTOCEntry
{
AsciiString name;
UnsignedShort id;
};
typedef std::list< DrawableTOCEntry > DrawableTOCList;
typedef DrawableTOCList::iterator DrawableTOCListIterator;
DrawableTOCList m_drawableTOC; ///< the drawable TOC
void addTOCEntry( AsciiString name, UnsignedShort id ); ///< add a new name/id TOC pair
DrawableTOCEntry *findTOCEntryByName( AsciiString name ); ///< find DrawableTOC by name
DrawableTOCEntry *findTOCEntryById( UnsignedShort id ); ///< find DrawableTOC by id
void xferDrawableTOC( Xfer *xfer ); ///< save/load drawable TOC for current state of map
typedef std::list< Drawable* > TextBearingDrawableList;
typedef TextBearingDrawableList::iterator TextBearingDrawableListIterator;
TextBearingDrawableList m_textBearingDrawableList; ///< the drawables that have registered here during drawablepostdraw
};
//Kris: Try not to use this if possible. In every case I found in the code base, the status was always Drawable::SELECTED.
// There is another iterator already in game that stores JUST selected drawables. Take a look at the efficient
// example, InGameUI::getAllSelectedDrawables().
#define BEGIN_ITERATE_DRAWABLES_WITH_STATUS(STATUS, DRAW) \
do \
{ \
Drawable* _xq_nextDrawable; \
for (Drawable* DRAW = TheGameClient->firstDrawable(); DRAW != nullptr; DRAW = _xq_nextDrawable ) \
{ \
_xq_nextDrawable = DRAW->getNextDrawable(); \
if (DRAW->getStatusFlags() & (STATUS)) \
{
#define END_ITERATE_DRAWABLES \
} \
} \
} while (0);
// the singleton
extern GameClient *TheGameClient;
// TheSuperHackers @logic-client-separation helmutbuhler 11/04/2025
// Some information about the architecture and headless mode:
// The game is structurally separated into GameLogic and GameClient.
// The Logic is responsible for everything that affects the game mechanic and what is synchronized over
// the network. The Client is responsible for rendering, input, audio and similar stuff.
//
// Unfortunately there are some places in the code that make the Logic depend on the Client.
// (Search for @logic-client-separation)
// That means if we want to run the game headless, we cannot just disable the Client. We need to disable
// the parts in the Client that don't work in headless mode and need to keep the parts that are needed
// to run the Logic.
// The following describes which parts we disable in headless mode:
//
// GameEngine:
// TheGameClient is partially disabled:
// TheKeyboard = nullptr
// TheMouse = nullptr
// TheDisplay is partially disabled:
// m_3DInterfaceScene = nullptr
// m_2DScene = nullptr
// m_3DScene = nullptr
// (m_assetManager remains!)
// TheWindowManager = GameWindowManagerDummy
// TheIMEManager = nullptr
// TheTerrainVisual is partially disabled:
// TheTerrainTracksRenderObjClassSystem = nullptr
// TheW3DShadowManager = nullptr
// TheWaterRenderObj = nullptr
// TheSmudgeManager = nullptr
// TheTerrainRenderObject is partially disabled:
// m_treeBuffer = nullptr
// m_propBuffer = nullptr
// m_bibBuffer = nullptr
// m_bridgeBuffer is partially disabled:
// m_vertexBridge = nullptr
// m_indexBridge = nullptr
// m_vertexMaterial = nullptr
// m_waypointBuffer = nullptr
// m_roadBuffer = nullptr
// m_shroud = nullptr
// TheRadar = RadarDummy