123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
- // Copyright (C) 2015 Faust Logic, Inc.
- //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
- #ifndef _SIMDATABLOCK_H_
- #define _SIMDATABLOCK_H_
- #ifndef _SIMBASE_H_
- #include "console/simBase.h"
- #endif
- // Forward Refs
- class BitStream;
- /// Root DataBlock class.
- ///
- /// @section SimDataBlock_intro Introduction
- ///
- /// Another powerful aspect of Torque's networking is the datablock. Datablocks
- /// are used to provide relatively static information about entities; for instance,
- /// what model a weapon should use to display itself, or how heavy a player class is.
- ///
- /// This gives significant gains in network efficiency, because it means that all
- /// the datablocks on a server can be transferred over the network at client
- /// connect time, instead of being intertwined with the update code for NetObjects.
- ///
- /// This makes the network code much simpler overall, as one-time initialization
- /// code is segregated from the standard object update code, as well as providing
- /// several powerful features, which we will discuss momentarily.
- ///
- /// @section SimDataBlock_preload preload() and File Downloading
- ///
- /// Because datablocks are sent over the wire, using SimDataBlockEvent, before
- /// gameplay starts in earnest, we gain in several areas. First, we don't have to
- /// try to keep up with the game state while working with incomplete information.
- /// Second, we can provide the user with a nice loading screen, instead of the more
- /// traditional "Connecting..." message. Finally, and most usefully, we can request
- /// missing files from the server as we become aware of them, since we are under
- /// no obligation to render anything for the user.
- ///
- /// The mechanism for this is fairly basic. After a datablock is unpacked, the
- /// preload() method is called. If it returns false and sets an error, then the
- /// network code checks to see if a file (or files) failed to be located by the
- /// ResManager; if so, then it requests those files from the server. If preload
- /// returns true, then the datablock is considered loaded. If preload returns
- /// false and sets no error, then the connection is aborted.
- ///
- /// Once the file(s) is downloaded, the datablock's preload() method is called again.
- /// If it fails with the same error, the connection is aborted. If a new error is
- /// returned, then the download-retry process is repeated until the preload works.
- ///
- /// @section SimDataBlock_guide Guide To Datablock Code
- ///
- /// To make a datablock subclass, you need to extend three functions:
- /// - preload()
- /// - packData()
- /// - unpackData()
- ///
- /// packData() and unpackData() simply read or write data to a network stream. If you
- /// add any fields, you need to add appropriate calls to read or write. Make sure that
- /// the order of reads and writes is the same in both functions. Make sure to call
- /// the Parent's version of these methods in every subclass.
- ///
- /// preload() is a bit more complex; it is responsible for taking the raw data read by
- /// unpackData() and processing it into a form useful by the datablock's owning object. For
- /// instance, the Player class' datablock, PlayerData, gets handles to commonly used
- /// nodes in the player model, as well as resolving handles to textures and other
- /// resources. <b>Any</b> code which loads files or performs other actions beyond simply
- /// reading the data from the packet, such as validation, must reside in preload().
- ///
- /// To write your own preload() methods, see any of the existing methods in the codebase; for instance,
- /// PlayerData::preload() is an excellent example of error-reporting, data validation, and so forth.
- ///
- /// @note A useful trick, which is used in several places in the engine, is that of temporarily
- /// storing SimObjectIds in the variable which will eventually hold the "real" handle. ShapeImage
- /// uses this trick in several pllaces; so do the vehicle classes. See GameBaseData for more on
- /// using this trick.
- ///
- /// @see GameBaseData for some more information on the datablocks used throughout
- /// most of the engine.
- /// @see http://hosted.tribalwar.com/t2faq/datablocks.shtml for an excellent
- /// explanation of the basics of datablocks from script. Note that these comments
- /// mostly apply to GameBaseData and its children.
- /// @nosubgrouping
- class SimDataBlock: public SimObject
- {
- typedef SimObject Parent;
- public:
- SimDataBlock();
- DECLARE_CONOBJECT(SimDataBlock);
-
- /// @name Datablock Internals
- /// @{
- protected:
- S32 modifiedKey;
- public:
- static SimObjectId sNextObjectId;
- static S32 sNextModifiedKey;
- /// Assign a new modified key.
- ///
- /// Datablocks are assigned a modified key which is updated every time
- /// a static field of the datablock is changed. These are gotten from
- /// a global store.
- static S32 getNextModifiedKey() { return sNextModifiedKey; }
- /// Returns true if this is a client side only datablock (in
- /// other words a datablock allocated with 'new' instead of
- /// the 'datablock' keyword).
- bool isClientOnly() const { return getId() < DataBlockObjectIdFirst || getId() > DataBlockObjectIdLast; }
- /// Get the modified key for this particular datablock.
- S32 getModifiedKey() const { return modifiedKey; }
- bool onAdd();
- virtual void onStaticModified(const char* slotName, const char*newValue = NULL);
- //void setLastError(const char*);
- void assignId();
- /// @}
- /// @name Datablock Interface
- /// @{
- ///
- virtual void packData(BitStream* stream);
- virtual void unpackData(BitStream* stream);
- /// Called to prepare the datablock for use, after it has been unpacked.
- ///
- /// @param server Set if we're running on the server (and therefore don't need to load
- /// things like textures or sounds).
- /// @param errorStr If an error occurs in loading, this is set to a short string describing
- /// the error.
- /// @returns True if all went well; false if something failed.
- ///
- /// @see @ref SimDataBlock_preload
- virtual bool preload(bool server, String &errorStr);
- /// @}
- /// Output the TorqueScript to recreate this object.
- ///
- /// This calls writeFields internally.
- /// @param stream Stream to output to.
- /// @param tabStop Indentation level for this object.
- /// @param flags If SelectedOnly is passed here, then
- /// only objects marked as selected (using setSelected)
- /// will output themselves.
- virtual void write(Stream &stream, U32 tabStop, U32 flags = 0);
- /// Used by the console system to automatically tell datablock classes apart
- /// from non-datablock classes.
- static const bool __smIsDatablock = true;
- protected:
- struct SubstitutionStatement
- {
- StringTableEntry mSlot;
- S32 mIdx;
- char* mValue;
- SubstitutionStatement(StringTableEntry slot, S32 idx, const char* value);
- ~SubstitutionStatement();
- void replaceValue(const char* value);
- };
- Vector<SubstitutionStatement*> substitutions;
- void clear_substitutions();
- public:
- /*C*/ SimDataBlock(const SimDataBlock&, bool = false);
- /*D*/ ~SimDataBlock();
- void addSubstitution(StringTableEntry field, S32 idx, const char* subst);
- const char* getSubstitution(StringTableEntry field, S32 idx);
- S32 getSubstitutionCount() { return substitutions.size(); }
- void performSubstitutions(SimDataBlock*, const SimObject*, S32 index=0);
- void copySubstitutionsFrom(SimDataBlock* other);
- void printSubstitutions();
- bool fieldHasSubstitution(StringTableEntry slot);
- virtual void onAddSubstitution(StringTableEntry, S32 idx, const char* subst) { }
- virtual void onRemoveSubstitution(StringTableEntry, S32 idx) { }
- virtual void onPerformSubstitutions() { }
- };
- //---------------------------------------------------------------------------
- class SimDataBlockGroup : public SimGroup
- {
- private:
- S32 mLastModifiedKey;
- public:
- static S32 QSORT_CALLBACK compareModifiedKey(const void* a,const void* b);
- void sort();
- SimDataBlockGroup();
- };
- #endif // _SIMDATABLOCK_H_
|