diff --git a/doc/lua_api.md b/doc/lua_api.md index a988f8804..57bc78b73 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -9136,6 +9136,13 @@ child will follow movement and rotation of that bone. * `get_lighting()`: returns the current state of lighting for the player. * Result is a table with the same fields as `light_definition` in `set_lighting`. +* `set_node_visual(node_name, node_visual)`: sets `node_visual` of `node_name` for the player + * `node_name` is a name of registered node. + * `node_visual` is a table with the following optional fields: + * `variant_offset` this value is added to variant from node param2 value (default: `0`). + +* `get_node_visual(node_name)`: returns the current `node_visual` of `node_name` for the player. + * Result is a table with the same fields as `node_visual` in `set_node_visual`. * `respawn()`: Respawns the player using the same mechanism as the death screen, including calling `on_respawnplayer` callbacks. * `get_flags()`: returns a table of player flags (the following boolean fields): diff --git a/games/devtest/mods/testnodes/init.lua b/games/devtest/mods/testnodes/init.lua index 7394cd657..7a0824b35 100644 --- a/games/devtest/mods/testnodes/init.lua +++ b/games/devtest/mods/testnodes/init.lua @@ -12,3 +12,4 @@ dofile(path.."/textures.lua") dofile(path.."/overlays.lua") dofile(path.."/variants.lua") dofile(path.."/commands.lua") +dofile(path.."/node_visual.lua") diff --git a/games/devtest/mods/testnodes/node_visual.lua b/games/devtest/mods/testnodes/node_visual.lua new file mode 100644 index 000000000..16123424e --- /dev/null +++ b/games/devtest/mods/testnodes/node_visual.lua @@ -0,0 +1,48 @@ +-- add command to change node_visual + +core.register_chatcommand("node_visual", { + params = "nodename field [value]", + description = "Change node_visual field of actual player to value or show value of field.", + func = function(name, param) + local player = core.get_player_by_name(name) + if not player then + return false, "No player." + end + + local splits = string.split(param, " ", false, 3) + + if #splits < 2 then + return false, "Expected node name and node_visual field as parameters." + end + + local node_name = splits[1] + local field_name = splits[2] + + if not core.registered_nodes[node_name] then + return false, "Unknown node "..node_name + end + + local node_visual = player:get_node_visual(node_name) + + if rawequal(node_visual[field_name], nil) then + return false, "Field "..field_name.." not found in node_visual." + end + + if #splits > 2 then + if type(node_visual[field_name]) == "number" then + node_visual[field_name] = tonumber(splits[3]) + elseif type(node_visual[field_name]) == "table" then + node_visual[field_name] = core.parse_json(splits[3]) + if type(node_visual[field_name]) ~= "table" then + return false, "Table in json format is expected as value." + end + else + node_visual[field_name] = splits[3] + end + player:set_node_visual(node_name, node_visual) + return true, "Node "..node_name.." node_visual field "..field_name.." set to value: "..dump(node_visual[field_name]) + else + return true, "Node "..node_name.." node_visual field "..field_name.." have value: "..dump(node_visual[field_name]) + end + end +}) diff --git a/games/devtest/mods/unittests/player.lua b/games/devtest/mods/unittests/player.lua index f8945f320..1f2f5c85d 100644 --- a/games/devtest/mods/unittests/player.lua +++ b/games/devtest/mods/unittests/player.lua @@ -204,3 +204,12 @@ local function run_player_hotbar_clamp_tests(player) player:hud_set_hotbar_itemcount(old_bar_size) end unittests.register("test_player_hotbar_clamp", run_player_hotbar_clamp_tests, {player=true}) + +unittests.register("test_player_node_visual", function (player) + local visual = player:get_node_visual("testnodes:variant_facedir") + player:set_node_visual("testnodes:variant_facedir", + {variant_offset = 5}) + local set_visual = player:get_node_visual("testnodes:variant_facedir") + assert(set_visual.variant_offset == 5) + player:set_node_visual("testnodes:variant_facedir", visual) + end, {player = true}) diff --git a/src/client/client.cpp b/src/client/client.cpp index 02e1805af..734e842cf 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1761,6 +1761,18 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur addUpdateMeshTask(blockpos + v3s16(0, 0, -1), false, urgent); } +void Client::updateDrawListBlocks(bool ack_to_server, bool urgent) +{ + Map *map = &m_env.getMap(); + ClientMap *client_map = dynamic_cast(map); + + auto cb_updateBlock = [this, map, ack_to_server, urgent] (v3s16 block_pos, MapBlock *map_block) { + m_mesh_update_manager->updateBlock(map, block_pos, ack_to_server, urgent); + }; + + client_map->callOverDrawList(cb_updateBlock); +} + ClientEvent *Client::getClientEvent() { FATAL_ERROR_IF(m_client_event_queue.empty(), diff --git a/src/client/client.h b/src/client/client.h index 12625f24e..73b6975f2 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -219,6 +219,7 @@ public: void handleCommand_MinimapModes(NetworkPacket *pkt); void handleCommand_SetLighting(NetworkPacket *pkt); void handleCommand_Camera(NetworkPacket* pkt); + void handleCommand_SetNodeVisual(NetworkPacket *pkt); void ProcessData(NetworkPacket *pkt); @@ -305,6 +306,8 @@ public: void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false); void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false); + void updateDrawListBlocks(bool ack_to_server=false, bool urgent=false); + bool hasClientEvents() const { return !m_client_event_queue.empty(); } // Get event from queue. If queue is empty, it triggers an assertion failure. ClientEvent * getClientEvent(); diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index aad5c700d..a8cbfa582 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -716,6 +716,13 @@ void ClientMap::updateDrawList() g_profiler->avg("MapBlocks drawn [#]", m_drawlist.size()); } +void ClientMap::callOverDrawList(const std::function &cb) +{ + for (auto &i : m_drawlist) { + cb(i.first, i.second); + } +} + void ClientMap::touchMapBlocks() { if (m_control.range_all || m_loops_occlusion_culler) diff --git a/src/client/clientmap.h b/src/client/clientmap.h index daa9d80f1..53a1bc3e8 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -90,6 +90,7 @@ public: void getBlocksInViewRange(v3s16 cam_pos_nodes, v3s16 *p_blocks_min, v3s16 *p_blocks_max, float range=-1.0f); void updateDrawList(); + void callOverDrawList(const std::function &cb); // @brief Calculate statistics about the map and keep the blocks alive void touchMapBlocks(); void updateDrawListShadow(v3f shadow_light_pos, v3f shadow_light_dir, float radius, float length); diff --git a/src/database/database-files.cpp b/src/database/database-files.cpp index 84684299d..b254abb78 100644 --- a/src/database/database-files.cpp +++ b/src/database/database-files.cpp @@ -140,7 +140,7 @@ void PlayerDatabaseFiles::savePlayer(RemotePlayer *player) std::string savedir = m_savedir + DIR_DELIM; std::string path = savedir + player->getName(); bool path_found = false; - RemotePlayer testplayer("", NULL); + RemotePlayer testplayer("", NULL, NULL); for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES && !path_found; i++) { if (!fs::PathExists(path)) { @@ -184,7 +184,7 @@ bool PlayerDatabaseFiles::removePlayer(const std::string &name) std::string players_path = m_savedir + DIR_DELIM; std::string path = players_path + name; - RemotePlayer temp_player("", NULL); + RemotePlayer temp_player("", NULL, NULL); for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) { // Open file and deserialize auto is = open_ifstream(path.c_str(), false); @@ -245,7 +245,7 @@ void PlayerDatabaseFiles::listPlayers(std::vector &res) if (!is.good()) continue; - RemotePlayer player(filename.c_str(), NULL); + RemotePlayer player(filename.c_str(), NULL, NULL); // Null env & dummy peer_id PlayerSAO playerSAO(NULL, &player, 15789, false); diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 0e23eec87..f7b7d3fc0 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -40,7 +40,9 @@ void MapNode::getColor(const ContentFeatures &f, video::SColor *color) const u16 MapNode::getVariant(const ContentFeatures &f) const { - return f.variant_count > 1 ? f.param2_variant.get(param2) % f.variant_count : 0; + if (f.variant_count > 1) + return (f.param2_variant.get(param2) + f.variant_offset) % f.variant_count; + return 0; } u8 MapNode::getFaceDir(const NodeDefManager *nodemgr, diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index 9a9cb5968..d5dad9efc 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -105,7 +105,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] = { "TOCLIENT_SET_MOON", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetMoon }, // 0x5b { "TOCLIENT_SET_STARS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetStars }, // 0x5c { "TOCLIENT_MOVE_PLAYER_REL", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MovePlayerRel }, // 0x5d, - null_command_handler, + { "TOCLIENT_SET_NODE_VISUAL", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_SetNodeVisual }, // 0x5e null_command_handler, { "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60 { "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61, diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index bb1930d96..3a799d623 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1795,3 +1795,18 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt) >> lighting.bloom_radius; } } + +void Client::handleCommand_SetNodeVisual(NetworkPacket *pkt) +{ + std::string node_name; + NodeVisual node_visual; + + *pkt >> node_name; + + if (pkt->getRemainingBytes() >= 2) + *pkt >> node_visual.variant_offset; + + m_nodedef->applyNodeVisual(node_name, node_visual); + + updateDrawListBlocks(); +} diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 5ce3f4221..c0751e898 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -648,6 +648,12 @@ enum ToClientCommand : u16 v3f added_pos */ + TOCLIENT_SET_NODE_VISUAL = 0x5e, + /* + std::string nodename + u16 variant_offset + */ + TOCLIENT_SRP_BYTES_S_B = 0x60, /* Belonging to AUTH_MECHANISM_SRP. diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index b50e13082..23294c7ed 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -205,7 +205,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] = { "TOCLIENT_SET_MOON", 0, true }, // 0x5b { "TOCLIENT_SET_STARS", 0, true }, // 0x5c { "TOCLIENT_MOVE_PLAYER_REL", 0, true }, // 0x5d - null_command_factory, // 0x5e + { "TOCLIENT_SET_NODE_VISUAL", 0, true }, // 0x5e null_command_factory, // 0x5f { "TOCLIENT_SRP_BYTES_S_B", 0, true }, // 0x60 { "TOCLIENT_FORMSPEC_PREPEND", 0, true }, // 0x61 diff --git a/src/nodedef.cpp b/src/nodedef.cpp index c8f740203..d959313a5 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -372,6 +372,7 @@ void ContentFeatures::reset() param_type = CPT_NONE; param_type_2 = CPT2_NONE; variant_count = 1; + variant_offset = 0; param2_variant = BitField(); is_ground_content = false; light_propagates = false; @@ -1076,6 +1077,22 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc } #endif +/* + NodeVisual +*/ + +NodeVisual::NodeVisual() : variant_offset(0) +{ +} +NodeVisual::NodeVisual(const ContentFeatures &f) +{ + from_contentFeature(f); +} +void NodeVisual::from_contentFeature(const ContentFeatures &f) +{ + variant_offset = f.variant_offset; +} + /* NodeDefManager */ @@ -1224,6 +1241,21 @@ const ContentFeatures& NodeDefManager::get(const std::string &name) const return get(id); } +void NodeDefManager::getNodeVisual(const std::string &name, NodeVisual &node_visual) const +{ + const ContentFeatures &f = get(name); + node_visual.from_contentFeature(f); +} + +void NodeDefManager::applyNodeVisual(const std::string &name, const NodeVisual &node_visual) +{ + content_t c = getId(name); + if (c < m_content_features.size() && !m_content_features[c].name.empty()) { + ContentFeatures& f = m_content_features[c]; + + f.variant_offset = node_visual.variant_offset; + } +} // returns CONTENT_IGNORE if no free ID found content_t NodeDefManager::allocateId() diff --git a/src/nodedef.h b/src/nodedef.h index 5c3580e29..bd603dd0f 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -340,6 +340,8 @@ struct ContentFeatures ContentParamType2 param_type_2; // Number of node variants u16 variant_count = 1; + // Node variant offset + u16 variant_offset = 0; // Bit field for variant in param2 BitField param2_variant; @@ -522,6 +524,15 @@ private: u8 getAlphaForLegacy() const; }; +struct NodeVisual { + u16 variant_offset = 0; + + NodeVisual(); + NodeVisual(const ContentFeatures &f); + + void from_contentFeature(const ContentFeatures &f); +}; + /*! * @brief This class is for getting the actual properties of nodes from their * content ID. @@ -617,6 +628,20 @@ public: return m_selection_box_int_union; } + /*! + * Get NodeVisual object of node + * @param name a node name + * @param node_visual NodeVisual object to be set + */ + void getNodeVisual(const std::string &name, NodeVisual &node_visual) const; + + /*! + * Apply NodeVisual object to node + * @param name a node name + * @param node_visual NodeVisual object to be applied to node + */ + void applyNodeVisual(const std::string &name, const NodeVisual &node_visual); + /*! * Checks whether a node connects to an adjacent node. * @param from the node to be checked diff --git a/src/remoteplayer.cpp b/src/remoteplayer.cpp index ca12a38e4..93d97d139 100644 --- a/src/remoteplayer.cpp +++ b/src/remoteplayer.cpp @@ -12,6 +12,7 @@ #include "settings.h" #include "convert_json.h" #include "server/player_sao.h" +#include "nodedef.h" /* RemotePlayer @@ -22,7 +23,8 @@ bool RemotePlayer::m_setting_cache_loaded = false; float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f; u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0; -RemotePlayer::RemotePlayer(const std::string &name, IItemDefManager *idef): +RemotePlayer::RemotePlayer(const std::string &name, IItemDefManager *idef, + NodeDefManager *ndef): Player(name, idef) { if (!RemotePlayer::m_setting_cache_loaded) { @@ -52,6 +54,9 @@ RemotePlayer::RemotePlayer(const std::string &name, IItemDefManager *idef): m_sun_params = SkyboxDefaults::getSunDefaults(); m_moon_params = SkyboxDefaults::getMoonDefaults(); m_star_params = SkyboxDefaults::getStarDefaults(); + + // NodeDefManager forNodeDefManager for NodeVisual + m_ndef = ndef; } RemotePlayer::~RemotePlayer() @@ -99,6 +104,23 @@ RemotePlayerChatResult RemotePlayer::canSendChatMessage() return RPLAYER_CHATRESULT_OK; } +void RemotePlayer::setNodeVisual(const std::string &node_name, const NodeVisual &node_visual) +{ + content_t c = m_ndef->getId(node_name); + + m_node_visuals[c] = node_visual; +} + +void RemotePlayer::getNodeVisual(const std::string &node_name, NodeVisual &node_visual) +{ + content_t c = m_ndef->getId(node_name); + + if (m_node_visuals.find(c) != m_node_visuals.end()) + node_visual = m_node_visuals[c]; + else + node_visual.from_contentFeature(m_ndef->get(c)); +} + void RemotePlayer::onSuccessfulSave() { setModified(false); diff --git a/src/remoteplayer.h b/src/remoteplayer.h index 1f2f8df9c..f5bfc51c1 100644 --- a/src/remoteplayer.h +++ b/src/remoteplayer.h @@ -9,8 +9,11 @@ #include "skyparams.h" #include "lighting.h" #include "network/networkprotocol.h" // session_t +#include "mapnode.h" // content_t class PlayerSAO; +class NodeDefManager; +struct NodeVisual; enum RemotePlayerChatResult { @@ -27,7 +30,8 @@ class RemotePlayer : public Player friend class PlayerDatabaseFiles; public: - RemotePlayer(const std::string &name, IItemDefManager *idef); + RemotePlayer(const std::string &name, IItemDefManager *idef, + NodeDefManager *ndef); virtual ~RemotePlayer(); PlayerSAO *getPlayerSAO() { return m_sao; } @@ -116,6 +120,10 @@ public: const Lighting& getLighting() const { return m_lighting; } + void setNodeVisual(const std::string &node_name, const NodeVisual &node_visual); + + void getNodeVisual(const std::string &node_name, NodeVisual &node_visual); + void setDirty(bool dirty) { m_dirty = true; } u16 protocol_version = 0; @@ -154,5 +162,8 @@ private: Lighting m_lighting; + NodeDefManager *m_ndef; + std::map m_node_visuals; + session_t m_peer_id = PEER_ID_INEXISTENT; }; diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 19c513dd3..5ea33d9e0 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -18,6 +18,7 @@ #include "remoteplayer.h" #include "server.h" #include "hud.h" +#include "nodedef.h" #include "scripting_server.h" #include "server/luaentity_sao.h" #include "server/player_sao.h" @@ -2749,6 +2750,50 @@ int ObjectRef::l_get_lighting(lua_State *L) return 1; } +// set_node_visual(self, node_name, node_visual) +int ObjectRef::l_set_node_visual(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkObject(L, 1); + RemotePlayer *player = getplayer(ref); + if (player == nullptr) + return 0; + + std::string node_name = readParam(L, 2); + + NodeVisual node_visual; + player->getNodeVisual(node_name, node_visual); + NodeVisual new_visual = node_visual; + + if (!lua_isnoneornil(L, 3)) { + luaL_checktype(L, 3, LUA_TTABLE); + new_visual.variant_offset = getfloatfield_default(L, -1, "variant_offset", node_visual.variant_offset); + } + + getServer(L)->setNodeVisual(player, node_name, new_visual); + return 0; +} + +// get_node_visual(self, node_name) +int ObjectRef::l_get_node_visual(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkObject(L, 1); + RemotePlayer *player = getplayer(ref); + if (player == nullptr) + return 0; + + std::string node_name = readParam(L, 2); + + NodeVisual node_visual; + player->getNodeVisual(node_name, node_visual); + + lua_newtable(L); // result + lua_pushnumber(L, node_visual.variant_offset); + lua_setfield(L, -2, "variant_offset"); + return 1; +} + // respawn(self) int ObjectRef::l_respawn(lua_State *L) { @@ -2950,6 +2995,8 @@ luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, set_minimap_modes), luamethod(ObjectRef, set_lighting), luamethod(ObjectRef, get_lighting), + luamethod(ObjectRef, set_node_visual), + luamethod(ObjectRef, get_node_visual), luamethod(ObjectRef, respawn), luamethod(ObjectRef, set_flags), luamethod(ObjectRef, get_flags), diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index f97d7d2da..8899ac7b0 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -406,6 +406,12 @@ private: // get_lighting(self) static int l_get_lighting(lua_State *L); + // set_node_visual(self, node_name, node_visual) + static int l_set_node_visual(lua_State *L); + + // get_node_visual(self, node_name) + static int l_get_node_visual(lua_State *L); + // respawn(self) static int l_respawn(lua_State *L); diff --git a/src/server.cpp b/src/server.cpp index 89bba75fb..cb2a4b74e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1965,6 +1965,17 @@ void Server::SendCamera(session_t peer_id, Player *player) Send(&pkt); } +void Server::SendSetNodeVisual(session_t peer_id, const std::string &node_name, const NodeVisual &node_visual) +{ + NetworkPacket pkt(TOCLIENT_SET_NODE_VISUAL, + 4, peer_id); + + pkt << node_name; + pkt << node_visual.variant_offset; + + Send(&pkt); +} + void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed) { NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id); @@ -3576,6 +3587,13 @@ void Server::setLighting(RemotePlayer *player, const Lighting &lighting) SendSetLighting(player->getPeerId(), lighting); } +void Server::setNodeVisual(RemotePlayer *player, const std::string &node_name, const NodeVisual &node_visual) +{ + sanity_check(player); + player->setNodeVisual(node_name, node_visual); + SendSetNodeVisual(player->getPeerId(), node_name, node_visual); +} + void Server::notifyPlayers(const std::wstring &msg) { SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg)); @@ -4103,7 +4121,7 @@ std::unique_ptr Server::emergePlayer(const char *name, session_t peer */ if (!player) { - player = new RemotePlayer(name, idef()); + player = new RemotePlayer(name, idef(), m_nodedef); } // Load player diff --git a/src/server.h b/src/server.h index 177af002f..cf3650bf5 100644 --- a/src/server.h +++ b/src/server.h @@ -24,6 +24,7 @@ #include "sound.h" #include "translation.h" #include "script/common/c_types.h" // LuaError +#include "nodedef.h" #include #include #include @@ -387,6 +388,8 @@ public: void setLighting(RemotePlayer *player, const Lighting &lighting); + void setNodeVisual(RemotePlayer *player, const std::string &node_name, const NodeVisual &node_visual); + /* con::PeerHandler implementation. */ void peerAdded(con::IPeer *peer); void deletingPeer(con::IPeer *peer, bool timeout); @@ -550,6 +553,7 @@ private: void SendCloudParams(session_t peer_id, const CloudParams ¶ms); void SendOverrideDayNightRatio(session_t peer_id, bool do_override, float ratio); void SendSetLighting(session_t peer_id, const Lighting &lighting); + void SendSetNodeVisual(session_t peer_id, const std::string &node_name, const NodeVisual &node_visual); void broadcastModChannelMessage(const std::string &channel, const std::string &message, session_t from_peer); diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 6368f4f8f..6beb8026c 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1902,7 +1902,7 @@ bool ServerEnvironment::migratePlayersDatabase(const GameParams &game_params, for (auto it = player_list.begin(); it != player_list.end(); ++it) { actionstream << "Migrating player " << it->c_str() << std::endl; - RemotePlayer player(it->c_str(), NULL); + RemotePlayer player(it->c_str(), NULL, NULL); PlayerSAO playerSAO(NULL, &player, 15000, false); srcdb->loadPlayer(&player, &playerSAO);