3 Copyright (C) 2010-2020 Minetest core development team
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "serverinventorymgr.h"
22 #include "nodemetadata.h"
23 #include "player_sao.h"
24 #include "remoteplayer.h"
26 #include "serverenvironment.h"
28 ServerInventoryManager::ServerInventoryManager() : InventoryManager()
32 ServerInventoryManager::~ServerInventoryManager()
34 // Delete detached inventories
35 for (auto &detached_inventory : m_detached_inventories) {
36 delete detached_inventory.second.inventory;
40 Inventory *ServerInventoryManager::getInventory(const InventoryLocation &loc)
43 case InventoryLocation::UNDEFINED:
44 case InventoryLocation::CURRENT_PLAYER:
46 case InventoryLocation::PLAYER: {
47 RemotePlayer *player = m_env->getPlayer(loc.name.c_str());
50 PlayerSAO *playersao = player->getPlayerSAO();
53 return playersao->getInventory();
55 case InventoryLocation::NODEMETA: {
56 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
59 return meta->getInventory();
61 case InventoryLocation::DETACHED: {
62 auto it = m_detached_inventories.find(loc.name);
63 if (it == m_detached_inventories.end())
65 return it->second.inventory;
68 sanity_check(false); // abort
74 void ServerInventoryManager::setInventoryModified(const InventoryLocation &loc)
77 case InventoryLocation::UNDEFINED:
79 case InventoryLocation::PLAYER: {
81 RemotePlayer *player = m_env->getPlayer(loc.name.c_str());
86 player->setModified(true);
87 player->inventory.setModified(true);
88 // Updates are sent in ServerEnvironment::step()
90 case InventoryLocation::NODEMETA: {
92 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
94 m_env->getMap().dispatchEvent(event);
96 case InventoryLocation::DETACHED: {
97 // Updates are sent in ServerEnvironment::step()
100 sanity_check(false); // abort
105 Inventory *ServerInventoryManager::createDetachedInventory(
106 const std::string &name, IItemDefManager *idef, const std::string &player)
108 if (m_detached_inventories.count(name) > 0) {
109 infostream << "Server clearing detached inventory \"" << name << "\""
111 delete m_detached_inventories[name].inventory;
113 infostream << "Server creating detached inventory \"" << name << "\""
117 Inventory *inv = new Inventory(idef);
119 m_detached_inventories[name].inventory = inv;
120 if (!player.empty()) {
121 m_detached_inventories[name].owner = player;
124 return inv; // Mods are not loaded yet, ignore
126 RemotePlayer *p = m_env->getPlayer(name.c_str());
128 // if player is connected, send him the inventory
129 if (p && p->getPeerId() != PEER_ID_INEXISTENT) {
130 m_env->getGameDef()->sendDetachedInventory(
131 inv, name, p->getPeerId());
135 return inv; // Mods are not loaded yet, don't send
137 // Inventory is for everybody, broadcast
138 m_env->getGameDef()->sendDetachedInventory(inv, name, PEER_ID_INEXISTENT);
144 bool ServerInventoryManager::removeDetachedInventory(const std::string &name)
146 const auto &inv_it = m_detached_inventories.find(name);
147 if (inv_it == m_detached_inventories.end())
150 delete inv_it->second.inventory;
151 const std::string &owner = inv_it->second.owner;
153 if (!owner.empty()) {
154 RemotePlayer *player = m_env->getPlayer(owner.c_str());
156 if (player && player->getPeerId() != PEER_ID_INEXISTENT)
157 m_env->getGameDef()->sendDetachedInventory(
158 nullptr, name, player->getPeerId());
161 // Notify all players about the change
162 m_env->getGameDef()->sendDetachedInventory(
163 nullptr, name, PEER_ID_INEXISTENT);
166 m_detached_inventories.erase(inv_it);
171 void ServerInventoryManager::sendDetachedInventories(const std::string &peer_name,
173 std::function<void(const std::string &, Inventory *)> apply_cb)
175 for (const auto &detached_inventory : m_detached_inventories) {
176 const DetachedInventory &dinv = detached_inventory.second;
178 if (!dinv.inventory || !dinv.inventory->checkModified())
182 // if we are pushing inventories to a specific player
183 // we should filter to send only the right inventories
184 if (!peer_name.empty()) {
185 const std::string &attached_player = dinv.owner;
186 if (!attached_player.empty() && peer_name != attached_player)
190 apply_cb(detached_inventory.first, detached_inventory.second.inventory);