aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/luaentity_sao.cpp13
-rw-r--r--src/server/luaentity_sao.h5
-rw-r--r--src/server/mods.cpp6
-rw-r--r--src/server/player_sao.cpp43
-rw-r--r--src/server/player_sao.h56
-rw-r--r--src/server/serveractiveobject.h7
-rw-r--r--src/server/serverinventorymgr.cpp28
-rw-r--r--src/server/unit_sao.cpp7
8 files changed, 94 insertions, 71 deletions
diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp
index 3bcbe107b..82f6da231 100644
--- a/src/server/luaentity_sao.cpp
+++ b/src/server/luaentity_sao.cpp
@@ -108,7 +108,12 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
m_env->getScriptIface()->
luaentity_Activate(m_id, m_init_state, dtime_s);
} else {
+ // It's an unknown object
+ // Use entitystring as infotext for debugging
m_prop.infotext = m_init_name;
+ // Set unknown object texture
+ m_prop.textures.clear();
+ m_prop.textures.emplace_back("unknown_object.png");
}
}
@@ -300,10 +305,11 @@ void LuaEntitySAO::getStaticData(std::string *result) const
*result = os.str();
}
-u16 LuaEntitySAO::punch(v3f dir,
+u32 LuaEntitySAO::punch(v3f dir,
const ToolCapabilities *toolcap,
ServerActiveObject *puncher,
- float time_from_last_punch)
+ float time_from_last_punch,
+ u16 initial_wear)
{
if (!m_registered) {
// Delete unknown LuaEntities when punched
@@ -321,7 +327,8 @@ u16 LuaEntitySAO::punch(v3f dir,
m_armor_groups,
toolcap,
&tool_item,
- time_from_last_punch);
+ time_from_last_punch,
+ initial_wear);
bool damage_handled = m_env->getScriptIface()->luaentity_Punch(m_id, puncher,
time_from_last_punch, toolcap, dir, result.did_punch ? result.damage : 0);
diff --git a/src/server/luaentity_sao.h b/src/server/luaentity_sao.h
index 6883ae1b9..87b664a8b 100644
--- a/src/server/luaentity_sao.h
+++ b/src/server/luaentity_sao.h
@@ -44,9 +44,10 @@ public:
bool isStaticAllowed() const { return m_prop.static_save; }
bool shouldUnload() const { return true; }
void getStaticData(std::string *result) const;
- u16 punch(v3f dir, const ToolCapabilities *toolcap = nullptr,
+ u32 punch(v3f dir, const ToolCapabilities *toolcap = nullptr,
ServerActiveObject *puncher = nullptr,
- float time_from_last_punch = 1000000.0f);
+ float time_from_last_punch = 1000000.0f,
+ u16 initial_wear = 0);
void rightClick(ServerActiveObject *clicker);
void setPos(const v3f &pos);
void moveTo(v3f pos, bool continuous);
diff --git a/src/server/mods.cpp b/src/server/mods.cpp
index 609d8c346..ba76d4746 100644
--- a/src/server/mods.cpp
+++ b/src/server/mods.cpp
@@ -41,8 +41,10 @@ ServerModManager::ServerModManager(const std::string &worldpath) :
SubgameSpec gamespec = findWorldSubgame(worldpath);
// Add all game mods and all world mods
- addModsInPath(gamespec.gamemods_path);
- addModsInPath(worldpath + DIR_DELIM + "worldmods");
+ std::string game_virtual_path;
+ game_virtual_path.append("games/").append(gamespec.id).append("/mods");
+ addModsInPath(gamespec.gamemods_path, game_virtual_path);
+ addModsInPath(worldpath + DIR_DELIM + "worldmods", "worldmods");
// Load normal mods
std::string worldmt = worldpath + DIR_DELIM + "world.mt";
diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp
index d4d036726..d076d5783 100644
--- a/src/server/player_sao.cpp
+++ b/src/server/player_sao.cpp
@@ -409,10 +409,11 @@ void PlayerSAO::setLookPitchAndSend(const float pitch)
m_env->getGameDef()->SendMovePlayer(m_peer_id);
}
-u16 PlayerSAO::punch(v3f dir,
+u32 PlayerSAO::punch(v3f dir,
const ToolCapabilities *toolcap,
ServerActiveObject *puncher,
- float time_from_last_punch)
+ float time_from_last_punch,
+ u16 initial_wear)
{
if (!toolcap)
return 0;
@@ -430,7 +431,7 @@ u16 PlayerSAO::punch(v3f dir,
s32 old_hp = getHP();
HitParams hitparams = getHitParams(m_armor_groups, toolcap,
- time_from_last_punch);
+ time_from_last_punch, initial_wear);
PlayerSAO *playersao = m_player->getPlayerSAO();
@@ -462,35 +463,33 @@ void PlayerSAO::rightClick(ServerActiveObject *clicker)
m_env->getScriptIface()->on_rightclickplayer(this, clicker);
}
-void PlayerSAO::setHP(s32 hp, const PlayerHPChangeReason &reason)
+void PlayerSAO::setHP(s32 target_hp, const PlayerHPChangeReason &reason, bool from_client)
{
- if (hp == (s32)m_hp)
- return; // Nothing to do
-
- if (m_hp <= 0 && hp < (s32)m_hp)
- return; // Cannot take more damage
+ target_hp = rangelim(target_hp, 0, U16_MAX);
- {
- s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - m_hp, reason);
- if (hp_change == 0)
- return;
+ if (target_hp == m_hp)
+ return; // Nothing to do
- hp = m_hp + hp_change;
- }
+ s32 hp_change = m_env->getScriptIface()->on_player_hpchange(this, target_hp - (s32)m_hp, reason);
- s32 oldhp = m_hp;
- hp = rangelim(hp, 0, m_prop.hp_max);
+ s32 hp = (s32)m_hp + std::min(hp_change, U16_MAX); // Protection against s32 overflow
+ hp = rangelim(hp, 0, U16_MAX);
- if (hp < oldhp && isImmortal())
- return; // Do not allow immortal players to be damaged
+ if (hp > m_prop.hp_max)
+ hp = m_prop.hp_max;
- m_hp = hp;
+ if (hp < m_hp && isImmortal())
+ hp = m_hp; // Do not allow immortal players to be damaged
// Update properties on death
- if ((hp == 0) != (oldhp == 0))
+ if ((hp == 0) != (m_hp == 0))
m_properties_sent = false;
- m_env->getGameDef()->SendPlayerHPOrDie(this, reason);
+ if (hp != m_hp) {
+ m_hp = hp;
+ m_env->getGameDef()->HandlePlayerHPChange(this, reason);
+ } else if (from_client)
+ m_env->getGameDef()->SendPlayerHP(this);
}
void PlayerSAO::setBreath(const u16 breath, bool send)
diff --git a/src/server/player_sao.h b/src/server/player_sao.h
index 8e2d8803f..1067801e7 100644
--- a/src/server/player_sao.h
+++ b/src/server/player_sao.h
@@ -72,24 +72,24 @@ public:
PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, session_t peer_id_,
bool is_singleplayer);
- ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_PLAYER; }
- ActiveObjectType getSendType() const { return ACTIVEOBJECT_TYPE_GENERIC; }
- std::string getDescription();
+ ActiveObjectType getType() const override { return ACTIVEOBJECT_TYPE_PLAYER; }
+ ActiveObjectType getSendType() const override { return ACTIVEOBJECT_TYPE_GENERIC; }
+ std::string getDescription() override;
/*
Active object <-> environment interface
*/
- void addedToEnvironment(u32 dtime_s);
- void removingFromEnvironment();
- bool isStaticAllowed() const { return false; }
- bool shouldUnload() const { return false; }
- std::string getClientInitializationData(u16 protocol_version);
- void getStaticData(std::string *result) const;
- void step(float dtime, bool send_recommended);
+ void addedToEnvironment(u32 dtime_s) override;
+ void removingFromEnvironment() override;
+ bool isStaticAllowed() const override { return false; }
+ 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 setBasePosition(const v3f &position);
- void setPos(const v3f &pos);
- void moveTo(v3f pos, bool continuous);
+ void setPos(const v3f &pos) override;
+ void moveTo(v3f pos, bool continuous) override;
void setPlayerYaw(const float yaw);
// Data should not be sent at player initialization
void setPlayerYawAndSend(const float yaw);
@@ -109,10 +109,14 @@ public:
Interaction interface
*/
- u16 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
- float time_from_last_punch);
- void rightClick(ServerActiveObject *clicker);
- void setHP(s32 hp, const PlayerHPChangeReason &reason);
+ u32 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
+ float time_from_last_punch, u16 initial_wear = 0) override;
+ void rightClick(ServerActiveObject *clicker) override;
+ void setHP(s32 hp, const PlayerHPChangeReason &reason) override
+ {
+ return setHP(hp, reason, false);
+ }
+ void setHP(s32 hp, const PlayerHPChangeReason &reason, bool from_client);
void setHPRaw(u16 hp) { m_hp = hp; }
u16 getBreath() const { return m_breath; }
void setBreath(const u16 breath, bool send = true);
@@ -120,13 +124,13 @@ public:
/*
Inventory interface
*/
- Inventory *getInventory() const;
- InventoryLocation getInventoryLocation() const;
- void setInventoryModified() {}
- std::string getWieldList() const { return "main"; }
- u16 getWieldIndex() const;
- ItemStack getWieldedItem(ItemStack *selected, ItemStack *hand = nullptr) const;
- bool setWieldedItem(const ItemStack &item);
+ Inventory *getInventory() const override;
+ InventoryLocation getInventoryLocation() const override;
+ void setInventoryModified() override {}
+ std::string getWieldList() const override { return "main"; }
+ u16 getWieldIndex() const override;
+ ItemStack getWieldedItem(ItemStack *selected, ItemStack *hand = nullptr) const override;
+ bool setWieldedItem(const ItemStack &item) override;
/*
PlayerSAO-specific
@@ -167,9 +171,9 @@ public:
m_is_singleplayer = is_singleplayer;
}
- bool getCollisionBox(aabb3f *toset) const;
- bool getSelectionBox(aabb3f *toset) const;
- bool collideWithObjects() const { return true; }
+ bool getCollisionBox(aabb3f *toset) const override;
+ bool getSelectionBox(aabb3f *toset) const override;
+ bool collideWithObjects() const override { return true; }
void finalize(RemotePlayer *player, const std::set<std::string> &privs);
diff --git a/src/server/serveractiveobject.h b/src/server/serveractiveobject.h
index 51f445914..5b0ee2d9b 100644
--- a/src/server/serveractiveobject.h
+++ b/src/server/serveractiveobject.h
@@ -145,11 +145,12 @@ public:
virtual bool shouldUnload() const
{ return true; }
- // Returns tool wear
- virtual u16 punch(v3f dir,
+ // Returns added tool wear
+ virtual u32 punch(v3f dir,
const ToolCapabilities *toolcap = nullptr,
ServerActiveObject *puncher = nullptr,
- float time_from_last_punch = 1000000.0f)
+ float time_from_last_punch = 1000000.0f,
+ u16 initial_wear = 0)
{ return 0; }
virtual void rightClick(ServerActiveObject *clicker)
{}
diff --git a/src/server/serverinventorymgr.cpp b/src/server/serverinventorymgr.cpp
index 3aee003b4..63d1645cb 100644
--- a/src/server/serverinventorymgr.cpp
+++ b/src/server/serverinventorymgr.cpp
@@ -39,24 +39,29 @@ ServerInventoryManager::~ServerInventoryManager()
Inventory *ServerInventoryManager::getInventory(const InventoryLocation &loc)
{
+ // No m_env check here: allow creation and modification of detached inventories
+
switch (loc.type) {
case InventoryLocation::UNDEFINED:
case InventoryLocation::CURRENT_PLAYER:
break;
case InventoryLocation::PLAYER: {
+ if (!m_env)
+ return nullptr;
+
RemotePlayer *player = m_env->getPlayer(loc.name.c_str());
if (!player)
return NULL;
+
PlayerSAO *playersao = player->getPlayerSAO();
- if (!playersao)
- return NULL;
- return playersao->getInventory();
+ return playersao ? playersao->getInventory() : nullptr;
} break;
case InventoryLocation::NODEMETA: {
+ if (!m_env)
+ return nullptr;
+
NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
- if (!meta)
- return NULL;
- return meta->getInventory();
+ return meta ? meta->getInventory() : nullptr;
} break;
case InventoryLocation::DETACHED: {
auto it = m_detached_inventories.find(loc.name);
@@ -151,12 +156,13 @@ bool ServerInventoryManager::removeDetachedInventory(const std::string &name)
const std::string &owner = inv_it->second.owner;
if (!owner.empty()) {
- RemotePlayer *player = m_env->getPlayer(owner.c_str());
-
- if (player && player->getPeerId() != PEER_ID_INEXISTENT)
- m_env->getGameDef()->sendDetachedInventory(
- nullptr, name, player->getPeerId());
+ if (m_env) {
+ RemotePlayer *player = m_env->getPlayer(owner.c_str());
+ if (player && player->getPeerId() != PEER_ID_INEXISTENT)
+ m_env->getGameDef()->sendDetachedInventory(
+ nullptr, name, player->getPeerId());
+ }
} else if (m_env) {
// Notify all players about the change as soon ServerEnv exists
m_env->getGameDef()->sendDetachedInventory(
diff --git a/src/server/unit_sao.cpp b/src/server/unit_sao.cpp
index acbdd478a..9a49b0f43 100644
--- a/src/server/unit_sao.cpp
+++ b/src/server/unit_sao.cpp
@@ -84,8 +84,11 @@ void UnitSAO::setBonePosition(const std::string &bone, v3f position, v3f rotatio
void UnitSAO::getBonePosition(const std::string &bone, v3f *position, v3f *rotation)
{
- *position = m_bone_position[bone].X;
- *rotation = m_bone_position[bone].Y;
+ auto it = m_bone_position.find(bone);
+ if (it != m_bone_position.end()) {
+ *position = it->second.X;
+ *rotation = it->second.Y;
+ }
}
// clang-format off