/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: MessageStream.h //////////////////////////////////////////////////////
// The message stream propagates all messages thru a series of "translators"
// Author: Michael S. Booth, February 2001
#pragma once
#ifndef _MESSAGE_STREAM_H_
#define _MESSAGE_STREAM_H_
#include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
#include "Common/SubsystemInterface.h"
#include "Lib/BaseType.h"
#include "Common/GameMemory.h"
enum { TRANSLATOR_ID_INVALID = -1 };
// how far the the cursor moves before a click becomes a drag
typedef UnsignedInt TranslatorID; ///< Unique identifiers for message stream translators
class Drawable;
class GameMessageList;
enum ObjectID;
enum DrawableID;
union GameMessageArgumentType ///< Union of possible data for given message type
{
Int integer;
Real real;
Bool boolean;
ObjectID objectID;
DrawableID drawableID;
UnsignedInt teamID;
UnsignedInt squadID;
Coord3D location;
ICoord2D pixel;
IRegion2D pixelRegion;
UnsignedInt timestamp;
WideChar wChar;
};
enum GameMessageArgumentDataType
{
ARGUMENTDATATYPE_INTEGER,
ARGUMENTDATATYPE_REAL,
ARGUMENTDATATYPE_BOOLEAN,
ARGUMENTDATATYPE_OBJECTID,
ARGUMENTDATATYPE_DRAWABLEID,
ARGUMENTDATATYPE_TEAMID,
ARGUMENTDATATYPE_LOCATION,
ARGUMENTDATATYPE_PIXEL,
ARGUMENTDATATYPE_PIXELREGION,
ARGUMENTDATATYPE_TIMESTAMP,
ARGUMENTDATATYPE_WIDECHAR,
ARGUMENTDATATYPE_UNKNOWN
};
class GameMessageArgument : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessageArgument, "GameMessageArgument")
public:
GameMessageArgument* m_next; ///< The next argument
GameMessageArgumentType m_data; ///< The data storage of an argument
GameMessageArgumentDataType m_type; ///< The type of the argument.
};
EMPTY_DTOR(GameMessageArgument)
/**
* A game message that either lives on TheMessageStream or TheCommandList.
* Messages consist of a type, defining what the message is, and zero or more arguments
* of various data types. The user of a message must know how many and what type of
* arguments are valid for a given message type.
*/
class GameMessage : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessage, "GameMessage")
public:
/// The various messages which can be sent in a MessageStream
/// @todo Replace this hardcoded enum with a generalized system that can be easily changed and updated
/** @todo Because the Client will run faster than Logic, we'll need "superceding" messages for events
such as mouse movements so we only send the latest one over the net */
/** @todo Create two classes of message: raw input messages, and command messages. Raw input messages
will be destroyed when they reach the end of the stream, whereas command messages will be
transferred to TheCommandList */
enum Type
{
MSG_INVALID, ///< (none) this msg should never actually occur
MSG_FRAME_TICK, ///< (timestamp) once each frame this message is sent thru the stream
// Client to Server messages
// Note: Please keep MSG_RAW_MOUSE between MSG_RAW_MOUSE_BEGIN and MSG_RAW_MOUSE_END
MSG_RAW_MOUSE_BEGIN,
MSG_RAW_MOUSE_POSITION, ///< (pixel) the cursor's position
MSG_RAW_MOUSE_LEFT_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_WHEEL, ///< (Int spin, + is away, - is toward user)
MSG_RAW_MOUSE_END,
MSG_RAW_KEY_DOWN, ///< (KeyDefType) the given key was pressed (uses Microsoft VK_ codes)
MSG_RAW_KEY_UP, ///< (KeyDefType) the given key was released
// Refined Mouse messages
// NOTE: All processing should attempt to use these refined mouse messages, rather than the
// RAW_* variants. (Please.) :-) jkmcd
MSG_MOUSE_LEFT_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_LEFT_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_MIDDLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_MIDDLE_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_RIGHT_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
// End Refined Mouse Messages
MSG_CLEAR_GAME_DATA, ///< Clear all game data in memory
MSG_NEW_GAME, ///< Start a new game
// "meta" messages should be thought of as "virtual keystrokes" -- they exist
// solely to provide an abstraction layer useful for keyboard/mouse remapping.
// they should NEVER be sent over the network.
MSG_BEGIN_META_MESSAGES, ///< Marker to delineate "meta" messages
MSG_META_SAVE_VIEW1, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW2, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW3, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW4, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW5, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW6, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW7, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW8, ///< save current view as the given user-defined view
MSG_META_VIEW_VIEW1, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW2, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW3, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW4, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW5, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW6, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW7, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW8, ///< center view on the given user-defined view
MSG_META_CREATE_TEAM0, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM1, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM2, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM3, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM4, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM5, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM6, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM7, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM8, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM9, ///< create user-defined team from the selected objects
MSG_META_SELECT_TEAM0, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM1, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM2, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM3, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM4, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM5, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM6, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM7, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM8, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM9, ///< deselect all, then select all units in the given user-defined team
MSG_META_ADD_TEAM0, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM1, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM2, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM3, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM4, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM5, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM6, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM7, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM8, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM9, ///< add the user-defined team to the current selection
MSG_META_VIEW_TEAM0, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM1, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM2, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM3, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM4, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM5, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM6, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM7, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM8, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM9, ///< center view on given user-defined team (but do not affect selection)
MSG_META_SELECT_MATCHING_UNITS, ///< selects mathcing units, used for both on screen and across map
MSG_META_SELECT_NEXT_UNIT, ///< select 'next' unit
MSG_META_SELECT_PREV_UNIT, ///< select 'prev' unit
MSG_META_SELECT_NEXT_WORKER, ///< select 'next' worker
MSG_META_SELECT_PREV_WORKER, ///< select 'prev' worker
MSG_META_VIEW_COMMAND_CENTER, ///< center view on command center
MSG_META_VIEW_LAST_RADAR_EVENT, ///< center view on last radar event
MSG_META_SELECT_HERO, ///< selects player's hero character, if exists...
MSG_META_SELECT_ALL, ///< selects all units across screen
MSG_META_SELECT_ALL_AIRCRAFT, ///< selects all air units just like select all
MSG_META_SCATTER, ///< selected units scatter
MSG_META_STOP, ///< selected units stop
MSG_META_DEPLOY, ///< selected units 'deploy'
MSG_META_CREATE_FORMATION, ///< selected units become a formation
MSG_META_FOLLOW, ///< selected units 'follow'
MSG_META_CHAT_PLAYERS, ///< send chat msg to all players
MSG_META_CHAT_ALLIES, ///< send chat msg to allied players
MSG_META_CHAT_EVERYONE, ///< send chat msg to everyone (incl. observers)
MSG_META_DIPLOMACY, ///< bring up diplomacy screen
MSG_META_OPTIONS, ///< bring up options screen
#if defined(_DEBUG) || defined(_INTERNAL)
MSG_META_HELP, ///< bring up help screen
#endif
MSG_META_TOGGLE_LOWER_DETAILS, ///< toggles graphics options to crappy mode instantly
MSG_META_TOGGLE_CONTROL_BAR, ///< show/hide controlbar
MSG_META_BEGIN_PATH_BUILD, ///< enter path-building mode
MSG_META_END_PATH_BUILD, ///< exit path-building mode
MSG_META_BEGIN_FORCEATTACK, ///< enter force-attack mode
MSG_META_END_FORCEATTACK, ///< exit force-attack mode
MSG_META_BEGIN_FORCEMOVE, ///< enter force-move mode
MSG_META_END_FORCEMOVE, ///< exit force-move mode
MSG_META_BEGIN_WAYPOINTS, ///< enter waypoint mode
MSG_META_END_WAYPOINTS, ///< exit waypoint mode
MSG_META_BEGIN_PREFER_SELECTION, ///< The Shift key has been depressed alone
MSG_META_END_PREFER_SELECTION, ///< The Shift key has been released.
MSG_META_TAKE_SCREENSHOT, ///< take screenshot
MSG_META_ALL_CHEER, ///< Yay! :)
MSG_META_TOGGLE_ATTACKMOVE, ///< enter attack-move mode
MSG_META_BEGIN_CAMERA_ROTATE_LEFT,
MSG_META_END_CAMERA_ROTATE_LEFT,
MSG_META_BEGIN_CAMERA_ROTATE_RIGHT,
MSG_META_END_CAMERA_ROTATE_RIGHT,
MSG_META_BEGIN_CAMERA_ZOOM_IN,
MSG_META_END_CAMERA_ZOOM_IN,
MSG_META_BEGIN_CAMERA_ZOOM_OUT,
MSG_META_END_CAMERA_ZOOM_OUT,
MSG_META_CAMERA_RESET,
MSG_META_TOGGLE_CAMERA_TRACKING_DRAWABLE,
MSG_META_TOGGLE_FAST_FORWARD_REPLAY, ///< Toggle the fast forward feature
MSG_META_DEMO_INSTANT_QUIT, ///< bail out of game immediately
#if defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)//may be defined in GameCommon.h
MSG_CHEAT_RUNSCRIPT1, ///< run script named "KEY_F1"
MSG_CHEAT_RUNSCRIPT2, ///< run script named "KEY_F2"
MSG_CHEAT_RUNSCRIPT3, ///< run script named "KEY_F3"
MSG_CHEAT_RUNSCRIPT4, ///< run script named "KEY_F4"
MSG_CHEAT_RUNSCRIPT5, ///< run script named "KEY_F5"
MSG_CHEAT_RUNSCRIPT6, ///< run script named "KEY_F6"
MSG_CHEAT_RUNSCRIPT7, ///< run script named "KEY_F7"
MSG_CHEAT_RUNSCRIPT8, ///< run script named "KEY_F8"
MSG_CHEAT_RUNSCRIPT9, ///< run script named "KEY_F9"
MSG_CHEAT_TOGGLE_SPECIAL_POWER_DELAYS, ///< Toggle special power delays on/off
MSG_CHEAT_SWITCH_TEAMS, ///< switch local control to another team
MSG_CHEAT_KILL_SELECTION, ///< kill the selected units (yeah!)
MSG_CHEAT_TOGGLE_HAND_OF_GOD_MODE, ///< do 100% damage to the selected units (w00t!)
MSG_CHEAT_INSTANT_BUILD, ///< All building is with a timer of 1
MSG_CHEAT_DESHROUD, ///< de-shroud the world for the local player
MSG_CHEAT_ADD_CASH, ///< adds 10000 cash to the player
MSG_CHEAT_GIVE_ALL_SCIENCES, ///< grant all grantable sciences
MSG_CHEAT_GIVE_SCIENCEPURCHASEPOINTS, ///< give yourself an SPP (but no rank change)
MSG_CHEAT_SHOW_HEALTH, ///< show object health
MSG_CHEAT_TOGGLE_MESSAGE_TEXT, ///< hides/shows the onscreen messages
#endif
// META items that are really for debug/demo/development use only...
// They do not get built into RELEASE builds.
#if defined(_DEBUG) || defined(_INTERNAL)
MSG_META_DEMO_TOGGLE_BEHIND_BUILDINGS, ///< Toggles showing units behind buildings or not
MSG_META_DEMO_TOGGLE_LETTERBOX, ///< enable/disable letterbox mode
MSG_META_DEMO_TOGGLE_MESSAGE_TEXT, ///< toggle the text from the UI messages
MSG_META_DEMO_LOD_DECREASE, ///< decrease LOD by 1
MSG_META_DEMO_LOD_INCREASE, ///< increase LOD by 1
MSG_META_DEMO_TOGGLE_ZOOM_LOCK, ///< Toggle the camera zoom lock on/off
MSG_META_DEMO_PLAY_CAMEO_MOVIE, ///< Play a movie in the cameo spot
MSG_META_DEMO_TOGGLE_SPECIAL_POWER_DELAYS, ///< Toggle special power delays on/off
MSG_META_DEMO_BATTLE_CRY, ///< battle cry
MSG_META_DEMO_SWITCH_TEAMS, ///< switch local control to another team
MSG_META_DEMO_SWITCH_TEAMS_BETWEEN_CHINA_USA, ///< switch the local player between china and usa
MSG_META_DEMO_TOGGLE_PARTICLEDEBUG, ///< show/hide the particle system debug info
MSG_META_DEMO_TOGGLE_SHADOW_VOLUMES, ///< show/hide shadow volumes
MSG_META_DEMO_TOGGLE_FOGOFWAR,
MSG_META_DEMO_KILL_ALL_ENEMIES, ///< kill ALL ENEMIES! (yeah!)
MSG_META_DEMO_KILL_SELECTION, ///< kill the selected units (yeah!)
MSG_META_DEMO_TOGGLE_HURT_ME_MODE, ///< do 10% damage to the selected units (yeah!)
MSG_META_DEMO_TOGGLE_HAND_OF_GOD_MODE, ///< do 100% damage to the selected units (w00t!)
MSG_META_DEMO_DEBUG_SELECTION, ///< select a given unit for state-machine debugging
MSG_META_DEMO_LOCK_CAMERA_TO_SELECTION, ///< lock the view camera to the selected object
MSG_META_DEMO_TOGGLE_SOUND, ///< toggle sound/video on/off
MSG_META_DEMO_TOGGLE_TRACKMARKS, ///< toggle tank tread marks on/off
MSG_META_DEMO_TOGGLE_WATERPLANE, ///< toggle waterplane on/off
MSG_META_DEMO_TIME_OF_DAY, ///< change time-of-day lighting
MSG_META_DEMO_TOGGLE_MUSIC, ///< turn background music on/off
MSG_META_DEMO_MUSIC_NEXT_TRACK, ///< play next track
MSG_META_DEMO_MUSIC_PREV_TRACK, ///< play prev track
MSG_META_DEMO_NEXT_OBJECTIVE_MOVIE, ///< play next "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE1, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE2, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE3, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE4, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE5, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE6, ///< play specific "Objective" movie
MSG_META_DEMO_BEGIN_ADJUST_PITCH, ///< enter adjust-pitch mode
MSG_META_DEMO_END_ADJUST_PITCH, ///< exit adjust-pitch mode
MSG_META_DEMO_BEGIN_ADJUST_FOV, ///< enter adjust-FOV mode
MSG_META_DEMO_END_ADJUST_FOV, ///< exit adjust-FOV mode
MSG_META_DEMO_LOCK_CAMERA_TO_PLANES, ///< lock camera to airborne thingies
MSG_META_DEMO_REMOVE_PREREQ, ///< Turn of Prerequisite checks in building legality
MSG_META_DEMO_INSTANT_BUILD, ///< All building is with a timer of 1
MSG_META_DEMO_FREE_BUILD, ///< All building is for 0 money
MSG_META_DEMO_RUNSCRIPT1, ///< run script named "KEY_F1"
MSG_META_DEMO_RUNSCRIPT2, ///< run script named "KEY_F2"
MSG_META_DEMO_RUNSCRIPT3, ///< run script named "KEY_F3"
MSG_META_DEMO_RUNSCRIPT4, ///< run script named "KEY_F4"
MSG_META_DEMO_RUNSCRIPT5, ///< run script named "KEY_F5"
MSG_META_DEMO_RUNSCRIPT6, ///< run script named "KEY_F6"
MSG_META_DEMO_RUNSCRIPT7, ///< run script named "KEY_F7"
MSG_META_DEMO_RUNSCRIPT8, ///< run script named "KEY_F8"
MSG_META_DEMO_RUNSCRIPT9, ///< run script named "KEY_F9"
MSG_META_DEMO_ENSHROUD, ///< re-shroud the world for the local player
MSG_META_DEMO_DESHROUD, ///< de-shroud the world for the local player
MSG_META_DEBUG_SHOW_EXTENTS, ///< show object extents
MSG_META_DEBUG_SHOW_AUDIO_LOCATIONS, ///< show audio objects and radii
MSG_META_DEBUG_SHOW_HEALTH, ///< show object health
MSG_META_DEBUG_GIVE_VETERANCY, ///< give a veterancy level to selected objects
MSG_META_DEBUG_TAKE_VETERANCY, ///< take a veterancy level from selected objects
MSG_META_DEMO_TOGGLE_AI_DEBUG, ///< show/hide the ai debug stats
MSG_META_DEMO_TOGGLE_SUPPLY_CENTER_PLACEMENT, ///