2007-12-02 19:20:55 +00:00
// Cyphesis Online RPG Server and AI Engine
// Copyright (C) 2000,2001 Alistair Riddoch
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# include "LocatedEntity.h"
2016-03-11 15:36:47 +01:00
# include "Domain.h"
2016-01-17 17:02:50 +01:00
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
# include "Script.h"
2018-10-31 21:38:35 +01:00
# include "rules/AtlasProperties.h"
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
2007-12-29 01:53:26 +00:00
# include "common/TypeNode.h"
2007-12-24 00:32:11 +00:00
2017-06-24 21:47:43 +02:00
# include <Atlas/Objects/RootOperation.h>
2017-06-27 18:33:13 +02:00
# include <Atlas/Objects/Operation.h>
# include <Atlas/Objects/Anonymous.h>
2017-06-24 21:47:43 +02:00
2007-12-02 20:53:50 +00:00
using Atlas : : Message : : Element ;
using Atlas : : Message : : MapType ;
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
/// \brief Set of attribute names which must not be changed
///
/// The attributes named are special and are modified using high level
/// operations, such as Move, not via Set operations, or assigned by
/// normal means.
2017-07-24 13:39:22 +02:00
std : : set < std : : string > LocatedEntity : : s_immutable = { " id " , " parent " , " pos " , " loc " , " velocity " , " orientation " , " contains " , " objtype " } ;
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
/// \brief Singleton accessor for immutables
///
2015-07-13 22:14:51 +02:00
/// The immutable attribute set m_immutables is returned.
2017-06-24 21:47:43 +02:00
const std : : set < std : : string > & LocatedEntity : : immutables ( )
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
{
2015-07-13 22:14:51 +02:00
return s_immutable ;
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
}
2007-12-02 20:53:50 +00:00
/// \brief LocatedEntity constructor
2017-06-24 21:47:43 +02:00
LocatedEntity : : LocatedEntity ( const std : : string & id , long intId ) :
Router ( id , intId ) ,
2018-04-19 10:19:35 +02:00
m_seq ( 0 ) ,
m_type ( nullptr ) ,
m_flags ( 0 ) ,
m_contains ( nullptr )
2007-12-02 20:53:50 +00:00
{
2018-04-27 20:55:02 +02:00
m_properties [ IdProperty : : property_name ] = new IdProperty ( getId ( ) ) ;
2007-12-02 20:53:50 +00:00
}
LocatedEntity : : ~ LocatedEntity ( )
{
2016-07-09 23:06:45 +02:00
clearProperties ( ) ;
2018-07-04 19:18:03 +02:00
for ( auto script : m_scripts ) {
delete script ;
}
2016-07-09 23:06:45 +02:00
delete m_contains ;
}
2017-06-24 21:47:43 +02:00
void LocatedEntity : : clearProperties ( )
{
2013-11-24 20:07:56 +01:00
if ( m_type ) {
for ( auto entry : m_type - > defaults ( ) ) {
//Only remove if there's no instance specific property.
if ( m_properties . find ( entry . first ) = = m_properties . end ( ) ) {
2014-08-25 22:42:00 +02:00
entry . second - > remove ( this , entry . first ) ;
2013-11-24 20:07:56 +01:00
}
}
}
for ( auto entry : m_properties ) {
2014-08-25 22:42:00 +02:00
entry . second - > remove ( this , entry . first ) ;
2013-11-24 20:07:56 +01:00
delete entry . second ;
2007-12-31 19:07:10 +00:00
}
2016-07-09 23:06:45 +02:00
m_properties . clear ( ) ;
2007-12-02 20:53:50 +00:00
}
2017-06-24 21:47:43 +02:00
void LocatedEntity : : setType ( const TypeNode * t )
{
2015-04-08 18:36:20 +02:00
m_type = t ;
}
2007-12-02 20:53:50 +00:00
/// \brief Check if this entity has a property with the given name
///
/// @param name Name of attribute to be checked
2018-04-26 19:48:53 +02:00
/// @return true if this entity has an attribute with the name given
2007-12-02 20:53:50 +00:00
/// false otherwise
2017-06-24 21:47:43 +02:00
bool LocatedEntity : : hasAttr ( const std : : string & name ) const
2007-12-02 20:53:50 +00:00
{
2018-06-02 17:23:22 +02:00
auto I = m_properties . find ( name ) ;
2007-12-24 00:32:11 +00:00
if ( I ! = m_properties . end ( ) ) {
2007-12-02 20:53:50 +00:00
return true ;
}
2018-06-02 17:23:22 +02:00
if ( m_type ! = nullptr ) {
2009-08-05 19:50:53 +01:00
I = m_type - > defaults ( ) . find ( name ) ;
if ( I ! = m_type - > defaults ( ) . end ( ) ) {
return true ;
}
}
2007-12-02 20:53:50 +00:00
return false ;
}
/// \brief Get the value of an attribute
///
/// @param name Name of attribute to be retrieved
/// @param attr Reference used to store value
2011-09-29 17:36:26 +01:00
/// @return zero if this entity has an attribute with the name given
/// nonzero otherwise
2017-06-24 21:47:43 +02:00
int LocatedEntity : : getAttr ( const std : : string & name ,
Element & attr ) const
2007-12-02 20:53:50 +00:00
{
2018-06-02 17:23:22 +02:00
auto I = m_properties . find ( name ) ;
2007-12-24 00:32:11 +00:00
if ( I ! = m_properties . end ( ) ) {
return I - > second - > get ( attr ) ;
2007-12-02 20:53:50 +00:00
}
2018-06-02 17:23:22 +02:00
if ( m_type ! = nullptr ) {
2007-12-29 01:53:26 +00:00
I = m_type - > defaults ( ) . find ( name ) ;
if ( I ! = m_type - > defaults ( ) . end ( ) ) {
return I - > second - > get ( attr ) ;
}
}
2011-09-29 17:36:26 +01:00
return - 1 ;
2007-12-02 20:53:50 +00:00
}
2008-09-29 02:49:45 +00:00
/// \brief Get the value of an attribute if it is the right type
///
/// @param name Name of attribute to be retrieved
/// @param attr Reference used to store value
2011-09-29 17:36:26 +01:00
/// @return zero if this entity has an attribute with the name given
/// nonzero otherwise
2017-06-24 21:47:43 +02:00
int LocatedEntity : : getAttrType ( const std : : string & name ,
Element & attr ,
2011-09-29 17:36:26 +01:00
int type ) const
2008-09-29 02:49:45 +00:00
{
2018-06-02 17:23:22 +02:00
auto I = m_properties . find ( name ) ;
2008-09-29 02:49:45 +00:00
if ( I ! = m_properties . end ( ) ) {
2011-09-29 20:59:14 +01:00
return I - > second - > get ( attr ) | | ( attr . getType ( ) = = type ? 0 : 1 ) ;
2008-09-29 02:49:45 +00:00
}
2018-06-02 17:23:22 +02:00
if ( m_type ! = nullptr ) {
2008-09-29 02:49:45 +00:00
I = m_type - > defaults ( ) . find ( name ) ;
if ( I ! = m_type - > defaults ( ) . end ( ) ) {
2011-09-29 20:59:14 +01:00
return I - > second - > get ( attr ) | | ( attr . getType ( ) = = type ? 0 : 1 ) ;
2008-09-29 02:49:45 +00:00
}
}
2011-09-29 17:36:26 +01:00
return - 1 ;
2008-09-29 02:49:45 +00:00
}
2007-12-02 20:53:50 +00:00
/// \brief Set the value of an attribute
///
/// @param name Name of attribute to be changed
/// @param attr Value to be stored
2017-06-24 21:47:43 +02:00
PropertyBase * LocatedEntity : : setAttr ( const std : : string & name ,
const Element & attr )
2007-12-02 20:53:50 +00:00
{
2007-12-24 00:32:11 +00:00
PropertyDict : : const_iterator I = m_properties . find ( name ) ;
if ( I ! = m_properties . end ( ) ) {
I - > second - > set ( attr ) ;
2011-02-27 23:56:11 +00:00
return I - > second ;
2007-12-02 20:53:50 +00:00
}
2018-07-30 10:22:50 +02:00
auto prop = new SoftProperty ( attr ) ;
prop - > addFlags ( PropertyBase : : flagsForPropertyName ( name ) ) ;
m_properties . emplace ( name , prop ) ;
return prop ;
2007-12-02 20:53:50 +00:00
}
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
/// \brief Get the property object for a given attribute
///
/// @param name name of the attribute for which the property is required.
/// @return a pointer to the property, or zero if the attributes does
/// not exist, or is not stored using a property object.
2017-06-24 21:47:43 +02:00
const PropertyBase * LocatedEntity : : getProperty ( const std : : string & name ) const
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
{
2018-02-26 12:05:10 +01:00
auto I = m_properties . find ( name ) ;
2007-12-24 00:32:11 +00:00
if ( I ! = m_properties . end ( ) ) {
return I - > second ;
}
2018-02-26 12:05:10 +01:00
return nullptr ;
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
}
2018-02-26 12:05:10 +01:00
PropertyBase * LocatedEntity : : modProperty ( const std : : string & name , const Atlas : : Message : : Element & def_val )
2013-01-17 10:17:07 +00:00
{
2018-02-26 12:05:10 +01:00
auto I = m_properties . find ( name ) ;
2013-01-17 10:17:07 +00:00
if ( I ! = m_properties . end ( ) ) {
return I - > second ;
}
2018-02-26 12:05:10 +01:00
return nullptr ;
2013-01-17 10:17:07 +00:00
}
2017-06-24 21:47:43 +02:00
PropertyBase * LocatedEntity : : setProperty ( const std : : string & name ,
PropertyBase * prop )
2013-01-17 10:17:07 +00:00
{
return m_properties [ name ] = prop ;
}
2017-06-24 21:47:43 +02:00
void LocatedEntity : : installDelegate ( int , const std : : string & )
2013-01-17 10:17:07 +00:00
{
}
2017-06-24 21:47:43 +02:00
void LocatedEntity : : removeDelegate ( int , const std : : string & )
2014-08-25 22:42:00 +02:00
{
}
2008-01-07 00:06:18 +00:00
/// \brief Called when the container of this entity changes.
///
2018-08-05 20:47:09 +02:00
void LocatedEntity : : onContainered ( const Ref < LocatedEntity > & new_loc )
2008-01-07 00:06:18 +00:00
{
}
2008-08-16 23:21:06 +00:00
/// \brief Called when the properties of this entity change.
///
void LocatedEntity : : onUpdated ( )
{
}
2013-01-24 22:52:05 +00:00
/// \brief Called when the entity needs to be removed from its context
2013-01-17 10:17:07 +00:00
void LocatedEntity : : destroy ( )
{
2018-08-05 14:31:04 +02:00
for ( auto script : m_scripts ) {
delete script ;
}
m_scripts . clear ( ) ;
2018-10-21 20:22:39 +02:00
if ( m_location . m_parent ) {
m_location . m_parent - > removeChild ( * this ) ;
}
2018-08-05 14:31:04 +02:00
2016-07-09 23:06:45 +02:00
clearProperties ( ) ;
2018-08-05 14:31:04 +02:00
m_flags . addFlags ( entity_destroyed ) ;
destroyed . emit ( ) ;
2013-01-17 10:17:07 +00:00
}
2017-07-01 15:26:47 +02:00
Domain * LocatedEntity : : getDomain ( )
2013-01-17 10:17:07 +00:00
{
2016-06-22 16:50:36 +02:00
return nullptr ;
2013-01-17 10:17:07 +00:00
}
2017-07-01 15:26:47 +02:00
const Domain * LocatedEntity : : getDomain ( ) const
2016-06-22 16:50:36 +02:00
{
return nullptr ;
}
2013-01-17 10:17:07 +00:00
/// \brief Send an operation to the world for dispatch.
///
2018-04-26 19:48:53 +02:00
/// sendWorld() bypasses serialno assignment, so you must ensure
2013-01-17 10:17:07 +00:00
/// that serialno is sorted. This allows client serialnos to get
2018-04-26 19:48:53 +02:00
/// in, so that client gets correct useful refnos back.
2017-06-24 21:47:43 +02:00
void LocatedEntity : : sendWorld ( const Operation & op )
2013-01-17 10:17:07 +00:00
{
}
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
/// \brief Associate a script with this entity
///
/// The previously associated script is deleted.
/// @param scrpt Pointer to the script to be associated with this entity
2017-06-24 21:47:43 +02:00
void LocatedEntity : : setScript ( Script * scrpt )
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
{
2018-07-04 19:18:03 +02:00
m_scripts . push_back ( scrpt ) ;
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
}
2015-05-26 22:27:39 +02:00
std : : vector < Atlas : : Objects : : Root > LocatedEntity : : getThoughts ( ) const
{
return std : : vector < Atlas : : Objects : : Root > ( ) ;
}
2008-01-05 Al Riddoch <alriddoch@googlemail.com>
* rulesets/LocatedEntity.cpp, rulesets/LocatedEntity.h:
Don't allocated storage for m_contains by default, only
on demand. Add a convenience method which checks, and
allocates the storage if required. Set up the ID property
on this base class rather then Entity.
* rulesets/Py_Thing.cpp: Remove special handling of ID attribute
as it is now handled by the property.
* rulesets/Character.cpp, rulesets/Entity.cpp, rulesets/MemMap.cpp,
rulesets/Motion.cpp, rulesets/Py_Mind.cpp, rulesets/Py_Thing.cpp,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp:
Make sure all parts of the code where contains is used have
the right checks, as it could be null.
2008-01-05 14:05:05 +00:00
/// \brief Make this entity a container
///
/// If this entity is not already a contains, set up the necessary
/// storage and property.
void LocatedEntity : : makeContainer ( )
{
2018-06-02 17:23:22 +02:00
if ( m_contains = = nullptr ) {
2008-01-05 Al Riddoch <alriddoch@googlemail.com>
* rulesets/LocatedEntity.cpp, rulesets/LocatedEntity.h:
Don't allocated storage for m_contains by default, only
on demand. Add a convenience method which checks, and
allocates the storage if required. Set up the ID property
on this base class rather then Entity.
* rulesets/Py_Thing.cpp: Remove special handling of ID attribute
as it is now handled by the property.
* rulesets/Character.cpp, rulesets/Entity.cpp, rulesets/MemMap.cpp,
rulesets/Motion.cpp, rulesets/Py_Mind.cpp, rulesets/Py_Thing.cpp,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp:
Make sure all parts of the code where contains is used have
the right checks, as it could be null.
2008-01-05 14:05:05 +00:00
m_contains = new LocatedEntitySet ;
m_properties [ " contains " ] = new ContainsProperty ( * m_contains ) ;
}
}
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
/// \brief Change the container of an entity
///
2017-06-27 18:33:13 +02:00
/// @param new_loc The entity which is to become this entity's new
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
/// container.
2018-08-05 20:47:09 +02:00
void LocatedEntity : : changeContainer ( const Ref < LocatedEntity > & new_loc )
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
{
2018-08-17 22:04:07 +02:00
auto oldLoc = m_location . m_parent ;
2014-09-18 22:41:23 +02:00
oldLoc - > removeChild ( * this ) ;
new_loc - > addChild ( * this ) ;
2018-08-17 22:04:07 +02:00
assert ( m_location . m_parent - > checkRef ( ) > 0 ) ;
2008-01-07 00:06:18 +00:00
2018-07-23 21:04:17 +02:00
onContainered ( oldLoc ) ;
2014-09-18 22:41:23 +02:00
}
2018-07-30 13:07:43 +02:00
void LocatedEntity : : broadcast ( const Atlas : : Objects : : Operation : : RootOperation & op , OpVector & res , Visibility visibility ) const
2017-06-24 21:47:43 +02:00
{
std : : set < const LocatedEntity * > receivers ;
2017-06-27 18:33:13 +02:00
collectObservers ( receivers ) ;
for ( auto & entity : receivers ) {
2018-07-30 13:07:43 +02:00
if ( visibility = = Visibility : : PRIVATE ) {
//Only send private ops to admins
if ( ! entity - > hasFlags ( entity_admin ) ) {
continue ;
}
} else if ( visibility = = Visibility : : PROTECTED ) {
//Protected ops also goes to the entity itself
if ( ! entity - > hasFlags ( entity_admin ) & &
entity - > getIntId ( ) ! = getIntId ( ) ) {
continue ;
}
}
2017-06-27 18:33:13 +02:00
auto newOp = op . copy ( ) ;
newOp - > setTo ( entity - > getId ( ) ) ;
newOp - > setFrom ( getId ( ) ) ;
res . push_back ( newOp ) ;
}
}
void LocatedEntity : : collectObservers ( std : : set < const LocatedEntity * > & receivers ) const
{
2017-06-24 21:47:43 +02:00
if ( isPerceptive ( ) ) {
receivers . insert ( this ) ;
}
2017-07-01 15:26:47 +02:00
const Domain * domain = getDomain ( ) ;
2017-06-24 21:47:43 +02:00
if ( domain ) {
auto observingEntities = domain - > getObservingEntitiesFor ( * this ) ;
receivers . insert ( observingEntities . begin ( ) , observingEntities . end ( ) ) ;
}
2018-08-17 22:04:07 +02:00
if ( m_location . m_parent ) {
m_location . m_parent - > collectObserversForChild ( * this , receivers ) ;
2017-06-24 21:47:43 +02:00
}
}
2017-06-27 18:33:13 +02:00
void LocatedEntity : : collectObserversForChild ( const LocatedEntity & child , std : : set < const LocatedEntity * > & receivers ) const
2017-06-24 21:47:43 +02:00
{
2017-07-01 15:26:47 +02:00
const Domain * domain = getDomain ( ) ;
2017-06-24 21:47:43 +02:00
if ( isPerceptive ( ) ) {
receivers . insert ( this ) ;
}
if ( domain ) {
2017-06-27 18:33:13 +02:00
auto observingEntities = domain - > getObservingEntitiesFor ( child ) ;
2017-06-24 21:47:43 +02:00
receivers . insert ( observingEntities . begin ( ) , observingEntities . end ( ) ) ;
}
2018-08-17 22:04:07 +02:00
if ( m_location . m_parent ) {
2017-06-24 21:47:43 +02:00
//If this entity have a movement domain, check if the child entity is visible to the parent entity (i.e. it's "exposed outside of the domain"). If not, the broadcast chain stops here.
2018-08-17 22:04:07 +02:00
if ( domain & & ! domain - > isEntityVisibleFor ( * m_location . m_parent , child ) ) {
2017-06-24 21:47:43 +02:00
return ;
}
2018-08-17 22:04:07 +02:00
m_location . m_parent - > collectObserversForChild ( * this , receivers ) ;
2017-06-27 18:33:13 +02:00
}
}
void LocatedEntity : : processAppearDisappear ( std : : set < const LocatedEntity * > previousObserving , OpVector & res ) const
{
std : : set < const LocatedEntity * > nowObservers ;
collectObservers ( nowObservers ) ;
for ( auto entity : nowObservers ) {
auto numberErased = previousObserving . erase ( entity ) ;
if ( numberErased = = 0 ) {
Atlas : : Objects : : Operation : : Appearance appear ;
Atlas : : Objects : : Entity : : Anonymous that_ent ;
that_ent - > setId ( getId ( ) ) ;
that_ent - > setStamp ( getSeq ( ) ) ;
appear - > setArgs1 ( that_ent ) ;
appear - > setTo ( entity - > getId ( ) ) ;
res . push_back ( appear ) ;
}
}
for ( auto entity : previousObserving ) {
Atlas : : Objects : : Operation : : Disappearance disappear ;
Atlas : : Objects : : Entity : : Anonymous that_ent ;
that_ent - > setId ( getId ( ) ) ;
that_ent - > setStamp ( getSeq ( ) ) ;
disappear - > setArgs1 ( that_ent ) ;
disappear - > setTo ( entity - > getId ( ) ) ;
res . push_back ( disappear ) ;
2017-06-24 21:47:43 +02:00
}
}
2018-08-14 21:32:06 +02:00
void LocatedEntity : : applyProperty ( const std : : string & name , PropertyBase * prop ) {
// Allow the value to take effect.
prop - > apply ( this ) ;
prop - > addFlags ( flag_unsent ) ;
propertyApplied ( name , * prop ) ;
// Mark the Entity as unclean
m_flags . removeFlags ( entity_clean ) ;
}
2017-06-27 18:33:13 +02:00
2014-09-18 22:41:23 +02:00
void LocatedEntity : : addChild ( LocatedEntity & childEntity )
{
makeContainer ( ) ;
bool was_empty = m_contains - > empty ( ) ;
m_contains - > insert ( & childEntity ) ;
if ( was_empty ) {
onUpdated ( ) ;
}
2018-08-17 22:04:07 +02:00
childEntity . m_location . m_parent = this ;
2014-09-18 22:41:23 +02:00
}
void LocatedEntity : : removeChild ( LocatedEntity & childEntity )
{
assert ( checkRef ( ) > 0 ) ;
2018-06-02 17:23:22 +02:00
assert ( m_contains ! = nullptr ) ;
2014-09-18 22:41:23 +02:00
assert ( m_contains - > count ( & childEntity ) ) ;
m_contains - > erase ( & childEntity ) ;
if ( m_contains - > empty ( ) ) {
onUpdated ( ) ;
}
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
}
2018-08-07 20:33:51 +02:00
void LocatedEntity : : addListener ( OperationsListener * listener )
{
//No-op in LocatedEntity
}
void LocatedEntity : : removeListener ( OperationsListener * listener )
{
//No-op in LocatedEntity
}
2016-06-26 14:18:37 +02:00
bool LocatedEntity : : isVisibleForOtherEntity ( const LocatedEntity * watcher ) const
{
//Are we looking at ourselves?
if ( watcher = = this ) {
return true ;
}
2018-06-02 17:23:22 +02:00
//Optimize for the most common case of both entities being direct child of a domain
2018-08-17 22:04:07 +02:00
if ( m_location . m_parent ! = nullptr & & watcher - > m_location . m_parent = = m_location . m_parent & & m_location . m_parent - > getDomain ( ) ) {
return m_location . m_parent - > getDomain ( ) - > isEntityVisibleFor ( * watcher , * this ) ;
2018-06-02 17:23:22 +02:00
}
2016-06-26 14:18:37 +02:00
//First find the domain which contains the watcher, as well as if the watcher has a domain itself.
2018-08-17 22:04:07 +02:00
const LocatedEntity * domainEntity = watcher - > m_location . m_parent . get ( ) ;
2016-06-26 14:18:37 +02:00
const LocatedEntity * topWatcherEntity = watcher ;
const Domain * watcherParentDomain = nullptr ;
while ( domainEntity ! = nullptr ) {
2017-07-01 15:26:47 +02:00
watcherParentDomain = domainEntity - > getDomain ( ) ;
2016-06-26 14:18:37 +02:00
if ( watcherParentDomain ) {
break ;
}
topWatcherEntity = domainEntity ;
2018-08-17 22:04:07 +02:00
domainEntity = domainEntity - > m_location . m_parent . get ( ) ;
2016-06-26 14:18:37 +02:00
}
2018-08-17 22:04:07 +02:00
domainEntity = watcher - > m_location . m_parent . get ( ) ;
2017-07-01 15:26:47 +02:00
const Domain * watcherOwnDomain = watcher - > getDomain ( ) ;
2016-06-26 14:18:37 +02:00
//Now walk upwards from the entity being looked at until we reach either the watcher's parent domain entity,
//or the watcher itself
std : : vector < const LocatedEntity * > toAncestors ;
toAncestors . reserve ( 4 ) ;
const LocatedEntity * ancestorEntity = this ;
const Domain * ancestorDomain = nullptr ;
while ( true ) {
toAncestors . push_back ( ancestorEntity ) ;
if ( ancestorEntity = = watcher ) {
ancestorDomain = watcherOwnDomain ;
break ;
}
if ( ancestorEntity = = domainEntity ) {
ancestorDomain = watcherParentDomain ;
break ;
}
if ( ancestorEntity = = topWatcherEntity ) {
break ;
}
2018-08-17 22:04:07 +02:00
ancestorEntity = ancestorEntity - > m_location . m_parent . get ( ) ;
2016-06-26 14:18:37 +02:00
if ( ancestorEntity = = nullptr ) {
//Could find no common ancestor; can't be seen.
return false ;
}
}
//Now walk back down the toAncestors list, checking if all entities on the way can be seen.
//Visibility is only checked for the first immediate child of a domain entity, further grandchildren are considered visible if the top one is, until
//another domain is reached.
for ( auto I = toAncestors . rbegin ( ) ; I ! = toAncestors . rend ( ) ; + + I ) {
const LocatedEntity * ancestor = * I ;
if ( ancestorDomain ) {
if ( ! ancestorDomain - > isEntityVisibleFor ( * watcher , * ancestor ) ) {
return false ;
}
}
2017-07-01 15:26:47 +02:00
ancestorDomain = ancestor - > getDomain ( ) ;
2016-06-26 14:18:37 +02:00
}
return true ;
}
2014-09-18 22:41:23 +02:00
2018-08-01 23:04:39 +02:00
bool LocatedEntity : : canReach ( const EntityLocation & entityLocation , float extraReach ) const
2018-06-15 13:46:17 +02:00
{
2018-08-01 23:04:39 +02:00
auto reachingEntity = this ;
2018-06-15 13:46:17 +02:00
//Are we reaching for our ourselves?
2018-08-17 22:04:07 +02:00
if ( reachingEntity = = entityLocation . m_parent . get ( ) ) {
2018-06-15 13:46:17 +02:00
return true ;
}
//Is the reacher a "creator"?
if ( reachingEntity - > getType ( ) - > isTypeOf ( " creator " ) ) {
return true ;
}
double reachDistance = 0 ;
auto reachProp = reachingEntity - > getPropertyType < double > ( " reach " ) ;
if ( reachProp ) {
reachDistance = reachProp - > data ( ) ;
}
2018-07-05 00:05:52 +02:00
reachDistance + = extraReach ;
2018-06-15 13:46:17 +02:00
//First find the domain which contains the reacher, as well as if the reacher has a domain itself.
2018-08-17 22:04:07 +02:00
const LocatedEntity * domainEntity = reachingEntity - > m_location . m_parent . get ( ) ;
2018-06-15 13:46:17 +02:00
const LocatedEntity * topReachingEntity = reachingEntity ;
const Domain * reacherParentDomain = nullptr ;
const LocatedEntity * reacherDomainEntity = nullptr ; //The entity which contains the reacher's domain
while ( domainEntity ! = nullptr ) {
reacherParentDomain = domainEntity - > getDomain ( ) ;
if ( reacherParentDomain ) {
reacherDomainEntity = domainEntity ;
break ;
}
topReachingEntity = domainEntity ;
2018-08-17 22:04:07 +02:00
domainEntity = domainEntity - > m_location . m_parent . get ( ) ;
2018-06-15 13:46:17 +02:00
}
//Now walk upwards from the entity being reached for until we reach either the reacher's parent domain entity,
//or the reacher itself
std : : vector < const LocatedEntity * > toAncestors ;
toAncestors . reserve ( 4 ) ;
2018-08-17 22:04:07 +02:00
auto ancestorEntity = entityLocation . m_parent ;
2018-06-15 13:46:17 +02:00
while ( true ) {
if ( ancestorEntity = = reacherDomainEntity ) {
2018-08-17 22:04:07 +02:00
if ( ancestorEntity = = entityLocation . m_parent ) {
2018-06-15 13:46:17 +02:00
//We're trying to reach our containing domain entity, handle separately
2018-08-01 23:04:39 +02:00
return ! ( reacherParentDomain & & ! reacherParentDomain - > isEntityReachable ( * reachingEntity , reachDistance , * reacherDomainEntity , entityLocation . m_pos ) ) ;
2018-06-15 13:46:17 +02:00
}
break ;
}
if ( ancestorEntity = = reachingEntity ) {
break ;
}
2018-08-05 20:47:09 +02:00
toAncestors . push_back ( ancestorEntity . get ( ) ) ;
2018-06-15 13:46:17 +02:00
if ( ancestorEntity = = topReachingEntity ) {
break ;
}
2018-08-17 22:04:07 +02:00
ancestorEntity = ancestorEntity - > m_location . m_parent ;
2018-06-15 13:46:17 +02:00
if ( ancestorEntity = = nullptr ) {
//Could find no common ancestor; can't be reached.
return false ;
}
}
if ( toAncestors . empty ( ) ) {
return false ;
}
//Now walk back down the toAncestors list, checking if all entities on the way can be reached.
//Reachability is only checked for the first immediate child of a domain entity, further grandchildren are considered reachable if the top one is, until
//another domain is reached.
for ( auto I = toAncestors . rbegin ( ) ; I ! = toAncestors . rend ( ) ; + + I ) {
const LocatedEntity * ancestor = * I ;
2018-08-17 22:04:07 +02:00
auto domain = ancestor - > m_location . m_parent ? ancestor - > m_location . m_parent - > getDomain ( ) : nullptr ;
2018-08-01 23:04:39 +02:00
if ( domain & & ! domain - > isEntityReachable ( * reachingEntity , reachDistance , * ancestor , entityLocation . m_pos ) ) {
2018-06-15 13:46:17 +02:00
return false ;
}
}
return true ;
}
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
/// \brief Read attributes from an Atlas element
///
/// @param ent The Atlas map element containing the attribute values
2017-06-24 21:47:43 +02:00
void LocatedEntity : : merge ( const MapType & ent )
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
{
2017-06-24 21:47:43 +02:00
const std : : set < std : : string > & imm = immutables ( ) ;
2018-06-15 13:46:17 +02:00
auto Iend = ent . end ( ) ;
for ( auto I = ent . begin ( ) ; I ! = Iend ; + + I ) {
2017-06-24 21:47:43 +02:00
const std : : string & key = I - > first ;
2016-07-10 00:10:48 +02:00
if ( key . empty ( ) ) {
continue ;
}
2017-06-24 21:47:43 +02:00
if ( imm . find ( key ) ! = imm . end ( ) ) { continue ; }
2007-12-02 Al Riddoch <alriddoch@zepler.org>
* client/CreatorClient.cpp, client/CreatorClient.h,
client/Py_CreatorClient.cpp, common/BaseWorld.h, common/types.h,
modules/Location.cpp, modules/Location.h,
rulesets/AtlasProperties.cpp, rulesets/AtlasProperties.h,
rulesets/BaseMind.cpp, rulesets/Character.cpp, rulesets/Character.h,
rulesets/Entity.cpp, rulesets/Entity.h,
rulesets/EntityProperties.cpp, rulesets/LocatedEntity.cpp,
rulesets/LocatedEntity.h, rulesets/MemEntity.cpp,
rulesets/MemEntity.h, rulesets/MemMap.cpp, rulesets/Motion.cpp,
rulesets/Motion.h, rulesets/Py_Location.h, rulesets/Py_Mind.cpp,
rulesets/Py_Thing.cpp, rulesets/Py_Thing.h,
rulesets/PythonMindScript.h, rulesets/PythonScript.h,
rulesets/PythonThingScript.cpp, rulesets/PythonThingScript.h,
rulesets/Python_API.cpp, rulesets/Script.cpp, rulesets/Script.h,
rulesets/Thing.cpp, rulesets/World.cpp, server/WorldRouter.cpp,
server/WorldRouter.h: Refactor all the entity code so there is now
a new base class for entities in the world simulation, and in the
mind which only contains things which are trully common to both.
This moves a lot of functionality which should not have been
present in mind entities away, and makes that code safer and more
efficient.
* tests/TestWorld.h: Update the test world API to match the base
class.
2007-12-02 23:49:05 +00:00
setAttr ( key , I - > second ) ;
}
}
2016-05-24 11:20:32 +02:00
std : : string LocatedEntity : : describeEntity ( ) const
{
std : : stringstream ss ;
Element nameAttr ;
int nameResult = getAttrType ( " name " , nameAttr , Element : : TYPE_STRING ) ;
ss < < getId ( ) ;
if ( m_type ) {
ss < < " ( " < < m_type - > name ( ) ;
if ( nameResult = = 0 ) {
ss < < " ,' " < < nameAttr . String ( ) < < " ' " ;
}
ss < < " ) " ;
} else {
if ( nameResult = = 0 ) {
ss < < " (' " < < nameAttr . String ( ) < < " ') " ;
}
}
return ss . str ( ) ;
}