summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/luaentity_sao.cpp30
-rw-r--r--src/server/luaentity_sao.h13
-rw-r--r--src/server/mods.cpp31
-rw-r--r--src/server/mods.h23
-rw-r--r--src/server/player_sao.cpp8
-rw-r--r--src/server/player_sao.h52
6 files changed, 96 insertions, 61 deletions
diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp
index 82f6da231..ab4a9e3f2 100644
--- a/src/server/luaentity_sao.cpp
+++ b/src/server/luaentity_sao.cpp
@@ -117,13 +117,13 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s)
}
}
-void LuaEntitySAO::dispatchScriptDeactivate()
+void LuaEntitySAO::dispatchScriptDeactivate(bool removal)
{
// Ensure that this is in fact a registered entity,
// and that it isn't already gone.
// The latter also prevents this from ever being called twice.
if (m_registered && !isGone())
- m_env->getScriptIface()->luaentity_Deactivate(m_id);
+ m_env->getScriptIface()->luaentity_Deactivate(m_id, removal);
}
void LuaEntitySAO::step(float dtime, bool send_recommended)
@@ -290,7 +290,7 @@ void LuaEntitySAO::getStaticData(std::string *result) const
os<<serializeString32(m_init_state);
}
writeU16(os, m_hp);
- writeV3F1000(os, m_velocity);
+ writeV3F1000(os, clampToF1000(m_velocity));
// yaw
writeF1000(os, m_rotation.Y);
@@ -337,19 +337,9 @@ u32 LuaEntitySAO::punch(v3f dir,
if (result.did_punch) {
setHP((s32)getHP() - result.damage,
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
-
- // create message and add to list
- sendPunchCommand();
}
}
- if (getHP() == 0 && !isGone()) {
- clearParentAttachment();
- clearChildAttachments();
- m_env->getScriptIface()->luaentity_on_death(m_id, puncher);
- markForRemoval();
- }
-
actionstream << puncher->getDescription() << " (id=" << puncher->getId() <<
", hp=" << puncher->getHP() << ") punched " <<
getDescription() << " (id=" << m_id << ", hp=" << m_hp <<
@@ -402,6 +392,20 @@ std::string LuaEntitySAO::getDescription()
void LuaEntitySAO::setHP(s32 hp, const PlayerHPChangeReason &reason)
{
m_hp = rangelim(hp, 0, U16_MAX);
+
+ sendPunchCommand();
+
+ if (m_hp == 0 && !isGone()) {
+ clearParentAttachment();
+ clearChildAttachments();
+ if (m_registered) {
+ ServerActiveObject *killer = nullptr;
+ if (reason.type == PlayerHPChangeReason::PLAYER_PUNCH)
+ killer = reason.object;
+ m_env->getScriptIface()->luaentity_on_death(m_id, killer);
+ }
+ markForRemoval();
+ }
}
u16 LuaEntitySAO::getHP() const
diff --git a/src/server/luaentity_sao.h b/src/server/luaentity_sao.h
index 87b664a8b..1dc72b150 100644
--- a/src/server/luaentity_sao.h
+++ b/src/server/luaentity_sao.h
@@ -36,23 +36,30 @@ public:
{
}
~LuaEntitySAO();
+
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);
std::string getClientInitializationData(u16 protocol_version);
+
bool isStaticAllowed() const { return m_prop.static_save; }
bool shouldUnload() const { return true; }
void getStaticData(std::string *result) const;
+
u32 punch(v3f dir, const ToolCapabilities *toolcap = nullptr,
ServerActiveObject *puncher = nullptr,
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);
float getMinimumSavedMovement();
+
std::string getDescription();
+
void setHP(s32 hp, const PlayerHPChangeReason &reason);
u16 getHP() const;
@@ -73,9 +80,9 @@ public:
bool collideWithObjects() const;
protected:
- void dispatchScriptDeactivate();
- virtual void onMarkedForDeactivation() { dispatchScriptDeactivate(); }
- virtual void onMarkedForRemoval() { dispatchScriptDeactivate(); }
+ void dispatchScriptDeactivate(bool removal);
+ virtual void onMarkedForDeactivation() { dispatchScriptDeactivate(false); }
+ virtual void onMarkedForRemoval() { dispatchScriptDeactivate(true); }
private:
std::string getPropertyPacket();
diff --git a/src/server/mods.cpp b/src/server/mods.cpp
index 609d8c346..f302d4240 100644
--- a/src/server/mods.cpp
+++ b/src/server/mods.cpp
@@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "scripting_server.h"
#include "content/subgames.h"
#include "porting.h"
-#include "util/metricsbackend.h"
/**
* Manage server mods
@@ -35,18 +34,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
* Creates a ServerModManager which targets worldpath
* @param worldpath
*/
-ServerModManager::ServerModManager(const std::string &worldpath) :
- ModConfiguration(worldpath)
+ServerModManager::ServerModManager(const std::string &worldpath):
+ configuration()
{
SubgameSpec gamespec = findWorldSubgame(worldpath);
// Add all game mods and all world mods
- addModsInPath(gamespec.gamemods_path);
- addModsInPath(worldpath + DIR_DELIM + "worldmods");
+ configuration.addGameMods(gamespec);
+ configuration.addModsInPath(worldpath + DIR_DELIM + "worldmods", "worldmods");
// Load normal mods
std::string worldmt = worldpath + DIR_DELIM + "world.mt";
- addModsFromConfig(worldmt, gamespec.addon_mods_paths);
+ configuration.addModsFromConfig(worldmt, gamespec.addon_mods_paths);
+ configuration.checkConflictsAndDeps();
}
// clang-format off
@@ -55,12 +55,13 @@ void ServerModManager::loadMods(ServerScripting *script)
{
// Print mods
infostream << "Server: Loading mods: ";
- for (const ModSpec &mod : m_sorted_mods) {
+ for (const ModSpec &mod : configuration.getMods()) {
infostream << mod.name << " ";
}
+
infostream << std::endl;
// Load and run "mod" scripts
- for (const ModSpec &mod : m_sorted_mods) {
+ for (const ModSpec &mod : configuration.getMods()) {
mod.checkAndLog();
std::string script_path = mod.path + DIR_DELIM + "init.lua";
@@ -77,24 +78,26 @@ void ServerModManager::loadMods(ServerScripting *script)
// clang-format on
const ModSpec *ServerModManager::getModSpec(const std::string &modname) const
{
- std::vector<ModSpec>::const_iterator it;
- for (it = m_sorted_mods.begin(); it != m_sorted_mods.end(); ++it) {
- const ModSpec &mod = *it;
+ for (const auto &mod : configuration.getMods()) {
if (mod.name == modname)
return &mod;
}
- return NULL;
+
+ return nullptr;
}
void ServerModManager::getModNames(std::vector<std::string> &modlist) const
{
- for (const ModSpec &spec : m_sorted_mods)
+ for (const ModSpec &spec : configuration.getMods())
modlist.push_back(spec.name);
}
void ServerModManager::getModsMediaPaths(std::vector<std::string> &paths) const
{
- for (auto it = m_sorted_mods.crbegin(); it != m_sorted_mods.crend(); it++) {
+ // Iterate mods in reverse load order: Media loading expects higher priority media files first
+ // and mods loading later should be able to override media of already loaded mods
+ const auto &mods = configuration.getMods();
+ for (auto it = mods.crbegin(); it != mods.crend(); it++) {
const ModSpec &spec = *it;
fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "textures");
fs::GetRecursiveDirs(paths, spec.path + DIR_DELIM + "sounds");
diff --git a/src/server/mods.h b/src/server/mods.h
index 8954bbf72..1d1b42d0f 100644
--- a/src/server/mods.h
+++ b/src/server/mods.h
@@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
-#include "content/mods.h"
+#include "content/mod_configuration.h"
#include <memory>
class MetricsBackend;
@@ -31,8 +31,10 @@ class ServerScripting;
*
* All new calls to this class must be tested in test_servermodmanager.cpp
*/
-class ServerModManager : public ModConfiguration
+class ServerModManager
{
+ ModConfiguration configuration;
+
public:
/**
* Creates a ServerModManager which targets worldpath
@@ -42,6 +44,23 @@ public:
void loadMods(ServerScripting *script);
const ModSpec *getModSpec(const std::string &modname) const;
void getModNames(std::vector<std::string> &modlist) const;
+
+ inline const std::vector<ModSpec> &getMods() const {
+ return configuration.getMods();
+ }
+
+ inline const std::vector<ModSpec> &getUnsatisfiedMods() const {
+ return configuration.getUnsatisfiedMods();
+ }
+
+ inline bool isConsistent() const {
+ return configuration.isConsistent();
+ }
+
+ inline void printUnsatisfiedModsError() const {
+ return configuration.printUnsatisfiedModsError();
+ }
+
/**
* Recursively gets all paths of mod folders that can contain media files.
*
diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp
index d076d5783..a58a0397f 100644
--- a/src/server/player_sao.cpp
+++ b/src/server/player_sao.cpp
@@ -319,7 +319,7 @@ std::string PlayerSAO::generateUpdatePhysicsOverrideCommand() const
return os.str();
}
-void PlayerSAO::setBasePosition(const v3f &position)
+void PlayerSAO::setBasePosition(v3f position)
{
if (m_player && position != m_base_position)
m_player->setDirty(true);
@@ -344,7 +344,7 @@ void PlayerSAO::setPos(const v3f &pos)
setBasePosition(pos);
// Movement caused by this command is always valid
- m_last_good_position = pos;
+ m_last_good_position = getBasePosition();
m_move_pool.empty();
m_time_from_last_teleport = 0.0;
m_env->getGameDef()->SendMovePlayer(m_peer_id);
@@ -357,7 +357,7 @@ void PlayerSAO::moveTo(v3f pos, bool continuous)
setBasePosition(pos);
// Movement caused by this command is always valid
- m_last_good_position = pos;
+ m_last_good_position = getBasePosition();
m_move_pool.empty();
m_time_from_last_teleport = 0.0;
m_env->getGameDef()->SendMovePlayer(m_peer_id);
@@ -489,7 +489,7 @@ void PlayerSAO::setHP(s32 target_hp, const PlayerHPChangeReason &reason, bool fr
m_hp = hp;
m_env->getGameDef()->HandlePlayerHPChange(this, reason);
} else if (from_client)
- m_env->getGameDef()->SendPlayerHP(this);
+ m_env->getGameDef()->SendPlayerHP(this, true);
}
void PlayerSAO::setBreath(const u16 breath, bool send)
diff --git a/src/server/player_sao.h b/src/server/player_sao.h
index 96d8f7189..5f48cae67 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 setBasePosition(const v3f &position);
- void setPos(const v3f &pos);
- void moveTo(v3f pos, bool continuous);
+ 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(v3f position);
+ 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);
@@ -110,8 +110,8 @@ public:
*/
u32 punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher,
- float time_from_last_punch, u16 initial_wear = 0);
- void rightClick(ServerActiveObject *clicker);
+ 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);
@@ -124,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
@@ -171,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);
@@ -235,6 +235,7 @@ struct PlayerHPChangeReason
enum Type : u8
{
SET_HP,
+ SET_HP_MAX, // internal type to allow distinguishing hp reset and damage (for effects)
PLAYER_PUNCH,
FALL,
NODE_DAMAGE,
@@ -277,6 +278,7 @@ struct PlayerHPChangeReason
{
switch (type) {
case PlayerHPChangeReason::SET_HP:
+ case PlayerHPChangeReason::SET_HP_MAX:
return "set_hp";
case PlayerHPChangeReason::PLAYER_PUNCH:
return "punch";