Working on entity Lua API.
This commit is contained in:
parent
675bdb112f
commit
5e6103d00d
@ -18,11 +18,11 @@ Adds a listener to a specific type of event.
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
```lua
|
```lua
|
||||||
openminer:add_listener(EventType.OnBlockPlaced, function(pos, player, world, client, server)
|
openminer:add_listener(EventType.OnBlockPlaced, function(pos, block, player, world, client, server)
|
||||||
server:send_chat_message(0, "Block placed at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
server:send_chat_message(0, "Block placed at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
||||||
end)
|
end)
|
||||||
|
|
||||||
openminer:add_listener(EventType.OnBlockDigged, function(pos, player, world, client, server)
|
openminer:add_listener(EventType.OnBlockDigged, function(pos, block, player, world, client, server)
|
||||||
server:send_chat_message(0, "Block digged at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
server:send_chat_message(0, "Block digged at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ end)
|
|||||||
|
|
||||||
Possible events:
|
Possible events:
|
||||||
|
|
||||||
- `OnBlockPlaced`: `funcion(pos, player, world, client, server)`
|
- `OnBlockPlaced`: `funcion(pos, block, player, world, client, server)`
|
||||||
- `OnBlockDigged`: `funcion(pos, player, world, client, server)`
|
- `OnBlockDigged`: `funcion(pos, block, player, world, client, server)`
|
||||||
- `OnBlockActivated`: `function(pos, block, player, world, client, server)`
|
- `OnBlockActivated`: `function(pos, block, player, world, client, server)`
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ dofile("trees.lua")
|
|||||||
dofile("biomes.lua")
|
dofile("biomes.lua")
|
||||||
dofile("dimensions.lua")
|
dofile("dimensions.lua")
|
||||||
|
|
||||||
-- openminer:add_listener(EventType.OnBlockPlaced, function(pos, player, world, client, server)
|
-- openminer:add_listener(EventType.OnBlockPlaced, function(pos, block, player, world, client, server)
|
||||||
-- server:send_chat_message(0, "Block placed at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
-- server:send_chat_message(0, "Block placed at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
||||||
-- end)
|
-- end)
|
||||||
|
|
||||||
-- openminer:add_listener(EventType.OnBlockDigged, function(pos, player, world, client, server)
|
-- openminer:add_listener(EventType.OnBlockDigged, function(pos, block, player, world, client, server)
|
||||||
-- server:send_chat_message(0, "Block digged at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
-- server:send_chat_message(0, "Block digged at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z .. " by Client" .. player:client_id(), client);
|
||||||
-- end)
|
-- end)
|
||||||
|
|
||||||
@ -141,3 +141,49 @@ function show_inventory(client, screen_width, screen_height, gui_scale)
|
|||||||
gui:show(client)
|
gui:show(client)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mod:entity {
|
||||||
|
id = "item_drop",
|
||||||
|
|
||||||
|
properties = {
|
||||||
|
visual = {
|
||||||
|
type = "inventorycube",
|
||||||
|
size = 0.25,
|
||||||
|
origin = {0.125, 0.125, 0.125},
|
||||||
|
},
|
||||||
|
|
||||||
|
is_rotatable = true,
|
||||||
|
|
||||||
|
animation = {
|
||||||
|
{
|
||||||
|
type = "rotation",
|
||||||
|
axis = {0, 0, 1},
|
||||||
|
angle = 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type = "translation",
|
||||||
|
delta = {0, 0, -0.0005},
|
||||||
|
min = -0.2,
|
||||||
|
max = 0,
|
||||||
|
loop = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hitbox = {0, 0, 0, 0.25, 0.25, 0.25},
|
||||||
|
},
|
||||||
|
|
||||||
|
on_collision = function(entity, other)
|
||||||
|
if other:type() == "player" then
|
||||||
|
other:inventory():add_item(entity:properties():itemstack())
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
openminer:add_listener(EventType.OnBlockDigged, function(pos, block, player, world, client, server)
|
||||||
|
mod:spawn_entity("item_drop", {
|
||||||
|
position = {pos.x, pos.y, pos.z},
|
||||||
|
dimension = world:dimension():id(),
|
||||||
|
|
||||||
|
itemstack = {block:string_id(), 1}
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
@ -117,6 +117,19 @@ Dimension &Registry::registerSerializedDimension(sf::Packet &packet) {
|
|||||||
return m_dimensions.back();
|
return m_dimensions.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entt::entity Registry::registerEntity(const std::string &stringID) {
|
||||||
|
auto it = m_entities.find(stringID);
|
||||||
|
if (it == m_entities.end()) {
|
||||||
|
entt::entity entity = m_entityRegistry.create();
|
||||||
|
m_entities.emplace(stringID, entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gkError() << "Redefinition of entity '" + stringID + "', keeping the first one";
|
||||||
|
|
||||||
|
return static_cast<entt::entity>(0);
|
||||||
|
}
|
||||||
|
|
||||||
const Block &Registry::getBlockFromStringID(const std::string &stringID) {
|
const Block &Registry::getBlockFromStringID(const std::string &stringID) {
|
||||||
if (stringID.empty()) return getBlock(0);
|
if (stringID.empty()) return getBlock(0);
|
||||||
auto it = m_blocksID.find(stringID);
|
auto it = m_blocksID.find(stringID);
|
||||||
@ -166,6 +179,21 @@ const Biome &Registry::getBiomeFromStringID(const std::string &stringID) {
|
|||||||
return getBiome(it->second);
|
return getBiome(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entt::entity Registry::getEntityFromStringID(const std::string &stringID) {
|
||||||
|
if (stringID.empty()) {
|
||||||
|
gkError() << "Failed to get entity from empty string ID";
|
||||||
|
return (entt::entity)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_entities.find(stringID);
|
||||||
|
if (it == m_entities.end()) {
|
||||||
|
gkError() << "Failed to get entity '" + stringID + "': Not found";
|
||||||
|
return (entt::entity)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
const Recipe *Registry::getRecipe(const Inventory &inventory) const {
|
const Recipe *Registry::getRecipe(const Inventory &inventory) const {
|
||||||
for (auto &recipe : m_recipes) {
|
for (auto &recipe : m_recipes) {
|
||||||
if (recipe->isMatching(inventory))
|
if (recipe->isMatching(inventory))
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <entt/entt.hpp>
|
||||||
|
|
||||||
#include "Biome.hpp"
|
#include "Biome.hpp"
|
||||||
#include "Block.hpp"
|
#include "Block.hpp"
|
||||||
#include "Dimension.hpp"
|
#include "Dimension.hpp"
|
||||||
@ -82,6 +84,9 @@ class Registry : public ISerializable {
|
|||||||
Dimension ®isterDimension(const std::string &stringID, const std::string &label);
|
Dimension ®isterDimension(const std::string &stringID, const std::string &label);
|
||||||
Dimension ®isterSerializedDimension(sf::Packet &packet);
|
Dimension ®isterSerializedDimension(sf::Packet &packet);
|
||||||
|
|
||||||
|
entt::registry &entityRegistry() { return m_entityRegistry; }
|
||||||
|
entt::entity registerEntity(const std::string &stringID);
|
||||||
|
|
||||||
const Block &getBlock(u16 id) const { return *m_blocks.at(id).get(); }
|
const Block &getBlock(u16 id) const { return *m_blocks.at(id).get(); }
|
||||||
const Item &getItem(u16 id) const { return m_items.at(id); }
|
const Item &getItem(u16 id) const { return m_items.at(id); }
|
||||||
const Sky &getSky(u16 id) const { return m_skies.at(id); }
|
const Sky &getSky(u16 id) const { return m_skies.at(id); }
|
||||||
@ -94,6 +99,7 @@ class Registry : public ISerializable {
|
|||||||
const Sky &getSkyFromStringID(const std::string &stringID);
|
const Sky &getSkyFromStringID(const std::string &stringID);
|
||||||
const Tree &getTreeFromStringID(const std::string &stringID);
|
const Tree &getTreeFromStringID(const std::string &stringID);
|
||||||
const Biome &getBiomeFromStringID(const std::string &stringID);
|
const Biome &getBiomeFromStringID(const std::string &stringID);
|
||||||
|
entt::entity getEntityFromStringID(const std::string &stringID);
|
||||||
|
|
||||||
const Recipe *getRecipe(const Inventory &inventory) const;
|
const Recipe *getRecipe(const Inventory &inventory) const;
|
||||||
|
|
||||||
@ -127,6 +133,10 @@ class Registry : public ISerializable {
|
|||||||
std::unordered_map<std::string, u16> m_biomesID;
|
std::unordered_map<std::string, u16> m_biomesID;
|
||||||
std::unordered_map<std::string, u16> m_dimensionsID;
|
std::unordered_map<std::string, u16> m_dimensionsID;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, entt::entity> m_entities;
|
||||||
|
|
||||||
|
entt::registry m_entityRegistry;
|
||||||
|
|
||||||
enum class DataType {
|
enum class DataType {
|
||||||
Block,
|
Block,
|
||||||
Item,
|
Item,
|
||||||
|
@ -44,6 +44,7 @@ class DrawableDef : public ISerializable {
|
|||||||
InventoryCubeDef &addInventoryCube();
|
InventoryCubeDef &addInventoryCube();
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
|
InventoryCubeDef &getInventoryCubeDef() { return m_cubes.back(); }
|
||||||
const InventoryCubeDef &getInventoryCubeDef() const { return m_cubes.back(); }
|
const InventoryCubeDef &getInventoryCubeDef() const { return m_cubes.back(); }
|
||||||
|
|
||||||
void serialize(sf::Packet &packet) const override;
|
void serialize(sf::Packet &packet) const override;
|
||||||
|
@ -65,9 +65,6 @@ class ServerApplication {
|
|||||||
gk::GameClock m_clock;
|
gk::GameClock m_clock;
|
||||||
gk::EventHandler *m_eventHandler = nullptr;
|
gk::EventHandler *m_eventHandler = nullptr;
|
||||||
|
|
||||||
ScriptEngine m_scriptEngine;
|
|
||||||
ServerModLoader m_modLoader{m_scriptEngine};
|
|
||||||
|
|
||||||
Registry m_registry;
|
Registry m_registry;
|
||||||
|
|
||||||
u16 m_port = 4242;
|
u16 m_port = 4242;
|
||||||
@ -75,6 +72,9 @@ class ServerApplication {
|
|||||||
WorldController m_worldController{m_registry, m_clock};
|
WorldController m_worldController{m_registry, m_clock};
|
||||||
PlayerList m_players;
|
PlayerList m_players;
|
||||||
|
|
||||||
|
ScriptEngine m_scriptEngine;
|
||||||
|
ServerModLoader m_modLoader{m_scriptEngine, m_registry, m_worldController};
|
||||||
|
|
||||||
Server m_server;
|
Server m_server;
|
||||||
ServerCommandHandler m_serverCommandHandler{m_scriptEngine, m_server, m_worldController, m_players, m_registry};
|
ServerCommandHandler m_serverCommandHandler{m_scriptEngine, m_server, m_worldController, m_players, m_registry};
|
||||||
};
|
};
|
||||||
|
@ -43,6 +43,7 @@ void LuaMod::commit() {
|
|||||||
case DefinitionType::Tree: m_biomeLoader.loadTree(it.second); break;
|
case DefinitionType::Tree: m_biomeLoader.loadTree(it.second); break;
|
||||||
case DefinitionType::Biome: m_biomeLoader.loadBiome(it.second); break;
|
case DefinitionType::Biome: m_biomeLoader.loadBiome(it.second); break;
|
||||||
case DefinitionType::Dimension: m_dimensionLoader.loadDimension(it.second); break;
|
case DefinitionType::Dimension: m_dimensionLoader.loadDimension(it.second); break;
|
||||||
|
case DefinitionType::Entity: m_entityLoader.loadEntity(it.second); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +63,8 @@ void LuaMod::initUsertype(sol::state &lua) {
|
|||||||
"sky", &LuaMod::registerSky,
|
"sky", &LuaMod::registerSky,
|
||||||
"tree", &LuaMod::registerTree,
|
"tree", &LuaMod::registerTree,
|
||||||
"biome", &LuaMod::registerBiome,
|
"biome", &LuaMod::registerBiome,
|
||||||
"dimension", &LuaMod::registerDimension
|
"dimension", &LuaMod::registerDimension,
|
||||||
|
"entity", &LuaMod::registerEntity
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,3 +100,11 @@ void LuaMod::registerDimension(const sol::table &table) {
|
|||||||
m_defs.emplace(DefinitionType::Dimension, table);
|
m_defs.emplace(DefinitionType::Dimension, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaMod::registerEntity(const sol::table &table) {
|
||||||
|
m_defs.emplace(DefinitionType::Entity, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaMod::spawnEntity(const std::string &entityID, const sol::table &table) {
|
||||||
|
m_entityLoader.spawnEntity(entityID, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -32,17 +32,19 @@
|
|||||||
#include "LuaBiomeLoader.hpp"
|
#include "LuaBiomeLoader.hpp"
|
||||||
#include "LuaBlockLoader.hpp"
|
#include "LuaBlockLoader.hpp"
|
||||||
#include "LuaDimensionLoader.hpp"
|
#include "LuaDimensionLoader.hpp"
|
||||||
|
#include "LuaEntityLoader.hpp"
|
||||||
#include "LuaItemLoader.hpp"
|
#include "LuaItemLoader.hpp"
|
||||||
#include "LuaRecipeLoader.hpp"
|
#include "LuaRecipeLoader.hpp"
|
||||||
#include "LuaSkyLoader.hpp"
|
#include "LuaSkyLoader.hpp"
|
||||||
|
|
||||||
|
class Registry;
|
||||||
|
class WorldController;
|
||||||
|
|
||||||
// This class is meant to be used ONLY in Lua
|
// This class is meant to be used ONLY in Lua
|
||||||
class LuaMod {
|
class LuaMod {
|
||||||
public:
|
public:
|
||||||
// FIXME: Check if this name has already been used
|
LuaMod(const std::string &id, Registry ®istry, WorldController &worldController)
|
||||||
// Check if this name matches [a-zA-Z0-9]+
|
: m_id(id), m_registry(registry), m_worldController(worldController) {}
|
||||||
// Check if this name != "group"
|
|
||||||
LuaMod(const std::string &id) : m_id(id) {}
|
|
||||||
|
|
||||||
void commit();
|
void commit();
|
||||||
|
|
||||||
@ -61,6 +63,9 @@ class LuaMod {
|
|||||||
void registerTree(const sol::table &table);
|
void registerTree(const sol::table &table);
|
||||||
void registerBiome(const sol::table &table);
|
void registerBiome(const sol::table &table);
|
||||||
void registerDimension(const sol::table &table);
|
void registerDimension(const sol::table &table);
|
||||||
|
void registerEntity(const sol::table &table);
|
||||||
|
|
||||||
|
void spawnEntity(const std::string &entityID, const sol::table &table);
|
||||||
|
|
||||||
enum class DefinitionType {
|
enum class DefinitionType {
|
||||||
Block,
|
Block,
|
||||||
@ -71,18 +76,24 @@ class LuaMod {
|
|||||||
Tree,
|
Tree,
|
||||||
Biome,
|
Biome,
|
||||||
Dimension,
|
Dimension,
|
||||||
|
Entity,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::queue<std::pair<DefinitionType, sol::table>> m_defs;
|
std::queue<std::pair<DefinitionType, sol::table>> m_defs;
|
||||||
|
|
||||||
std::string m_id;
|
std::string m_id;
|
||||||
|
|
||||||
|
// TODO: Add registry instance to loaders in order to avoid using singleton
|
||||||
|
Registry &m_registry;
|
||||||
|
WorldController &m_worldController;
|
||||||
|
|
||||||
LuaBlockLoader m_blockLoader{*this};
|
LuaBlockLoader m_blockLoader{*this};
|
||||||
LuaItemLoader m_itemLoader{*this};
|
LuaItemLoader m_itemLoader{*this};
|
||||||
LuaRecipeLoader m_recipeLoader;
|
LuaRecipeLoader m_recipeLoader;
|
||||||
LuaSkyLoader m_skyLoader{*this};
|
LuaSkyLoader m_skyLoader{*this};
|
||||||
LuaBiomeLoader m_biomeLoader{*this};
|
LuaBiomeLoader m_biomeLoader{*this};
|
||||||
LuaDimensionLoader m_dimensionLoader{*this};
|
LuaDimensionLoader m_dimensionLoader{*this};
|
||||||
|
LuaEntityLoader m_entityLoader{*this, m_worldController};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LUAMOD_HPP_
|
#endif // LUAMOD_HPP_
|
||||||
|
@ -77,7 +77,7 @@ LuaMod &ServerModLoader::registerMod(const std::string &name) {
|
|||||||
if (it != m_mods.end())
|
if (it != m_mods.end())
|
||||||
throw std::runtime_error("The mod '" + name + "' has already been loaded. Mod name must be unique.");
|
throw std::runtime_error("The mod '" + name + "' has already been loaded. Mod name must be unique.");
|
||||||
|
|
||||||
m_mods.emplace(name, name);
|
m_mods.emplace(name, LuaMod{name, m_registry, m_worldController});
|
||||||
|
|
||||||
return m_mods.at(name);
|
return m_mods.at(name);
|
||||||
}
|
}
|
||||||
|
@ -32,11 +32,14 @@
|
|||||||
|
|
||||||
#include "LuaMod.hpp"
|
#include "LuaMod.hpp"
|
||||||
|
|
||||||
|
class Registry;
|
||||||
class ScriptEngine;
|
class ScriptEngine;
|
||||||
|
class WorldController;
|
||||||
|
|
||||||
class ServerModLoader {
|
class ServerModLoader {
|
||||||
public:
|
public:
|
||||||
ServerModLoader(ScriptEngine &scriptEngine) : m_scriptEngine(scriptEngine) {}
|
ServerModLoader(ScriptEngine &scriptEngine, Registry ®istry, WorldController &worldController)
|
||||||
|
: m_scriptEngine(scriptEngine), m_registry(registry), m_worldController(worldController) {}
|
||||||
|
|
||||||
void loadMods();
|
void loadMods();
|
||||||
|
|
||||||
@ -44,6 +47,8 @@ class ServerModLoader {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ScriptEngine &m_scriptEngine;
|
ScriptEngine &m_scriptEngine;
|
||||||
|
Registry &m_registry;
|
||||||
|
WorldController &m_worldController;
|
||||||
|
|
||||||
std::unordered_map<std::string, LuaMod> m_mods;
|
std::unordered_map<std::string, LuaMod> m_mods;
|
||||||
};
|
};
|
||||||
|
162
source/server/lua/loader/LuaEntityLoader.cpp
Normal file
162
source/server/lua/loader/LuaEntityLoader.cpp
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* =====================================================================================
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* =====================================================================================
|
||||||
|
*/
|
||||||
|
#include <gk/core/Debug.hpp>
|
||||||
|
|
||||||
|
#include "AnimationComponent.hpp"
|
||||||
|
#include "DrawableDef.hpp"
|
||||||
|
#include "LuaEntityLoader.hpp"
|
||||||
|
#include "LuaMod.hpp"
|
||||||
|
#include "NetworkComponent.hpp"
|
||||||
|
#include "PositionComponent.hpp"
|
||||||
|
#include "Registry.hpp"
|
||||||
|
#include "RotationComponent.hpp"
|
||||||
|
|
||||||
|
void LuaEntityLoader::loadEntity(const sol::table &table) const {
|
||||||
|
std::string stringID = m_mod.id() + ":" + table["id"].get<std::string>();
|
||||||
|
|
||||||
|
entt::registry ®istry = Registry::getInstance().entityRegistry();
|
||||||
|
entt::entity entity = Registry::getInstance().registerEntity(stringID);
|
||||||
|
|
||||||
|
// TODO: Create a struct to store these functions
|
||||||
|
sol::unsafe_function onSpawn = table["on_spawn"];
|
||||||
|
sol::unsafe_function onCollision = table["on_collision"];
|
||||||
|
|
||||||
|
sol::optional<sol::table> properties = table["properties"];
|
||||||
|
if (properties != sol::nullopt) {
|
||||||
|
sol::optional<sol::table> visual = properties.value()["visual"];
|
||||||
|
if (visual != sol::nullopt) {
|
||||||
|
std::string type = visual.value()["type"];
|
||||||
|
if (type == "inventorycube") {
|
||||||
|
auto &drawable = registry.emplace<DrawableDef>(entity);
|
||||||
|
auto &cube = drawable.addInventoryCube();
|
||||||
|
|
||||||
|
cube.size = visual.value()["size"].get_or(1.0f);
|
||||||
|
|
||||||
|
sol::optional<sol::table> origin = visual.value()["origin"];
|
||||||
|
if (origin != sol::nullopt) {
|
||||||
|
cube.origin = {origin.value()[1], origin.value()[2], origin.value()[3]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gkError() << "For entity '" + stringID + "': Visual type '" + type + "' unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isRotatable = properties.value()["is_rotatable"].get_or(false);
|
||||||
|
if (isRotatable)
|
||||||
|
registry.emplace<RotationComponent>(entity);
|
||||||
|
|
||||||
|
sol::optional<sol::table> animation = properties.value()["animation"];
|
||||||
|
if (animation != sol::nullopt) {
|
||||||
|
auto &animationComponent = registry.emplace<AnimationComponent>(entity);
|
||||||
|
for (auto &it : animation.value()) {
|
||||||
|
sol::table anim = it.second.as<sol::table>();
|
||||||
|
std::string type = anim["type"];
|
||||||
|
if (type == "rotation") {
|
||||||
|
sol::table axis = anim["axis"];
|
||||||
|
animationComponent.addRotation(axis[1], axis[2], axis[3], anim["angle"]);
|
||||||
|
}
|
||||||
|
else if (type == "translation") {
|
||||||
|
sol::table delta = anim["delta"];
|
||||||
|
animationComponent.addTranslation(delta[1], delta[2], delta[3], anim["min"], anim["max"], anim["loop"].get_or(true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gkError() << "For entity '" + stringID + "': Animation type '" + type + "' unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::optional<sol::table> hitboxTable = properties.value()["hitbox"];
|
||||||
|
if (hitboxTable != sol::nullopt) {
|
||||||
|
registry.emplace<gk::FloatBox>(entity,
|
||||||
|
hitboxTable.value()[1], hitboxTable.value()[2], hitboxTable.value()[3],
|
||||||
|
hitboxTable.value()[4], hitboxTable.value()[5], hitboxTable.value()[6]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "WorldController.hpp"
|
||||||
|
|
||||||
|
void LuaEntityLoader::spawnEntity(const std::string &entityID, const sol::table &table) const {
|
||||||
|
gk::Vector3f pos;
|
||||||
|
u16 dim;
|
||||||
|
|
||||||
|
sol::optional<sol::table> position = table["position"];
|
||||||
|
sol::optional<u16> dimension = table["dimension"];
|
||||||
|
if (position != sol::nullopt && dimension != sol::nullopt) {
|
||||||
|
pos = {position.value()[1], position.value()[2], position.value()[3]};
|
||||||
|
dim = dimension.value();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gkError() << "In mod '" + m_mod.id() + "': Cannot spawn entity '" + entityID + "' without a position and a dimension";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack stack;
|
||||||
|
sol::optional<sol::table> itemStack = table["itemstack"];
|
||||||
|
if (itemStack != sol::nullopt) {
|
||||||
|
stack.setItem(itemStack.value()[1]);
|
||||||
|
stack.setAmount(itemStack.value()[2].get_or(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create entity copy here
|
||||||
|
entt::registry ®istry = Registry::getInstance().entityRegistry();
|
||||||
|
entt::entity entityModel = Registry::getInstance().getEntityFromStringID(entityID);
|
||||||
|
if (entityModel != (entt::entity)0) {
|
||||||
|
ServerWorld &world = m_worldController.getWorld(dim);
|
||||||
|
entt::registry &sceneRegistry = world.scene().registry();
|
||||||
|
entt::entity entity = sceneRegistry.create();
|
||||||
|
|
||||||
|
sceneRegistry.emplace<PositionComponent>(entity, pos.x, pos.y, pos.z, dim);
|
||||||
|
sceneRegistry.emplace<NetworkComponent>(entity, entity);
|
||||||
|
|
||||||
|
if (registry.has<RotationComponent>(entityModel))
|
||||||
|
sceneRegistry.emplace<RotationComponent>(entity);
|
||||||
|
|
||||||
|
auto *drawable = registry.try_get<DrawableDef>(entityModel);
|
||||||
|
if (drawable) {
|
||||||
|
auto &drawableDef = sceneRegistry.emplace<DrawableDef>(entity, *drawable);
|
||||||
|
if (stack.amount()) {
|
||||||
|
auto &cube = drawableDef.getInventoryCubeDef();
|
||||||
|
cube.blockID = stack.item().stringID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *animation = registry.try_get<AnimationComponent>(entityModel);
|
||||||
|
if (animation)
|
||||||
|
sceneRegistry.emplace<AnimationComponent>(entity, *animation);
|
||||||
|
|
||||||
|
auto *hitbox = registry.try_get<gk::FloatBox>(entityModel);
|
||||||
|
if (hitbox)
|
||||||
|
sceneRegistry.emplace<gk::FloatBox>(entity, *hitbox);
|
||||||
|
|
||||||
|
if (stack.amount())
|
||||||
|
sceneRegistry.emplace<ItemStack>(entity, stack);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gkError() << "In mod '" + m_mod.id() + "': Cannot find entity with id '" + entityID + "'";
|
||||||
|
}
|
||||||
|
|
48
source/server/lua/loader/LuaEntityLoader.hpp
Normal file
48
source/server/lua/loader/LuaEntityLoader.hpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* =====================================================================================
|
||||||
|
*
|
||||||
|
* 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 LUAENTITYLOADER_HPP_
|
||||||
|
#define LUAENTITYLOADER_HPP_
|
||||||
|
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
class LuaMod;
|
||||||
|
class WorldController;
|
||||||
|
|
||||||
|
class LuaEntityLoader {
|
||||||
|
public:
|
||||||
|
LuaEntityLoader(LuaMod &mod, WorldController &worldController)
|
||||||
|
: m_mod(mod), m_worldController(worldController) {}
|
||||||
|
|
||||||
|
void loadEntity(const sol::table &table) const;
|
||||||
|
void spawnEntity(const std::string &entityID, const sol::table &table) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LuaMod &m_mod;
|
||||||
|
WorldController &m_worldController;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LUAENTITYLOADER_HPP_
|
@ -264,8 +264,9 @@ void ServerCommandHandler::setupCallbacks() {
|
|||||||
ServerWorld &world = getWorldForClient(client.id);
|
ServerWorld &world = getWorldForClient(client.id);
|
||||||
world.setData(x, y, z, block >> 16);
|
world.setData(x, y, z, block >> 16);
|
||||||
world.setBlock(x, y, z, block & 0xffff);
|
world.setBlock(x, y, z, block & 0xffff);
|
||||||
|
const Block &blockDef = Registry::getInstance().getBlock(block & 0xffff);
|
||||||
|
|
||||||
m_scriptEngine.luaCore().onEvent(LuaEventType::OnBlockPlaced, glm::ivec3{x, y, z}, *player, world, client, *this);
|
m_scriptEngine.luaCore().onEvent(LuaEventType::OnBlockPlaced, glm::ivec3{x, y, z}, blockDef, *player, world, client, *this);
|
||||||
|
|
||||||
Network::Packet answer;
|
Network::Packet answer;
|
||||||
answer << Network::Command::BlockUpdate << x << y << z << block;
|
answer << Network::Command::BlockUpdate << x << y << z << block;
|
||||||
@ -282,10 +283,11 @@ void ServerCommandHandler::setupCallbacks() {
|
|||||||
packet >> x >> y >> z;
|
packet >> x >> y >> z;
|
||||||
|
|
||||||
ServerWorld &world = getWorldForClient(client.id);
|
ServerWorld &world = getWorldForClient(client.id);
|
||||||
world.onBlockDigged(x, y, z, Registry::getInstance().getBlock(world.getBlock(x, y, z)), *player);
|
const Block &blockDef = Registry::getInstance().getBlock(world.getBlock(x, y, z));
|
||||||
|
world.onBlockDigged(x, y, z, blockDef, *player);
|
||||||
world.setBlock(x, y, z, 0);
|
world.setBlock(x, y, z, 0);
|
||||||
|
|
||||||
m_scriptEngine.luaCore().onEvent(LuaEventType::OnBlockDigged, glm::ivec3{x, y, z}, *player, world, client, *this);
|
m_scriptEngine.luaCore().onEvent(LuaEventType::OnBlockDigged, glm::ivec3{x, y, z}, blockDef, *player, world, client, *this);
|
||||||
|
|
||||||
Network::Packet answer;
|
Network::Packet answer;
|
||||||
answer << Network::Command::BlockUpdate << x << y << z << u32(0);
|
answer << Network::Command::BlockUpdate << x << y << z << u32(0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user