diff options
author | Elias Fleckenstein <eliasfleckenstein@web.de> | 2020-10-19 13:09:38 +0200 |
---|---|---|
committer | Elias Fleckenstein <eliasfleckenstein@web.de> | 2020-10-19 13:09:38 +0200 |
commit | f1ff05bf5932a7825509dbe896e60183a96a6d36 (patch) | |
tree | 73f2e361a7fd8010345880071aa29f0495171879 | |
parent | 35da7306dcd07fd43252468cdf71c9d8c09faeeb (diff) | |
download | dragonfireclient-f1ff05bf5932a7825509dbe896e60183a96a6d36.tar.xz |
Added ThroughWalls, InventoryActions API and AutoTotem
-rw-r--r-- | builtin/client/cheats/combat.lua | 72 | ||||
-rw-r--r-- | builtin/client/cheats/init.lua | 2 | ||||
-rw-r--r-- | builtin/client/cheats/inventory.lua | 8 | ||||
-rw-r--r-- | builtin/client/util.lua | 19 | ||||
-rw-r--r-- | doc/client_lua_api.txt | 46 | ||||
-rw-r--r-- | src/client/game.cpp | 2 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 2 | ||||
-rw-r--r-- | src/environment.cpp | 6 | ||||
-rw-r--r-- | src/raycast.cpp | 5 | ||||
-rw-r--r-- | src/raycast.h | 3 | ||||
-rw-r--r-- | src/script/lua_api/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/script/lua_api/l_inventoryaction.cpp | 216 | ||||
-rw-r--r-- | src/script/lua_api/l_inventoryaction.h | 72 | ||||
-rw-r--r-- | src/script/scripting_client.cpp | 2 |
14 files changed, 408 insertions, 48 deletions
diff --git a/builtin/client/cheats/combat.lua b/builtin/client/cheats/combat.lua index 25aaaec34..b497c6c1b 100644 --- a/builtin/client/cheats/combat.lua +++ b/builtin/client/cheats/combat.lua @@ -1,47 +1,57 @@ local placed_crystal local switched_to_totem = 0 local used_sneak = true +local totem_move_action = InventoryAction("move") +totem_move_action:to("current_player", "main", 8) core.register_globalstep(function(dtime) - if not minetest.settings:get_bool("crystal_pvp") then return end local player = core.localplayer if not player then return end local control = player:get_control() local pointed = core.get_pointed_thing() local item = player:get_wielded_item():get_name() - if placed_crystal then - if core.switch_to_item("mobs_mc:totem") then - switched_to_totem = 5 - end - placed_crystal = false - elseif switched_to_totem > 0 then - if item ~= "mobs_mc:totem" then - switched_to_totem = 0 - elseif pointed and pointed.type == "object" then - pointed.ref:punch() - switched_to_totem = 0 + if core.settings:get_bool("crystal_pvp") then + if placed_crystal then + if core.switch_to_item("mobs_mc:totem") then + switched_to_totem = 5 + end + placed_crystal = false + elseif switched_to_totem > 0 then + if item ~= "mobs_mc:totem" then + switched_to_totem = 0 + elseif pointed and pointed.type == "object" then + pointed.ref:punch() + switched_to_totem = 0 + else + switched_to_totem = switched_to_totem + end + elseif control.RMB and item == "mcl_end:crystal" then + placed_crystal = true + elseif control.sneak then + if pointed and pointed.type == "node" and not used_sneak then + local pos = core.get_pointed_thing_position(pointed) + local node = core.get_node_or_nil(pos) + if node and (node.name == "mcl_core:obsidian" or node.name == "mcl_core:bedrock") then + core.switch_to_item("mcl_end:crystal") + core.place_node(pos) + placed_crystal = true + end + end + used_sneak = true else - switched_to_totem = switched_to_totem + used_sneak = false end - elseif control.RMB and item == "mcl_end:crystal" then - placed_crystal = true - elseif control.sneak then - if used_sneak then - core.switch_to_item("mobs_mc:totem") - return - end - core.switch_to_item("mcl_end:crystal") - if pointed and pointed.type == "node" then - local pos = core.get_pointed_thing_position(pointed) - local node = core.get_node_or_nil(pos) - if node and (node.name == "mcl_core:obsidian" or node.name == "mcl_core:bedrock") then - core.place_node(pos) - placed_crystal = true + end + + if core.settings:get_bool("autototem") then + local totem_stack = core.get_inventory("current_player").main[9] + if totem_stack and totem_stack:get_name() ~= "mobs_mc:totem" then + local totem_index = core.find_item("mobs_mc:totem") + if totem_index then + totem_move_action:from("current_player", "main", totem_index - 1) + totem_move_action:apply() + player:set_wield_index(8) end end - used_sneak = true - else - used_sneak = false end end) - diff --git a/builtin/client/cheats/init.lua b/builtin/client/cheats/init.lua index cdeae78c8..a7be83cee 100644 --- a/builtin/client/cheats/init.lua +++ b/builtin/client/cheats/init.lua @@ -5,6 +5,8 @@ core.cheats = { ["FastHit"] = "spamclick", ["AttachmentFloat"] = "float_above_parent", ["CrystalPvP"] = "crystal_pvp", + ["AutoTotem"] = "autototem", + ["ThroughWalls"] = "dont_point_nodes", }, ["Movement"] = { ["Freecam"] = "freecam", diff --git a/builtin/client/cheats/inventory.lua b/builtin/client/cheats/inventory.lua index d12052d7c..faa7d1c0e 100644 --- a/builtin/client/cheats/inventory.lua +++ b/builtin/client/cheats/inventory.lua @@ -1,5 +1,6 @@ local elapsed_time = 0 local tick_time = 0.05 +local drop_action = InventoryAction("drop") core.register_globalstep(function(dtime) -- AutoEject @@ -9,11 +10,8 @@ core.register_globalstep(function(dtime) local inventory = core.get_inventory("current_player") for index, stack in pairs(inventory.main) do if table.indexof(list, stack:get_name()) ~= -1 then - local old_index = player:get_wield_index() - player:set_wield_index(index - 1) - core.drop_selected_item() - player:set_wield_index(old_index) - return + drop_action:from("current_player", "main", index - 1) + drop_action:apply() end end end diff --git a/builtin/client/util.lua b/builtin/client/util.lua index 4a6a72d72..d61b547c6 100644 --- a/builtin/client/util.lua +++ b/builtin/client/util.lua @@ -21,20 +21,27 @@ function core.parse_relative_pos(param) return success, pos end -function core.switch_to_item(item) +function core.find_item(item) for index, stack in ipairs(core.get_inventory("current_player").main) do if stack:get_name() == item then - core.localplayer:set_wield_index(index - 1) - return true + return index end end - return false +end + +function core.switch_to_item(item) + local i = core.find_item(item) + if i then + core.localplayer:set_wield_index(i - 1) + return true + else + return false + end end function core.get_pointed_thing() local pos = core.camera:get_pos() local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 5)) - local ray = core.raycast(pos, pos2, true, true) - + local ray = core.raycast(pos, pos2, true, core.settings:get_bool("point_liquids") or core.get_item_def(core.localplayer:get_wielded_item():get_name()).liquids_pointable) return ray:next() end diff --git a/doc/client_lua_api.txt b/doc/client_lua_api.txt index 735173580..50c33940e 100644 --- a/doc/client_lua_api.txt +++ b/doc/client_lua_api.txt @@ -1012,6 +1012,9 @@ Passed to `HTTPApiTable.fetch` callback. Returned by * e.g. minetest.set_keypress("jump", true) will cause te player to jump until minetest.set_keypress("jump", false) is called or the player presses & releases the space bar himself * `minetest.get_inventory(location)` * Returns the inventory at location +* `minetest.find_item(item)` + * finds and an item in the inventory + * returns index on success or nil if item is not found * `minetest.switch_to_item(item)` * `item` is an Itemstring * searches to item in inventory, sets the wield index to it if found @@ -1706,3 +1709,46 @@ Same as `image`, but does not accept a `position`; the position is instead deter -- ^ Uses texture (string) } +### InventoryAction +A reference to a C++ InventoryAction. You can move, drop and craft items in all accessible inventories using InventoryActions. + +#### methods + +* `InventoryAction(type)`: + * creates a new InventoryAction + * type is on of "move", "drop", or "craft", else returns nil +* `apply()`: + * applies the InventoryAction (InventoryActions can be applied multible times) +* `from(inventorylocation, listname, stack)` + * this is valid for move or drop actions + * when `apply()` is called items are moved / dropped from `listname` `inventorylocation` in` at `stack` +* `to(inventorylocation, listname, stack)` + * this is valid for move actions + * when `apply()` is called items are moved to `listname` in`inventorylocation` at `stack` +* `craft(inventoryaction)` + * this is valid for craft actions + * when `apply()` is called a craft event for this inventory will be triggered +* `set_count(count)` + * this is valid for all actions + * it specifies how many items to drop / craft / move + * `0` means move all items + * default count: `0` + +#### example + `local move_act = InventoryAction("move") + move_act:from("current_player", "main", 0) + move_act:to("current_player", "craft", 0) + move_act:set_count(1) + local craft_act = InventoryAction("craft") + craft_act:craft("current_player") + local drop_act = InventoryAction("drop") + drop_act:from("current_player", "craft", 0) + move_act:apply() + craft_act:apply() + drop_act:apply() + ` + * e.g. In first hotbar slot there are tree logs: Move one to craft field, then craft wood out of it and immediately drop it + + + + diff --git a/src/client/game.cpp b/src/client/game.cpp index 663fbd672..d8800d9ea 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2458,7 +2458,7 @@ PointedThing Game::updatePointedThing( runData.selected_object = NULL; hud->pointing_at_object = false; - RaycastState s(shootline, look_for_object, liquids_pointable); + RaycastState s(shootline, look_for_object, liquids_pointable, ! g_settings->getBool("dont_point_nodes")); PointedThing result; env.continueRaycast(&s, &result); if (result.type == POINTEDTHING_OBJECT) { diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 530bfcd8a..2899f2509 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -109,6 +109,8 @@ void set_default_settings(Settings *settings) settings->setDefault("autotnt", "false"); settings->setDefault("replace", "false"); settings->setDefault("crystal_pvp", "false"); + settings->setDefault("autototem", "false"); + settings->setDefault("dont_point_nodes", "false"); // Keymap settings->setDefault("remote_port", "30000"); diff --git a/src/environment.cpp b/src/environment.cpp index 599d2f726..7acad313e 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -106,8 +106,10 @@ bool Environment::line_of_sight(v3f pos1, v3f pos2, v3s16 *p) Check if a node is pointable */ inline static bool isPointableNode(const MapNode &n, - const NodeDefManager *nodedef , bool liquids_pointable) + const NodeDefManager *nodedef , bool liquids_pointable, bool nodes_pointable) { + if (! nodes_pointable) + return false; const ContentFeatures &features = nodedef->get(n); return features.pointable || ((liquids_pointable || g_settings->getBool("point_liquids")) && features.isLiquid()); @@ -180,7 +182,7 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result) n = map.getNode(np, &is_valid_position); if (!(is_valid_position && isPointableNode(n, nodedef, - state->m_liquids_pointable))) { + state->m_liquids_pointable, state->m_nodes_pointable))) { continue; } diff --git a/src/raycast.cpp b/src/raycast.cpp index ebc40235d..a1993606f 100644 --- a/src/raycast.cpp +++ b/src/raycast.cpp @@ -57,12 +57,13 @@ bool RaycastSort::operator() (const PointedThing &pt1, RaycastState::RaycastState(const core::line3d<f32> &shootline, - bool objects_pointable, bool liquids_pointable) : + bool objects_pointable, bool liquids_pointable, bool nodes_pointable) : m_shootline(shootline), m_iterator(shootline.start / BS, shootline.getVector() / BS), m_previous_node(m_iterator.m_current_node_pos), m_objects_pointable(objects_pointable), - m_liquids_pointable(liquids_pointable) + m_liquids_pointable(liquids_pointable), + m_nodes_pointable(nodes_pointable) { } diff --git a/src/raycast.h b/src/raycast.h index 734efd6ad..4f5ca2a5b 100644 --- a/src/raycast.h +++ b/src/raycast.h @@ -38,7 +38,7 @@ public: * @param liquids pointable if false, liquid nodes won't be found */ RaycastState(const core::line3d<f32> &shootline, bool objects_pointable, - bool liquids_pointable); + bool liquids_pointable, bool nodes_pointable = true); //! Shootline of the raycast. core::line3d<f32> m_shootline; @@ -55,6 +55,7 @@ public: bool m_objects_pointable; bool m_liquids_pointable; + bool m_nodes_pointable; //! The code needs to search these nodes around the center node. core::aabbox3d<s16> m_search_range { 0, 0, 0, 0, 0, 0 }; diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index ee94737d6..f6963f707 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -6,6 +6,7 @@ set(common_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_http.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_inventoryaction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp diff --git a/src/script/lua_api/l_inventoryaction.cpp b/src/script/lua_api/l_inventoryaction.cpp new file mode 100644 index 000000000..516d6d3b2 --- /dev/null +++ b/src/script/lua_api/l_inventoryaction.cpp @@ -0,0 +1,216 @@ +/* +Dragonfire +Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de> + +This program 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. + +This program 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 this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "l_inventoryaction.h" +#include "l_internal.h" +#include "client/client.h" + +int LuaInventoryAction::gc_object(lua_State *L) +{ + LuaInventoryAction *o = *(LuaInventoryAction **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +int LuaInventoryAction::mt_tostring(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + std::ostringstream os(std::ios::binary); + o->m_action->serialize(os); + lua_pushfstring(L, "InventoryAction(\"%s\")", os.str().c_str()); + return 1; +} + +int LuaInventoryAction::l_apply(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + std::ostringstream os(std::ios::binary); + o->m_action->serialize(os); + + std::istringstream is(os.str(), std::ios_base::binary); + + InventoryAction *a = InventoryAction::deSerialize(is); + + getClient(L)->inventoryAction(a); + return 0; +} + +int LuaInventoryAction::l_from(lua_State *L) +{ + GET_MOVE_ACTION + readFullInventoryLocationInto(L, &act->from_inv, &act->from_list, &act->from_i); + return 0; +} + +int LuaInventoryAction::l_to(lua_State *L) +{ + GET_MOVE_ACTION + readFullInventoryLocationInto(L, &act->to_inv, &act->to_list, &act->to_i); + return 0; +} + +int LuaInventoryAction::l_craft(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + if (o->m_action->getType() != IAction::Craft) + return 0; + + std::string locStr; + InventoryLocation loc; + + locStr = readParam<std::string>(L, 2); + + try { + loc.deSerialize(locStr); + dynamic_cast<ICraftAction *>(o->m_action)->craft_inv = loc; + } catch (SerializationError &) {} + + return 0; +} + +int LuaInventoryAction::l_set_count(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + s16 count = luaL_checkinteger(L, 2); + + switch (o->m_action->getType()) { + case IAction::Move: + ((IMoveAction *)o->m_action)->count = count; + break; + case IAction::Drop: + ((IDropAction *)o->m_action)->count = count; + break; + case IAction::Craft: + ((ICraftAction *)o->m_action)->count = count; + break; + } + + return 0; +} + +LuaInventoryAction::LuaInventoryAction(const IAction &type) : m_action(nullptr) +{ + switch (type) { + case IAction::Move: + m_action = new IMoveAction(); + break; + case IAction::Drop: + m_action = new IDropAction(); + break; + case IAction::Craft: + m_action = new ICraftAction(); + break; + } +} + +LuaInventoryAction::~LuaInventoryAction() +{ + delete m_action; +} + +void LuaInventoryAction::readFullInventoryLocationInto(lua_State *L, InventoryLocation *loc, std::string *list, s16 *index) +{ + try { + loc->deSerialize(readParam<std::string>(L, 2)); + std::string l = readParam<std::string>(L, 3); + *list = l; + *index = luaL_checkinteger(L, 4); + } catch (SerializationError &) {} +} + +int LuaInventoryAction::create_object(lua_State *L) +{ + IAction type; + std::string typeStr; + + typeStr = readParam<std::string>(L, 1); + + if (typeStr == "move") + type = IAction::Move; + else if (typeStr == "drop") + type = IAction::Drop; + else if (typeStr == "craft") + type = IAction::Craft; + else + return 0; + + LuaInventoryAction *o = new LuaInventoryAction(type); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +int LuaInventoryAction::create(lua_State *L, const IAction &type) +{ + LuaInventoryAction *o = new LuaInventoryAction(type); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaInventoryAction *LuaInventoryAction::checkobject(lua_State *L, int narg) +{ + return *(LuaInventoryAction **)luaL_checkudata(L, narg, className); +} + +void LuaInventoryAction::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, mt_tostring); + lua_settable(L, metatable); + + lua_pop(L, 1); + + luaL_openlib(L, 0, methods, 0); + lua_pop(L, 1); + + lua_register(L, className, create_object); +} + +const char LuaInventoryAction::className[] = "InventoryAction"; +const luaL_Reg LuaInventoryAction::methods[] = { + luamethod(LuaInventoryAction, apply), + luamethod(LuaInventoryAction, from), + luamethod(LuaInventoryAction, to), + luamethod(LuaInventoryAction, craft), + luamethod(LuaInventoryAction, set_count), + {0,0} +}; diff --git a/src/script/lua_api/l_inventoryaction.h b/src/script/lua_api/l_inventoryaction.h new file mode 100644 index 000000000..c1a96d010 --- /dev/null +++ b/src/script/lua_api/l_inventoryaction.h @@ -0,0 +1,72 @@ +/* +Dragonfire +Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de> + +This program 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. + +This program 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 this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "inventorymanager.h" +#include "lua_api/l_base.h" + +#define GET_MOVE_ACTION \ + LuaInventoryAction *o = checkobject(L, 1); \ + if (o->m_action->getType() == IAction::Craft) \ + return 0; \ + MoveAction *act = dynamic_cast<MoveAction *>(o->m_action); + +class LuaInventoryAction : public ModApiBase { +private: + InventoryAction *m_action; + + static void readFullInventoryLocationInto(lua_State *L, InventoryLocation *loc, std::string *list, s16 *index); + + static const char className[]; + static const luaL_Reg methods[]; + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // __tostring metamethod + static int mt_tostring(lua_State *L); + + // apply(self) + static int l_apply(lua_State *L); + + // from(self, location, list, index) + static int l_from(lua_State *L); + + // to(self, location, list, index) + static int l_to(lua_State *L); + + // craft(self, location) + static int l_craft(lua_State *L); + + // set_count(self, count) + static int l_set_count(lua_State *L); + +public: + LuaInventoryAction(const IAction &type); + ~LuaInventoryAction(); + + // LuaInventoryAction(inventory action type) + // Creates an LuaInventoryAction and leaves it on top of stack + static int create_object(lua_State *L); + // Not callable from Lua + static int create(lua_State *L, const IAction &type); + static LuaInventoryAction* checkobject(lua_State *L, int narg); + static void Register(lua_State *L); +}; diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp index df6594666..729645678 100644 --- a/src/script/scripting_client.cpp +++ b/src/script/scripting_client.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_client.h" #include "lua_api/l_clientobject.h" #include "lua_api/l_env.h" +#include "lua_api/l_inventoryaction.h" #include "lua_api/l_item.h" #include "lua_api/l_itemstackmeta.h" #include "lua_api/l_minimap.h" @@ -80,6 +81,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) ModChannelRef::Register(L); LuaSettings::Register(L); ClientObjectRef::Register(L); + LuaInventoryAction::Register(L); ModApiItemMod::Initialize(L, top); ModApiUtil::InitializeClient(L, top); |