]> git.lizzy.rs Git - minetest.git/blob - src/scriptapi_item.cpp
Don't erase modified_blocks
[minetest.git] / src / scriptapi_item.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "scriptapi.h"
21 #include "server.h"
22 #include "script.h"
23 #include "tool.h"
24 #include "nodedef.h"
25 #include "util/pointedthing.h"
26 #include "scriptapi_item.h"
27 #include "scriptapi_types.h"
28 #include "scriptapi_common.h"
29 #include "scriptapi_object.h"
30 #include "scriptapi_content.h"
31
32
33 struct EnumString es_ItemType[] =
34 {
35         {ITEM_NONE, "none"},
36         {ITEM_NODE, "node"},
37         {ITEM_CRAFT, "craft"},
38         {ITEM_TOOL, "tool"},
39         {0, NULL},
40 };
41
42
43 /*
44         ItemDefinition
45 */
46
47 ItemDefinition read_item_definition(lua_State *L, int index,
48                 ItemDefinition default_def)
49 {
50         if(index < 0)
51                 index = lua_gettop(L) + 1 + index;
52
53         // Read the item definition
54         ItemDefinition def = default_def;
55
56         def.type = (ItemType)getenumfield(L, index, "type",
57                         es_ItemType, ITEM_NONE);
58         getstringfield(L, index, "name", def.name);
59         getstringfield(L, index, "description", def.description);
60         getstringfield(L, index, "inventory_image", def.inventory_image);
61         getstringfield(L, index, "wield_image", def.wield_image);
62
63         lua_getfield(L, index, "wield_scale");
64         if(lua_istable(L, -1)){
65                 def.wield_scale = check_v3f(L, -1);
66         }
67         lua_pop(L, 1);
68
69         def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max);
70         if(def.stack_max == 0)
71                 def.stack_max = 1;
72
73         lua_getfield(L, index, "on_use");
74         def.usable = lua_isfunction(L, -1);
75         lua_pop(L, 1);
76
77         getboolfield(L, index, "liquids_pointable", def.liquids_pointable);
78
79         warn_if_field_exists(L, index, "tool_digging_properties",
80                         "deprecated: use tool_capabilities");
81
82         lua_getfield(L, index, "tool_capabilities");
83         if(lua_istable(L, -1)){
84                 def.tool_capabilities = new ToolCapabilities(
85                                 read_tool_capabilities(L, -1));
86         }
87
88         // If name is "" (hand), ensure there are ToolCapabilities
89         // because it will be looked up there whenever any other item has
90         // no ToolCapabilities
91         if(def.name == "" && def.tool_capabilities == NULL){
92                 def.tool_capabilities = new ToolCapabilities();
93         }
94
95         lua_getfield(L, index, "groups");
96         read_groups(L, -1, def.groups);
97         lua_pop(L, 1);
98
99         // Client shall immediately place this node when player places the item.
100         // Server will update the precise end result a moment later.
101         // "" = no prediction
102         getstringfield(L, index, "node_placement_prediction",
103                         def.node_placement_prediction);
104
105         return def;
106 }
107
108 // register_item_raw({lots of stuff})
109 int l_register_item_raw(lua_State *L)
110 {
111         luaL_checktype(L, 1, LUA_TTABLE);
112         int table = 1;
113
114         // Get the writable item and node definition managers from the server
115         IWritableItemDefManager *idef =
116                         get_server(L)->getWritableItemDefManager();
117         IWritableNodeDefManager *ndef =
118                         get_server(L)->getWritableNodeDefManager();
119
120         // Check if name is defined
121         std::string name;
122         lua_getfield(L, table, "name");
123         if(lua_isstring(L, -1)){
124                 name = lua_tostring(L, -1);
125                 verbosestream<<"register_item_raw: "<<name<<std::endl;
126         } else {
127                 throw LuaError(L, "register_item_raw: name is not defined or not a string");
128         }
129
130         // Check if on_use is defined
131
132         ItemDefinition def;
133         // Set a distinctive default value to check if this is set
134         def.node_placement_prediction = "__default";
135
136         // Read the item definition
137         def = read_item_definition(L, table, def);
138
139         // Default to having client-side placement prediction for nodes
140         // ("" in item definition sets it off)
141         if(def.node_placement_prediction == "__default"){
142                 if(def.type == ITEM_NODE)
143                         def.node_placement_prediction = name;
144                 else
145                         def.node_placement_prediction = "";
146         }
147
148         // Register item definition
149         idef->registerItem(def);
150
151         // Read the node definition (content features) and register it
152         if(def.type == ITEM_NODE)
153         {
154                 ContentFeatures f = read_content_features(L, table);
155                 ndef->set(f.name, f);
156         }
157
158         return 0; /* number of results */
159 }
160
161 // register_alias_raw(name, convert_to_name)
162 int l_register_alias_raw(lua_State *L)
163 {
164         std::string name = luaL_checkstring(L, 1);
165         std::string convert_to = luaL_checkstring(L, 2);
166
167         // Get the writable item definition manager from the server
168         IWritableItemDefManager *idef =
169                         get_server(L)->getWritableItemDefManager();
170
171         idef->registerAlias(name, convert_to);
172
173         return 0; /* number of results */
174 }
175
176 // Retrieves minetest.registered_items[name][callbackname]
177 // If that is nil or on error, return false and stack is unchanged
178 // If that is a function, returns true and pushes the
179 // function onto the stack
180 // If minetest.registered_items[name] doesn't exist, minetest.nodedef_default
181 // is tried instead so unknown items can still be manipulated to some degree
182 bool get_item_callback(lua_State *L,
183                 const char *name, const char *callbackname)
184 {
185         lua_getglobal(L, "minetest");
186         lua_getfield(L, -1, "registered_items");
187         lua_remove(L, -2);
188         luaL_checktype(L, -1, LUA_TTABLE);
189         lua_getfield(L, -1, name);
190         lua_remove(L, -2);
191         // Should be a table
192         if(lua_type(L, -1) != LUA_TTABLE)
193         {
194                 // Report error and clean up
195                 errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
196                 lua_pop(L, 1);
197
198                 // Try minetest.nodedef_default instead
199                 lua_getglobal(L, "minetest");
200                 lua_getfield(L, -1, "nodedef_default");
201                 lua_remove(L, -2);
202                 luaL_checktype(L, -1, LUA_TTABLE);
203         }
204         lua_getfield(L, -1, callbackname);
205         lua_remove(L, -2);
206         // Should be a function or nil
207         if(lua_type(L, -1) == LUA_TFUNCTION)
208         {
209                 return true;
210         }
211         else if(lua_isnil(L, -1))
212         {
213                 lua_pop(L, 1);
214                 return false;
215         }
216         else
217         {
218                 errorstream<<"Item \""<<name<<"\" callback \""
219                         <<callbackname<<" is not a function"<<std::endl;
220                 lua_pop(L, 1);
221                 return false;
222         }
223 }
224
225 bool scriptapi_item_on_drop(lua_State *L, ItemStack &item,
226                 ServerActiveObject *dropper, v3f pos)
227 {
228         realitycheck(L);
229         assert(lua_checkstack(L, 20));
230         StackUnroller stack_unroller(L);
231
232         // Push callback function on stack
233         if(!get_item_callback(L, item.name.c_str(), "on_drop"))
234                 return false;
235
236         // Call function
237         LuaItemStack::create(L, item);
238         objectref_get_or_create(L, dropper);
239         pushFloatPos(L, pos);
240         if(lua_pcall(L, 3, 1, 0))
241                 script_error(L, "error: %s", lua_tostring(L, -1));
242         if(!lua_isnil(L, -1))
243                 item = read_item(L, -1);
244         return true;
245 }
246
247 bool scriptapi_item_on_place(lua_State *L, ItemStack &item,
248                 ServerActiveObject *placer, const PointedThing &pointed)
249 {
250         realitycheck(L);
251         assert(lua_checkstack(L, 20));
252         StackUnroller stack_unroller(L);
253
254         // Push callback function on stack
255         if(!get_item_callback(L, item.name.c_str(), "on_place"))
256                 return false;
257
258         // Call function
259         LuaItemStack::create(L, item);
260         objectref_get_or_create(L, placer);
261         push_pointed_thing(L, pointed);
262         if(lua_pcall(L, 3, 1, 0))
263                 script_error(L, "error: %s", lua_tostring(L, -1));
264         if(!lua_isnil(L, -1))
265                 item = read_item(L, -1);
266         return true;
267 }
268
269 bool scriptapi_item_on_use(lua_State *L, ItemStack &item,
270                 ServerActiveObject *user, const PointedThing &pointed)
271 {
272         realitycheck(L);
273         assert(lua_checkstack(L, 20));
274         StackUnroller stack_unroller(L);
275
276         // Push callback function on stack
277         if(!get_item_callback(L, item.name.c_str(), "on_use"))
278                 return false;
279
280         // Call function
281         LuaItemStack::create(L, item);
282         objectref_get_or_create(L, user);
283         push_pointed_thing(L, pointed);
284         if(lua_pcall(L, 3, 1, 0))
285                 script_error(L, "error: %s", lua_tostring(L, -1));
286         if(!lua_isnil(L, -1))
287                 item = read_item(L, -1);
288         return true;
289 }
290
291 // garbage collector
292 int LuaItemStack::gc_object(lua_State *L)
293 {
294         LuaItemStack *o = *(LuaItemStack **)(lua_touserdata(L, 1));
295         delete o;
296         return 0;
297 }
298
299 // is_empty(self) -> true/false
300 int LuaItemStack::l_is_empty(lua_State *L)
301 {
302         LuaItemStack *o = checkobject(L, 1);
303         ItemStack &item = o->m_stack;
304         lua_pushboolean(L, item.empty());
305         return 1;
306 }
307
308 // get_name(self) -> string
309 int LuaItemStack::l_get_name(lua_State *L)
310 {
311         LuaItemStack *o = checkobject(L, 1);
312         ItemStack &item = o->m_stack;
313         lua_pushstring(L, item.name.c_str());
314         return 1;
315 }
316
317 // get_count(self) -> number
318 int LuaItemStack::l_get_count(lua_State *L)
319 {
320         LuaItemStack *o = checkobject(L, 1);
321         ItemStack &item = o->m_stack;
322         lua_pushinteger(L, item.count);
323         return 1;
324 }
325
326 // get_wear(self) -> number
327 int LuaItemStack::l_get_wear(lua_State *L)
328 {
329         LuaItemStack *o = checkobject(L, 1);
330         ItemStack &item = o->m_stack;
331         lua_pushinteger(L, item.wear);
332         return 1;
333 }
334
335 // get_metadata(self) -> string
336 int LuaItemStack::l_get_metadata(lua_State *L)
337 {
338         LuaItemStack *o = checkobject(L, 1);
339         ItemStack &item = o->m_stack;
340         lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
341         return 1;
342 }
343
344 // clear(self) -> true
345 int LuaItemStack::l_clear(lua_State *L)
346 {
347         LuaItemStack *o = checkobject(L, 1);
348         o->m_stack.clear();
349         lua_pushboolean(L, true);
350         return 1;
351 }
352
353 // replace(self, itemstack or itemstring or table or nil) -> true
354 int LuaItemStack::l_replace(lua_State *L)
355 {
356         LuaItemStack *o = checkobject(L, 1);
357         o->m_stack = read_item(L, 2);
358         lua_pushboolean(L, true);
359         return 1;
360 }
361
362 // to_string(self) -> string
363 int LuaItemStack::l_to_string(lua_State *L)
364 {
365         LuaItemStack *o = checkobject(L, 1);
366         std::string itemstring = o->m_stack.getItemString();
367         lua_pushstring(L, itemstring.c_str());
368         return 1;
369 }
370
371 // to_table(self) -> table or nil
372 int LuaItemStack::l_to_table(lua_State *L)
373 {
374         LuaItemStack *o = checkobject(L, 1);
375         const ItemStack &item = o->m_stack;
376         if(item.empty())
377         {
378                 lua_pushnil(L);
379         }
380         else
381         {
382                 lua_newtable(L);
383                 lua_pushstring(L, item.name.c_str());
384                 lua_setfield(L, -2, "name");
385                 lua_pushinteger(L, item.count);
386                 lua_setfield(L, -2, "count");
387                 lua_pushinteger(L, item.wear);
388                 lua_setfield(L, -2, "wear");
389                 lua_pushlstring(L, item.metadata.c_str(), item.metadata.size());
390                 lua_setfield(L, -2, "metadata");
391         }
392         return 1;
393 }
394
395 // get_stack_max(self) -> number
396 int LuaItemStack::l_get_stack_max(lua_State *L)
397 {
398         LuaItemStack *o = checkobject(L, 1);
399         ItemStack &item = o->m_stack;
400         lua_pushinteger(L, item.getStackMax(get_server(L)->idef()));
401         return 1;
402 }
403
404 // get_free_space(self) -> number
405 int LuaItemStack::l_get_free_space(lua_State *L)
406 {
407         LuaItemStack *o = checkobject(L, 1);
408         ItemStack &item = o->m_stack;
409         lua_pushinteger(L, item.freeSpace(get_server(L)->idef()));
410         return 1;
411 }
412
413 // is_known(self) -> true/false
414 // Checks if the item is defined.
415 int LuaItemStack::l_is_known(lua_State *L)
416 {
417         LuaItemStack *o = checkobject(L, 1);
418         ItemStack &item = o->m_stack;
419         bool is_known = item.isKnown(get_server(L)->idef());
420         lua_pushboolean(L, is_known);
421         return 1;
422 }
423
424 // get_definition(self) -> table
425 // Returns the item definition table from minetest.registered_items,
426 // or a fallback one (name="unknown")
427 int LuaItemStack::l_get_definition(lua_State *L)
428 {
429         LuaItemStack *o = checkobject(L, 1);
430         ItemStack &item = o->m_stack;
431
432         // Get minetest.registered_items[name]
433         lua_getglobal(L, "minetest");
434         lua_getfield(L, -1, "registered_items");
435         luaL_checktype(L, -1, LUA_TTABLE);
436         lua_getfield(L, -1, item.name.c_str());
437         if(lua_isnil(L, -1))
438         {
439                 lua_pop(L, 1);
440                 lua_getfield(L, -1, "unknown");
441         }
442         return 1;
443 }
444
445 // get_tool_capabilities(self) -> table
446 // Returns the effective tool digging properties.
447 // Returns those of the hand ("") if this item has none associated.
448 int LuaItemStack::l_get_tool_capabilities(lua_State *L)
449 {
450         LuaItemStack *o = checkobject(L, 1);
451         ItemStack &item = o->m_stack;
452         const ToolCapabilities &prop =
453                 item.getToolCapabilities(get_server(L)->idef());
454         push_tool_capabilities(L, prop);
455         return 1;
456 }
457
458 // add_wear(self, amount) -> true/false
459 // The range for "amount" is [0,65535]. Wear is only added if the item
460 // is a tool. Adding wear might destroy the item.
461 // Returns true if the item is (or was) a tool.
462 int LuaItemStack::l_add_wear(lua_State *L)
463 {
464         LuaItemStack *o = checkobject(L, 1);
465         ItemStack &item = o->m_stack;
466         int amount = lua_tointeger(L, 2);
467         bool result = item.addWear(amount, get_server(L)->idef());
468         lua_pushboolean(L, result);
469         return 1;
470 }
471
472 // add_item(self, itemstack or itemstring or table or nil) -> itemstack
473 // Returns leftover item stack
474 int LuaItemStack::l_add_item(lua_State *L)
475 {
476         LuaItemStack *o = checkobject(L, 1);
477         ItemStack &item = o->m_stack;
478         ItemStack newitem = read_item(L, 2);
479         ItemStack leftover = item.addItem(newitem, get_server(L)->idef());
480         create(L, leftover);
481         return 1;
482 }
483
484 // item_fits(self, itemstack or itemstring or table or nil) -> true/false, itemstack
485 // First return value is true iff the new item fits fully into the stack
486 // Second return value is the would-be-left-over item stack
487 int LuaItemStack::l_item_fits(lua_State *L)
488 {
489         LuaItemStack *o = checkobject(L, 1);
490         ItemStack &item = o->m_stack;
491         ItemStack newitem = read_item(L, 2);
492         ItemStack restitem;
493         bool fits = item.itemFits(newitem, &restitem, get_server(L)->idef());
494         lua_pushboolean(L, fits);  // first return value
495         create(L, restitem);       // second return value
496         return 2;
497 }
498
499 // take_item(self, takecount=1) -> itemstack
500 int LuaItemStack::l_take_item(lua_State *L)
501 {
502         LuaItemStack *o = checkobject(L, 1);
503         ItemStack &item = o->m_stack;
504         u32 takecount = 1;
505         if(!lua_isnone(L, 2))
506                 takecount = luaL_checkinteger(L, 2);
507         ItemStack taken = item.takeItem(takecount);
508         create(L, taken);
509         return 1;
510 }
511
512 // peek_item(self, peekcount=1) -> itemstack
513 int LuaItemStack::l_peek_item(lua_State *L)
514 {
515         LuaItemStack *o = checkobject(L, 1);
516         ItemStack &item = o->m_stack;
517         u32 peekcount = 1;
518         if(!lua_isnone(L, 2))
519                 peekcount = lua_tointeger(L, 2);
520         ItemStack peekaboo = item.peekItem(peekcount);
521         create(L, peekaboo);
522         return 1;
523 }
524
525 LuaItemStack::LuaItemStack(const ItemStack &item):
526         m_stack(item)
527 {
528 }
529
530 LuaItemStack::~LuaItemStack()
531 {
532 }
533
534 const ItemStack& LuaItemStack::getItem() const
535 {
536         return m_stack;
537 }
538 ItemStack& LuaItemStack::getItem()
539 {
540         return m_stack;
541 }
542
543 // LuaItemStack(itemstack or itemstring or table or nil)
544 // Creates an LuaItemStack and leaves it on top of stack
545 int LuaItemStack::create_object(lua_State *L)
546 {
547         ItemStack item = read_item(L, 1);
548         LuaItemStack *o = new LuaItemStack(item);
549         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
550         luaL_getmetatable(L, className);
551         lua_setmetatable(L, -2);
552         return 1;
553 }
554 // Not callable from Lua
555 int LuaItemStack::create(lua_State *L, const ItemStack &item)
556 {
557         LuaItemStack *o = new LuaItemStack(item);
558         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
559         luaL_getmetatable(L, className);
560         lua_setmetatable(L, -2);
561         return 1;
562 }
563
564 LuaItemStack* LuaItemStack::checkobject(lua_State *L, int narg)
565 {
566         luaL_checktype(L, narg, LUA_TUSERDATA);
567         void *ud = luaL_checkudata(L, narg, className);
568         if(!ud) luaL_typerror(L, narg, className);
569         return *(LuaItemStack**)ud;  // unbox pointer
570 }
571
572 void LuaItemStack::Register(lua_State *L)
573 {
574         lua_newtable(L);
575         int methodtable = lua_gettop(L);
576         luaL_newmetatable(L, className);
577         int metatable = lua_gettop(L);
578
579         lua_pushliteral(L, "__metatable");
580         lua_pushvalue(L, methodtable);
581         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
582
583         lua_pushliteral(L, "__index");
584         lua_pushvalue(L, methodtable);
585         lua_settable(L, metatable);
586
587         lua_pushliteral(L, "__gc");
588         lua_pushcfunction(L, gc_object);
589         lua_settable(L, metatable);
590
591         lua_pop(L, 1);  // drop metatable
592
593         luaL_openlib(L, 0, methods, 0);  // fill methodtable
594         lua_pop(L, 1);  // drop methodtable
595
596         // Can be created from Lua (LuaItemStack(itemstack or itemstring or table or nil))
597         lua_register(L, className, create_object);
598 }
599
600 const char LuaItemStack::className[] = "ItemStack";
601 const luaL_reg LuaItemStack::methods[] = {
602         luamethod(LuaItemStack, is_empty),
603         luamethod(LuaItemStack, get_name),
604         luamethod(LuaItemStack, get_count),
605         luamethod(LuaItemStack, get_wear),
606         luamethod(LuaItemStack, get_metadata),
607         luamethod(LuaItemStack, clear),
608         luamethod(LuaItemStack, replace),
609         luamethod(LuaItemStack, to_string),
610         luamethod(LuaItemStack, to_table),
611         luamethod(LuaItemStack, get_stack_max),
612         luamethod(LuaItemStack, get_free_space),
613         luamethod(LuaItemStack, is_known),
614         luamethod(LuaItemStack, get_definition),
615         luamethod(LuaItemStack, get_tool_capabilities),
616         luamethod(LuaItemStack, add_wear),
617         luamethod(LuaItemStack, add_item),
618         luamethod(LuaItemStack, item_fits),
619         luamethod(LuaItemStack, take_item),
620         luamethod(LuaItemStack, peek_item),
621         {0,0}
622 };
623
624 ItemStack read_item(lua_State *L, int index)
625 {
626         if(index < 0)
627                 index = lua_gettop(L) + 1 + index;
628
629         if(lua_isnil(L, index))
630         {
631                 return ItemStack();
632         }
633         else if(lua_isuserdata(L, index))
634         {
635                 // Convert from LuaItemStack
636                 LuaItemStack *o = LuaItemStack::checkobject(L, index);
637                 return o->getItem();
638         }
639         else if(lua_isstring(L, index))
640         {
641                 // Convert from itemstring
642                 std::string itemstring = lua_tostring(L, index);
643                 IItemDefManager *idef = get_server(L)->idef();
644                 try
645                 {
646                         ItemStack item;
647                         item.deSerialize(itemstring, idef);
648                         return item;
649                 }
650                 catch(SerializationError &e)
651                 {
652                         infostream<<"WARNING: unable to create item from itemstring"
653                                         <<": "<<itemstring<<std::endl;
654                         return ItemStack();
655                 }
656         }
657         else if(lua_istable(L, index))
658         {
659                 // Convert from table
660                 IItemDefManager *idef = get_server(L)->idef();
661                 std::string name = getstringfield_default(L, index, "name", "");
662                 int count = getintfield_default(L, index, "count", 1);
663                 int wear = getintfield_default(L, index, "wear", 0);
664                 std::string metadata = getstringfield_default(L, index, "metadata", "");
665                 return ItemStack(name, count, wear, metadata, idef);
666         }
667         else
668         {
669                 throw LuaError(L, "Expecting itemstack, itemstring, table or nil");
670         }
671 }
672
673 std::vector<ItemStack> read_items(lua_State *L, int index)
674 {
675         if(index < 0)
676                 index = lua_gettop(L) + 1 + index;
677
678         std::vector<ItemStack> items;
679         luaL_checktype(L, index, LUA_TTABLE);
680         lua_pushnil(L);
681         while(lua_next(L, index) != 0){
682                 // key at index -2 and value at index -1
683                 items.push_back(read_item(L, -1));
684                 // removes value, keeps key for next iteration
685                 lua_pop(L, 1);
686         }
687         return items;
688 }
689
690 // creates a table of ItemStacks
691 void push_items(lua_State *L, const std::vector<ItemStack> &items)
692 {
693         // Get the table insert function
694         lua_getglobal(L, "table");
695         lua_getfield(L, -1, "insert");
696         int table_insert = lua_gettop(L);
697         // Create and fill table
698         lua_newtable(L);
699         int table = lua_gettop(L);
700         for(u32 i=0; i<items.size(); i++){
701                 ItemStack item = items[i];
702                 lua_pushvalue(L, table_insert);
703                 lua_pushvalue(L, table);
704                 LuaItemStack::create(L, item);
705                 if(lua_pcall(L, 2, 0, 0))
706                         script_error(L, "error: %s", lua_tostring(L, -1));
707         }
708         lua_remove(L, -2); // Remove table
709         lua_remove(L, -2); // Remove insert
710 }