]> git.lizzy.rs Git - dragonfireclient.git/commitdiff
Added ThroughWalls, InventoryActions API and AutoTotem
authorElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 19 Oct 2020 11:09:38 +0000 (13:09 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 19 Oct 2020 11:09:38 +0000 (13:09 +0200)
14 files changed:
builtin/client/cheats/combat.lua
builtin/client/cheats/init.lua
builtin/client/cheats/inventory.lua
builtin/client/util.lua
doc/client_lua_api.txt
src/client/game.cpp
src/defaultsettings.cpp
src/environment.cpp
src/raycast.cpp
src/raycast.h
src/script/lua_api/CMakeLists.txt
src/script/lua_api/l_inventoryaction.cpp [new file with mode: 0644]
src/script/lua_api/l_inventoryaction.h [new file with mode: 0644]
src/script/scripting_client.cpp

index 25aaaec348b5b1bf164b2bc3a324c30aa0be1cf4..b497c6c1bdfed1a7a40adb0958feecf8ee6c3ddd 100644 (file)
@@ -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)
-
index cdeae78c813bc6f434b72d592acc1fc48c9b1014..a7be83ceedfc73f6bd85c640d0e1739515c9937c 100644 (file)
@@ -5,6 +5,8 @@ core.cheats = {
                ["FastHit"] = "spamclick",
                ["AttachmentFloat"] = "float_above_parent",
                ["CrystalPvP"] = "crystal_pvp",
+               ["AutoTotem"] = "autototem",
+               ["ThroughWalls"] = "dont_point_nodes",
        },
        ["Movement"] = {
                ["Freecam"] = "freecam",
index d12052d7ce782b7d075bc21c3d2d8254b46b4cf1..faa7d1c0eca18f8bae517447f963a3c0b18b84f0 100644 (file)
@@ -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
index 4a6a72d72e6ee4de96abd934161b298fea0cdda5..d61b547c6b45d1281aa055673861375ca621169e 100644 (file)
@@ -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    
index 735173580eb8d467e403f8f0fd4eeceff3ae211a..50c33940e84fc93e02997f385a9008feb0428ee8 100644 (file)
@@ -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
+    
+
+    
+
index 663fbd672f97836e806607f1d6c6d4dc24ec0fba..d8800d9ea44c2e389117c31f0e640236324bf46c 100644 (file)
@@ -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) {
index 530bfcd8ab9357b33f140be27af0fa650c98f5a4..2899f2509ae4c8c26dee313d771293afc964357c 100644 (file)
@@ -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");
index 599d2f726ce84da7a9497cf2550ff668e20214d9..7acad313e134e7db5c903156896019d71e20fe6f 100644 (file)
@@ -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;
                        }
 
index ebc40235db815042b8d785732af2a9720a5230c1..a1993606f83b419756a55862220dc7413fb5f5f2 100644 (file)
@@ -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)
 {
 }
 
index 734efd6ad4ae2cc76f7b1ca9d92b8566bb9d3711..4f5ca2a5bfde5d55d25f2cb91e5f8276bf396d11 100644 (file)
@@ -38,7 +38,7 @@ class RaycastState
         * @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 @@ class RaycastState
 
        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 };
index ee94737d6c457ba93992db1e535e4ba7ff64132b..f6963f707cad037b17bd4df630a72463a63952a5 100644 (file)
@@ -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 (file)
index 0000000..516d6d3
--- /dev/null
@@ -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 (file)
index 0000000..c1a96d0
--- /dev/null
@@ -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);
+};
index df6594666cefab03c08b498a6845b436d90b07ce..7296456786a9074d7020621984346b1f0315dff5 100644 (file)
@@ -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);