[LuaMod] Added helpers to despawn an entity and add an item stack to a player's inventory.

This commit is contained in:
Quentin Bazin 2020-05-19 16:42:32 +02:00
parent f9dcc6c016
commit 17af1861b5
11 changed files with 121 additions and 17 deletions

View File

@ -174,11 +174,9 @@ mod:entity {
hitbox = {0, 0, 0, 0.25, 0.25, 0.25},
},
on_collision = function(item_stack, entity, entity_net_id, player, registry, server)
player:inventory():add_stack(item_stack:item():string_id(), item_stack:amount())
server:send_player_inv_update(player:client_id(), player:client());
server:send_entity_despawn(entity_net_id, nil)
registry:destroy(entity)
on_collision = function(entity, player, server)
mods["default"]:give_item_stack(player, entity:item_stack());
mods["default"]:despawn_entity(entity)
end,
}
@ -188,11 +186,10 @@ openminer:add_listener(EventType.OnBlockDigged, function(pos, block, player, wor
position = {pos.x + 0.5, pos.y + 0.5, pos.z + 0.5},
dimension = world:dimension():id(),
itemstack = {block:get_item_drop():item():string_id(), block:get_item_drop():amount()}
item_stack = {block:get_item_drop():item():string_id(), block:get_item_drop():amount()}
})
else
player:inventory():add_stack(block:get_item_drop():item():string_id(), block:get_item_drop():amount());
server:send_player_inv_update(player:client_id(), player:client());
mods["default"]:give_item_stack(player, block:get_item_drop())
end
end)

View File

