From 1485c15808454d5ecdbe9376f673f1236c73f4ba Mon Sep 17 00:00:00 2001 From: Quentin Bazin Date: Mon, 13 Jul 2020 06:54:05 +0200 Subject: [PATCH] [Lua API] Added item definition property 'effective_on'. Fixed #143. --- docs/lua-api-item.md | 13 +++++++++++ mods/default/blocks.lua | 27 +++++++++++++++++++++- mods/default/blocks/door.lua | 5 +++- mods/default/blocks/workbench.lua | 3 +++ mods/default/tools.lua | 9 ++++++++ source/client/hud/BlockCursor.cpp | 10 +++++++- source/common/inventory/Item.cpp | 6 +++-- source/common/inventory/Item.hpp | 5 ++++ source/common/world/BlockState.hpp | 4 ++-- source/server/lua/loader/LuaItemLoader.cpp | 12 ++++++++++ 10 files changed, 87 insertions(+), 7 deletions(-) diff --git a/docs/lua-api-item.md b/docs/lua-api-item.md index 1f7751a47..35082cb3a 100644 --- a/docs/lua-api-item.md +++ b/docs/lua-api-item.md @@ -12,6 +12,18 @@ mod:item { ## Attributes +### `effective_on` + +List of groups or block string IDs on which that item is effective when mining. + +Example: +```lua +effective_on = { + "group:om_material_dirt", + "group:om_material_sand" +} +``` + ### `groups` Groups of the item. They can be used in recipes, and can also filter Lua-defined inventory widgets. @@ -30,6 +42,7 @@ Engine groups always start with `om_` prefix. If you create your own groups, ple Available engine groups: - `om_fuel`: used in `default:furnace` and `MouseWidgetItem`, the value represents the burn time +- `om_material_dirt/sand/wood/stone`: these groups are not used in the engine, but it's nice to use them if you can ### `harvest_capability` diff --git a/mods/default/blocks.lua b/mods/default/blocks.lua index db7f9e148..ca0560d64 100644 --- a/mods/default/blocks.lua +++ b/mods/default/blocks.lua @@ -29,6 +29,9 @@ mod:block { id = "dirt", name = "Dirt", tiles = "dirt.png", + groups = { + om_material_dirt = 1, + }, } mod:block { @@ -45,6 +48,9 @@ mod:block { name = "Grass", tiles = {"grass_block_top.png", "dirt.png", "grass_block_side.png"}, color_multiplier = {129, 191, 91, 255}, + groups = { + om_material_dirt = 1, + }, item_drop = { id = mod:id()..":dirt", @@ -68,6 +74,9 @@ mod:block { id = "oak_wood", name = "Oak Wood", tiles = {"oak_log_top.png", "oak_log.png"}, + groups = { + om_material_wood = 1, + } } mod:block { @@ -86,6 +95,9 @@ mod:block { id = "sand", name = "Sand", tiles = "sand.png", + groups = { + om_material_sand = 1 + } } mod:block { @@ -130,6 +142,7 @@ mod:block { hardness = 1, groups = { + om_material_wood = 1, default_planks = 1 } } @@ -198,6 +211,9 @@ mod:block { id = "oak_slab", name = "Oak Wood Slab", tiles = "oak_planks.png", + groups = { + om_material_wood = 1, + }, draw_type = "boundingbox", is_opaque = false, @@ -238,6 +254,9 @@ mod:block { id = "soul_sand", name = "Soul Sand", tiles = "soul_sand.png", + groups = { + om_material_sand = 1 + } } mod:block { @@ -257,6 +276,7 @@ mod:block { id = "cactus", name = "Cactus", tiles = {"cactus_top.png", "cactus_bottom.png", "cactus_side.png"}, + hardness = 0, draw_type = "cactus", bounding_box = {1/16, 1/16, 0, 14/16, 14/16, 1}; @@ -318,7 +338,6 @@ mod:block { id = "redstone_lamp", name = "Redstone Lamp", tiles = "redstone_lamp_off.png", - harvest_requirements = 1, states = { { is_light_source = true, tiles = "redstone_lamp_on.png" } @@ -335,6 +354,9 @@ mod:block { name = "Farmland", tiles = {"farmland_dry.png", "dirt.png", "dirt.png"}, is_opaque = false, + groups = { + om_material_dirt = 1, + }, states = { { alt_tiles = {"farmland_wet.png", "dirt.png", "dirt.png"} }, @@ -349,6 +371,9 @@ mod:block { name = "Grass Path", tiles = {"grass_path_top.png", "dirt.png", "grass_path_side.png"}, is_opaque = false, + groups = { + om_material_dirt = 1, + }, draw_type = "boundingbox", bounding_box = {0, 0, 0, 1, 1, 15 / 16}, diff --git a/mods/default/blocks/door.lua b/mods/default/blocks/door.lua index ecd9eab44..09b95beea 100644 --- a/mods/default/blocks/door.lua +++ b/mods/default/blocks/door.lua @@ -47,7 +47,10 @@ mod:block { name = "Wooden Door", tiles = "door_wood_upper.png", inventory_image = "door_wood.png", - groups = {ci_ignore = 1}, + groups = { + ci_ignore = 1, + om_material_wood = 1 + }, is_rotatable = true, is_opaque = false, diff --git a/mods/default/blocks/workbench.lua b/mods/default/blocks/workbench.lua index 20912606e..0292f7e65 100644 --- a/mods/default/blocks/workbench.lua +++ b/mods/default/blocks/workbench.lua @@ -30,6 +30,9 @@ mod:block { id = "workbench", name = "Workbench", tiles = {"crafting_table_top.png", "crafting_table_top.png", "crafting_table_front.png", "crafting_table_side.png"}, + groups = { + om_material_wood = 1 + }, hardness = 1, harvest_requirements = 4, diff --git a/mods/default/tools.lua b/mods/default/tools.lua index ad1009453..618bae460 100644 --- a/mods/default/tools.lua +++ b/mods/default/tools.lua @@ -47,11 +47,20 @@ function register_tool(name, material, mining_speed, harvest_capability) end end elseif name == "shovel" then + tool_def.effective_on = { + "group:om_material_dirt", + "group:om_material:sand" + } + tool_def.on_item_activated = function(pos, block, player, world, client, server, screen_width, screen_height, gui_scale) if block:string_id() == "default:grass" then world:set_block_from_str(pos.x, pos.y, pos.z, "default:grass_path") end end + elseif name == "axe" then + tool_def.effective_on = { + "group:om_material_wood" + } end mod:item(tool_def) diff --git a/source/client/hud/BlockCursor.cpp b/source/client/hud/BlockCursor.cpp index 6f23c3a97..53da58a78 100644 --- a/source/client/hud/BlockCursor.cpp +++ b/source/client/hud/BlockCursor.cpp @@ -160,7 +160,15 @@ void BlockCursor::update(const Hotbar &hotbar) { m_currentTool = ¤tStack; } else { - timeToBreak = m_currentBlock->timeToBreak(currentStack.item().harvestCapability(), currentStack.item().miningSpeed()); + bool isEffective = false; + for (auto &it : currentStack.item().effectiveOn()) { + if (m_currentBlock->block().hasGroup(it)) { + isEffective = true; + break; + } + } + + timeToBreak = m_currentBlock->timeToBreak(currentStack.item().harvestCapability(), currentStack.item().miningSpeed(), isEffective); if (ticks > m_animationStart + timeToBreak * 1000) { m_world.setBlock(m_selectedBlock.x, m_selectedBlock.y, m_selectedBlock.z, 0); diff --git a/source/common/inventory/Item.cpp b/source/common/inventory/Item.cpp index 55aae0504..fff575348 100644 --- a/source/common/inventory/Item.cpp +++ b/source/common/inventory/Item.cpp @@ -37,12 +37,14 @@ Item::Item(u32 id, const TilesDef &tiles, const std::string &stringID, const std void Item::serialize(sf::Packet &packet) const { packet << m_id << m_tiles << m_stringID << m_label << m_isBlock - << m_miningSpeed << m_harvestCapability << m_groups << m_canBeActivated; + << m_miningSpeed << m_harvestCapability << m_groups << m_canBeActivated + << m_effectiveOn; } void Item::deserialize(sf::Packet &packet) { packet >> m_id >> m_tiles >> m_stringID >> m_label >> m_isBlock - >> m_miningSpeed >> m_harvestCapability >> m_groups >> m_canBeActivated; + >> m_miningSpeed >> m_harvestCapability >> m_groups >> m_canBeActivated + >> m_effectiveOn; } // Please update 'docs/lua-api-cpp.md' if you change this diff --git a/source/common/inventory/Item.hpp b/source/common/inventory/Item.hpp index 739527504..851a8d1ca 100644 --- a/source/common/inventory/Item.hpp +++ b/source/common/inventory/Item.hpp @@ -73,6 +73,9 @@ class Item : public gk::ISerializable { bool canBeActivated() const { return m_canBeActivated; } + const std::vector &effectiveOn() const { return m_effectiveOn; } + void addEffectiveBlock(const std::string &blockID) { m_effectiveOn.emplace_back(blockID); } + static void initUsertype(sol::state &lua); protected: @@ -91,6 +94,8 @@ class Item : public gk::ISerializable { float m_miningSpeed = 1; std::unordered_map m_groups; + + std::vector m_effectiveOn; }; #endif // ITEM_HPP_ diff --git a/source/common/world/BlockState.hpp b/source/common/world/BlockState.hpp index 04235fcee..4c1327cf5 100644 --- a/source/common/world/BlockState.hpp +++ b/source/common/world/BlockState.hpp @@ -92,8 +92,8 @@ class BlockState : public gk::ISerializable { u16 id() const { return m_id; } - float timeToBreak(u8 harvestCapability, float miningSpeed) const { - if ((harvestRequirements() & harvestCapability) || (harvestCapability == 0 && harvestRequirements() == 0)) + float timeToBreak(u8 harvestCapability, float miningSpeed, bool isEffective) const { + if (isEffective || (harvestRequirements() & harvestCapability) || (harvestCapability == 0 && harvestRequirements() == 0)) return 1.5 * m_hardness / miningSpeed; else return 5 * m_hardness; diff --git a/source/server/lua/loader/LuaItemLoader.cpp b/source/server/lua/loader/LuaItemLoader.cpp index b1cce9517..54b4ae25f 100644 --- a/source/server/lua/loader/LuaItemLoader.cpp +++ b/source/server/lua/loader/LuaItemLoader.cpp @@ -54,5 +54,17 @@ void LuaItemLoader::loadItem(const sol::table &table) const { else gkError() << "For item" << stringID << ": 'groups' should be a table"; } + + sol::object effectiveOnObject = table["effective_on"]; + if (effectiveOnObject.valid()) { + if (effectiveOnObject.get_type() == sol::type::table) { + sol::table effectiveOnTable = effectiveOnObject.as(); + for (auto &effectiveOnObject : effectiveOnTable) { + item.addEffectiveBlock(effectiveOnObject.second.as()); + } + } + else + gkError() << "For item" << stringID << ": 'effective_on' should be a table"; + } }