1 /** @file thinkerdata.h Base class for thinker private data. 2 * 3 * @authors Copyright (c) 2014-2017 Jaakko Keränen <jaakko.keranen@iki.fi> 4 * 5 * @par License 6 * GPL: http://www.gnu.org/licenses/gpl.html 7 * 8 * <small>This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. This program is distributed in the hope that it 12 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 14 * Public License for more details. You should have received a copy of the GNU 15 * General Public License along with this program; if not, write to the Free 16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 17 * 02110-1301 USA</small> 18 */ 19 20 #ifndef LIBDOOMSDAY_THINKERDATA_H 21 #define LIBDOOMSDAY_THINKERDATA_H 22 23 #include "thinker.h" 24 25 #include <de/Process> 26 #include <de/Id> 27 #include <de/IObject> 28 #include <de/ISerializable> 29 30 /** 31 * Base class for thinker private data. 32 * 33 * Contains internal functionality common to all thinkers regardless of their type. 34 */ 35 class LIBDOOMSDAY_PUBLIC ThinkerData 36 : public Thinker::IData 37 , public de::IObject 38 , public de::ISerializable 39 , public de::Deletable 40 { 41 public: 42 DENG2_DEFINE_AUDIENCE2(Deletion, void thinkerBeingDeleted(thinker_s &)) 43 44 public: 45 ThinkerData(de::Id const &id = de::Id::none()); 46 ThinkerData(ThinkerData const &other); 47 48 /** 49 * Returns the unique and persistent ID of the thinker. 50 * 51 * Note that due to historical reasons game-side mobj IDs are separately enumerated 52 * 16-bit numbers. 53 * 54 * @return Thinker ID. 55 * 56 * @todo Use this for identifying all thinkers everywhere, including mobjs. 57 */ 58 de::Id const &id() const; 59 60 void setId(de::Id const &id); 61 62 void setThinker(thinker_s *thinker) override; 63 void think() override; 64 IData *duplicate() const override; 65 66 thinker_s &thinker(); 67 thinker_s const &thinker() const; 68 69 /** 70 * Initializes Doomsday Script bindings for the thinker. This is called 71 * when the thinker is added to the world, so mobjs have been assigned 72 * their IDs. 73 */ 74 virtual void initBindings(); 75 76 // Implements IObject. 77 de::Record &objectNamespace() override; 78 de::Record const &objectNamespace() const override; 79 80 // Implements ISerializable. 81 void operator >> (de::Writer &to) const override; 82 void operator << (de::Reader &from) override; 83 84 public: 85 /* 86 * Finds a thinker based on its unique identifier. This searches all ThinkerData 87 * instances in existence at the moment. If there happens to be multiple ThinkerData 88 * instances with the same ID, returns the most recently created instance. 89 * 90 * @param id Identifier. 91 * @return Thinker or @c nullptr. 92 */ 93 static ThinkerData *find(de::Id const &id); 94 95 private: 96 DENG2_PRIVATE(d) 97 98 #ifdef DENG2_DEBUG 99 public: 100 struct DebugCounter { 101 de::Id id; 102 static de::duint32 total; 103 DebugCounterDebugCounter104 DebugCounter() { total++; } ~DebugCounterDebugCounter105 ~DebugCounter() { total--; } 106 }; 107 DebugCounter _debugCounter; 108 109 struct DebugValidator { DebugValidatorDebugValidator110 DebugValidator() { DENG2_ASSERT(DebugCounter::total == 0); } ~DebugValidatorDebugValidator111 ~DebugValidator() { DENG2_ASSERT(DebugCounter::total == 0); } 112 }; 113 #endif 114 }; 115 116 DENG2_SCRIPT_ARGUMENT_TYPE(ThinkerData *, 117 if (!arg) return ScriptLex::NONE; 118 return scriptArgumentAsText(arg->objectNamespace()); 119 ) 120 121 DENG2_SCRIPT_ARGUMENT_TYPE(ThinkerData const *, 122 if (!arg) return ScriptLex::NONE; 123 return scriptArgumentAsText(arg->objectNamespace()); 124 ) 125 126 #endif // LIBDOOMSDAY_THINKERDATA_H 127