simDatablock.h
Engine/source/console/simDatablock.h
Classes:
class
Root DataBlock class.
class
Detailed Description
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 _SIMDATABLOCK_H_ 25#define _SIMDATABLOCK_H_ 26 27#ifndef _SIMBASE_H_ 28#include "console/simBase.h" 29#endif 30 31// Forward Refs 32class BitStream; 33 34/// Root DataBlock class. 35/// 36/// @section SimDataBlock_intro Introduction 37/// 38/// Another powerful aspect of Torque's networking is the datablock. Datablocks 39/// are used to provide relatively static information about entities; for instance, 40/// what model a weapon should use to display itself, or how heavy a player class is. 41/// 42/// This gives significant gains in network efficiency, because it means that all 43/// the datablocks on a server can be transferred over the network at client 44/// connect time, instead of being intertwined with the update code for NetObjects. 45/// 46/// This makes the network code much simpler overall, as one-time initialization 47/// code is segregated from the standard object update code, as well as providing 48/// several powerful features, which we will discuss momentarily. 49/// 50/// @section SimDataBlock_preload preload() and File Downloading 51/// 52/// Because datablocks are sent over the wire, using SimDataBlockEvent, before 53/// gameplay starts in earnest, we gain in several areas. First, we don't have to 54/// try to keep up with the game state while working with incomplete information. 55/// Second, we can provide the user with a nice loading screen, instead of the more 56/// traditional "Connecting..." message. Finally, and most usefully, we can request 57/// missing files from the server as we become aware of them, since we are under 58/// no obligation to render anything for the user. 59/// 60/// The mechanism for this is fairly basic. After a datablock is unpacked, the 61/// preload() method is called. If it returns false and sets an error, then the 62/// network code checks to see if a file (or files) failed to be located by the 63/// ResManager; if so, then it requests those files from the server. If preload 64/// returns true, then the datablock is considered loaded. If preload returns 65/// false and sets no error, then the connection is aborted. 66/// 67/// Once the file(s) is downloaded, the datablock's preload() method is called again. 68/// If it fails with the same error, the connection is aborted. If a new error is 69/// returned, then the download-retry process is repeated until the preload works. 70/// 71/// @section SimDataBlock_guide Guide To Datablock Code 72/// 73/// To make a datablock subclass, you need to extend three functions: 74/// - preload() 75/// - packData() 76/// - unpackData() 77/// 78/// packData() and unpackData() simply read or write data to a network stream. If you 79/// add any fields, you need to add appropriate calls to read or write. Make sure that 80/// the order of reads and writes is the same in both functions. Make sure to call 81/// the Parent's version of these methods in every subclass. 82/// 83/// preload() is a bit more complex; it is responsible for taking the raw data read by 84/// unpackData() and processing it into a form useful by the datablock's owning object. For 85/// instance, the Player class' datablock, PlayerData, gets handles to commonly used 86/// nodes in the player model, as well as resolving handles to textures and other 87/// resources. <b>Any</b> code which loads files or performs other actions beyond simply 88/// reading the data from the packet, such as validation, must reside in preload(). 89/// 90/// To write your own preload() methods, see any of the existing methods in the codebase; for instance, 91/// PlayerData::preload() is an excellent example of error-reporting, data validation, and so forth. 92/// 93/// @note A useful trick, which is used in several places in the engine, is that of temporarily 94/// storing SimObjectIds in the variable which will eventually hold the "real" handle. ShapeImage 95/// uses this trick in several pllaces; so do the vehicle classes. See GameBaseData for more on 96/// using this trick. 97/// 98/// @see GameBaseData for some more information on the datablocks used throughout 99/// most of the engine. 100/// @see http://hosted.tribalwar.com/t2faq/datablocks.shtml for an excellent 101/// explanation of the basics of datablocks from script. Note that these comments 102/// mostly apply to GameBaseData and its children. 103/// @nosubgrouping 104class SimDataBlock: public SimObject 105{ 106 typedef SimObject Parent; 107public: 108 109 SimDataBlock(); 110 DECLARE_CONOBJECT(SimDataBlock); 111 112 /// @name Datablock Internals 113 /// @{ 114 115protected: 116 S32 modifiedKey; 117 118public: 119 static SimObjectId sNextObjectId; 120 static S32 sNextModifiedKey; 121 122 /// Assign a new modified key. 123 /// 124 /// Datablocks are assigned a modified key which is updated every time 125 /// a static field of the datablock is changed. These are gotten from 126 /// a global store. 127 static S32 getNextModifiedKey() { return sNextModifiedKey; } 128 129 /// Returns true if this is a client side only datablock (in 130 /// other words a datablock allocated with 'new' instead of 131 /// the 'datablock' keyword). 132 bool isClientOnly() const { return getId() < DataBlockObjectIdFirst || getId() > DataBlockObjectIdLast; } 133 134 /// Get the modified key for this particular datablock. 135 S32 getModifiedKey() const { return modifiedKey; } 136 137 bool onAdd(); 138 virtual void onStaticModified(const char* slotName, const char*newValue = NULL); 139 //void setLastError(const char*); 140 void assignId(); 141 142 /// @} 143 144 /// @name Datablock Interface 145 /// @{ 146 147 /// 148 virtual void packData(BitStream* stream); 149 virtual void unpackData(BitStream* stream); 150 151 /// Called to prepare the datablock for use, after it has been unpacked. 152 /// 153 /// @param server Set if we're running on the server (and therefore don't need to load 154 /// things like textures or sounds). 155 /// @param errorStr If an error occurs in loading, this is set to a short string describing 156 /// the error. 157 /// @returns True if all went well; false if something failed. 158 /// 159 /// @see @ref SimDataBlock_preload 160 virtual bool preload(bool server, String &errorStr); 161 /// @} 162 163 /// Output the TorqueScript to recreate this object. 164 /// 165 /// This calls writeFields internally. 166 /// @param stream Stream to output to. 167 /// @param tabStop Indentation level for this object. 168 /// @param flags If SelectedOnly is passed here, then 169 /// only objects marked as selected (using setSelected) 170 /// will output themselves. 171 virtual void write(Stream &stream, U32 tabStop, U32 flags = 0); 172 173 /// Used by the console system to automatically tell datablock classes apart 174 /// from non-datablock classes. 175 static const bool __smIsDatablock = true; 176}; 177 178//--------------------------------------------------------------------------- 179 180class SimDataBlockGroup : public SimGroup 181{ 182private: 183 S32 mLastModifiedKey; 184 185public: 186 static S32 QSORT_CALLBACK compareModifiedKey(const void* a,const void* b); 187 void sort(); 188 SimDataBlockGroup(); 189}; 190 191#endif // _SIMDATABLOCK_H_ 192
