/*
** 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. //
// //
////////////////////////////////////////////////////////////////////////////////
// GameClient.h ///////////////////////////////////////////////////////////////
// GameClient singleton class - defines interface to GameClient methods and drawables
// Author: Michael S. Booth, March 2001
#pragma once
#ifndef _GAME_INTERFACE_H_
#define _GAME_INTERFACE_H_
#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, rts::equal_to > 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( void ); ///< Initialize resources
virtual void update( void ); ///< Updates the GUI, display, audio, etc
virtual void reset( void ); ///< 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 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( void ) { return m_nextDrawableID; }
virtual Drawable *firstDrawable( void ) { return m_drawableList; }
virtual GameMessage::Type evaluateContextCommand( Drawable *draw,
const Coord3D *pos,
CommandTranslator::CommandEvaluateType cmdType );
void addTextBearingDrawable( Drawable *tbd );
void flushTextBearingDrawables( void);
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, DrawableStatus statusBits = DRAWABLE_STATUS_NONE ) = 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( void ) { 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 adjustLOD( Int adj ) = 0; ///< @todo hack for evaluation, remove.
virtual void releaseShadows(void); ///< frees all shadow resources used by this module - used by Options screen.
virtual void allocateShadows(void); ///< create shadow resources if not already present. Used by Options screen.
virtual void preloadAssets( TimeOfDay timeOfDay ); ///< preload assets
virtual Drawable *getDrawableList( void ) { return m_drawableList; }
void resetRenderedObjectCount() { m_renderedObjectCount = 0; }
UnsignedInt getRenderedObjectCount() const { return m_renderedObjectCount; }
void incrementRenderedObjectCount() { m_renderedObjectCount++; }
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
// @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( void ); ///< 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( void ) = 0; ///< Factory for Display classes. Called during init to instantiate TheDisplay.
virtual InGameUI *createInGameUI( void ) = 0; ///< Factory for InGameUI classes. Called during init to instantiate TheInGameUI
virtual GameWindowManager *createWindowManager( void ) = 0; ///< Factory to window manager
virtual FontLibrary *createFontLibrary( void ) = 0; ///< Factory for font library
virtual DisplayStringManager *createDisplayStringManager( void ) = 0; ///< Factory for display strings
virtual VideoPlayerInterface *createVideoPlayer( void ) = 0;///< Factory for video device
virtual TerrainVisual *createTerrainVisual( void ) = 0; ///< Factory for TerrainVisual classes. Called during init to instance TheTerrainVisual
virtual Keyboard *createKeyboard( void ) = 0; ///< factory for the keyboard
virtual Mouse *createMouse( void ) = 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 != NULL; DRAW = _xq_nextDrawable ) \
{ \
_xq_nextDrawable = DRAW->getNextDrawable(); \
if (DRAW->getStatusFlags() & (STATUS)) \
{
#define END_ITERATE_DRAWABLES \
} \
} \
} while (0);
// the singleton
extern GameClient *TheGameClient;
#endif // _GAME_INTERFACE_H_