First stab at it. Still need to find all the entity position change spots.

This commit is contained in:
ExeVirus 2024-05-05 23:51:10 -04:00
parent b23042839b
commit e9a8ba386f
10 changed files with 198 additions and 5 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -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> &current_objects,
std::vector<u16> &added_objects);
SpatialMap m_spatial_map;
};
} // namespace server

View File

@ -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;

View File

@ -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; }

View File

@ -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);
}

View File

@ -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;

View File

@ -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

120
src/server/spatial_map.cpp Normal file
View File

@ -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

65
src/server/spatial_map.h Normal file
View File

@ -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