2
0

item.lua 22 KB

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