mirror of https://github.com/minetest/minetest.git
Merge a21d8ef8e0
into 0ea1ec31fc
This commit is contained in:
commit
323a39511f
|
@ -39,6 +39,7 @@ core.features = {
|
|||
dynamic_add_media_filepath = true,
|
||||
lsystem_decoration_type = true,
|
||||
item_meta_range = true,
|
||||
have_guids = true,
|
||||
}
|
||||
|
||||
function core.has_feature(arg)
|
||||
|
|
|
@ -5432,6 +5432,8 @@ Utilities
|
|||
lsystem_decoration_type = true,
|
||||
-- Overrideable pointing range using the itemstack meta key `"range"` (5.9.0)
|
||||
item_meta_range = true,
|
||||
-- objects have get_guid method and lua entities alse set_guid method (5.9.0)
|
||||
have_guids = true,
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -7283,6 +7285,8 @@ Global tables
|
|||
as they are only read when spawning.
|
||||
* `minetest.object_refs`
|
||||
* Map of object references, indexed by active object id
|
||||
* `minetest.objects_by_guid`
|
||||
* Map of object references, indexed by active object GUID
|
||||
* `minetest.luaentities`
|
||||
* Map of Lua entities, indexed by active object id
|
||||
* `minetest.registered_abms`
|
||||
|
@ -7934,6 +7938,9 @@ child will follow movement and rotation of that bone.
|
|||
-- Default: false
|
||||
}
|
||||
```
|
||||
* `get_guid()`: returns a global unique identifier (a string)
|
||||
* For players a global unique identiticator is a player name.
|
||||
* For non-player objects, it is unique generated string.
|
||||
|
||||
#### Lua entity only (no-op for other objects)
|
||||
|
||||
|
@ -7941,6 +7948,10 @@ child will follow movement and rotation of that bone.
|
|||
* The object is removed after returning from Lua. However the `ObjectRef`
|
||||
itself instantly becomes unusable with all further method calls having
|
||||
no effect and returning `nil`.
|
||||
* `set_guid(guid)`:
|
||||
* Set a global unique identifier string of entity.
|
||||
* Is valid to be called only in `on_activate` callback.
|
||||
* Should be used ONLY for restoring saved guid from staticdata!!!
|
||||
* `set_velocity(vel)`
|
||||
* Sets the velocity
|
||||
* `vel` is a vector, e.g. `{x=0.0, y=2.3, z=1.0}`
|
||||
|
|
|
@ -582,6 +582,9 @@ Since protocol version 37:
|
|||
* `u8` `version2` (=1)
|
||||
* `s32` pitch * 1000
|
||||
* `s32` roll * 1000
|
||||
* if version2 >= 2:
|
||||
* u32 len
|
||||
* u8[len] guid
|
||||
|
||||
# Itemstring Format
|
||||
|
||||
|
|
|
@ -52,6 +52,22 @@ core.register_entity("unittests:callbacks", {
|
|||
end,
|
||||
})
|
||||
|
||||
core.register_entity("unittests:guid", {
|
||||
initial_properties = {
|
||||
static_save = false,
|
||||
},
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
self.object:set_guid("@UNITTEST")
|
||||
insert_log("on_activate(%d)", #staticdata)
|
||||
end,
|
||||
on_deactivate = function(self, removal)
|
||||
insert_log("on_deactivate(%s)", tostring(removal))
|
||||
end,
|
||||
get_staticdata = function(self)
|
||||
assert(false)
|
||||
end,
|
||||
})
|
||||
|
||||
--
|
||||
|
||||
local function check_log(expect)
|
||||
|
@ -130,3 +146,26 @@ local function test_entity_attach(player, pos)
|
|||
obj:remove()
|
||||
end
|
||||
unittests.register("test_entity_attach", test_entity_attach, {player=true, map=true})
|
||||
|
||||
local function test_entity_guid(_, pos)
|
||||
log = {}
|
||||
|
||||
local obj = core.add_entity(pos, "unittests:callbacks")
|
||||
check_log({"on_activate(0)"})
|
||||
|
||||
assert(obj:get_guid()~="")
|
||||
|
||||
obj:remove()
|
||||
check_log({"on_deactivate(true)"})
|
||||
|
||||
assert(core.objects_by_guid["@UNITTEST"]==nil)
|
||||
obj = core.add_entity(pos, "unittests:guid")
|
||||
check_log({"on_activate(0)"})
|
||||
|
||||
assert(obj:get_guid()=="@UNITTEST")
|
||||
assert(core.objects_by_guid["@UNITTEST"]~=nil)
|
||||
|
||||
obj:remove()
|
||||
end
|
||||
unittests.register("test_entity_guid", test_entity_guid, {map=true})
|
||||
|
||||
|
|
|
@ -84,3 +84,10 @@ local function run_player_add_pos_tests(player)
|
|||
end
|
||||
unittests.register("test_player_add_pos", run_player_add_pos_tests, {player=true})
|
||||
|
||||
--
|
||||
-- Player get uuid
|
||||
--
|
||||
local function test_player_guid_tests(player)
|
||||
assert(player:get_guid()==player:get_player_name())
|
||||
end
|
||||
unittests.register("test_player_guid", test_player_guid_tests, {player=true})
|
||||
|
|
|
@ -381,6 +381,7 @@ set(common_SRCS
|
|||
face_position_cache.cpp
|
||||
filesys.cpp
|
||||
gettext.cpp
|
||||
guid.cpp
|
||||
httpfetch.cpp
|
||||
hud.cpp
|
||||
inventory.cpp
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2021, DS
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser 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 "guid.h"
|
||||
#include <sstream>
|
||||
|
||||
#include "serverenvironment.h"
|
||||
#include "util/base64.h"
|
||||
|
||||
GUIdGenerator::GUIdGenerator() :
|
||||
m_uniform(0, UINT64_MAX)
|
||||
{
|
||||
m_rand_usable = m_rand.entropy() > 0.01;
|
||||
}
|
||||
|
||||
GUId GUIdGenerator::next(const std::string &prefix)
|
||||
{
|
||||
std::stringstream s_guid;
|
||||
|
||||
u64 a[2];
|
||||
if (m_rand_usable) {
|
||||
a[0] = m_uniform(m_rand);
|
||||
a[1] = m_uniform(m_rand);
|
||||
}
|
||||
else {
|
||||
a[0] = (static_cast<u64>(m_env->getGameTime()) << 32) + m_next;
|
||||
a[1] = m_uniform(m_rand);
|
||||
m_next++;
|
||||
}
|
||||
s_guid << prefix << base64_encode(std::string_view(reinterpret_cast<char *>(a), 16));
|
||||
|
||||
return s_guid.str();
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2021, DS
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "util/basic_macros.h"
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
class ServerEnvironment;
|
||||
|
||||
/**
|
||||
* A global unique identifier.
|
||||
* It is global because it stays valid in a world forever.
|
||||
* It is unique because there are no collisions.
|
||||
*/
|
||||
typedef std::string GUId;
|
||||
|
||||
/**
|
||||
* Generates infinitely many guids.
|
||||
*/
|
||||
class GUIdGenerator {
|
||||
public:
|
||||
/**
|
||||
* Creates a new uninitialized generator.
|
||||
* @param env ServerEnvironment where generator is running
|
||||
* @param prefix Prefix of generated GUId
|
||||
* @param next next value getted from loadMeta
|
||||
*/
|
||||
GUIdGenerator();
|
||||
|
||||
~GUIdGenerator() = default;
|
||||
DISABLE_CLASS_COPY(GUIdGenerator)
|
||||
|
||||
/**
|
||||
* Generates the next guid, which it will never return again.
|
||||
* @return the new guid, or "" if the generator is not yet initialized
|
||||
*/
|
||||
GUId next(const std::string &prefix);
|
||||
|
||||
private:
|
||||
void setServerEnvironment(ServerEnvironment *env) { m_env = env; }
|
||||
|
||||
ServerEnvironment *m_env;
|
||||
std::random_device m_rand;
|
||||
std::uniform_int_distribution<u64> m_uniform;
|
||||
bool m_rand_usable;
|
||||
u32 m_next;
|
||||
|
||||
friend class ServerEnvironment;
|
||||
};
|
|
@ -433,11 +433,12 @@ void ScriptApiBase::setOriginFromTableRaw(int index, const char *fxn)
|
|||
/*
|
||||
* How ObjectRefs are handled in Lua:
|
||||
* When an active object is created, an ObjectRef is created on the Lua side
|
||||
* and stored in core.object_refs[id].
|
||||
* and stored in core.object_refs[id] and in core.objects_by_guids[[GUID].
|
||||
* Methods that require an ObjectRef to a certain object retrieve it from that
|
||||
* table instead of creating their own.(*)
|
||||
* When an active object is removed, the existing ObjectRef is invalidated
|
||||
* using ::set_null() and removed from the core.object_refs table.
|
||||
* using ::set_null() and removed from the core.object_refs and
|
||||
* core.object_by_guids tables.
|
||||
* (*) An exception to this are NULL ObjectRefs and anonymous ObjectRefs
|
||||
* for objects without ID.
|
||||
* It's unclear what the latter are needed for and their use is problematic
|
||||
|
@ -465,6 +466,27 @@ void ScriptApiBase::addObjectReference(ServerActiveObject *cobj)
|
|||
lua_settable(L, objectstable);
|
||||
}
|
||||
|
||||
void ScriptApiBase::addObjectByGuid(ServerActiveObject *cobj)
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
assert(getType() == ScriptingType::Server);
|
||||
|
||||
// Create object on stack
|
||||
ObjectRef::create(L, cobj); // Puts ObjectRef (as userdata) on stack
|
||||
int object = lua_gettop(L);
|
||||
|
||||
// Get core.objects_by_guid table
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "objects_by_guid");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int objectstable = lua_gettop(L);
|
||||
|
||||
// objects_by_guid[GUID] = object
|
||||
lua_pushstring(L, cobj->getGuid().c_str()); // Push GUID
|
||||
lua_pushvalue(L, object); // Copy object to top of stack
|
||||
lua_settable(L, objectstable);
|
||||
}
|
||||
|
||||
void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
@ -472,6 +494,7 @@ void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
|
|||
|
||||
// Get core.object_refs table
|
||||
lua_getglobal(L, "core");
|
||||
int core = lua_gettop(L);
|
||||
lua_getfield(L, -1, "object_refs");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int objectstable = lua_gettop(L);
|
||||
|
@ -484,7 +507,17 @@ void ScriptApiBase::removeObjectReference(ServerActiveObject *cobj)
|
|||
lua_pop(L, 1); // pop object
|
||||
|
||||
// Set object_refs[id] = nil
|
||||
lua_pushnumber(L, cobj->getId()); // Push id
|
||||
lua_pushnumber(L, cobj->getId()); // Push GUID
|
||||
lua_pushnil(L);
|
||||
lua_settable(L, objectstable);
|
||||
|
||||
// Get core.objects_by_guid
|
||||
lua_getfield(L, core, "objects_by_guid");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
objectstable = lua_gettop(L);
|
||||
|
||||
// Set objects_by_guid[GUID] = nil
|
||||
lua_pushstring(L, cobj->getGuid().c_str()); // Push GUID
|
||||
lua_pushnil(L);
|
||||
lua_settable(L, objectstable);
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
|
||||
/* object */
|
||||
void addObjectReference(ServerActiveObject *cobj);
|
||||
void addObjectByGuid(ServerActiveObject *cobj);
|
||||
void removeObjectReference(ServerActiveObject *cobj);
|
||||
|
||||
ScriptingType getType() { return m_type; }
|
||||
|
|
|
@ -106,6 +106,21 @@ int ObjectRef::l_remove(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// get_guid()
|
||||
int ObjectRef::l_get_guid(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
|
||||
ServerActiveObject *sao = getobject(ref);
|
||||
if (sao == nullptr)
|
||||
return 0;
|
||||
|
||||
const std::string &guid = sao->getGuid();
|
||||
|
||||
lua_pushstring(L, guid.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_pos(self)
|
||||
int ObjectRef::l_get_pos(lua_State *L)
|
||||
{
|
||||
|
@ -1120,6 +1135,25 @@ int ObjectRef::l_set_sprite(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// set_guid(self, guid)
|
||||
int ObjectRef::l_set_guid(lua_State *L)
|
||||
{
|
||||
NO_MAP_LOCK_REQUIRED;
|
||||
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
|
||||
LuaEntitySAO *entitysao = getluaobject(ref);
|
||||
if (entitysao == nullptr)
|
||||
return 0;
|
||||
|
||||
std::string guid = readParam<std::string>(L, 2, "");
|
||||
|
||||
if (!guid.empty())
|
||||
lua_pushboolean(L, entitysao->setGuid(guid));
|
||||
else
|
||||
lua_pushboolean(L, false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// get_entity_name(self)
|
||||
int ObjectRef::l_get_entity_name(lua_State *L)
|
||||
|
@ -2632,6 +2666,7 @@ const char ObjectRef::className[] = "ObjectRef";
|
|||
luaL_Reg ObjectRef::methods[] = {
|
||||
// ServerActiveObject
|
||||
luamethod(ObjectRef, remove),
|
||||
luamethod(ObjectRef, get_guid),
|
||||
luamethod_aliased(ObjectRef, get_pos, getpos),
|
||||
luamethod_aliased(ObjectRef, set_pos, setpos),
|
||||
luamethod(ObjectRef, add_pos),
|
||||
|
@ -2679,6 +2714,7 @@ luaL_Reg ObjectRef::methods[] = {
|
|||
luamethod_aliased(ObjectRef, set_texture_mod, settexturemod),
|
||||
luamethod(ObjectRef, get_texture_mod),
|
||||
luamethod_aliased(ObjectRef, set_sprite, setsprite),
|
||||
luamethod(ObjectRef, set_guid),
|
||||
luamethod(ObjectRef, get_entity_name),
|
||||
luamethod(ObjectRef, get_luaentity),
|
||||
|
||||
|
|
|
@ -67,6 +67,9 @@ private:
|
|||
// remove(self)
|
||||
static int l_remove(lua_State *L);
|
||||
|
||||
// get_guid()
|
||||
static int l_get_guid(lua_State *L);
|
||||
|
||||
// get_pos(self)
|
||||
static int l_get_pos(lua_State *L);
|
||||
|
||||
|
@ -200,6 +203,9 @@ private:
|
|||
|
||||
// set_sprite(self, start_frame, num_frames, framelength, select_x_by_camera)
|
||||
static int l_set_sprite(lua_State *L);
|
||||
|
||||
// set_guid(self, guid)
|
||||
static int l_set_guid(lua_State *L);
|
||||
|
||||
// DEPRECATED
|
||||
// get_entity_name(self)
|
||||
|
|
|
@ -76,6 +76,9 @@ ServerScripting::ServerScripting(Server* server):
|
|||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "object_refs");
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "objects_by_guid");
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "luaentities");
|
||||
|
||||
|
|
|
@ -85,6 +85,13 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &d
|
|||
m_rotation = rotation;
|
||||
}
|
||||
|
||||
LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &name,
|
||||
const std::string &state) :
|
||||
UnitSAO(env, pos),
|
||||
m_init_name(name), m_init_state(state)
|
||||
{
|
||||
}
|
||||
|
||||
LuaEntitySAO::~LuaEntitySAO()
|
||||
{
|
||||
if(m_registered){
|
||||
|
@ -113,6 +120,10 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
|
|||
// Activate entity, supplying serialized state
|
||||
m_env->getScriptIface()->
|
||||
luaentity_Activate(m_id, m_init_state, dtime_s);
|
||||
// if Activate callback does not set guid, set it.
|
||||
if (m_guid.empty()) {
|
||||
getGuid();
|
||||
}
|
||||
} else {
|
||||
// It's an unknown object
|
||||
// Use entitystring as infotext for debugging
|
||||
|
@ -428,6 +439,22 @@ u16 LuaEntitySAO::getHP() const
|
|||
return m_hp;
|
||||
}
|
||||
|
||||
bool LuaEntitySAO::setGuid(std::string &guid)
|
||||
{
|
||||
if (m_guid.empty()) {
|
||||
m_guid = guid;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
GUId LuaEntitySAO::getGuid()
|
||||
{
|
||||
if (m_guid.empty()) {
|
||||
m_guid = m_env->getGUIdGenerator().next(std::string("@"));
|
||||
}
|
||||
return m_guid;
|
||||
}
|
||||
|
||||
void LuaEntitySAO::setVelocity(v3f velocity)
|
||||
{
|
||||
m_velocity = velocity;
|
||||
|
|
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#pragma once
|
||||
|
||||
#include "unit_sao.h"
|
||||
#include "guid.h"
|
||||
|
||||
class LuaEntitySAO : public UnitSAO
|
||||
{
|
||||
|
@ -30,11 +31,7 @@ public:
|
|||
LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &data);
|
||||
// Used by the Lua API
|
||||
LuaEntitySAO(ServerEnvironment *env, v3f pos, const std::string &name,
|
||||
const std::string &state) :
|
||||
UnitSAO(env, pos),
|
||||
m_init_name(name), m_init_state(state)
|
||||
{
|
||||
}
|
||||
const std::string &state);
|
||||
~LuaEntitySAO();
|
||||
|
||||
ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
||||
|
@ -62,6 +59,8 @@ public:
|
|||
|
||||
void setHP(s32 hp, const PlayerHPChangeReason &reason);
|
||||
u16 getHP() const;
|
||||
bool setGuid(std::string &guid);
|
||||
GUId getGuid() override;
|
||||
|
||||
/* LuaEntitySAO-specific */
|
||||
void setVelocity(v3f velocity);
|
||||
|
@ -95,6 +94,8 @@ private:
|
|||
std::string m_init_state;
|
||||
bool m_registered = false;
|
||||
|
||||
GUId m_guid;
|
||||
|
||||
v3f m_velocity;
|
||||
v3f m_acceleration;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t p
|
|||
UnitSAO(env_, v3f(0,0,0)),
|
||||
m_player(player_),
|
||||
m_peer_id_initial(peer_id_),
|
||||
m_guid(player_->getName()),
|
||||
m_is_singleplayer(is_singleplayer)
|
||||
{
|
||||
SANITY_CHECK(m_peer_id_initial != PEER_ID_INEXISTENT);
|
||||
|
@ -417,6 +418,11 @@ void PlayerSAO::setPlayerYaw(const float yaw)
|
|||
UnitSAO::setRotation(rotation);
|
||||
}
|
||||
|
||||
GUId PlayerSAO::getGuid()
|
||||
{
|
||||
return m_guid;
|
||||
}
|
||||
|
||||
void PlayerSAO::setFov(const float fov)
|
||||
{
|
||||
if (m_player && fov != m_fov)
|
||||
|
|
|
@ -93,6 +93,7 @@ public:
|
|||
void addPos(const v3f &added_pos) override;
|
||||
void moveTo(v3f pos, bool continuous) override;
|
||||
void setPlayerYaw(const float yaw);
|
||||
GUId getGuid() override;
|
||||
// Data should not be sent at player initialization
|
||||
void setPlayerYawAndSend(const float yaw);
|
||||
void setLookPitch(const float pitch);
|
||||
|
@ -195,6 +196,7 @@ private:
|
|||
|
||||
RemotePlayer *m_player = nullptr;
|
||||
session_t m_peer_id_initial = 0; ///< only used to initialize RemotePlayer
|
||||
GUId m_guid;
|
||||
|
||||
// Cheat prevention
|
||||
LagPool m_dig_pool;
|
||||
|
|
|
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "irrlichttypes_bloated.h"
|
||||
#include "activeobject.h"
|
||||
#include "itemgroup.h"
|
||||
#include "guid.h"
|
||||
#include "util/container.h"
|
||||
|
||||
|
||||
|
@ -160,6 +161,9 @@ public:
|
|||
virtual u16 getHP() const
|
||||
{ return 0; }
|
||||
|
||||
// Returns always the same unique string for the same object.
|
||||
virtual GUId getGuid() = 0;
|
||||
|
||||
virtual void setArmorGroups(const ItemGroupList &armor_groups)
|
||||
{}
|
||||
virtual const ItemGroupList &getArmorGroups() const
|
||||
|
@ -235,6 +239,11 @@ public:
|
|||
about handling it.
|
||||
*/
|
||||
bool m_static_exists = false;
|
||||
/*
|
||||
Set this to true when the staticdata needs to be saved even though it
|
||||
looks like it did not change.
|
||||
*/
|
||||
bool m_force_write_staticdata = false;
|
||||
/*
|
||||
The block from which the object was loaded from, and in which
|
||||
a copy of the static data resides.
|
||||
|
|
|
@ -448,6 +448,8 @@ ServerEnvironment::ServerEnvironment(std::unique_ptr<ServerMap> map,
|
|||
|
||||
m_active_object_gauge = mb->addGauge(
|
||||
"minetest_env_active_objects", "Number of active objects");
|
||||
|
||||
m_guid_generator.setServerEnvironment(this);
|
||||
}
|
||||
|
||||
void ServerEnvironment::init()
|
||||
|
@ -1889,6 +1891,8 @@ u16 ServerEnvironment::addActiveObjectRaw(std::unique_ptr<ServerActiveObject> ob
|
|||
// Post-initialize object
|
||||
// Note that this can change the value of isStaticAllowed() in case of LuaEntitySAO
|
||||
object->addedToEnvironment(dtime_s);
|
||||
// After post-initialize, GUID is known
|
||||
m_script->addObjectByGuid(object);
|
||||
|
||||
// Activate object
|
||||
if (object->m_static_exists)
|
||||
|
@ -2199,7 +2203,9 @@ void ServerEnvironment::deactivateFarObjects(const bool _force_delete)
|
|||
While changes are always saved, blocks are only marked as modified
|
||||
if the object has moved or different staticdata. (see above)
|
||||
*/
|
||||
bool shall_be_written = (!stays_in_same_block || data_changed);
|
||||
bool shall_be_written = (!stays_in_same_block || data_changed ||
|
||||
obj->m_force_write_staticdata);
|
||||
obj->m_force_write_staticdata = false;
|
||||
u32 reason = shall_be_written ? MOD_REASON_STATIC_DATA_CHANGED : MOD_REASON_UNKNOWN;
|
||||
|
||||
// Delete old static object
|
||||
|
|
|
@ -25,6 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "activeobject.h"
|
||||
#include "environment.h"
|
||||
#include "servermap.h"
|
||||
#include "guid.h"
|
||||
#include "map.h"
|
||||
#include "settings.h"
|
||||
#include "server/activeobjectmgr.h"
|
||||
#include "util/numeric.h"
|
||||
|
@ -238,6 +240,9 @@ public:
|
|||
float getSendRecommendedInterval()
|
||||
{ return m_recommended_send_interval; }
|
||||
|
||||
GUIdGenerator & getGUIdGenerator()
|
||||
{ return m_guid_generator; }
|
||||
|
||||
// Save players
|
||||
void saveLoadedPlayers(bool force = false);
|
||||
void savePlayer(RemotePlayer *player);
|
||||
|
@ -463,6 +468,10 @@ private:
|
|||
server::ActiveObjectMgr m_ao_manager;
|
||||
// on_mapblocks_changed map event receiver
|
||||
OnMapblocksChangedReceiver m_on_mapblocks_changed_receiver;
|
||||
// Generator for luaentity guids
|
||||
GUIdGenerator m_guid_generator;
|
||||
// World path
|
||||
const std::string m_path_world;
|
||||
// Outgoing network message buffer for active objects
|
||||
std::queue<ActiveObjectMessage> m_active_object_messages;
|
||||
// Some timers
|
||||
|
|
|
@ -29,4 +29,5 @@ public:
|
|||
virtual bool getCollisionBox(aabb3f *toset) const { return false; }
|
||||
virtual bool getSelectionBox(aabb3f *toset) const { return false; }
|
||||
virtual bool collideWithObjects() const { return false; }
|
||||
virtual std::string getGuid() {return "";}
|
||||
};
|
||||
|
|
|
@ -31,18 +31,18 @@ public:
|
|||
|
||||
void runTests(IGameDef *gamedef);
|
||||
|
||||
void testMove(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMoveFillStack(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMoveSomewhere(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMoveUnallowed(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMovePartial(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMove(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMoveFillStack(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMoveSomewhere(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMoveUnallowed(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testMovePartial(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
|
||||
void testSwap(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testSwapFromUnallowed(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testSwapToUnallowed(ServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testSwap(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testSwapFromUnallowed(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
void testSwapToUnallowed(MockServerActiveObject *obj, IGameDef *gamedef);
|
||||
|
||||
void testCallbacks(ServerActiveObject *obj, Server *server);
|
||||
void testCallbacksSwap(ServerActiveObject *obj, Server *server);
|
||||
void testCallbacks(MockServerActiveObject *obj, Server *server);
|
||||
void testCallbacksSwap(MockServerActiveObject *obj, Server *server);
|
||||
};
|
||||
|
||||
static TestMoveAction g_test_instance;
|
||||
|
@ -97,7 +97,7 @@ static void apply_action(const char *s, InventoryManager *inv, ServerActiveObjec
|
|||
delete action;
|
||||
}
|
||||
|
||||
void TestMoveAction::testMove(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testMove(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -110,7 +110,7 @@ void TestMoveAction::testMove(ServerActiveObject *obj, IGameDef *gamedef)
|
|||
UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:stone 20");
|
||||
}
|
||||
|
||||
void TestMoveAction::testMoveFillStack(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testMoveFillStack(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -130,7 +130,7 @@ void TestMoveAction::testMoveFillStack(ServerActiveObject *obj, IGameDef *gamede
|
|||
UASSERT(list->getItem(1).getItemString() == "default:stone 200");
|
||||
}
|
||||
|
||||
void TestMoveAction::testMoveSomewhere(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testMoveSomewhere(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -146,7 +146,7 @@ void TestMoveAction::testMoveSomewhere(ServerActiveObject *obj, IGameDef *gamede
|
|||
UASSERT(inv.p2.getList("main")->getItem(2).getItemString() == "default:stone 99");
|
||||
}
|
||||
|
||||
void TestMoveAction::testMoveUnallowed(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testMoveUnallowed(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -159,7 +159,7 @@ void TestMoveAction::testMoveUnallowed(ServerActiveObject *obj, IGameDef *gamede
|
|||
UASSERT(inv.p2.getList("main")->getItem(0).empty())
|
||||
}
|
||||
|
||||
void TestMoveAction::testMovePartial(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testMovePartial(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -173,7 +173,7 @@ void TestMoveAction::testMovePartial(ServerActiveObject *obj, IGameDef *gamedef)
|
|||
UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:takeput_max_5 5");
|
||||
}
|
||||
|
||||
void TestMoveAction::testSwap(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testSwap(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -186,7 +186,7 @@ void TestMoveAction::testSwap(ServerActiveObject *obj, IGameDef *gamedef)
|
|||
UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:stone 50");
|
||||
}
|
||||
|
||||
void TestMoveAction::testSwapFromUnallowed(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testSwapFromUnallowed(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -199,7 +199,7 @@ void TestMoveAction::testSwapFromUnallowed(ServerActiveObject *obj, IGameDef *ga
|
|||
UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:brick 60");
|
||||
}
|
||||
|
||||
void TestMoveAction::testSwapToUnallowed(ServerActiveObject *obj, IGameDef *gamedef)
|
||||
void TestMoveAction::testSwapToUnallowed(MockServerActiveObject *obj, IGameDef *gamedef)
|
||||
{
|
||||
MockInventoryManager inv(gamedef);
|
||||
|
||||
|
@ -230,7 +230,7 @@ static bool check_function(lua_State *L, bool expect_swap)
|
|||
return ok;
|
||||
}
|
||||
|
||||
void TestMoveAction::testCallbacks(ServerActiveObject *obj, Server *server)
|
||||
void TestMoveAction::testCallbacks(MockServerActiveObject *obj, Server *server)
|
||||
{
|
||||
server->m_inventory_mgr = std::make_unique<MockInventoryManager>(server);
|
||||
MockInventoryManager &inv = *(MockInventoryManager *)server->getInventoryMgr();
|
||||
|
@ -246,7 +246,7 @@ void TestMoveAction::testCallbacks(ServerActiveObject *obj, Server *server)
|
|||
server->m_inventory_mgr.reset();
|
||||
}
|
||||
|
||||
void TestMoveAction::testCallbacksSwap(ServerActiveObject *obj, Server *server)
|
||||
void TestMoveAction::testCallbacksSwap(MockServerActiveObject *obj, Server *server)
|
||||
{
|
||||
server->m_inventory_mgr = std::make_unique<MockInventoryManager>(server);
|
||||
MockInventoryManager &inv = *(MockInventoryManager *)server->getInventoryMgr();
|
||||
|
|
|
@ -26,7 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#include "profiler.h"
|
||||
|
||||
|
||||
class TestServerActiveObjectMgr : public TestBase
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue