mirror of https://github.com/minetest/minetest.git
First stab at it. Still need to find all the entity position change spots.
This commit is contained in:
parent
b23042839b
commit
e9a8ba386f
|
@ -8,6 +8,7 @@ set(server_SRCS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/serveractiveobject.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/serverinventorymgr.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/serverlist.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spatial_map.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/unit_sao.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rollback.cpp
|
||||
PARENT_SCOPE)
|
||||
|
|
|
@ -93,6 +93,7 @@ bool ActiveObjectMgr::registerObject(std::unique_ptr<ServerActiveObject> obj)
|
|||
|
||||
auto obj_id = obj->getId();
|
||||
m_active_objects.put(obj_id, std::move(obj));
|
||||
m_spatial_map.insert(obj.get());
|
||||
|
||||
auto new_size = m_active_objects.size();
|
||||
verbosestream << "Server::ActiveObjectMgr::addActiveObjectRaw(): "
|
||||
|
@ -110,6 +111,8 @@ void ActiveObjectMgr::removeObject(u16 id)
|
|||
verbosestream << "Server::ActiveObjectMgr::removeObject(): "
|
||||
<< "id=" << id << std::endl;
|
||||
|
||||
m_spatial_map.remove(m_active_objects.get(id).get());
|
||||
|
||||
// this will take the object out of the map and then destruct it
|
||||
bool ok = m_active_objects.remove(id);
|
||||
if (!ok) {
|
||||
|
|
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <vector>
|
||||
#include "../activeobjectmgr.h"
|
||||
#include "serveractiveobject.h"
|
||||
#include "spatial_map.h"
|
||||
|
||||
namespace server
|
||||
{
|
||||
|
@ -48,5 +49,7 @@ public:
|
|||
void getAddedActiveObjectsAroundPos(v3f player_pos, f32 radius,
|
||||
f32 player_radius, const std::set<u16> ¤t_objects,
|
||||
std::vector<u16> &added_objects);
|
||||
|
||||
SpatialMap m_spatial_map;
|
||||
};
|
||||
} // namespace server
|
||||
|
|
|
@ -132,7 +132,7 @@ void LuaEntitySAO::dispatchScriptDeactivate(bool removal)
|
|||
m_env->getScriptIface()->luaentity_Deactivate(m_id, removal);
|
||||
}
|
||||
|
||||
void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
void LuaEntitySAO::step(float dtime, bool send_recommended, bool &position_changed)
|
||||
{
|
||||
if (!m_properties_sent) {
|
||||
m_properties_sent = true;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_LUAENTITY; }
|
||||
ActiveObjectType getSendType() const { return ACTIVEOBJECT_TYPE_GENERIC; }
|
||||
virtual void addedToEnvironment(u32 dtime_s);
|
||||
void step(float dtime, bool send_recommended);
|
||||
void step(float dtime, bool send_recommended, bool &position_changed) override;
|
||||
std::string getClientInitializationData(u16 protocol_version);
|
||||
|
||||
bool isStaticAllowed() const { return m_prop.static_save; }
|
||||
|
|
|
@ -154,7 +154,7 @@ void PlayerSAO::getStaticData(std::string * result) const
|
|||
FATAL_ERROR("This function shall not be called for PlayerSAO");
|
||||
}
|
||||
|
||||
void PlayerSAO::step(float dtime, bool send_recommended)
|
||||
void PlayerSAO::step(float dtime, bool send_recommended, bool &position_changed)
|
||||
{
|
||||
if (!isImmortal() && m_drowning_interval.step(dtime, 2.0f)) {
|
||||
// Get nose/mouth position, approximate with eye position
|
||||
|
@ -238,6 +238,7 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
|||
warningstream << "PlayerSAO::step() id=" << m_id <<
|
||||
" is attached to nonexistent parent. This is a bug." << std::endl;
|
||||
clearParentAttachment();
|
||||
// FIXHERE
|
||||
setBasePosition(m_last_good_position);
|
||||
m_env->getGameDef()->SendMovePlayer(this);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ public:
|
|||
bool shouldUnload() const override { return false; }
|
||||
std::string getClientInitializationData(u16 protocol_version) override;
|
||||
void getStaticData(std::string *result) const override;
|
||||
void step(float dtime, bool send_recommended) override;
|
||||
void step(float dtime, bool send_recommended, bool &position_changed) override;
|
||||
void setBasePosition(v3f position);
|
||||
void setPos(const v3f &pos) override;
|
||||
void addPos(const v3f &added_pos) override;
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
same time so that the data can be combined in a single
|
||||
packet.
|
||||
*/
|
||||
virtual void step(float dtime, bool send_recommended){}
|
||||
virtual void step(float dtime, bool send_recommended, bool &position_changed){}
|
||||
|
||||
/*
|
||||
The return value of this is passed to the client-side object
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2018 nerzhul, Loic BLOT <loic.blot@unix-experience.fr>
|
||||
|
||||
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 "spatial_map.h"
|
||||
|
||||
namespace server
|
||||
{
|
||||
|
||||
// all inserted entires go into the uncached vector
|
||||
void SpatialMap::insert(ServerActiveObject* obj)
|
||||
{
|
||||
m_uncached.push_back(obj->getId());
|
||||
}
|
||||
|
||||
// Invalidates upon position update
|
||||
void SpatialMap::invalidate(ServerActiveObject* obj)
|
||||
{
|
||||
// remove from cache, if present
|
||||
u16 id = obj->getId();
|
||||
bool found = false;
|
||||
auto range = m_cached.equal_range(SpatialKey(obj->getBasePosition()));
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if (it->second == id) {
|
||||
m_cached.erase(it);
|
||||
found = true;
|
||||
break; // Erase and leave early
|
||||
}
|
||||
}
|
||||
|
||||
if(found) {
|
||||
// place back in uncached
|
||||
insert(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void SpatialMap::remove(ServerActiveObject* obj)
|
||||
{
|
||||
SpatialKey key(obj->getBasePosition());
|
||||
u16 idToRemove = obj->getId();
|
||||
if(m_cached.find(key) != m_cached.end()) {
|
||||
auto range = m_cached.equal_range(key);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if (it->second == idToRemove) {
|
||||
m_cached.erase(it);
|
||||
return; // Erase and leave early
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto it = std::find(m_uncached.begin(), m_uncached.end(), idToRemove);
|
||||
if (it != m_uncached.end()) {
|
||||
m_uncached.erase(it);
|
||||
return;
|
||||
} else {
|
||||
// Error, this shouldn't ever be hit.
|
||||
}
|
||||
}
|
||||
|
||||
// Only when at least 64 uncached objects or 10% uncached overall
|
||||
void SpatialMap::cacheUpdate(ActiveObjectMgr& mgr)
|
||||
{
|
||||
bool shouldUpdate = false;
|
||||
if(m_uncached.size() >= 64 || (m_uncached.size() >= 64 && m_uncached.size() * 10 > m_cached.size())) {
|
||||
for(u16& entry : m_uncached) {
|
||||
m_cached.insert(std::pair<SpatialKey,u16>(mgr.getActiveObject(entry)->getBasePosition(), entry));
|
||||
}
|
||||
m_uncached.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SpatialMap::getRelevantObjectIds(const aabb3f &box, std::vector<u16> &relevant_objs)
|
||||
{
|
||||
if(!m_cached.empty()) {
|
||||
// when searching, we must round to maximum extent of relevant mapblock indexes
|
||||
auto shrinkRnd = [](f32 val) {
|
||||
//return val < 0 ? floor(val) : ceil(val);}
|
||||
s16 rounded = std::lround(val);
|
||||
s16 remainder = (rounded & 0xF) != 0; // same as (val % 16) != 0
|
||||
return (rounded >> 4) + ((rounded < 0) ? -remainder : remainder);
|
||||
};
|
||||
|
||||
v3s16 min(shrinkRnd(box.MinEdge.X), shrinkRnd(box.MinEdge.Y), shrinkRnd(box.MinEdge.Z)),
|
||||
max(shrinkRnd(box.MaxEdge.X), shrinkRnd(box.MaxEdge.Y), shrinkRnd(box.MaxEdge.Z));
|
||||
|
||||
for (int x = box.MinEdge.X; x < box.MaxEdge.X;x++) {
|
||||
for (int y = box.MinEdge.Y; y < box.MaxEdge.Y;y++) {
|
||||
for (int z = box.MinEdge.Z; z < box.MaxEdge.Z;z++) {
|
||||
SpatialKey key(x,y,z);
|
||||
if (m_cached.find(key) != m_cached.end()) {
|
||||
auto range = m_cached.equal_range(key);
|
||||
relevant_objs.insert(relevant_objs.end(), range.first, range.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the the rest, uncached objectIDs
|
||||
relevant_objs.insert(relevant_objs.end(), m_uncached.begin(), m_uncached.end());
|
||||
}
|
||||
|
||||
} // namespace server
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2010-2018 nerzhul, Loic BLOT <loic.blot@unix-experience.fr>
|
||||
|
||||
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 <functional>
|
||||
#include <vector>
|
||||
#include "serveractiveobject.h"
|
||||
#include "activeobjectmgr.h"
|
||||
|
||||
namespace server
|
||||
{
|
||||
class SpatialMap
|
||||
{
|
||||
public:
|
||||
// all inserted entires go into the uncached vector
|
||||
void insert(ServerActiveObject* obj);
|
||||
|
||||
// Invalidates upon position update or removal
|
||||
void invalidate(ServerActiveObject* obj);
|
||||
|
||||
// On active_object removal, remove.
|
||||
void remove(ServerActiveObject* obj);
|
||||
|
||||
// Only when at least 64 uncached objects or 10% uncached overall
|
||||
void cacheUpdate(ActiveObjectMgr& mgr);
|
||||
|
||||
// Use the same basic algorithm for both area and radius lookups
|
||||
void getRelevantObjectIds(const aabb3f &box, std::vector<u16> &relevant_objs);
|
||||
|
||||
protected:
|
||||
typedef struct SpatialKey{
|
||||
u16 padding{0};
|
||||
s16 x;
|
||||
s16 y;
|
||||
s16 z;
|
||||
|
||||
SpatialKey(s16 _x, s16 _y, s16 _z) {
|
||||
x = _x >> 4;
|
||||
y = _y >> 4;
|
||||
z = _z >> 4;
|
||||
}
|
||||
SpatialKey(v3f _pos) : SpatialKey(_pos.X, _pos.Y, _pos.Z){}
|
||||
} SpatialKey;
|
||||
|
||||
std::unordered_multimap<SpatialKey, u16> m_cached;
|
||||
std::vector<u16> m_uncached;
|
||||
};
|
||||
} // namespace server
|
Loading…
Reference in New Issue