root/cafu/trunk/Games/BaseEntity.hpp

Revision 533, 23.9 KB (checked in by Carsten, 24 hours ago)

Net code:
Introduce new classes for managing the game entity state.

The BaseEntityT methods

void BaseEntityT::Serialize(cf::Network::OutStreamT& Stream) const;
void BaseEntityT::Deserialize(cf::Network::InStreamT& Stream, bool IsIniting);

previously introduced in r528, have been updated accordingly.

References #113.

Line 
1/*
2=================================================================================
3This file is part of Cafu, the open-source game engine and graphics engine
4for multiplayer, cross-platform, real-time 3D action.
5Copyright (C) 2002-2012 Carsten Fuchs Software.
6
7Cafu is free software: you can redistribute it and/or modify it under the terms
8of the GNU General Public License as published by the Free Software Foundation,
9either version 3 of the License, or (at your option) any later version.
10
11Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with Cafu. If not, see <http://www.gnu.org/licenses/>.
17
18For support and more information about Cafu, visit us at <http://www.cafu.de>.
19=================================================================================
20*/
21
22#ifndef CAFU_GAMEDLL_HPP_INCLUDED
23#define CAFU_GAMEDLL_HPP_INCLUDED
24
25#include "Math3D/BoundingBox.hpp"
26#include "ClipSys/ClipModel.hpp"
27
28#include <map>
29
30
31class EntityCreateParamsT;
32class PhysicsWorldT;
33struct lua_State;
34namespace cf { namespace ClipSys { class CollisionModelT; } }
35namespace cf { namespace GameSys { class GameWorldI; } }
36namespace cf { namespace Network { class InStreamT; } }
37namespace cf { namespace Network { class OutStreamT; } }
38namespace cf { namespace TypeSys { class TypeInfoT; } }
39namespace cf { namespace TypeSys { class TypeInfoManT; } }
40namespace cf { namespace TypeSys { class CreateParamsT; } }
41
42
43/// The TypeInfoTs of all BaseEntityT derived classes must register with this TypeInfoManT instance.
44cf::TypeSys::TypeInfoManT& GetBaseEntTIM();
45
46
47// This structure describes each entitys state and is transmitted from the server to the clients over the network.
48struct EntityStateT
49{
50    /***************************************************************************************************************/
51    /*** EntityStateT field changes FORCE protocol changes in ALL places that are marked *like this* (use grep)! ***/
52    /***************************************************************************************************************/
53
54    VectorT               Origin;           // World coordinate of (the eye of) this entity.
55    VectorT               Velocity;         // Velocity of this entity.
56    BoundingBox3T<double> Dimensions;       // The bounding box of this entity (relative to the eye).
57
58    unsigned short Heading;                 // Heading (North is down the ??-axis).
59    unsigned short Pitch;                   // Pitch (for looking up/down).
60    unsigned short Bank;                    // Bank (e.g. used when dead and lying on the side).
61
62    char           StateOfExistance;        // For entity defined state machines, e.g. "specator, dead, alive, ...".
63    char           Flags;                   // Entity defined flags.
64    char           PlayerName[64];          // If it is a human player, this is its name. Usually unused otherwise.
65 // ArrayT<char>   PlayerName;
66    char           ModelIndex;              // An arbitrary (game defined) number that describes the BODY model of this entity (that OTHERS see).
67    char           ModelSequNr;             // The sequence number of the body model.
68    float          ModelFrameNr;            // The frame number of the current sequence of the body model.
69
70    char           Health;                  // Health.
71    char           Armor;                   // Armor.
72    unsigned long  HaveItems;               // Bit field, entity can carry 32 different items.
73    unsigned long  HaveWeapons;             // Bit field, entity can carry 32 different weapons.
74    char           ActiveWeaponSlot;        // Index into HaveWeapons, HaveAmmoInWeapons, and for determining the weapon model index.
75    char           ActiveWeaponSequNr;      // The weapon sequ. that WE see (the LOCAL clients VIEW weapon model). Could (and should in the future) also be used for other clients PLAYER weapon model, but currently is not.
76    float          ActiveWeaponFrameNr;     // Respectively, this is the frame number of the current weapon sequence.
77    unsigned short HaveAmmo[16];            // Entity can carry 16 different types of ammo (weapon independent). This is the amount of each.
78    unsigned char  HaveAmmoInWeapons[32];   // Entity can carry ammo in each of the 32 weapons. This is the amount of each.
79
80    // Special variable used to notify clients about events.
81    // On server side, in 'BaseEntityT::Think()', use bit-wise XOR to toggle event flags (as in 'State.Events^=MY_EVENT_BIT').
82    // On client side, the function 'BaseEntityT::ProcessEvent(i)' is automatically called for each toggled bit i.
83    // TODO: This should be hidden in 'EngineEntityT', as 'Events' receives special treatment in the engine.
84    //       At that opportunity, also think about a proper fixed-point presentation of 'Origin', 'Velocity', ...
85    //       (Or, more generally, about the convenient types here and the requ. precision across the net.)
86    unsigned long  Events;
87
88    EntityStateT(const VectorT& Origin_, const VectorT& Velocity_, const BoundingBox3T<double>& Dimensions_,
89                 unsigned short Heading_, unsigned short Pitch_, unsigned short Bank_,
90                 char StateOfExistance_, char Flags_, char ModelIndex_, char ModelSequNr_, float ModelFrameNr_,
91                 char Health_, char Armor_, unsigned long HaveItems_, unsigned long HaveWeapons_,
92                 char ActiveWeaponSlot_, char ActiveWeaponSequNr_, float ActiveWeaponFrameNr_);
93};
94
95
96// This class describes "base entities", the most central component in game<-->engine communication.
97class BaseEntityT
98{
99    public:
100
101    const unsigned long ID;             // The unique ID of this entity.
102    const std::string   Name;           ///< The unique instance name of this entity, normally equal to and obtained from Properties["name"]. It's explicitly kept (possibly redundantly to Properties["name"]), because with it: a) there is no confusion when "name" is not found in the Properties list, b) its const-ness is more obvious and easier to guarantee (e.g. the ScriptStateT class relies on the name never changing throughout entity lifetime, because script objects are addressed and found by name, not by instance pointer (light userdata)!), and c) access like   MyEnt->Name   is much easier to write than using Properties.find().
103    const std::map<std::string, std::string> Properties;    ///< The properties of this entities from the map file. THIS IS UNSAFE due to the EXE/DLL boundaries (if a const operation modified memory...), but for now it seems to work on all STL implementations - TODO: revision required later!!!
104    const unsigned long WorldFileIndex; // The index of this entity into the array in the world file, -1 is no such information exists. See [1].
105    unsigned long       ParentID;       // The 'ID' of the entity that created us.
106 // ID[]                ChildrenIDs;    // The entities that we have created (e.g. the rockets that a human player fired).
107    EntityStateT        State;          // The current state of this entity.
108
109    cf::GameSys::GameWorldI*            GameWorld;      ///< Pointer to the game world implementation.
110    PhysicsWorldT*                      PhysicsWorld;   ///< Pointer to the physics world implementation.
111    const cf::ClipSys::CollisionModelT* CollisionModel; ///< The collision model of this entity, NULL for none.
112    cf::ClipSys::ClipModelT             ClipModel;      ///< The clip model of this entity. Note that clip models can take NULL collision model pointers, so that the ClipModel instance is always non-NULL and available.
113
114    // [1]  I have been trying hard to save this variable, because 'ID' seems to handle the same purpose.
115    // This would mean to overload 'ID' with multiple purposes though, and that doesn't seem right to me:
116    // a) Care must be taken that 'ID's are always unique (never get re-used), but this should be the case anyway.
117    // b) Worse is the implied order assumption (both on server and on *CLIENT* side):
118    //    In order to conclude from the 'ID' to the (no-longer-present) 'MapFileID', assumptions must hold that are hard and dangerous to enforce.
119    //    For example, 'ID==MapFileID' must hold for all entities that have map file information associated with them.
120    // c) Even if all that worked, it would e.g. be impossible to duplicate such an entity.
121    // d) Moreover, it isn't worth the effort: 'MapFileID' causes network load only once, during the baseline message for this entity.
122    //    That doesn't happen all that often, so I rather keep it than introducing a lot of complicated dependencies and problems.
123
124
125    /// The destructor.
126    virtual ~BaseEntityT();
127
128    /// Writes the current state of this entity into the given stream.
129    /// This method is called to send the state of the entity over the network or to save it to disk.
130    /// Note that this method is the twin of Deserialize(), whose implementation it must match.
131    virtual void Serialize(cf::Network::OutStreamT& Stream) const;
132
133    /// Reads the state of this entity from the given stream, and updates the entity accordingly.
134    /// This method is called after the state of the entity has been received over the network,
135    /// has been loaded from disk or must be "reset" for the purpose of (re-)prediction.
136    /// Note that this method is the twin of Serialize(), whose implementation it must match.
137    ///
138    /// @param IsIniting   Only used by the ctor implementation: Set to \c true in order to indicate
139    ///     that the entity is newly constructed. User code should always leave this at \c false.
140    virtual void Deserialize(cf::Network::InStreamT& Stream, bool IsIniting=false);
141
142    /// Returns the origin point of this entity. Used for
143    ///   - obtaining the camera position of the local human player entity (1st person view),
144    ///   - interpolating the origin (NPC entities) and
145    ///   - computing light source positions.
146    virtual const Vector3dT& GetOrigin() const { return State.Origin; }
147
148    /// This method is a temporary hack, used so that the caller can temporarily set the origin to the "interpolated" origin,
149    /// draw the entity or get the entity light source position, then set the origin back to the previous origin.
150    /// Interpolation of client entities needs to be thoroughly redone anyway (e.g. combined with interpolating animation sequences),
151    /// this is also when this method will be removed again.
152    void SetInterpolationOrigin(const Vector3dT& O) { State.Origin=O; }
153
154    /// Returns the dimensions of this entity.
155    virtual const BoundingBox3dT& GetDimensions() const { return State.Dimensions; }
156
157    /// Returns the camera orientation angles of this entity.
158    /// Used for setting up the camera of the local human player entity (1st person view).
159    virtual void GetCameraOrientation(unsigned short& h, unsigned short& p, unsigned short& b) const { h=State.Heading; p=State.Pitch; b=State.Bank; }
160
161    /// Returns the orientation angles of the entity itself.
162    /// Used for computing the light source and eye positions in entity (model) space.
163    /// TODO: Both the signature as well as the implementation of this method are temporary, and fully expected to change later.
164    virtual void GetBodyOrientation(unsigned short& h, unsigned short& p, unsigned short& b) const { h=State.Heading; p=State.Pitch; b=State.Bank; }
165
166
167    // Some convenience functions for reading the Properties.
168    // Actually, the Properties should be replaced by a PropDictT class that has these functions as its methods...
169    float       GetProp(const std::string& Key, float       Default=0.0f) const;
170    double      GetProp(const std::string& Key, double      Default=0.0) const;
171    int         GetProp(const std::string& Key, int         Default=0) const;
172    std::string GetProp(const std::string& Key, std::string Default="") const;
173    Vector3fT   GetProp(const std::string& Key, Vector3fT   Default=Vector3fT()) const;
174    Vector3dT   GetProp(const std::string& Key, Vector3dT   Default=Vector3dT()) const;
175
176
177    /// This SERVER-SIDE function is used to notify this entity that it was touched by another entity.
178    /// 'Entity' is the entity that touches this one, and is usually the entity from which the call is made.
179    /// Calls are only made from within other entities 'Think()' functions.
180    /// (Unfortunately, this function cannot be declared as "protected": see "C++ FAQs, 2nd edition" by Cline, Lomow, Girou, pages 249f.)
181    virtual void NotifyTouchedBy(BaseEntityT* Entity);
182
183    /// This SERVER-SIDE method is called whenever another entity walked into one of our trigger volumes (trigger brushes).
184    /// It is called once per frame as long as the other entity stays within our trigger volume.
185    ///
186    /// @param Activator   The entity that walked into our trigger volume and thus caused the call of this method.
187    ///
188    /// Note that most entity classes just do nothing in their implementation of this method, usually because they never have trigger brushes anyway.
189    /// Entity classes that are very likely to provide an implementation though are EntTriggerT (of course!) and the items like weapons,
190    /// so they can e.g. detect being picked up.
191    /// Calls to this method normally come from within the Activator->Think() method, because it are the activators themselves that detect
192    /// that they entered a trigger volume (it are not the entities with the triggers that detect that something entered their volume).
193    /// (Unfortunately, this function cannot be declared as "protected": see "C++ FAQs, 2nd edition" by Cline, Lomow, Girou, pages 249f.)
194    virtual void OnTrigger(BaseEntityT* Activator);
195
196    /// This SERVER-SIDE method is called whenever another entity pushes us.
197    /// Whenever an entity moves, it may want to push other entities that are touching it.
198    /// Examples are lifts that give the objects on it a ride, or players that push barrels or crates.
199    /// As the pusher itself may be pushed (e.g. when a player pushes a barrel that pushes a barrel or when a lift pushes a crate
200    /// that pushes the player on top of it), there can be an entire chain of pushers.
201    ///
202    /// @param Pushers
203    ///   The chain of pushers that are pushing this entity. Usually, there is only one element in this list,
204    ///   but in theory, e.g. when a train pushes a waggon that pushes a waggon that pushes a waggon..., the list can be
205    ///   arbitrarily long.
206    ///   The topmost pusher, i.e. Pushers[i] with i==Pushers.Size()-1, is our immediate pusher, Pushers[i-1] is the pusher of our pusher,
207    ///   and so forth. Pushers[0] is the source pusher of the entire chain.
208    ///   Note that the Pushers list must always be kept acyclic, i.e. each entity must occur in the list at most once,
209    ///   or otherwise there is momentum to infinite recursion. For example, the last waggon of as train must not also be a pusher of the train;
210    ///   when a T-shaped object pushes a U-shaped object sideways (with its vertical bar in the center of the U), the U must not also push the T, etc.
211    ///
212    /// @param PushVector
213    ///   This vector describes the desired and required direction and length of the push.
214    virtual void OnPush(ArrayT<BaseEntityT*>& Pushers, const Vector3dT& PushVector);
215
216    /// This SERVER-SIDE function is used to have this entity take damage.
217    /// 'Entity' is the entitiy that causes the damage (i.e., who fired a shot). It is usually the entity from which the call is made.
218    /// 'Amount' is the amount of damage that was caused, and is usually subtracted from this entitys health.
219    /// 'ImpactDir' is the direction from which we were hit.
220    /// Calls are only made from within other entities 'Think()' functions.
221    /// (Unfortunately, this function cannot be declared as "protected": see "C++ FAQs, 2nd edition" by Cline, Lomow, Girou, pages 249f.)
222    virtual void TakeDamage(BaseEntityT* Entity, char Amount, const VectorT& ImpactDir);
223
224    /// THIS FUNCTION IS DEPRECATED! TRY TO AVOID TO USE IT!
225    /// This DEPRECATED, SERVER-SIDE function is called in order to "communicate" with this entity.
226    /// It is probably a (bad) replacement for additional, missing member functions, so don't use it!
227    /// Mostly used for setting/querying the properties of specific, concrete entities,
228    /// e.g. the player names, player model names, player commands, or if something is solid,
229    /// alive or was picked up (and is thus "invisible" for a while), and so on.
230    /// This should most certainly be resolved as soon as possible, requires careful design considerations, however.
231    /// At a first glance, the related methods are *only* called from the server (like passing in player commands),
232    /// or from within the Think() functions, but never on the client side.
233    virtual void ProcessConfigString(const void* ConfigData, const char* ConfigString);
234
235    /// This SERVER-SIDE function is called by the server in order to advance the world one clock-tick.
236    /// That is, basing on the present (old) 'State', it is called for computing the next (new) state.
237    /// 'FrameTime' is the time of the clock-tick, in seconds.
238    /// 'ServerFrameNr' is the number of the current server frame.
239    /// >>> IMPORTANT NOTE: In truth, also the CLIENT-SIDE calls this function for the purpose of predicting the local human player entity! <<<
240    /// >>> As a consequence, special rules apply when this function is called for predicted entities (that is, human player entities).     <<<
241    /// >>> For further details and examples, please refer to the EntHumanPlayerT::Think() function in HumanPlayer.cpp.                     <<<
242    virtual void Think(float FrameTime, unsigned long ServerFrameNr);
243
244
245    /// The client calls this method when it received an update of this entitys state from the server.
246    // /// @param NetMsg   The network message that contains the update.
247    virtual void Cl_UnserializeFrom(/*TODO: Add NetMsg param here.*/);
248
249    /// This CLIENT-SIDE function is called exactly once per received event (on client-side).
250    /// Usually, the server code (in 'Think()') will trigger events like "fire current weapon"
251    /// (using event ID 'EventID'), and then this is the place to react accordingly.
252    /// Note that both the name and the prototype of this function are subject to change in the future,
253    /// in order to take also more flexible, custom network messages into account.
254    ///
255    /// Notes for future prototypes:
256    ///   - What's the difference between events and custom network messages?
257    ///     Events are fully predictable, i.e. they work well even in the presence of client prediction,
258    ///     and are always related to a certain entity.
259    ///     Custom network messages are (currently) not predictable, and not necessarily associated with an entity.
260    ///     Examples for custom messages include radar displays, and so on.
261    virtual void ProcessEvent(char EventID);
262
263    /// This CLIENT-SIDE function is called in order to retrieve light source information about this entity.
264    /// Returns 'true' if this entity is a light source and 'DiffuseColor', 'SpecularColor', 'Position' (in world space!), 'Radius' and 'CastsShadows' have been set.
265    /// Returns 'false' if this entity is no light source.
266    /// (In theory, this function might also be called on server-side, from within Think().)
267    virtual bool GetLightSourceInfo(unsigned long& DiffuseColor, unsigned long& SpecularColor, VectorT& Position, float& Radius, bool& CastsShadows) const;
268
269    /// This CLIENT-SIDE method determines whether the engine should interpolate the origin (State.Origin) of this entity for drawing.
270    /// The normal return value is true, but e.g. rigid bodies (EntRigidBodyT) use some variables in the State member in a fashion
271    /// that doesn't work with the engines interpolation, so they can turn if off by overriding this method.
272    /// (This in turn makes this method a kind of hack for the EntRigidBodyT class...)
273    virtual bool DrawInterpolated() const;
274
275    /// This CLIENT-SIDE function is called by the client in order to get this entity drawn.
276    ///
277    /// Note that it is usually called several times per frame, in order to gather the individual terms of the lighting equation:
278    /// there is a call for the ambient contribution (everything that is independent of a lightsource) and for each light source there is
279    /// a call for the shadows, followed by another call for adding the lightsource-dependent contribution (diffuse and specular terms etc.).
280    ///
281    /// Also note that the calling code has properly set up the Cafu Material Systems global lighting parameters before calling.
282    /// That is, the ambient light color, light source position (in model space), radius, diff+spec color and the eye position (in model space) are set.
283    /// However, normally only those parameters that are relevant for the current Material Systems rendering action are set:
284    /// In the AMBIENT rendering action, only the ambient colors are set, in the STENCILSHADOW action only the light source position may be set,
285    /// and in the LIGHTING action all parameters except for the ambient light color are set.
286    ///
287    /// @param FirstPersonView   is true when the engine has rendered the world from this entities viewpoint, e.g. because this is the local players entity.
288    /// @param LodDist           is the world-space distance of the entity to the viewer, supposed to be used for level-of-detail reductions.
289    virtual void Draw(bool FirstPersonView, float LodDist) const;
290
291    /// This CLIENT-SIDE function is called once per frame, for each entity, after the regular rendering (calls to 'Draw()') is completed,
292    /// in order to provide entities an opportunity to render the HUD, employ simple "mini-prediction", triggers sounds,
293    /// register particles, do other server-independent eye-candy, and so on.
294    /// 'FrameTime' is the time in seconds that it took to render the last (previous) frame.
295    /// 'FirstPersonView' is true when the engine has rendered the world from this entities viewpoint, e.g. because this is the local players entity.
296    /// As it is convenient for current code (dealing with the particle system...), it is guaranteed that there is exactly one call to this function
297    /// with 'FirstPersonView==true', which occurs after the appropriate calls for all other entities. This behaviour may change in the future.
298    virtual void PostDraw(float FrameTime, bool FirstPersonView);
299
300
301    /// Returns the proper type info for this entity.
302    virtual const cf::TypeSys::TypeInfoT* GetType() const;
303    static void* CreateInstance(const cf::TypeSys::CreateParamsT& Params);
304    static const cf::TypeSys::TypeInfoT TypeInfo;     ///< The type info object for (objects/instances of) this class.
305
306    virtual unsigned long GetTypeNr() const;    ///< This method is needed only *TEMPORARILY*, because the code that needs it is still in the engine core.
307
308
309    // Methods provided to be called from the map/entity Lua scripts.
310    static int GetName(lua_State* L);
311    static int GetOrigin(lua_State* L);
312    static int SetOrigin(lua_State* L);
313
314
315    protected:
316
317    // Protected constructor such that only concrete entities can call this for creating a 'BaseEntityT', but nobody else.
318    // Concrete entities are created in the GameI::CreateBaseEntityFromMapFile() method for the server-side,
319    // and in the GameI::CreateBaseEntityFromTypeNr() method for the client-side.
320    BaseEntityT(const EntityCreateParamsT& Params, const EntityStateT& State_);
321
322
323    private:
324
325    BaseEntityT(const BaseEntityT&);        ///< Use of the Copy    Constructor is not allowed.
326    void operator = (const BaseEntityT&);   ///< Use of the Assignment Operator is not allowed.
327
328    unsigned long m_OldEvents;
329};
330
331#endif
Note: See TracBrowser for help on using the browser.