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