m_startup_server_map = nullptr; // Ownership moved to ServerEnvironment
m_env = new ServerEnvironment(servermap, m_script, this,
m_path_world, m_metrics_backend.get());
+ m_env->init();
m_inventory_mgr->setEnv(m_env);
m_clients.setEnv(m_env);
static std::random_device seed;
ServerEnvironment::ServerEnvironment(ServerMap *map,
- ServerScripting *scriptIface, Server *server,
+ ServerScripting *script_iface, Server *server,
const std::string &path_world, MetricsBackend *mb):
Environment(server),
m_map(map),
- m_script(scriptIface),
+ m_script(script_iface),
m_server(server),
m_path_world(path_world),
m_rgen(seed())
+{
+ m_step_time_counter = mb->addCounter(
+ "minetest_env_step_time", "Time spent in environment step (in microseconds)");
+
+ m_active_block_gauge = mb->addGauge(
+ "minetest_env_active_blocks", "Number of active blocks");
+
+ m_active_object_gauge = mb->addGauge(
+ "minetest_env_active_objects", "Number of active objects");
+}
+
+void ServerEnvironment::init()
{
// Determine which database backend to use
- std::string conf_path = path_world + DIR_DELIM + "world.mt";
+ std::string conf_path = m_path_world + DIR_DELIM + "world.mt";
Settings conf;
std::string player_backend_name = "sqlite3";
<< "please read http://wiki.minetest.net/Database_backends." << std::endl;
}
- m_player_database = openPlayerDatabase(player_backend_name, path_world, conf);
- m_auth_database = openAuthDatabase(auth_backend_name, path_world, conf);
-
- m_step_time_counter = mb->addCounter(
- "minetest_env_step_time", "Time spent in environment step (in microseconds)");
-
- m_active_block_gauge = mb->addGauge(
- "minetest_env_active_blocks", "Number of active blocks");
-
- m_active_object_gauge = mb->addGauge(
- "minetest_env_active_objects", "Number of active objects");
+ m_player_database = openPlayerDatabase(player_backend_name, m_path_world, conf);
+ m_auth_database = openAuthDatabase(auth_backend_name, m_path_world, conf);
}
ServerEnvironment::~ServerEnvironment()
deactivateFarObjects(true);
// Drop/delete map
- m_map->drop();
+ if (m_map)
+ m_map->drop();
// Delete ActiveBlockModifiers
for (ABMWithState &m_abm : m_abms) {
CLEAR_OBJECTS_MODE_QUICK,
};
-class ServerEnvironment : public Environment
+class ServerEnvironment final : public Environment
{
public:
- ServerEnvironment(ServerMap *map, ServerScripting *scriptIface,
+ ServerEnvironment(ServerMap *map, ServerScripting *script_iface,
Server *server, const std::string &path_world, MetricsBackend *mb);
~ServerEnvironment();
+ void init();
+
Map & getMap();
ServerMap & getServerMap();
${CMAKE_CURRENT_SOURCE_DIR}/test_mapnode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_modchannels.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_modmetadatadatabase.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/test_moveaction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_nodedef.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_noderesolver.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_noise.cpp
set (TEST_WORLDDIR ${CMAKE_CURRENT_SOURCE_DIR}/test_world)
set (TEST_SUBGAME_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../games/devtest)
set (TEST_MOD_PATH ${CMAKE_CURRENT_SOURCE_DIR}/test_mod)
+set (HELPERS_PATH ${CMAKE_CURRENT_SOURCE_DIR}/helpers)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/test_config.h.in"
--- /dev/null
+minetest.register_allow_player_inventory_action(function(player, action, inventory, info)
+ if info.stack:get_name() == "default:water" then
+ return 0
+ end
+
+ if info.stack:get_name() == "default:lava" then
+ return 5
+ end
+
+ return info.stack:get_count()
+end)
--- /dev/null
+/*
+Minetest
+Copyright (C) 2022 Minetest core developers & community
+
+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 <activeobject.h>
+
+class MockActiveObject : public ActiveObject
+{
+public:
+ MockActiveObject(u16 id) : ActiveObject(id) {}
+
+ virtual ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_TEST; }
+ virtual bool getCollisionBox(aabb3f *toset) const { return false; }
+ virtual bool getSelectionBox(aabb3f *toset) const { return false; }
+ virtual bool collideWithObjects() const { return false; }
+};
--- /dev/null
+/*
+Minetest
+Copyright (C) 2022 Minetest core developers & community
+
+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 <gamedef.h>
+#include <inventorymanager.h>
+
+class MockInventoryManager : public InventoryManager
+{
+public:
+ MockInventoryManager(IGameDef *gamedef) :
+ p1(gamedef->getItemDefManager()),
+ p2(gamedef->getItemDefManager())
+ {};
+
+ virtual Inventory* getInventory(const InventoryLocation &loc){
+ if (loc.type == InventoryLocation::PLAYER && loc.name == "p1")
+ return &p1;
+ if (loc.type == InventoryLocation::PLAYER && loc.name == "p2")
+ return &p2;
+ return nullptr;
+ }
+
+ Inventory p1;
+ Inventory p2;
+};
--- /dev/null
+/*
+Minetest
+Copyright (C) 2022 Minetest core developers & community
+
+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 <server.h>
+
+class MockServer : public Server
+{
+public:
+ MockServer() : Server(TEST_WORLDDIR, SubgameSpec("fakespec", "fakespec"), true,
+ Address(), true, nullptr)
+ {}
+
+private:
+ void SendChatMessage(session_t peer_id, const ChatMessage &message) {}
+};
--- /dev/null
+/*
+Minetest
+Copyright (C) 2022 Minetest core developers & community
+
+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 <server/serveractiveobject.h>
+
+class MockServerActiveObject : public ServerActiveObject
+{
+public:
+ MockServerActiveObject(ServerEnvironment *env = nullptr, const v3f &p = v3f()) :
+ ServerActiveObject(env, p) {}
+
+ virtual ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_TEST; }
+ virtual bool getCollisionBox(aabb3f *toset) const { return false; }
+ virtual bool getSelectionBox(aabb3f *toset) const { return false; }
+ virtual bool collideWithObjects() const { return false; }
+};
#include "test.h"
-#include "activeobject.h"
+#include "mock_activeobject.h"
class TestActiveObject : public TestBase
{
TEST(testAOAttributes);
}
-class TestAO : public ActiveObject
-{
-public:
- TestAO(u16 id) : ActiveObject(id) {}
-
- virtual ActiveObjectType getType() const { return ACTIVEOBJECT_TYPE_TEST; }
- virtual bool getCollisionBox(aabb3f *toset) const { return false; }
- virtual bool getSelectionBox(aabb3f *toset) const { return false; }
- virtual bool collideWithObjects() const { return false; }
-};
-
void TestActiveObject::testAOAttributes()
{
- TestAO ao(44);
+ MockActiveObject ao(44);
UASSERT(ao.getId() == 44);
ao.setId(558);
#define TEST_WORLDDIR "@TEST_WORLDDIR@"
#define TEST_SUBGAME_PATH "@TEST_SUBGAME_PATH@"
#define TEST_MOD_PATH "@TEST_MOD_PATH@"
+#define HELPERS_PATH "@HELPERS_PATH@"
--- /dev/null
+/*
+Minetest
+Copyright (C) 2022 Minetest core developers & community
+
+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 "test.h"
+#include "test_config.h"
+
+#include "mock_inventorymanager.h"
+#include "mock_server.h"
+#include "mock_serveractiveobject.h"
+
+#include <scripting_server.h>
+
+
+class TestMoveAction : public TestBase
+{
+public:
+ TestMoveAction() { TestManager::registerTestModule(this); }
+ const char *getName() { return "TestMoveAction"; }
+
+ void runTests(IGameDef *gamedef);
+
+ void testMove(ServerActiveObject *obj, IGameDef *gamedef);
+ void testMoveSomewhere(ServerActiveObject *obj, IGameDef *gamedef);
+ void testMoveUnallowed(ServerActiveObject *obj, IGameDef *gamedef);
+ void testMovePartial(ServerActiveObject *obj, IGameDef *gamedef);
+ void testSwap(ServerActiveObject *obj, IGameDef *gamedef);
+ void testSwapFromUnallowed(ServerActiveObject *obj, IGameDef *gamedef);
+ void testSwapToUnallowed(ServerActiveObject *obj, IGameDef *gamedef);
+};
+
+static TestMoveAction g_test_instance;
+
+void TestMoveAction::runTests(IGameDef *gamedef)
+{
+ MockServer server;
+
+ ServerScripting server_scripting(&server);
+ server_scripting.loadMod(Server::getBuiltinLuaPath() + DIR_DELIM "init.lua", BUILTIN_MOD_NAME);
+ server_scripting.loadMod(std::string(HELPERS_PATH) + DIR_DELIM "helper_moveaction.lua", BUILTIN_MOD_NAME);
+
+ MetricsBackend mb;
+ ServerEnvironment server_env(nullptr, &server_scripting, &server, "", &mb);
+ MockServerActiveObject obj(&server_env);
+
+ TEST(testMove, &obj, gamedef);
+ TEST(testMoveSomewhere, &obj, gamedef);
+ TEST(testMoveUnallowed, &obj, gamedef);
+ TEST(testMovePartial, &obj, gamedef);
+ TEST(testSwap, &obj, gamedef);
+ TEST(testSwapFromUnallowed, &obj, gamedef);
+ TEST(testSwapToUnallowed, &obj, gamedef);
+}
+
+static ItemStack parse_itemstack(const char *s)
+{
+ ItemStack item;
+ item.deSerialize(s, nullptr);
+ return item;
+}
+
+static void apply_action(const char *s, InventoryManager *inv, ServerActiveObject *obj, IGameDef *gamedef)
+{
+ std::istringstream str(s);
+ InventoryAction *action = InventoryAction::deSerialize(str);
+ action->apply(inv, obj, gamedef);
+ delete action;
+}
+
+void TestMoveAction::testMove(ServerActiveObject *obj, IGameDef *gamedef)
+{
+ MockInventoryManager inv(gamedef);
+
+ inv.p1.addList("main", 10)->addItem(0, parse_itemstack("default:stone 50"));
+ inv.p2.addList("main", 10);
+
+ apply_action("Move 20 player:p1 main 0 player:p2 main 0", &inv, obj, gamedef);
+
+ UASSERT(inv.p1.getList("main")->getItem(0).getItemString() == "default:stone 30");
+ UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:stone 20");
+}
+
+void TestMoveAction::testMoveSomewhere(ServerActiveObject *obj, IGameDef *gamedef)
+{
+ MockInventoryManager inv(gamedef);
+
+ inv.p1.addList("main", 10)->addItem(0, parse_itemstack("default:stone 50"));
+ InventoryList *list = inv.p2.addList("main", 10);
+ list->addItem(0, parse_itemstack("default:brick 10"));
+ list->addItem(2, parse_itemstack("default:stone 85"));
+
+ apply_action("MoveSomewhere 50 player:p1 main 0 player:p2 main", &inv, obj, gamedef);
+
+ UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:brick 10");
+ UASSERT(inv.p2.getList("main")->getItem(1).getItemString() == "default:stone 36");
+ UASSERT(inv.p2.getList("main")->getItem(2).getItemString() == "default:stone 99");
+}
+
+void TestMoveAction::testMoveUnallowed(ServerActiveObject *obj, IGameDef *gamedef)
+{
+ MockInventoryManager inv(gamedef);
+
+ inv.p1.addList("main", 10)->addItem(0, parse_itemstack("default:water 50"));
+ inv.p2.addList("main", 10);
+
+ apply_action("Move 20 player:p1 main 0 player:p2 main 0", &inv, obj, gamedef);
+
+ UASSERT(inv.p1.getList("main")->getItem(0).getItemString() == "default:water 50");
+ UASSERT(inv.p2.getList("main")->getItem(0).empty())
+}
+
+void TestMoveAction::testMovePartial(ServerActiveObject *obj, IGameDef *gamedef)
+{
+ MockInventoryManager inv(gamedef);
+
+ inv.p1.addList("main", 10)->addItem(0, parse_itemstack("default:lava 50"));
+ inv.p2.addList("main", 10);
+
+ apply_action("Move 20 player:p1 main 0 player:p2 main 0", &inv, obj, gamedef);
+
+ UASSERT(inv.p1.getList("main")->getItem(0).getItemString() == "default:lava 45");
+ UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:lava 5");
+}
+
+void TestMoveAction::testSwap(ServerActiveObject *obj, IGameDef *gamedef)
+{
+ MockInventoryManager inv(gamedef);
+
+ inv.p1.addList("main", 10)->addItem(0, parse_itemstack("default:stone 50"));
+ inv.p2.addList("main", 10)->addItem(0, parse_itemstack("default:brick 60"));
+
+ apply_action("Move 50 player:p1 main 0 player:p2 main 0", &inv, obj, gamedef);
+
+ UASSERT(inv.p1.getList("main")->getItem(0).getItemString() == "default:brick 60");
+ UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:stone 50");
+}
+
+void TestMoveAction::testSwapFromUnallowed(ServerActiveObject *obj, IGameDef *gamedef)
+{
+ MockInventoryManager inv(gamedef);
+
+ inv.p1.addList("main", 10)->addItem(0, parse_itemstack("default:water 50"));
+ inv.p2.addList("main", 10)->addItem(0, parse_itemstack("default:brick 60"));
+
+ apply_action("Move 50 player:p1 main 0 player:p2 main 0", &inv, obj, gamedef);
+
+ UASSERT(inv.p1.getList("main")->getItem(0).getItemString() == "default:water 50");
+ UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:brick 60");
+}
+
+void TestMoveAction::testSwapToUnallowed(ServerActiveObject *obj, IGameDef *gamedef)
+{
+ MockInventoryManager inv(gamedef);
+
+ inv.p1.addList("main", 10)->addItem(0, parse_itemstack("default:stone 50"));
+ inv.p2.addList("main", 10)->addItem(0, parse_itemstack("default:water 60"));
+
+ apply_action("Move 50 player:p1 main 0 player:p2 main 0", &inv, obj, gamedef);
+
+ UASSERT(inv.p1.getList("main")->getItem(0).getItemString() == "default:stone 50");
+ UASSERT(inv.p2.getList("main")->getItem(0).getItemString() == "default:water 60");
+}
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <server.h>
#include "test.h"
+#include "test_config.h"
+
+#include "mock_server.h"
#include "util/string.h"
#include "util/serialize.h"
-class FakeServer : public Server
-{
-public:
- FakeServer() : Server("fakeworld", SubgameSpec("fakespec", "fakespec"), true,
- Address(), true, nullptr)
- {
- }
-
-private:
- void SendChatMessage(session_t peer_id, const ChatMessage &message)
- {
- // NOOP
- }
-};
-
class TestServerShutdownState : public TestBase
{
public:
void TestServerShutdownState::testTick()
{
- auto fakeServer = std::make_unique<FakeServer>();
+ auto server = std::make_unique<MockServer>();
Server::ShutdownState ss;
ss.trigger(28.0f, "testtrigger", true);
- ss.tick(0.0f, fakeServer.get());
+ ss.tick(0.0f, server.get());
// Tick with no time should not change anything
UASSERT(!ss.is_requested);
UASSERT(ss.m_timer == 28.0f);
// Tick 2 seconds
- ss.tick(2.0f, fakeServer.get());
+ ss.tick(2.0f, server.get());
UASSERT(!ss.is_requested);
UASSERT(ss.should_reconnect);
UASSERT(ss.message == "testtrigger");
UASSERT(ss.m_timer == 26.0f);
// Tick remaining seconds + additional expire
- ss.tick(26.1f, fakeServer.get());
+ ss.tick(26.1f, server.get());
UASSERT(ss.is_requested);
UASSERT(ss.should_reconnect);
UASSERT(ss.message == "testtrigger");
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "server/activeobjectmgr.h"
+#include "test.h"
+#include "mock_serveractiveobject.h"
#include <algorithm>
#include <queue>
-#include "test.h"
+
+#include "server/activeobjectmgr.h"
#include "profiler.h"
-class TestServerActiveObject : public ServerActiveObject
-{
-public:
- TestServerActiveObject(const v3f &p = v3f()) : ServerActiveObject(nullptr, p) {}
- ~TestServerActiveObject() = default;
- ActiveObjectType getType() const override { return ACTIVEOBJECT_TYPE_TEST; }
- bool getCollisionBox(aabb3f *toset) const override { return false; }
- bool getSelectionBox(aabb3f *toset) const override { return false; }
- bool collideWithObjects() const override { return false; }
-};
class TestServerActiveObjectMgr : public TestBase
{
// Register basic objects, ensure we never found
for (u8 i = 0; i < UINT8_MAX; i++) {
// Register an object
- auto tsao = new TestServerActiveObject();
- saomgr.registerObject(tsao);
- aoids.push_back(tsao->getId());
+ auto sao = new MockServerActiveObject();
+ saomgr.registerObject(sao);
+ aoids.push_back(sao->getId());
// Ensure next id is not in registered list
UASSERT(std::find(aoids.begin(), aoids.end(), saomgr.getFreeId()) ==
void TestServerActiveObjectMgr::testRegisterObject()
{
server::ActiveObjectMgr saomgr;
- auto tsao = new TestServerActiveObject();
- UASSERT(saomgr.registerObject(tsao));
+ auto sao = new MockServerActiveObject();
+ UASSERT(saomgr.registerObject(sao));
- u16 id = tsao->getId();
+ u16 id = sao->getId();
- auto tsaoToCompare = saomgr.getActiveObject(id);
- UASSERT(tsaoToCompare->getId() == id);
- UASSERT(tsaoToCompare == tsao);
+ auto saoToCompare = saomgr.getActiveObject(id);
+ UASSERT(saoToCompare->getId() == id);
+ UASSERT(saoToCompare == sao);
- tsao = new TestServerActiveObject();
- UASSERT(saomgr.registerObject(tsao));
- UASSERT(saomgr.getActiveObject(tsao->getId()) == tsao);
- UASSERT(saomgr.getActiveObject(tsao->getId()) != tsaoToCompare);
+ sao = new MockServerActiveObject();
+ UASSERT(saomgr.registerObject(sao));
+ UASSERT(saomgr.getActiveObject(sao->getId()) == sao);
+ UASSERT(saomgr.getActiveObject(sao->getId()) != saoToCompare);
clearSAOMgr(&saomgr);
}
void TestServerActiveObjectMgr::testRemoveObject()
{
server::ActiveObjectMgr saomgr;
- auto tsao = new TestServerActiveObject();
- UASSERT(saomgr.registerObject(tsao));
+ auto sao = new MockServerActiveObject();
+ UASSERT(saomgr.registerObject(sao));
- u16 id = tsao->getId();
+ u16 id = sao->getId();
UASSERT(saomgr.getActiveObject(id) != nullptr)
- saomgr.removeObject(tsao->getId());
+ saomgr.removeObject(sao->getId());
UASSERT(saomgr.getActiveObject(id) == nullptr);
clearSAOMgr(&saomgr);
};
for (const auto &p : sao_pos) {
- saomgr.registerObject(new TestServerActiveObject(p));
+ saomgr.registerObject(new MockServerActiveObject(nullptr, p));
}
std::vector<ServerActiveObject *> result;
};
for (const auto &p : sao_pos) {
- saomgr.registerObject(new TestServerActiveObject(p));
+ saomgr.registerObject(new MockServerActiveObject(nullptr, p));
}
std::queue<u16> result;