item.lua 22 KB

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