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)
-
["FastHit"] = "spamclick",
["AttachmentFloat"] = "float_above_parent",
["CrystalPvP"] = "crystal_pvp",
+ ["AutoTotem"] = "autototem",
+ ["ThroughWalls"] = "dont_point_nodes",
},
["Movement"] = {
["Freecam"] = "freecam",
local elapsed_time = 0
local tick_time = 0.05
+local drop_action = InventoryAction("drop")
core.register_globalstep(function(dtime)
-- AutoEject
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
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
* 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
-- ^ 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
+
+
+
+
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) {
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");
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());
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;
}
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)
{
}
* @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;
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 };
${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
--- /dev/null
+/*
+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}
+};
--- /dev/null
+/*
+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);
+};
#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"
ModChannelRef::Register(L);
LuaSettings::Register(L);
ClientObjectRef::Register(L);
+ LuaInventoryAction::Register(L);
ModApiItemMod::Initialize(L, top);
ModApiUtil::InitializeClient(L, top);