item.lua 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. -- Minetest: builtin/item.lua
  2. local builtin_shared = ...
  3. local function copy_pointed_thing(pointed_thing)
  4. return {
  5. type = pointed_thing.type,
  6. above = pointed_thing.above and vector.copy(pointed_thing.above),
  7. under = pointed_thing.under and vector.copy(pointed_thing.under),
  8. ref = pointed_thing.ref,
  9. }
  10. end
  11. --
  12. -- Item definition helpers
  13. --
  14. function core.get_pointed_thing_position(pointed_thing, above)
  15. if pointed_thing.type == "node" then
  16. if above then
  17. -- The position where a node would be placed
  18. return pointed_thing.above
  19. end
  20. -- The position where a node would be dug
  21. return pointed_thing.under
  22. elseif pointed_thing.type == "object" then
  23. return pointed_thing.ref and pointed_thing.ref:get_pos()
  24. end
  25. end
  26. local function has_all_groups(tbl, required_groups)
  27. if type(required_groups) == "string" then
  28. return (tbl[required_groups] or 0) ~= 0
  29. end
  30. for _, group in ipairs(required_groups) do
  31. if (tbl[group] or 0) == 0 then
  32. return false
  33. end
  34. end
  35. return true
  36. end
  37. function core.get_node_drops(node, toolname)
  38. -- Compatibility, if node is string
  39. local nodename = node
  40. local param2 = 0
  41. -- New format, if node is table
  42. if (type(node) == "table") then
  43. nodename = node.name
  44. param2 = node.param2
  45. end
  46. local def = core.registered_nodes[nodename]
  47. local drop = def and def.drop
  48. local ptype = def and def.paramtype2
  49. -- get color, if there is color (otherwise nil)
  50. local palette_index = core.strip_param2_color(param2, ptype)
  51. if drop == nil then
  52. -- default drop
  53. if palette_index then
  54. local stack = ItemStack(nodename)
  55. stack:get_meta():set_int("palette_index", palette_index)
  56. return {stack:to_string()}
  57. end
  58. return {nodename}
  59. elseif type(drop) == "string" then
  60. -- itemstring drop
  61. return drop ~= "" and {drop} or {}
  62. elseif drop.items == nil then
  63. -- drop = {} to disable default drop
  64. return {}
  65. end
  66. -- Extended drop table
  67. local got_items = {}
  68. local got_count = 0
  69. for _, item in ipairs(drop.items) do
  70. local good_rarity = true
  71. local good_tool = true
  72. if item.rarity ~= nil then
  73. good_rarity = item.rarity < 1 or math.random(item.rarity) == 1
  74. end
  75. if item.tools ~= nil or item.tool_groups ~= nil then
  76. good_tool = false
  77. end
  78. if item.tools ~= nil and toolname then
  79. for _, tool in ipairs(item.tools) do
  80. if tool:sub(1, 1) == '~' then
  81. good_tool = toolname:find(tool:sub(2)) ~= nil
  82. else
  83. good_tool = toolname == tool
  84. end
  85. if good_tool then
  86. break
  87. end
  88. end
  89. end
  90. if item.tool_groups ~= nil and toolname then
  91. local tooldef = core.registered_items[toolname]
  92. if tooldef ~= nil and type(tooldef.groups) == "table" then
  93. if type(item.tool_groups) == "string" then
  94. -- tool_groups can be a string which specifies the required group
  95. good_tool = core.get_item_group(toolname, item.tool_groups) ~= 0
  96. else
  97. -- tool_groups can be a list of sufficient requirements.
  98. -- i.e. if any item in the list can be satisfied then the tool is good
  99. assert(type(item.tool_groups) == "table")
  100. for _, required_groups in ipairs(item.tool_groups) do
  101. -- required_groups can be either a string (a single group),
  102. -- or an array of strings where all must be in tooldef.groups
  103. good_tool = has_all_groups(tooldef.groups, required_groups)
  104. if good_tool then
  105. break
  106. end
  107. end
  108. end
  109. end
  110. end
  111. if good_rarity and good_tool then
  112. got_count = got_count + 1
  113. for _, add_item in ipairs(item.items) do
  114. -- add color, if necessary
  115. if item.inherit_color and palette_index then
  116. local stack = ItemStack(add_item)
  117. stack:get_meta():set_int("palette_index", palette_index)
  118. add_item = stack:to_string()
  119. end
  120. got_items[#got_items+1] = add_item
  121. end
  122. if drop.max_items ~= nil and got_count == drop.max_items then
  123. break
  124. end
  125. end
  126. end
  127. return got_items
  128. end
  129. local function user_name(user)
  130. return user and user:get_player_name() or ""
  131. end
  132. -- Returns a logging function. For empty names, does not log.
  133. local function make_log(name)
  134. return name ~= "" and core.log or function() end
  135. end
  136. function core.item_place_node(itemstack, placer, pointed_thing, param2,
  137. prevent_after_place)
  138. local def = itemstack:get_definition()
  139. if def.type ~= "node" or pointed_thing.type ~= "node" then
  140. return itemstack, nil
  141. end
  142. local under = pointed_thing.under
  143. local oldnode_under = core.get_node_or_nil(under)
  144. local above = pointed_thing.above
  145. local oldnode_above = core.get_node_or_nil(above)
  146. local playername = user_name(placer)
  147. local log = make_log(playername)
  148. if not oldnode_under or not oldnode_above then
  149. log("info", playername .. " tried to place"
  150. .. " node in unloaded position " .. core.pos_to_string(above))
  151. return itemstack, nil
  152. end
  153. local olddef_under = core.registered_nodes[oldnode_under.name]
  154. olddef_under = olddef_under or core.nodedef_default
  155. local olddef_above = core.registered_nodes[oldnode_above.name]
  156. olddef_above = olddef_above or core.nodedef_default
  157. if not olddef_above.buildable_to and not olddef_under.buildable_to then
  158. log("info", playername .. " tried to place"
  159. .. " node in invalid position " .. core.pos_to_string(above)
  160. .. ", replacing " .. oldnode_above.name)
  161. return itemstack, nil
  162. end
  163. -- Place above pointed node
  164. local place_to = vector.copy(above)
  165. -- If node under is buildable_to, place into it instead (eg. snow)
  166. if olddef_under.buildable_to then
  167. log("info", "node under is buildable to")
  168. place_to = vector.copy(under)
  169. end
  170. if core.is_protected(place_to, playername) then
  171. log("action", playername
  172. .. " tried to place " .. def.name
  173. .. " at protected position "
  174. .. core.pos_to_string(place_to))
  175. core.record_protection_violation(place_to, playername)
  176. return itemstack, nil
  177. end
  178. local oldnode = core.get_node(place_to)
  179. local newnode = {name = def.name, param1 = 0, param2 = param2 or 0}
  180. -- Calculate direction for wall mounted stuff like torches and signs
  181. if def.place_param2 ~= nil then
  182. newnode.param2 = def.place_param2
  183. elseif (def.paramtype2 == "wallmounted" or
  184. def.paramtype2 == "colorwallmounted") and not param2 then
  185. local dir = vector.subtract(under, above)
  186. newnode.param2 = core.dir_to_wallmounted(dir)
  187. -- Calculate the direction for furnaces and chests and stuff
  188. elseif (def.paramtype2 == "facedir" or
  189. def.paramtype2 == "colorfacedir" or
  190. def.paramtype2 == "4dir" or
  191. def.paramtype2 == "color4dir") and not param2 then
  192. local placer_pos = placer and placer:get_pos()
  193. if placer_pos then
  194. local dir = vector.subtract(above, placer_pos)
  195. newnode.param2 = core.dir_to_facedir(dir)
  196. log("info", "facedir: " .. newnode.param2)
  197. end
  198. end
  199. local metatable = itemstack:get_meta():to_table().fields
  200. -- Transfer color information
  201. if metatable.palette_index and not def.place_param2 then
  202. local color_divisor = nil
  203. if def.paramtype2 == "color" then
  204. color_divisor = 1
  205. elseif def.paramtype2 == "colorwallmounted" then
  206. color_divisor = 8
  207. elseif def.paramtype2 == "colorfacedir" then
  208. color_divisor = 32
  209. elseif def.paramtype2 == "color4dir" then
  210. color_divisor = 4
  211. elseif def.paramtype2 == "colordegrotate" then
  212. color_divisor = 32
  213. end
  214. if color_divisor then
  215. local color = math.floor(metatable.palette_index / color_divisor)
  216. local other = newnode.param2 % color_divisor
  217. newnode.param2 = color * color_divisor + other
  218. end
  219. end
  220. -- Check if the node is attached and if it can be placed there
  221. if core.get_item_group(def.name, "attached_node") ~= 0 and
  222. not builtin_shared.check_attached_node(place_to, newnode) then
  223. log("action", "attached node " .. def.name ..
  224. " can not be placed at " .. core.pos_to_string(place_to))
  225. return itemstack, nil
  226. end
  227. log("action", playername .. " places node "
  228. .. def.name .. " at " .. core.pos_to_string(place_to))
  229. -- Add node and update
  230. core.add_node(place_to, newnode)
  231. -- Play sound if it was done by a player
  232. if playername ~= "" and def.sounds and def.sounds.place then
  233. core.sound_play(def.sounds.place, {
  234. pos = place_to,
  235. exclude_player = playername,
  236. }, true)
  237. end
  238. local take_item = true
  239. -- Run callback
  240. if def.after_place_node and not prevent_after_place then
  241. -- Deepcopy place_to and pointed_thing because callback can modify it
  242. local place_to_copy = vector.copy(place_to)
  243. local pointed_thing_copy = copy_pointed_thing(pointed_thing)
  244. if def.after_place_node(place_to_copy, placer, itemstack,
  245. pointed_thing_copy) then
  246. take_item = false
  247. end
  248. end
  249. -- Run script hook
  250. for _, callback in ipairs(core.registered_on_placenodes) do
  251. -- Deepcopy pos, node and pointed_thing because callback can modify them
  252. local place_to_copy = vector.copy(place_to)
  253. local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2}
  254. local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2}
  255. local pointed_thing_copy = copy_pointed_thing(pointed_thing)
  256. if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then
  257. take_item = false
  258. end
  259. end
  260. if take_item then
  261. itemstack:take_item()
  262. end
  263. return itemstack, place_to
  264. end
  265. -- deprecated, item_place does not call this
  266. function core.item_place_object(itemstack, placer, pointed_thing)
  267. local pos = core.get_pointed_thing_position(pointed_thing, true)
  268. if pos ~= nil then
  269. local item = itemstack:take_item()
  270. core.add_item(pos, item)
  271. end
  272. return itemstack
  273. end
  274. function core.item_place(itemstack, placer, pointed_thing, param2)
  275. -- Call on_rightclick if the pointed node defines it
  276. if pointed_thing.type == "node" and placer and
  277. not placer:get_player_control().sneak then
  278. local n = core.get_node(pointed_thing.under)
  279. local nn = n.name
  280. if core.registered_nodes[nn] and core.registered_nodes[nn].on_rightclick then
  281. return core.registered_nodes[nn].on_rightclick(pointed_thing.under, n,
  282. placer, itemstack, pointed_thing) or itemstack, nil
  283. end
  284. end
  285. -- Place if node, otherwise do nothing
  286. if itemstack:get_definition().type == "node" then
  287. return core.item_place_node(itemstack, placer, pointed_thing, param2)
  288. end
  289. return itemstack, nil
  290. end
  291. function core.item_secondary_use(itemstack, placer)
  292. return itemstack
  293. end
  294. function core.item_drop(itemstack, dropper, pos)
  295. local dropper_is_player = dropper and dropper:is_player()
  296. local p = table.copy(pos)
  297. local cnt = itemstack:get_count()
  298. if dropper_is_player then
  299. p.y = p.y + 1.2
  300. end
  301. local item = itemstack:take_item(cnt)
  302. local obj = core.add_item(p, item)
  303. if obj then
  304. if dropper_is_player then
  305. local dir = dropper:get_look_dir()
  306. dir.x = dir.x * 2.9
  307. dir.y = dir.y * 2.9 + 2
  308. dir.z = dir.z * 2.9
  309. obj:set_velocity(dir)
  310. obj:get_luaentity().dropped_by = dropper:get_player_name()
  311. end
  312. return itemstack
  313. end
  314. -- If we reach this, adding the object to the
  315. -- environment failed
  316. end
  317. function core.item_pickup(itemstack, picker, pointed_thing, ...)
  318. itemstack = ItemStack(itemstack)
  319. -- Invoke global on_item_pickup callbacks.
  320. for _, callback in ipairs(core.registered_on_item_pickups) do
  321. local result = callback(itemstack, picker, pointed_thing, ...)
  322. if result then
  323. return ItemStack(result)
  324. end
  325. end
  326. -- Pickup item.
  327. local inv = picker and picker:get_inventory()
  328. if inv then
  329. return inv:add_item("main", itemstack)
  330. end
  331. return itemstack
  332. end
  333. function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
  334. for _, callback in ipairs(core.registered_on_item_eats) do
  335. local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
  336. if result then
  337. return result
  338. end
  339. end
  340. -- read definition before potentially emptying the stack
  341. local def = itemstack:get_definition()
  342. if itemstack:take_item():is_empty() then
  343. return itemstack
  344. end
  345. if def and def.sound and def.sound.eat then
  346. core.sound_play(def.sound.eat, {
  347. pos = user:get_pos(),
  348. max_hear_distance = 16
  349. }, true)
  350. end
  351. -- Changing hp might kill the player causing mods to do who-knows-what to the
  352. -- inventory, so do this before set_hp().
  353. if replace_with_item then
  354. if itemstack:is_empty() then
  355. itemstack:add_item(replace_with_item)
  356. else
  357. local inv = user:get_inventory()
  358. -- Check if inv is null, since non-players don't have one
  359. if inv and inv:room_for_item("main", {name=replace_with_item}) then
  360. inv:add_item("main", replace_with_item)
  361. else
  362. local pos = user:get_pos()
  363. pos.y = math.floor(pos.y + 0.5)
  364. core.add_item(pos, replace_with_item)
  365. end
  366. end
  367. end
  368. user:set_wielded_item(itemstack)
  369. user:set_hp(user:get_hp() + hp_change)
  370. return nil -- don't overwrite wield item a second time
  371. end
  372. function core.item_eat(hp_change, replace_with_item)
  373. return function(itemstack, user, pointed_thing) -- closure
  374. if user then
  375. return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
  376. end
  377. end
  378. end
  379. function core.node_punch(pos, node, puncher, pointed_thing)
  380. -- Run script hook
  381. for _, callback in ipairs(core.registered_on_punchnodes) do
  382. -- Copy pos and node because callback can modify them
  383. local pos_copy = vector.copy(pos)
  384. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  385. local pointed_thing_copy = pointed_thing and copy_pointed_thing(pointed_thing) or nil
  386. callback(pos_copy, node_copy, puncher, pointed_thing_copy)
  387. end
  388. end
  389. function core.handle_node_drops(pos, drops, digger)
  390. -- Add dropped items to object's inventory
  391. local inv = digger and digger:get_inventory()
  392. local give_item
  393. if inv then
  394. give_item = function(item)
  395. return inv:add_item("main", item)
  396. end
  397. else
  398. give_item = function(item)
  399. -- itemstring to ItemStack for left:is_empty()
  400. return ItemStack(item)
  401. end
  402. end
  403. for _, dropped_item in pairs(drops) do
  404. local left = give_item(dropped_item)
  405. if not left:is_empty() then
  406. local p = vector.offset(pos,
  407. math.random()/2-0.25,
  408. math.random()/2-0.25,
  409. math.random()/2-0.25
  410. )
  411. core.add_item(p, left)
  412. end
  413. end
  414. end
  415. function core.node_dig(pos, node, digger)
  416. local diggername = user_name(digger)
  417. local log = make_log(diggername)
  418. local def = core.registered_nodes[node.name]
  419. -- Copy pos because the callback could modify it
  420. if def and (not def.diggable or
  421. (def.can_dig and not def.can_dig(vector.copy(pos), digger))) then
  422. log("info", diggername .. " tried to dig "
  423. .. node.name .. " which is not diggable "
  424. .. core.pos_to_string(pos))
  425. return false
  426. end
  427. if core.is_protected(pos, diggername) then
  428. log("action", diggername
  429. .. " tried to dig " .. node.name
  430. .. " at protected position "
  431. .. core.pos_to_string(pos))
  432. core.record_protection_violation(pos, diggername)
  433. return false
  434. end
  435. log('action', diggername .. " digs "
  436. .. node.name .. " at " .. core.pos_to_string(pos))
  437. local wielded = digger and digger:get_wielded_item()
  438. local drops = core.get_node_drops(node, wielded and wielded:get_name())
  439. if wielded then
  440. local wdef = wielded:get_definition()
  441. local tp = wielded:get_tool_capabilities()
  442. local dp = core.get_dig_params(def and def.groups, tp, wielded:get_wear())
  443. if wdef and wdef.after_use then
  444. wielded = wdef.after_use(wielded, digger, node, dp) or wielded
  445. else
  446. -- Wear out tool
  447. if not core.is_creative_enabled(diggername) then
  448. wielded:add_wear(dp.wear)
  449. if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then
  450. core.sound_play(wdef.sound.breaks, {
  451. pos = pos,
  452. gain = 0.5
  453. }, true)
  454. end
  455. end
  456. end
  457. digger:set_wielded_item(wielded)
  458. end
  459. -- Check to see if metadata should be preserved.
  460. if def and def.preserve_metadata then
  461. local oldmeta = core.get_meta(pos):to_table().fields
  462. -- Copy pos and node because the callback can modify them.
  463. local pos_copy = vector.copy(pos)
  464. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  465. local drop_stacks = {}
  466. for k, v in pairs(drops) do
  467. drop_stacks[k] = ItemStack(v)
  468. end
  469. drops = drop_stacks
  470. def.preserve_metadata(pos_copy, node_copy, oldmeta, drops)
  471. end
  472. -- Handle drops
  473. core.handle_node_drops(pos, drops, digger)
  474. local oldmetadata = nil
  475. if def and def.after_dig_node then
  476. oldmetadata = core.get_meta(pos):to_table()
  477. end
  478. -- Remove node and update
  479. core.remove_node(pos)
  480. -- Play sound if it was done by a player
  481. if diggername ~= "" and def and def.sounds and def.sounds.dug then
  482. core.sound_play(def.sounds.dug, {
  483. pos = pos,
  484. exclude_player = diggername,
  485. }, true)
  486. end
  487. -- Run callback
  488. if def and def.after_dig_node then
  489. -- Copy pos and node because callback can modify them
  490. local pos_copy = vector.copy(pos)
  491. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  492. def.after_dig_node(pos_copy, node_copy, oldmetadata, digger)
  493. end
  494. -- Run script hook
  495. for _, callback in ipairs(core.registered_on_dignodes) do
  496. local origin = core.callback_origins[callback]
  497. core.set_last_run_mod(origin.mod)
  498. -- Copy pos and node because callback can modify them
  499. local pos_copy = vector.copy(pos)
  500. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  501. callback(pos_copy, node_copy, digger)
  502. end
  503. return true
  504. end
  505. function core.itemstring_with_palette(item, palette_index)
  506. local stack = ItemStack(item) -- convert to ItemStack
  507. stack:get_meta():set_int("palette_index", palette_index)
  508. return stack:to_string()
  509. end
  510. function core.itemstring_with_color(item, colorstring)
  511. local stack = ItemStack(item) -- convert to ItemStack
  512. stack:get_meta():set_string("color", colorstring)
  513. return stack:to_string()
  514. end
  515. -- This is used to allow mods to redefine core.item_place and so on
  516. -- NOTE: This is not the preferred way. Preferred way is to provide enough
  517. -- callbacks to not require redefining global functions. -celeron55
  518. local function redef_wrapper(table, name)
  519. return function(...)
  520. return table[name](...)
  521. end
  522. end
  523. --
  524. -- Item definition defaults
  525. --
  526. local default_stack_max = tonumber(core.settings:get("default_stack_max")) or 99
  527. core.nodedef_default = {
  528. -- Item properties
  529. type="node",
  530. -- name intentionally not defined here
  531. description = "",
  532. groups = {},
  533. inventory_image = "",
  534. wield_image = "",
  535. wield_scale = vector.new(1, 1, 1),
  536. stack_max = default_stack_max,
  537. usable = false,
  538. liquids_pointable = false,
  539. tool_capabilities = nil,
  540. node_placement_prediction = nil,
  541. -- Interaction callbacks
  542. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  543. on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
  544. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  545. on_use = nil,
  546. can_dig = nil,
  547. on_punch = redef_wrapper(core, 'node_punch'), -- core.node_punch
  548. on_rightclick = nil,
  549. on_dig = redef_wrapper(core, 'node_dig'), -- core.node_dig
  550. on_receive_fields = nil,
  551. -- Node properties
  552. drawtype = "normal",
  553. visual_scale = 1.0,
  554. tiles = nil,
  555. special_tiles = nil,
  556. post_effect_color = {a=0, r=0, g=0, b=0},
  557. paramtype = "none",
  558. paramtype2 = "none",
  559. is_ground_content = true,
  560. sunlight_propagates = false,
  561. walkable = true,
  562. pointable = true,
  563. diggable = true,
  564. climbable = false,
  565. buildable_to = false,
  566. floodable = false,
  567. liquidtype = "none",
  568. liquid_alternative_flowing = "",
  569. liquid_alternative_source = "",
  570. liquid_viscosity = 0,
  571. drowning = 0,
  572. light_source = 0,
  573. damage_per_second = 0,
  574. selection_box = {type="regular"},
  575. legacy_facedir_simple = false,
  576. legacy_wallmounted = false,
  577. }
  578. core.craftitemdef_default = {
  579. type="craft",
  580. -- name intentionally not defined here
  581. description = "",
  582. groups = {},
  583. inventory_image = "",
  584. wield_image = "",
  585. wield_scale = vector.new(1, 1, 1),
  586. stack_max = default_stack_max,
  587. liquids_pointable = false,
  588. tool_capabilities = nil,
  589. -- Interaction callbacks
  590. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  591. on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
  592. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  593. on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
  594. on_use = nil,
  595. }
  596. core.tooldef_default = {
  597. type="tool",
  598. -- name intentionally not defined here
  599. description = "",
  600. groups = {},
  601. inventory_image = "",
  602. wield_image = "",
  603. wield_scale = vector.new(1, 1, 1),
  604. stack_max = 1,
  605. liquids_pointable = false,
  606. tool_capabilities = nil,
  607. -- Interaction callbacks
  608. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  609. on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
  610. on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
  611. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  612. on_use = nil,
  613. }
  614. core.noneitemdef_default = { -- This is used for the hand and unknown items
  615. type="none",
  616. -- name intentionally not defined here
  617. description = "",
  618. groups = {},
  619. inventory_image = "",
  620. wield_image = "",
  621. wield_scale = vector.new(1, 1, 1),
  622. stack_max = default_stack_max,
  623. liquids_pointable = false,
  624. tool_capabilities = nil,
  625. -- Interaction callbacks
  626. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  627. on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
  628. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  629. on_drop = nil,
  630. on_use = nil,
  631. }