item.lua 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  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. local an = core.get_item_group(def.name, "attached_node")
  222. if an ~= 0 and
  223. not builtin_shared.check_attached_node(place_to, newnode, an) then
  224. log("action", "attached node " .. def.name ..
  225. " cannot be placed at " .. core.pos_to_string(place_to))
  226. return itemstack, nil
  227. end
  228. log("action", playername .. " places node "
  229. .. def.name .. " at " .. core.pos_to_string(place_to))
  230. -- Add node and update
  231. core.add_node(place_to, newnode)
  232. -- Play sound if it was done by a player
  233. if playername ~= "" and def.sounds and def.sounds.place then
  234. core.sound_play(def.sounds.place, {
  235. pos = place_to,
  236. exclude_player = playername,
  237. }, true)
  238. end
  239. local take_item = true
  240. -- Run callback
  241. if def.after_place_node and not prevent_after_place then
  242. -- Deepcopy place_to and pointed_thing because callback can modify it
  243. local place_to_copy = vector.copy(place_to)
  244. local pointed_thing_copy = copy_pointed_thing(pointed_thing)
  245. if def.after_place_node(place_to_copy, placer, itemstack,
  246. pointed_thing_copy) then
  247. take_item = false
  248. end
  249. end
  250. -- Run script hook
  251. for _, callback in ipairs(core.registered_on_placenodes) do
  252. -- Deepcopy pos, node and pointed_thing because callback can modify them
  253. local place_to_copy = vector.copy(place_to)
  254. local newnode_copy = {name=newnode.name, param1=newnode.param1, param2=newnode.param2}
  255. local oldnode_copy = {name=oldnode.name, param1=oldnode.param1, param2=oldnode.param2}
  256. local pointed_thing_copy = copy_pointed_thing(pointed_thing)
  257. if callback(place_to_copy, newnode_copy, placer, oldnode_copy, itemstack, pointed_thing_copy) then
  258. take_item = false
  259. end
  260. end
  261. if take_item then
  262. itemstack:take_item()
  263. end
  264. return itemstack, place_to
  265. end
  266. -- deprecated, item_place does not call this
  267. function core.item_place_object(itemstack, placer, pointed_thing)
  268. local pos = core.get_pointed_thing_position(pointed_thing, true)
  269. if pos ~= nil then
  270. local item = itemstack:take_item()
  271. core.add_item(pos, item)
  272. end
  273. return itemstack
  274. end
  275. function core.item_place(itemstack, placer, pointed_thing, param2)
  276. -- Call on_rightclick if the pointed node defines it
  277. if pointed_thing.type == "node" and placer and
  278. not placer:get_player_control().sneak then
  279. local n = core.get_node(pointed_thing.under)
  280. local nn = n.name
  281. if core.registered_nodes[nn] and core.registered_nodes[nn].on_rightclick then
  282. return core.registered_nodes[nn].on_rightclick(pointed_thing.under, n,
  283. placer, itemstack, pointed_thing) or itemstack, nil
  284. end
  285. end
  286. -- Place if node, otherwise do nothing
  287. if itemstack:get_definition().type == "node" then
  288. return core.item_place_node(itemstack, placer, pointed_thing, param2)
  289. end
  290. return itemstack, nil
  291. end
  292. function core.item_secondary_use(itemstack, placer)
  293. return itemstack
  294. end
  295. function core.item_drop(itemstack, dropper, pos)
  296. local dropper_is_player = dropper and dropper:is_player()
  297. local p = table.copy(pos)
  298. local cnt = itemstack:get_count()
  299. if dropper_is_player then
  300. p.y = p.y + 1.2
  301. end
  302. local item = itemstack:take_item(cnt)
  303. local obj = core.add_item(p, item)
  304. if obj then
  305. if dropper_is_player then
  306. local dir = dropper:get_look_dir()
  307. dir.x = dir.x * 2.9
  308. dir.y = dir.y * 2.9 + 2
  309. dir.z = dir.z * 2.9
  310. obj:set_velocity(dir)
  311. obj:get_luaentity().dropped_by = dropper:get_player_name()
  312. end
  313. return itemstack
  314. end
  315. -- If we reach this, adding the object to the
  316. -- environment failed
  317. end
  318. function core.item_pickup(itemstack, picker, pointed_thing, ...)
  319. itemstack = ItemStack(itemstack)
  320. -- Invoke global on_item_pickup callbacks.
  321. for _, callback in ipairs(core.registered_on_item_pickups) do
  322. local result = callback(itemstack, picker, pointed_thing, ...)
  323. if result then
  324. return ItemStack(result)
  325. end
  326. end
  327. -- Pickup item.
  328. local inv = picker and picker:get_inventory()
  329. if inv then
  330. return inv:add_item("main", itemstack)
  331. end
  332. return itemstack
  333. end
  334. function core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
  335. for _, callback in ipairs(core.registered_on_item_eats) do
  336. local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing)
  337. if result then
  338. return result
  339. end
  340. end
  341. -- read definition before potentially emptying the stack
  342. local def = itemstack:get_definition()
  343. if itemstack:take_item():is_empty() then
  344. return itemstack
  345. end
  346. if def and def.sound and def.sound.eat then
  347. core.sound_play(def.sound.eat, {
  348. pos = user:get_pos(),
  349. max_hear_distance = 16
  350. }, true)
  351. end
  352. -- Changing hp might kill the player causing mods to do who-knows-what to the
  353. -- inventory, so do this before set_hp().
  354. if replace_with_item then
  355. if itemstack:is_empty() then
  356. itemstack:add_item(replace_with_item)
  357. else
  358. local inv = user:get_inventory()
  359. -- Check if inv is null, since non-players don't have one
  360. if inv and inv:room_for_item("main", {name=replace_with_item}) then
  361. inv:add_item("main", replace_with_item)
  362. else
  363. local pos = user:get_pos()
  364. pos.y = math.floor(pos.y + 0.5)
  365. core.add_item(pos, replace_with_item)
  366. end
  367. end
  368. end
  369. user:set_wielded_item(itemstack)
  370. user:set_hp(user:get_hp() + hp_change)
  371. return nil -- don't overwrite wield item a second time
  372. end
  373. function core.item_eat(hp_change, replace_with_item)
  374. return function(itemstack, user, pointed_thing) -- closure
  375. if user then
  376. return core.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
  377. end
  378. end
  379. end
  380. function core.node_punch(pos, node, puncher, pointed_thing)
  381. -- Run script hook
  382. for _, callback in ipairs(core.registered_on_punchnodes) do
  383. -- Copy pos and node because callback can modify them
  384. local pos_copy = vector.copy(pos)
  385. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  386. local pointed_thing_copy = pointed_thing and copy_pointed_thing(pointed_thing) or nil
  387. callback(pos_copy, node_copy, puncher, pointed_thing_copy)
  388. end
  389. end
  390. function core.handle_node_drops(pos, drops, digger)
  391. -- Add dropped items to object's inventory
  392. local inv = digger and digger:get_inventory()
  393. local give_item
  394. if inv then
  395. give_item = function(item)
  396. return inv:add_item("main", item)
  397. end
  398. else
  399. give_item = function(item)
  400. -- itemstring to ItemStack for left:is_empty()
  401. return ItemStack(item)
  402. end
  403. end
  404. for _, dropped_item in pairs(drops) do
  405. local left = give_item(dropped_item)
  406. if not left:is_empty() then
  407. local p = vector.offset(pos,
  408. math.random()/2-0.25,
  409. math.random()/2-0.25,
  410. math.random()/2-0.25
  411. )
  412. core.add_item(p, left)
  413. end
  414. end
  415. end
  416. function core.node_dig(pos, node, digger)
  417. local diggername = user_name(digger)
  418. local log = make_log(diggername)
  419. local def = core.registered_nodes[node.name]
  420. -- Copy pos because the callback could modify it
  421. if def and (not def.diggable or
  422. (def.can_dig and not def.can_dig(vector.copy(pos), digger))) then
  423. log("info", diggername .. " tried to dig "
  424. .. node.name .. " which is not diggable "
  425. .. core.pos_to_string(pos))
  426. return false
  427. end
  428. if core.is_protected(pos, diggername) then
  429. log("action", diggername
  430. .. " tried to dig " .. node.name
  431. .. " at protected position "
  432. .. core.pos_to_string(pos))
  433. core.record_protection_violation(pos, diggername)
  434. return false
  435. end
  436. log('action', diggername .. " digs "
  437. .. node.name .. " at " .. core.pos_to_string(pos))
  438. local wielded = digger and digger:get_wielded_item()
  439. local drops = core.get_node_drops(node, wielded and wielded:get_name())
  440. if wielded then
  441. local wdef = wielded:get_definition()
  442. local tp = wielded:get_tool_capabilities()
  443. local dp = core.get_dig_params(def and def.groups, tp, wielded:get_wear())
  444. if wdef and wdef.after_use then
  445. wielded = wdef.after_use(wielded, digger, node, dp) or wielded
  446. else
  447. -- Wear out tool
  448. if not core.is_creative_enabled(diggername) then
  449. wielded:add_wear(dp.wear)
  450. if wielded:get_count() == 0 and wdef.sound and wdef.sound.breaks then
  451. core.sound_play(wdef.sound.breaks, {
  452. pos = pos,
  453. gain = 0.5
  454. }, true)
  455. end
  456. end
  457. end
  458. digger:set_wielded_item(wielded)
  459. end
  460. -- Check to see if metadata should be preserved.
  461. if def and def.preserve_metadata then
  462. local oldmeta = core.get_meta(pos):to_table().fields
  463. -- Copy pos and node because the callback can modify them.
  464. local pos_copy = vector.copy(pos)
  465. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  466. local drop_stacks = {}
  467. for k, v in pairs(drops) do
  468. drop_stacks[k] = ItemStack(v)
  469. end
  470. drops = drop_stacks
  471. def.preserve_metadata(pos_copy, node_copy, oldmeta, drops)
  472. end
  473. -- Handle drops
  474. core.handle_node_drops(pos, drops, digger)
  475. local oldmetadata = nil
  476. if def and def.after_dig_node then
  477. oldmetadata = core.get_meta(pos):to_table()
  478. end
  479. -- Remove node and update
  480. core.remove_node(pos)
  481. -- Play sound if it was done by a player
  482. if diggername ~= "" and def and def.sounds and def.sounds.dug then
  483. core.sound_play(def.sounds.dug, {
  484. pos = pos,
  485. exclude_player = diggername,
  486. }, true)
  487. end
  488. -- Run callback
  489. if def and def.after_dig_node then
  490. -- Copy pos and node because callback can modify them
  491. local pos_copy = vector.copy(pos)
  492. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  493. def.after_dig_node(pos_copy, node_copy, oldmetadata, digger)
  494. end
  495. -- Run script hook
  496. for _, callback in ipairs(core.registered_on_dignodes) do
  497. local origin = core.callback_origins[callback]
  498. core.set_last_run_mod(origin.mod)
  499. -- Copy pos and node because callback can modify them
  500. local pos_copy = vector.copy(pos)
  501. local node_copy = {name=node.name, param1=node.param1, param2=node.param2}
  502. callback(pos_copy, node_copy, digger)
  503. end
  504. return true
  505. end
  506. function core.itemstring_with_palette(item, palette_index)
  507. local stack = ItemStack(item) -- convert to ItemStack
  508. stack:get_meta():set_int("palette_index", palette_index)
  509. return stack:to_string()
  510. end
  511. function core.itemstring_with_color(item, colorstring)
  512. local stack = ItemStack(item) -- convert to ItemStack
  513. stack:get_meta():set_string("color", colorstring)
  514. return stack:to_string()
  515. end
  516. -- This is used to allow mods to redefine core.item_place and so on
  517. -- NOTE: This is not the preferred way. Preferred way is to provide enough
  518. -- callbacks to not require redefining global functions. -celeron55
  519. local function redef_wrapper(table, name)
  520. return function(...)
  521. return table[name](...)
  522. end
  523. end
  524. --
  525. -- Item definition defaults
  526. --
  527. local default_stack_max = tonumber(core.settings:get("default_stack_max")) or 99
  528. core.nodedef_default = {
  529. -- Item properties
  530. type="node",
  531. -- name intentionally not defined here
  532. description = "",
  533. groups = {},
  534. inventory_image = "",
  535. wield_image = "",
  536. wield_scale = vector.new(1, 1, 1),
  537. stack_max = default_stack_max,
  538. usable = false,
  539. liquids_pointable = false,
  540. tool_capabilities = nil,
  541. node_placement_prediction = nil,
  542. -- Interaction callbacks
  543. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  544. on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
  545. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  546. on_use = nil,
  547. can_dig = nil,
  548. on_punch = redef_wrapper(core, 'node_punch'), -- core.node_punch
  549. on_rightclick = nil,
  550. on_dig = redef_wrapper(core, 'node_dig'), -- core.node_dig
  551. on_receive_fields = nil,
  552. -- Node properties
  553. drawtype = "normal",
  554. visual_scale = 1.0,
  555. tiles = nil,
  556. special_tiles = nil,
  557. post_effect_color = {a=0, r=0, g=0, b=0},
  558. paramtype = "none",
  559. paramtype2 = "none",
  560. is_ground_content = true,
  561. sunlight_propagates = false,
  562. walkable = true,
  563. pointable = true,
  564. diggable = true,
  565. climbable = false,
  566. buildable_to = false,
  567. floodable = false,
  568. liquidtype = "none",
  569. liquid_alternative_flowing = "",
  570. liquid_alternative_source = "",
  571. liquid_viscosity = 0,
  572. drowning = 0,
  573. light_source = 0,
  574. damage_per_second = 0,
  575. selection_box = {type="regular"},
  576. legacy_facedir_simple = false,
  577. legacy_wallmounted = false,
  578. }
  579. core.craftitemdef_default = {
  580. type="craft",
  581. -- name intentionally not defined here
  582. description = "",
  583. groups = {},
  584. inventory_image = "",
  585. wield_image = "",
  586. wield_scale = vector.new(1, 1, 1),
  587. stack_max = default_stack_max,
  588. liquids_pointable = false,
  589. tool_capabilities = nil,
  590. -- Interaction callbacks
  591. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  592. on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
  593. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  594. on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
  595. on_use = nil,
  596. }
  597. core.tooldef_default = {
  598. type="tool",
  599. -- name intentionally not defined here
  600. description = "",
  601. groups = {},
  602. inventory_image = "",
  603. wield_image = "",
  604. wield_scale = vector.new(1, 1, 1),
  605. stack_max = 1,
  606. liquids_pointable = false,
  607. tool_capabilities = nil,
  608. -- Interaction callbacks
  609. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  610. on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
  611. on_drop = redef_wrapper(core, 'item_drop'), -- core.item_drop
  612. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  613. on_use = nil,
  614. }
  615. core.noneitemdef_default = { -- This is used for the hand and unknown items
  616. type="none",
  617. -- name intentionally not defined here
  618. description = "",
  619. groups = {},
  620. inventory_image = "",
  621. wield_image = "",
  622. wield_scale = vector.new(1, 1, 1),
  623. stack_max = default_stack_max,
  624. liquids_pointable = false,
  625. tool_capabilities = nil,
  626. -- Interaction callbacks
  627. on_place = redef_wrapper(core, 'item_place'), -- core.item_place
  628. on_secondary_use = redef_wrapper(core, 'item_secondary_use'),
  629. on_pickup = redef_wrapper(core, 'item_pickup'), -- core.item_pickup
  630. on_drop = nil,
  631. on_use = nil,
  632. }