gameBase.h
Engine/source/T3D/gameBase/gameBase.h
Classes:
class
Base class for game objects which use datablocks, networking, are editable, and need to process ticks.
class
Scriptable, demo-able datablock.
Public Defines
define
Public Functions
bool
PACK_DB_ID(BitStream * stream, U32 id)
bool
PRELOAD_DB(U32 & id, SimDataBlock ** data, bool server, const char * clientMissing, const char * serverMissing)
bool
UNPACK_DB_ID(BitStream * stream, U32 & id)
Detailed Description
Public Defines
__SCENEMANAGER_H__()
Public Functions
PACK_DB_ID(BitStream * stream, U32 id)
PRELOAD_DB(U32 & id, SimDataBlock ** data, bool server, const char * clientMissing, const char * serverMissing)
UNPACK_DB_ID(BitStream * stream, U32 & id)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#ifndef _GAMEBASE_H_ 25#define _GAMEBASE_H_ 26 27#ifndef _SCENEOBJECT_H_ 28#include "scene/sceneObject.h" 29#endif 30#ifndef _PROCESSLIST_H_ 31#include "T3D/gameBase/processList.h" 32#endif 33#ifndef _TICKCACHE_H_ 34#include "T3D/gameBase/tickCache.h" 35#endif 36#ifndef _DYNAMIC_CONSOLETYPES_H_ 37#include "console/dynamicTypes.h" 38#endif 39#ifndef __SCENEMANAGER_H__ 40#include "scene/sceneManager.h" 41#define __SCENEMANAGER_H__ 42#endif 43#ifndef _IDISPLAYDEVICE_H_ 44#include "platform/output/IDisplayDevice.h" 45#endif 46 47class NetConnection; 48class ProcessList; 49class GameBase; 50struct Move; 51 52//---------------------------------------------------------------------------- 53//---------------------------------------------------------------------------- 54 55/// Scriptable, demo-able datablock. 56/// 57/// This variant of SimDataBlock performs these additional tasks: 58/// - Linking datablock's namepsaces to the namespace of their C++ class, so 59/// that datablocks can expose script functionality. 60/// - Linking datablocks to a user defined scripting namespace, by setting the 61/// 'class' field at datablock definition time. 62/// - Adds a category field; this is used by the world creator in the editor to 63/// classify creatable shapes. Creatable shapes are placed under the Shapes 64/// node in the treeview for this; additional levels are created, named after 65/// the category fields. 66/// - Adds support for demo stream recording. This support takes the form 67/// of the member variable packed. When a demo is being recorded by a client, 68/// data is unpacked, then packed again to the data stream, then, in the case 69/// of datablocks, preload() is called to process the data. It is occasionally 70/// the case that certain references in the datablock stream cannot be resolved 71/// until preload is called, in which case a raw ID field is stored in the variable 72/// which will eventually be used to store a pointer to the object. However, if 73/// packData() is called before we resolve this ID, trying to call getID() on the 74/// objecct ID would be a fatal error. Therefore, in these cases, we test packed; 75/// if it is true, then we know we have to write the raw data, instead of trying 76/// to resolve an ID. 77/// 78/// @see SimDataBlock for further details about datablocks. 79/// @see http://hosted.tribalwar.com/t2faq/datablocks.shtml for an excellent 80/// explanation of the basics of datablocks from a scripting perspective. 81/// @nosubgrouping 82struct GameBaseData : public SimDataBlock 83{ 84private: 85 86 typedef SimDataBlock Parent; 87 88public: 89 90 bool packed; 91 StringTableEntry category; 92 93 // Signal triggered when this datablock is modified. 94 // GameBase objects referencing this datablock notify with this signal. 95 Signal<void(void)> mReloadSignal; 96 97 // Triggers the reload signal. 98 void inspectPostApply(); 99 100 bool onAdd(); 101 102 // The derived class should provide the following: 103 DECLARE_CONOBJECT(GameBaseData); 104 GameBaseData(); 105 static void initPersistFields(); 106 bool preload(bool server, String &errorStr); 107 void unpackData(BitStream* stream); 108 109 /// @name Callbacks 110 /// @{ 111 DECLARE_CALLBACK( void, onAdd, ( GameBase* obj ) ); 112 DECLARE_CALLBACK( void, onRemove, ( GameBase* obj ) ); 113 DECLARE_CALLBACK( void, onNewDataBlock, ( GameBase* obj ) ); 114 DECLARE_CALLBACK( void, onMount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) ); 115 DECLARE_CALLBACK( void, onUnmount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) ); 116 /// @} 117}; 118 119//---------------------------------------------------------------------------- 120// A few utility methods for sending datablocks over the net 121//---------------------------------------------------------------------------- 122 123bool UNPACK_DB_ID(BitStream *, U32 & id); 124bool PACK_DB_ID(BitStream *, U32 id); 125bool PRELOAD_DB(U32 & id, SimDataBlock **, bool server, const char * clientMissing = NULL, const char * serverMissing = NULL); 126 127//---------------------------------------------------------------------------- 128class GameConnection; 129class WaterObject; 130class MoveList; 131 132// For truly it is written: "The wise man extends GameBase for his purposes, 133// while the fool has the ability to eject shell casings from the belly of his 134// dragon." -- KillerBunny 135 136/// Base class for game objects which use datablocks, networking, are editable, 137/// and need to process ticks. 138/// 139/// @section GameBase_process GameBase and ProcessList 140/// 141/// GameBase adds two kinds of time-based updates. Torque works off of a concept 142/// of ticks. Ticks are slices of time 32 milliseconds in length. There are three 143/// methods which are used to update GameBase objects that are registered with 144/// the ProcessLists: 145/// - processTick(Move*) is called on each object once for every tick, regardless 146/// of the "real" framerate. 147/// - interpolateTick(float) is called on client objects when they need to interpolate 148/// to match the next tick. 149/// - advanceTime(float) is called on client objects so they can do time-based behaviour, 150/// like updating animations. 151/// 152/// Torque maintains a server and a client processing list; in a local game, both 153/// are populated, while in multiplayer situations, either one or the other is 154/// populated. 155/// 156/// You can control whether an object is considered for ticking by means of the 157/// setProcessTick() method. 158/// 159/// @section GameBase_datablock GameBase and Datablocks 160/// 161/// GameBase adds support for datablocks. Datablocks are secondary classes which store 162/// static data for types of game elements. For instance, this means that all "light human 163/// male armor" type Players share the same datablock. Datablocks typically store not only 164/// raw data, but perform precalculations, like finding nodes in the game model, or 165/// validating movement parameters. 166/// 167/// There are three parts to the datablock interface implemented in GameBase: 168/// - <b>getDataBlock()</b>, which gets a pointer to the current datablock. This is 169/// mostly for external use; for in-class use, it's better to directly access the 170/// mDataBlock member. 171/// - <b>setDataBlock()</b>, which sets mDataBlock to point to a new datablock; it 172/// uses the next part of the interface to inform subclasses of this. 173/// - <b>onNewDataBlock()</b> is called whenever a new datablock is assigned to a GameBase. 174/// 175/// Datablocks are also usable through the scripting language. 176/// 177/// @see SimDataBlock for more details. 178/// 179/// @section GameBase_networking GameBase and Networking 180/// 181/// writePacketData() and readPacketData() are called to transfer information needed for client 182/// side prediction. They are usually used when updating a client of its control object state. 183/// 184/// Subclasses of GameBase usually transmit positional and basic status data in the packUpdate() 185/// functions, while giving velocity, momentum, and similar state information in the writePacketData(). 186/// 187/// writePacketData()/readPacketData() are called <i>in addition</i> to packUpdate/unpackUpdate(). 188/// 189/// @nosubgrouping 190class GameBase : public SceneObject 191{ 192 typedef SceneObject Parent; 193 194 /// @name Datablock 195 /// @{ 196 197 GameBaseData* mDataBlock; 198 199 /// @} 200 201 TickCache mTickCache; 202 203 // Control interface 204 GameConnection* mControllingClient; 205 206public: 207 208 static bool gShowBoundingBox; ///< Should we render bounding boxes? 209 210protected: 211 212 F32 mCameraFov; 213 214 /// The WaterObject we are currently within. 215 WaterObject *mCurrentWaterObject; 216 217 static bool setDataBlockProperty( void *object, const char *index, const char *data ); 218 219#ifdef TORQUE_DEBUG_NET_MOVES 220 U32 mLastMoveId; 221 U32 mTicksSinceLastMove; 222 bool mIsAiControlled; 223#endif 224 225public: 226 227 GameBase(); 228 ~GameBase(); 229 230 enum GameBaseMasks { 231 DataBlockMask = Parent::NextFreeMask << 0, 232 ExtendedInfoMask = Parent::NextFreeMask << 1, 233 NextFreeMask = Parent::NextFreeMask << 2 234 }; 235 236 // net flags added by game base 237 enum 238 { 239 NetOrdered = BIT(Parent::MaxNetFlagBit+1), /// Process in same order on client and server. 240 NetNearbyAdded = BIT(Parent::MaxNetFlagBit+2), /// Is set during client catchup when neighbors have been checked. 241 GhostUpdated = BIT(Parent::MaxNetFlagBit+3), /// Is set whenever ghost updated (and reset) on the client, for hifi objects. 242 TickLast = BIT(Parent::MaxNetFlagBit+4), /// Tick this object after all others. 243 NewGhost = BIT(Parent::MaxNetFlagBit+5), /// This ghost was just added during the last update. 244 HiFiPassive = BIT(Parent::MaxNetFlagBit+6), /// Do not interact with other hifi passive objects. 245 MaxNetFlagBit = Parent::MaxNetFlagBit+6 246 }; 247 248 /// @name Inherited Functionality. 249 /// @{ 250 251 bool onAdd(); 252 void onRemove(); 253 void inspectPostApply(); 254 static void initPersistFields(); 255 static void consoleInit(); 256 257 /// @} 258 259 ///@name Datablock 260 ///@{ 261 262 /// Assigns this object a datablock and loads attributes with onNewDataBlock. 263 /// 264 /// @see onNewDataBlock 265 /// @param dptr Datablock 266 bool setDataBlock( GameBaseData *dptr ); 267 268 /// Returns the datablock for this object. 269 GameBaseData* getDataBlock() { return mDataBlock; } 270 271 /// Called when a new datablock is set. This allows subclasses to 272 /// appropriately handle new datablocks. 273 /// 274 /// @see setDataBlock() 275 /// @param dptr New datablock 276 /// @param reload Is this a new datablock or are we reloading one 277 /// we already had. 278 virtual bool onNewDataBlock( GameBaseData *dptr, bool reload ); 279 ///@} 280 281 /// @name Script 282 /// The scriptOnXX methods are invoked by the leaf classes 283 /// @{ 284 285 /// Executes the 'onAdd' script function for this object. 286 /// @note This must be called after everything is ready 287 void scriptOnAdd(); 288 289 /// Executes the 'onNewDataBlock' script function for this object. 290 /// 291 /// @note This must be called after everything is loaded. 292 void scriptOnNewDataBlock(); 293 294 /// Executes the 'onRemove' script function for this object. 295 /// @note This must be called while the object is still valid 296 void scriptOnRemove(); 297 298 /// @} 299 300 // ProcessObject override 301 void processTick( const Move *move ); 302 303 /// @name GameBase NetFlags & Hifi-Net Interface 304 /// @{ 305 306 /// Set or clear the GhostUpdated bit in our NetFlags. 307 /// @see GhostUpdated 308 void setGhostUpdated( bool b ) { if (b) mNetFlags.set(GhostUpdated); else mNetFlags.clear(GhostUpdated); } 309 310 /// Returns true if the GhostUpdated bit in our NetFlags is set. 311 /// @see GhostUpdated 312 bool isGhostUpdated() const { return mNetFlags.test(GhostUpdated); } 313 314 /// Set or clear the NewGhost bit in our NetFlags. 315 /// @see NewGhost 316 void setNewGhost( bool n ) { if (n) mNetFlags.set(NewGhost); else mNetFlags.clear(NewGhost); } 317 318 /// Returns true if the NewGhost bit in out NetFlags is set. 319 /// @see NewGhost 320 bool isNewGhost() const { return mNetFlags.test(NewGhost); } 321 322 /// Set or clear the NetNearbyAdded bit in our NetFlags. 323 /// @see NetNearbyAdded 324 void setNetNearbyAdded( bool b ) { if (b) mNetFlags.set(NetNearbyAdded); else mNetFlags.clear(NetNearbyAdded); } 325 326 /// Returns true if the NetNearby bit in our NetFlags is set. 327 /// @see NetNearbyAdded 328 bool isNetNearbyAdded() const { return mNetFlags.test(NetNearbyAdded); } 329 330 /// Returns true if the HiFiPassive bit in our NetFlags is set. 331 /// @see HiFiPassive 332 bool isHifiPassive() const { return mNetFlags.test(HiFiPassive); } 333 334 /// Returns true if the TickLast bit in our NetFlags is set. 335 /// @see TickLast 336 bool isTickLast() const { return mNetFlags.test(TickLast); } 337 338 /// Returns true if the NetOrdered bit in our NetFlags is set. 339 /// @see NetOrdered 340 bool isNetOrdered() const { return mNetFlags.test(NetOrdered); } 341 342 /// Called during client catchup under the hifi-net model. 343 virtual void computeNetSmooth( F32 backDelta ) {} 344 345 /// Returns TickCache used under the hifi-net model. 346 TickCache& getTickCache() { return mTickCache; } 347 /// @} 348 349 /// @name Network 350 /// @see NetObject, NetConnection 351 /// @{ 352 353 F32 getUpdatePriority( CameraScopeQuery *focusObject, U32 updateMask, S32 updateSkips ); 354 U32 packUpdate ( NetConnection *conn, U32 mask, BitStream *stream ); 355 void unpackUpdate( NetConnection *conn, BitStream *stream ); 356 357 /// Write state information necessary to perform client side prediction of an object. 358 /// 359 /// This information is sent only to the controlling object. For example, if you are a client 360 /// controlling a Player, the server uses writePacketData() instead of packUpdate() to 361 /// generate the data you receive. 362 /// 363 /// @param conn Connection for which we're generating this data. 364 /// @param stream Bitstream for output. 365 virtual void writePacketData( GameConnection *conn, BitStream *stream ); 366 367 /// Read data written with writePacketData() and update the object state. 368 /// 369 /// @param conn Connection for which we're generating this data. 370 /// @param stream Bitstream to read. 371 virtual void readPacketData( GameConnection *conn, BitStream *stream ); 372 373 /// Gets the checksum for packet data. 374 /// 375 /// Basically writes a packet, does a CRC check on it, and returns 376 /// that CRC. 377 /// 378 /// @see writePacketData 379 /// @param conn Game connection 380 virtual U32 getPacketDataChecksum( GameConnection *conn ); 381 ///@} 382 383 384 /// @name Mounted objects ( overrides ) 385 /// @{ 386 387public: 388 389 virtual void onMount( SceneObject *obj, S32 node ); 390 virtual void onUnmount( SceneObject *obj,S32 node ); 391 392 /// @} 393 394 /// @name User control 395 /// @{ 396 397 /// Returns the client controlling this object 398 GameConnection *getControllingClient() { return mControllingClient; } 399 const GameConnection *getControllingClient() const { return mControllingClient; } 400 401 /// Returns the MoveList of the client controlling this object. 402 /// If there is no client it returns NULL; 403 MoveList* getMoveList(); 404 405 /// Sets the client controlling this object 406 /// @param client Client that is now controlling this object 407 virtual void setControllingClient( GameConnection *client ); 408 409 virtual GameBase * getControllingObject() { return NULL; } 410 virtual GameBase * getControlObject() { return NULL; } 411 virtual void setControlObject( GameBase * ) { } 412 /// @} 413 414 virtual F32 getDefaultCameraFov() { return 90.f; } 415 virtual F32 getCameraFov() { return 90.f; } 416 virtual void setCameraFov( F32 fov ) { } 417 virtual bool isValidCameraFov( F32 fov ) { return true; } 418 virtual bool useObjsEyePoint() const { return false; } 419 virtual bool onlyFirstPerson() const { return false; } 420 virtual F32 getDamageFlash() const { return 0.0f; } 421 virtual F32 getWhiteOut() const { return 0.0f; } 422 423 // Not implemented here, but should return the Camera to world transformation matrix 424 virtual void getCameraTransform (F32 *pos, MatrixF *mat ) { *mat = MatrixF::Identity; } 425 virtual void getEyeCameraTransform ( IDisplayDevice *device, U32 eyeId, MatrixF *mat ) { *mat = MatrixF::Identity; } 426 427 /// Returns the water object we are colliding with, it is up to derived 428 /// classes to actually set this object. 429 virtual WaterObject* getCurrentWaterObject() { return mCurrentWaterObject; } 430 431 #ifdef TORQUE_DEBUG_NET_MOVES 432 bool isAIControlled() const { return mIsAiControlled; } 433 #endif 434 435 DECLARE_CONOBJECT (GameBase ); 436 437 /// @name Callbacks 438 /// @{ 439 DECLARE_CALLBACK( void, setControl, ( bool controlled ) ); 440 /// @} 441 442private: 443 444 /// This is called by the reload signal in our datablock when it is 445 /// modified in the editor. 446 /// 447 /// This method is private and is not virtual. To handle a datablock-modified 448 /// even in a child-class specific way you should override onNewDatablock 449 /// and handle the reload( true ) case. 450 /// 451 /// Warning: For local-client, editor situations only. 452 /// 453 /// Warning: Do not attempt to call .remove or .notify on mDataBlock->mReloadSignal 454 /// within this callback. 455 /// 456 void _onDatablockModified(); 457}; 458 459 460#endif // _GAMEBASE_H_ 461