@ -73,7 +73,7 @@ class ServerApplication {
PlayerList m_players;
ScriptEngine m_scriptEngine;
ServerModLoader m_modLoader{m_scriptEngine, m_registry, m_worldController};
ServerModLoader m_modLoader{m_scriptEngine, m_registry, m_worldController, m_players};
Server m_server;
ServerCommandHandler m_serverCommandHandler{m_scriptEngine, m_server, m_worldController, m_players, m_registry};

View File

@ -25,10 +25,14 @@
* =====================================================================================
*/
#include "Biome.hpp"
#include "EntityWrapper.hpp"
#include "LuaMod.hpp"
#include "PlacementEntry.hpp"
#include "Registry.hpp"
#include "ServerCommandHandler.hpp"
#include "ServerPlayer.hpp"
#include "Tree.hpp"
#include "WorldController.hpp"
void LuaMod::commit() {
while (!m_defs.empty()) {
@ -61,6 +65,9 @@ void LuaMod::initUsertype(sol::state &lua) {
"path", &LuaMod::path,
"spawn_entity", &LuaMod::spawnEntity,
"despawn_entity", &LuaMod::despawnEntity,
"give_item_stack", &LuaMod::giveItemStack,
"block", DEF_FUNC(DefinitionType::Block),
"item", DEF_FUNC(DefinitionType::Item),
@ -78,3 +85,24 @@ void LuaMod::spawnEntity(const std::string &entityID, const sol::table &table) {
m_entityLoader.spawnEntity(entityID, table);
}
void LuaMod::despawnEntity(EntityWrapper &entity) {
PositionComponent *position = entity.getPositionComponent();
NetworkComponent *network = entity.getNetworkComponent();
if (position && network) {
m_worldController.server()->sendEntityDespawn(network->entityID);
m_worldController.getWorld(position->dimension).scene().registry().destroy(entity.id());
}
else
// FIXME: Maybe improve this message with the type of entity that caused the error
gkError() << "In mod '" + m_id + "': Failed to despawn entity: Missing position and network components";
}
void LuaMod::giveItemStack(ServerPlayer &player, ItemStack *itemStack) {
if (itemStack) {
player.inventory().addStack(itemStack->item().stringID(), itemStack->amount());
m_worldController.server()->sendPlayerInvUpdate(player.clientID(), &player.client());
}
else
gkError() << "In mod '" + m_id + "': Failed to add stack to player";
}

View File

@ -29,6 +29,10 @@
#include <queue>
#include <gk/core/IntTypes.hpp>
#include <entt/entt.hpp>
#include "LuaBiomeLoader.hpp"
#include "LuaBlockLoader.hpp"
#include "LuaDimensionLoader.hpp"
@ -37,14 +41,18 @@
#include "LuaRecipeLoader.hpp"
#include "LuaSkyLoader.hpp"
class EntityWrapper;
class ItemStack;
class PlayerList;
class Registry;
class ServerPlayer;
class WorldController;
// This class is meant to be used ONLY in Lua
class LuaMod {
public:
LuaMod(const std::string &id, Registry &registry, WorldController &worldController)
: m_id(id), m_registry(registry), m_worldController(worldController) {}
LuaMod(const std::string &id, Registry &registry, WorldController &worldController, PlayerList &players)
: m_id(id), m_registry(registry), m_worldController(worldController), m_players(players) {}
void commit();
@ -56,6 +64,9 @@ class LuaMod {
private:
void spawnEntity(const std::string &entityID, const sol::table &table);
void despawnEntity(EntityWrapper &entity);
void giveItemStack(ServerPlayer &player, ItemStack *itemStack);
enum class DefinitionType {
Block,
@ -76,6 +87,7 @@ class LuaMod {
// TODO: Add registry instance to loaders in order to avoid using singleton
Registry &m_registry;
WorldController &m_worldController;
PlayerList &m_players;
LuaBlockLoader m_blockLoader{*this};
LuaItemLoader m_itemLoader{*this};

View File

@ -25,6 +25,7 @@
* =====================================================================================
*/
#include "BlockMetadata.hpp"
#include "EntityWrapper.hpp"
#include "LuaCore.hpp"
#include "LuaGUI.hpp"
#include "LuaMod.hpp"
@ -55,6 +56,14 @@ void ScriptEngine::initUsertypes() {
"destroy", static_cast<void (entt::registry::*)(const entt::entity)>(&entt::registry::destroy)
);
m_lua.new_usertype<EntityWrapper>("EntityWrapper",
"id", &EntityWrapper::id,
"position", &EntityWrapper::getPositionComponent,
"network", &EntityWrapper::getNetworkComponent,
"item_stack", &EntityWrapper::getItemStack
);
m_lua.new_usertype<Registry>("Registry",
"get_block", &Registry::getBlock,
"get_item", &Registry::getItem,

View File

@ -80,7 +80,7 @@ LuaMod &ServerModLoader::registerMod(const std::string &name) {
m_mods.emplace(
std::piecewise_construct,
std::forward_as_tuple(name),
std::forward_as_tuple(name, m_registry, m_worldController)
std::forward_as_tuple(name, m_registry, m_worldController, m_players)
);
return m_mods.at(name);

View File

@ -32,14 +32,15 @@
#include "LuaMod.hpp"
class PlayerList;
class Registry;
class ScriptEngine;
class WorldController;
class ServerModLoader {
public:
ServerModLoader(ScriptEngine &scriptEngine, Registry &registry, WorldController &worldController)
: m_scriptEngine(scriptEngine), m_registry(registry), m_worldController(worldController) {}
ServerModLoader(ScriptEngine &scriptEngine, Registry &registry, WorldController &worldController, PlayerList &players)
: m_scriptEngine(scriptEngine), m_registry(registry), m_worldController(worldController), m_players(players) {}
void loadMods();
@ -49,6 +50,7 @@ class ServerModLoader {
ScriptEngine &m_scriptEngine;
Registry &m_registry;
WorldController &m_worldController;
PlayerList &m_players;
std::unordered_map<std::string, LuaMod> m_mods;
};

View File

@ -119,7 +119,7 @@ void LuaEntityLoader::spawnEntity(const std::string &entityID, const sol::table
}
ItemStack stack;
sol::optional<sol::table> itemStack = table["itemstack"];
sol::optional<sol::table> itemStack = table["item_stack"];
if (itemStack != sol::nullopt) {
stack.setItem(itemStack.value()[1]);
stack.setAmount(itemStack.value()[2].get_or(1));

View File

@ -0,0 +1,53 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner 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.
*
* OpenMiner 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 OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#ifndef ENTITYWRAPPER_HPP_
#define ENTITYWRAPPER_HPP_
#include <entt/entt.hpp>
#include "ItemStack.hpp"
#include "NetworkComponent.hpp"
#include "PositionComponent.hpp"
// This class is meant to be used ONLY in Lua or Lua-related C++ classes
class EntityWrapper {
public:
EntityWrapper(entt::entity id, entt::registry &registry)
: m_id(id), m_registry(registry) {}
entt::entity id() const { return m_id; }
PositionComponent *getPositionComponent() const { return m_registry.try_get<PositionComponent>(m_id); }
NetworkComponent *getNetworkComponent() const { return m_registry.try_get<NetworkComponent>(m_id); }
ItemStack *getItemStack() const { return m_registry.try_get<ItemStack>(m_id); }
private:
entt::entity m_id;
entt::registry &m_registry;
};
#endif // ENTITYWRAPPER_HPP_

View File

@ -27,6 +27,7 @@
#include <gk/core/Debug.hpp>
#include "CollisionController.hpp"
#include "EntityWrapper.hpp"
#include "ItemStack.hpp"
#include "LuaCallbackComponent.hpp"
#include "NetworkComponent.hpp"
@ -35,13 +36,14 @@
#include "ServerCommandHandler.hpp"
void CollisionController::update(entt::registry &registry) {
registry.view<PositionComponent, gk::DoubleBox, ItemStack, NetworkComponent, LuaCallbackComponent>().each([&](auto entity, auto &position, auto &box, auto &itemStack, auto &network, auto &luaCallbackComponent) {
registry.view<PositionComponent, gk::DoubleBox, LuaCallbackComponent>().each([&](auto id, auto &position, auto &box, auto &luaCallbackComponent) {
for (auto &it : m_players) {
if (it.second.dimension() == position.dimension) {
gk::DoubleBox hitbox = box + gk::Vector3d{position.x, position.y, position.z};
gk::DoubleBox playerHitbox = it.second.hitbox() + gk::Vector3d{it.second.x(), it.second.y(), it.second.z()};
if (hitbox.intersects(playerHitbox)) {
luaCallbackComponent.collisionCallback(itemStack, entity, network.entityID, it.second, registry, *m_server);
EntityWrapper entity{id, registry};
luaCallbackComponent.collisionCallback(entity, it.second, *m_server);
}
}
}

View File

@ -50,6 +50,7 @@ class WorldController {
ServerWorld &getWorld(u16 dimension) { return m_worldList.at(dimension); }
const ServerCommandHandler *server() const { return m_server; }
void setServer(ServerCommandHandler &server) { m_server = &server; }
private: