init.lua 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. if not minetest.global_exists("default") then default = {} end
  2. if not minetest.global_exists("utility") then utility = {} end
  3. utility.modpath = minetest.get_modpath("utility")
  4. -- Localize for performance.
  5. local vector_round = vector.round
  6. local math_floor = math.floor
  7. local math_random = math.random
  8. dofile(utility.modpath .. "/sound_compat.lua")
  9. -- Dummy function.
  10. fireambiance = {}
  11. function fireambiance.on_flame_addremove(pos)
  12. end
  13. function utility.trim_remove_special_chars(msg)
  14. local sub = string.gsub
  15. msg = sub(msg, "%z", "") -- Zero byte.
  16. msg = sub(msg, "%c", "") -- Control bytes.
  17. -- Trim whitespace.
  18. msg = sub(msg, "^%s+", "")
  19. msg = sub(msg, "%s+$", "")
  20. return msg
  21. end
  22. -- Minetest's armor resistance calculation assumes that if an armor group is NOT
  23. -- specified, then all damage that WOULD have been applied through that kind of
  24. -- armor is completely nullified. This is stupid ... if an entity doesn't specify
  25. -- an armor group, then for purposes of damage calculation, the code SHOULD behave
  26. -- as if all damage for that damage group is applied. But whatever. This function
  27. -- fixes that by pre-defining all damage groups used in Enyekala, and setting them
  28. -- to 100 (means 100% of damage passes through that type of armor, without being
  29. -- mitigated).
  30. --
  31. -- Note: many weapons use a special damage_group, 'knockback', which should NOT
  32. -- have a corresponding armor group, because it is treated specially.
  33. function utility.builtin_armor_groups(groups)
  34. local tb = {
  35. -- Slashing/cutting.
  36. fleshy = 100,
  37. -- Bashing.
  38. cracky = 100,
  39. -- Withering.
  40. crumbly = 100,
  41. -- Piercing/striking.
  42. snappy = 100,
  43. -- Cleaving.
  44. choppy = 100,
  45. -- Aura/magic.
  46. radiation = 100,
  47. -- Explosives.
  48. boom = 100,
  49. -- Poison.
  50. poison = 100,
  51. -- Magic I guess.
  52. electrocute = 100,
  53. -- Ranged.
  54. arrow = 100,
  55. -- Ranged fire.
  56. fireball = 100,
  57. -- Water, usually.
  58. pressure = 100,
  59. -- Falling stuff. Or being hugged by a golem.
  60. crush = 100,
  61. -- Heat sources.
  62. heat = 100,
  63. -- Extreme heat from lava.
  64. lava = 100,
  65. }
  66. if groups then
  67. for k, v in pairs(groups) do
  68. tb[k] = v
  69. end
  70. end
  71. return tb
  72. end
  73. -- `level = 0/1, snappy = 3` enables quick digging via shears.
  74. -- Otherwise item cannot be dug by shears at all.
  75. --
  76. -- The 'hand' only digs items `level = 0` or `level = 1`, with some additional
  77. -- restrictions. See tool-data file for details.
  78. --
  79. -- Important/hard-to-craft nodes should be level 0 (like machines) otherwise
  80. -- player will lose the item if dug with a tool without a high enough level.
  81. --
  82. -- Shears only dig nodes with `level = 0/1, snappy = 3`.
  83. --
  84. -- `oddly_breakable_by_hand` only works if `level = 0/1`. HOWEVER, node drops
  85. -- can ONLY be obtained if the node's level is 0! Level 1 nodes may be dug if
  86. -- they're `oddly_breakable_by_hand`, but the player won't get the drops.
  87. --
  88. -- Base hardness for regular stone is `level = 2, cracky = 2`. Cobble is at
  89. -- `level = 1, cracky = 3`. These are both carefully tuned to allow new players
  90. -- to advance: wooden pick digs cobble to make stone pick, and a stone pick is
  91. -- able to dig regular stone. All other rocks/stones in the game should have
  92. -- their hardness calculated around regular stone/cobble.
  93. --
  94. -- The base hardness for tree trunks is `level = 2, choppy = 2`. Wood is
  95. -- calculated at `level = 2, choppy = 3`. All other wooden nodes should be
  96. -- calculated around these two.
  97. local dig_groups = {}
  98. -- Special undiggable group.
  99. dig_groups["ignore"] = {}
  100. -- Cracky stuff (stones/rocks/minerals).
  101. dig_groups["stone"] = {level = 2, cracky = 2} -- Carefully tuned dig-params! Do not modify.
  102. dig_groups["softstone"] = {level = 2, cracky = 3} -- Like sandstone.
  103. dig_groups["cobble"] = {level = 1, cracky = 3} -- Must be `cracky=3` otherwise cannot be dug by wooden pick.
  104. dig_groups["softcobble"] = {level = 1, cracky = 3, crumbly = 1} -- Can be dug by wodden pick.
  105. dig_groups["clay"] = {level = 0, cracky = 2, crumbly = 2}
  106. dig_groups["hardore"] = {level = 2, cracky = 1}
  107. dig_groups["hardclay"] = {level = 1, cracky = 2}
  108. dig_groups["ice"] = {level = 0, cracky = 2}
  109. dig_groups["hardice"] = {level = 1, cracky = 1}
  110. dig_groups["glass"] = {level = 1, cracky = 3}
  111. dig_groups["netherack"] = {level = 1, cracky = 3, oddly_breakable_by_hand = 1} -- Easiest thing to dig, practically!
  112. dig_groups["mineral"] = {level = 2, cracky = 3}
  113. dig_groups["hardmineral"] = {level = 2, cracky = 1}
  114. dig_groups["obsidian"] = {level = 3, cracky = 1} -- Obsidian, etc. Hardest possible.
  115. dig_groups["hardstone"] = {level = 3, cracky = 2} -- Granites, marbles.
  116. dig_groups["crystal"] = {level = 2, cracky = 3}
  117. -- Cracky stuff (building blocks/walls/bricks/etc).
  118. dig_groups["wall"] = {level = 1, cracky = 2}
  119. dig_groups["brick"] = {level = 1, cracky = 1}
  120. dig_groups["block"] = {level = 1, cracky = 1} -- Stone blocks, metal blocks, etc.
  121. -- Crumbly stuff (loose earth material).
  122. dig_groups["gravel"] = {level = 2, crumbly = 2} -- Cannot be dug by hand (level 1).
  123. dig_groups["dirt"] = {level = 2, crumbly = 3}
  124. dig_groups["sand"] = {level = 1, crumbly = 2}
  125. dig_groups["snow"] = {level = 0, crumbly = 3, oddly_breakable_by_hand = 3}
  126. dig_groups["mud"] = {level = 0, crumbly = 3, oddly_breakable_by_hand = 1}
  127. dig_groups["racksand"] = {level = 2, crumbly = 3}
  128. -- Choppy stuff (trees/wood).
  129. dig_groups["tree"] = {level = 2, choppy = 2} -- Carefully tuned dig-params! Do not change.
  130. dig_groups["deadtree"] = {level = 0, choppy = 2, oddly_breakable_by_hand = 1}
  131. dig_groups["wood"] = {level = 2, choppy = 3} -- Also wooden 'blocklike'. Planks & stuff.
  132. dig_groups["nyan"] = {level = 3, choppy = 1}
  133. -- Choppy stuff (crafted building materials).
  134. dig_groups["hardwood"] = {level = 1, choppy = 1}
  135. dig_groups["softwood"] = {level = 1, choppy = 3} -- Cactus, etc.
  136. -- Snappy stuff (plants/crops/leaves).
  137. -- Plants/crops can be dug by hand, but leaves cannot without proper tool.
  138. -- Addendum: player can dig leaves by hand but won't get drops.
  139. dig_groups["leaves"] = {level = 1, snappy = 3, choppy = 2, oddly_breakable_by_hand = 1} -- Must be `snappy=3` otherwise shears won't work.
  140. dig_groups["seeds"] = {level = 1, snappy = 2, oddly_breakable_by_hand = 3}
  141. dig_groups["plant"] = {level = 0, snappy = 3, choppy = 2} -- Must be `snappy=3` otherwise shears won't work.
  142. dig_groups["crop"] = {level = 0, snappy = 3, choppy = 2} -- Ditto ^^^. Also diggable by hand.
  143. dig_groups["straw"] = {level = 1, snappy = 2, choppy = 1, oddly_breakable_by_hand = 1}
  144. dig_groups["shroom"] = {level = 1, snappy = 2, choppy = 3, oddly_breakable_by_hand = 1}
  145. -- Misc items (items/machines/furniture/etc).
  146. dig_groups["wool"] = {level = 1, snappy = 3, choppy = 3}
  147. dig_groups["pane_wood"] = {level = 1, choppy = 3}
  148. dig_groups["pane_metal"] = {level = 1, cracky = 2}
  149. dig_groups["pane_glass"] = {level = 1, cracky = 3}
  150. dig_groups["fence_metal"] = {level = 1, cracky = 2}
  151. dig_groups["fence_wood"] = {level = 1, choppy = 2}
  152. dig_groups["furniture"] = {level = 0, snappy = 1, choppy = 3, oddly_breakable_by_hand = 3}
  153. dig_groups["item"] = {level = 0, dig_immediate = 3}
  154. dig_groups["bigitem"] = {level = 0, dig_immediate = 2}
  155. dig_groups["door_metal"] = {level = 1, cracky = 1}
  156. dig_groups["door_glass"] = {level = 1, cracky = 2}
  157. dig_groups["door_wood"] = {level = 1, choppy = 2}
  158. dig_groups["door_woodglass"]= {level = 1, choppy = 1}
  159. dig_groups["door_stone"] = {level = 1, cracky = 1}
  160. dig_groups["scaffolding"] = {level = 0, dig_immediate = 2}
  161. dig_groups["chest"] = {level = 0, choppy = 3, oddly_breakable_by_hand = 3}
  162. dig_groups["metalchest"] = {level = 0, cracky = 3, oddly_breakable_by_hand = 3}
  163. dig_groups["machine"] = {level = 0, cracky = 3} -- Must be level 0, or player may lose machine when dug!
  164. -- Get dig groups for a node based on its broad category.
  165. -- When choosing a name for a node, choose the name closest to the node's main material.
  166. function utility.dig_groups(name, ex)
  167. local groups = {}
  168. if not dig_groups[name] then
  169. minetest.log("error", "Could not find data for digging group '" .. name .. "'!")
  170. end
  171. local dig = dig_groups[name] or {level = 1, oddly_breakable_by_hand = 3}
  172. for k, v in pairs(dig) do
  173. groups[k] = v
  174. end
  175. -- Let custom groups override, include other stuff from groups.
  176. if ex then
  177. for k, v in pairs(ex) do
  178. groups[k] = v
  179. end
  180. end
  181. return groups
  182. end
  183. -- Copy standard/builtin groups only.
  184. -- Used mainly to ensure that stairs/microblock nodes don't include strange groups
  185. -- that should ONLY apply to their parent fullblock nodes.
  186. --
  187. -- Shall not return any groups used in crafting recipes!
  188. -- Shall return any/all groups required by tools!
  189. function utility.copy_builtin_groups(old_groups)
  190. local groups = {}
  191. groups.level = old_groups.level or 1
  192. if old_groups.crumbly then
  193. groups.crumbly = old_groups.crumbly
  194. end
  195. if old_groups.cracky then
  196. groups.cracky = old_groups.cracky
  197. end
  198. if old_groups.snappy then
  199. groups.snappy = old_groups.snappy
  200. end
  201. if old_groups.choppy then
  202. groups.choppy = old_groups.choppy
  203. end
  204. if old_groups.oddly_breakable_by_hand then
  205. groups.oddly_breakable_by_hand = old_groups.oddly_breakable_by_hand
  206. end
  207. if old_groups.flammable then
  208. groups.flammable = old_groups.flammable
  209. end
  210. if old_groups.dig_immediate then
  211. groups.dig_immediate = old_groups.dig_immediate
  212. end
  213. return groups
  214. end
  215. function utility.inventory_count_items(inv, listname, itemname)
  216. local list = inv:get_list(listname)
  217. local count = 0
  218. for i = 1, #list, 1 do
  219. if list[i]:get_name() == itemname then
  220. count = count + list[i]:get_count()
  221. end
  222. end
  223. return count
  224. end
  225. function utility.get_short_desc(str)
  226. if string.find(str, "[\n%(]") then
  227. str = string.sub(str, 1, string.find(str, "[\n%(]")-1)
  228. end
  229. str = string.gsub(str, "^%s+", "")
  230. str = string.gsub(str, "%s+$", "")
  231. return str
  232. end
  233. dofile(utility.modpath .. "/particle_override.lua")
  234. dofile(utility.modpath .. "/mapsave.lua")
  235. dofile(utility.modpath .. "/functions.lua")
  236. dofile(utility.modpath .. "/getopts.lua")
  237. -- Get a player's foot position, given the player's position.
  238. -- Should help compatibility going into 0.5.0 and beyond.
  239. function utility.get_foot_pos(pos)
  240. return vector.add(pos, {x=0, y=0, z=0})
  241. end
  242. function utility.get_middle_pos(pos)
  243. return vector.add(pos, {x=0, y=1, z=0})
  244. end
  245. function utility.get_head_pos(pos)
  246. return vector.add(pos, {x=0, y=1.75, z=0})
  247. end
  248. -- Get rounded position of node player is standing on.
  249. function utility.node_under_pos(pos)
  250. return vector_round(vector.add(pos, {x=0, y=-0.05, z=0}))
  251. end
  252. -- Global multipliers for ABMs. Performance setting.
  253. default.ABM_TIMER_MULTIPLIER = 1
  254. default.ABM_CHANCE_MULTIPLIER = 2
  255. -- Global player-movement multiplier values.
  256. default.ROAD_SPEED = 1.3
  257. default.ROAD_SPEED_NETHER = 1.1
  258. default.ROAD_SPEED_CAVERN = 1.15
  259. default.SLOW_SPEED = 0.7
  260. default.SLOW_SPEED_SNOW_LIGHT = 0.95
  261. default.SLOW_SPEED_SNOW = 0.75
  262. default.SLOW_SPEED_SNOW_THICK = 0.6
  263. default.SLOW_SPEED_SNOW_TRACKS_ADDITIVE = 0.15
  264. default.SLOW_SPEED_NETHER = 0.85
  265. default.SLOW_SPEED_ICE = 0.85
  266. default.SLOW_SPEED_GRASS = 0.85
  267. default.SLOW_SPEED_PLANTS = 0.55
  268. default.NORM_SPEED = 1.0
  269. default.ROPE_SPEED = 1.1
  270. default.FAST_JUMP = 1.0
  271. default.SLOW_JUMP = 1.0
  272. default.NORM_JUMP = 1.0
  273. function utility.transform_nodebox(nodebox)
  274. for k, v in ipairs(nodebox) do
  275. for m, n in ipairs(v) do
  276. local p = nodebox[k][m]
  277. p = p / 16
  278. p = p - 0.5
  279. nodebox[k][m] = p
  280. end
  281. end
  282. return nodebox
  283. end
  284. -- Public API function. Sort two positions such that the first is always less than the second.
  285. utility.sort_positions = function(p1, p2)
  286. local pos1 = {x=p1.x, y=p1.y, z=p1.z}
  287. local pos2 = {x=p2.x, y=p2.y, z=p2.z}
  288. if pos1.x > pos2.x then pos2.x, pos1.x = pos1.x, pos2.x end
  289. if pos1.y > pos2.y then pos2.y, pos1.y = pos1.y, pos2.y end
  290. if pos1.z > pos2.z then pos2.z, pos1.z = pos1.z, pos2.z end
  291. return pos1, pos2
  292. end
  293. --
  294. -- optimized helper to put all items in an inventory into a drops list
  295. --
  296. function default.get_inventory_drops(pos, inventory, drops)
  297. local inv = minetest.get_meta(pos):get_inventory()
  298. local n = #drops
  299. for i = 1, inv:get_size(inventory) do
  300. local stack = inv:get_stack(inventory, i)
  301. if stack:get_count() > 0 then
  302. drops[n+1] = stack:to_table()
  303. n = n + 1
  304. end
  305. end
  306. end
  307. --
  308. -- dig upwards
  309. --
  310. function default.dig_up(pos, node, digger)
  311. if digger == nil then return end
  312. local np = {x = pos.x, y = pos.y + 1, z = pos.z}
  313. local nn = minetest.get_node(np)
  314. if nn.name == node.name then
  315. minetest.node_dig(np, nn, digger)
  316. end
  317. end
  318. function default.dig_down(pos, node, digger)
  319. if digger == nil then return end
  320. local np = {x = pos.x, y = pos.y - 1, z = pos.z}
  321. local nn = minetest.get_node(np)
  322. if nn.name == node.name then
  323. minetest.node_dig(np, nn, digger)
  324. end
  325. end
  326. --
  327. -- Checks if specified volume intersects a protected volume
  328. --
  329. function default.intersects_protection(minp, maxp, player_name, interval)
  330. -- 'interval' is the largest allowed interval for the 3D lattice of checks
  331. -- Compute the optimal float step 'd' for each axis so that all corners and
  332. -- borders are checked. 'd' will be smaller or equal to 'interval'.
  333. -- Subtracting 1e-4 ensures that the max co-ordinate will be reached by the
  334. -- for loop (which might otherwise not be the case due to rounding errors).
  335. local d = {}
  336. for _, c in pairs({"x", "y", "z"}) do
  337. if maxp[c] > minp[c] then
  338. d[c] = (maxp[c] - minp[c]) / math.ceil((maxp[c] - minp[c]) / interval) - 1e-4
  339. elseif maxp[c] == minp[c] then
  340. d[c] = 1 -- Any value larger than 0 to avoid division by zero
  341. else -- maxp[c] < minp[c], print error and treat as protection intersected
  342. minetest.log("error", "maxp < minp in 'default.intersects_protection()'")
  343. return true
  344. end
  345. end
  346. for zf = minp.z, maxp.z, d.z do
  347. local z = math_floor(zf + 0.5)
  348. for yf = minp.y, maxp.y, d.y do
  349. local y = math_floor(yf + 0.5)
  350. for xf = minp.x, maxp.x, d.x do
  351. local x = math_floor(xf + 0.5)
  352. if minetest.test_protection({x = x, y = y, z = z}, player_name) then
  353. return true
  354. end
  355. end
  356. end
  357. end
  358. return false
  359. end
  360. default.get_raillike_selection_box = function()
  361. return {
  362. type = "fixed",
  363. -- but how to specify the dimensions for curved and sideways rails?
  364. fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
  365. }
  366. end
  367. default.get_raillike_collision_box = function()
  368. return {
  369. type = "fixed",
  370. fixed = {
  371. {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
  372. },
  373. }
  374. end
  375. --
  376. -- Sapling 'on place' function to check protection of node and resulting tree volume
  377. --
  378. function default.sapling_on_place(itemstack, placer, pointed_thing,
  379. sapling_name, minp_relative, maxp_relative, interval)
  380. -- Position of sapling
  381. local pos = pointed_thing.under
  382. local node = minetest.get_node_or_nil(pos)
  383. local pdef = node and minetest.reg_ns_nodes[node.name]
  384. if pdef and pdef.on_rightclick and not placer:get_player_control().sneak then
  385. return pdef.on_rightclick(pos, node, placer, itemstack, pointed_thing)
  386. end
  387. if not pdef or not pdef.buildable_to then
  388. pos = pointed_thing.above
  389. node = minetest.get_node_or_nil(pos)
  390. pdef = node and minetest.reg_ns_nodes[node.name]
  391. if not pdef or not pdef.buildable_to then
  392. return itemstack
  393. end
  394. end
  395. local player_name = placer:get_player_name()
  396. -- Check sapling position for protection
  397. if minetest.is_protected(pos, player_name) then
  398. minetest.record_protection_violation(pos, player_name)
  399. return itemstack
  400. end
  401. -- Check tree volume for protection
  402. if default.intersects_protection(
  403. vector.add(pos, vector.add(minp_relative, {x=-1, y=0, z=-1})),
  404. vector.add(pos, vector.add(maxp_relative, {x=1, y=1, z=1})),
  405. player_name,
  406. interval) then
  407. minetest.record_protection_violation(pos, player_name)
  408. -- Print extra information to explain
  409. minetest.chat_send_player(player_name, "# Server: Tree may intersect protection!")
  410. return itemstack
  411. end
  412. minetest.log("action", player_name .. " places node "
  413. .. sapling_name .. " at " .. minetest.pos_to_string(pos))
  414. local take_item = true
  415. local newnode = {name = sapling_name}
  416. local ndef = minetest.reg_ns_nodes[sapling_name]
  417. minetest.set_node(pos, newnode)
  418. -- Run callback
  419. if ndef and ndef.after_place_node then
  420. -- Deepcopy place_to and pointed_thing because callback can modify it
  421. if ndef.after_place_node(table.copy(pos), placer,
  422. itemstack, table.copy(pointed_thing)) then
  423. take_item = false
  424. end
  425. end
  426. -- Run script hook
  427. for _, callback in ipairs(minetest.registered_on_placenodes) do
  428. -- Deepcopy pos, node and pointed_thing because callback can modify them
  429. if callback(table.copy(pos), table.copy(newnode),
  430. placer, table.copy(node or {}),
  431. itemstack, table.copy(pointed_thing)) then
  432. take_item = false
  433. end
  434. end
  435. -- Notify other hooks.
  436. dirtspread.on_environment(pos)
  437. droplift.notify(pos)
  438. if take_item then
  439. itemstack:take_item()
  440. end
  441. return itemstack
  442. end
  443. --
  444. -- NOTICE: This method is not an official part of the API yet!
  445. -- This method may change in future.
  446. --
  447. function utility.can_interact_with_node(player, pos)
  448. if player then
  449. if minetest.check_player_privs(player, "protection_bypass") then
  450. return true
  451. end
  452. else
  453. return false
  454. end
  455. local meta = minetest.get_meta(pos)
  456. local owner = meta:get_string("owner") or ""
  457. if owner == "" or owner == player:get_player_name() then
  458. -- Owner can access the node to any time
  459. return true
  460. end
  461. -- is player wielding the right key?
  462. local item = player:get_wielded_item()
  463. if item:get_name() == "key:key" or item:get_name() == "key:chain" then
  464. local key_meta = item:get_meta()
  465. if key_meta:get_string("secret") == "" then
  466. local key_oldmeta = item:get_metadata()
  467. if key_oldmeta == "" or not minetest.parse_json(key_oldmeta) then
  468. return false
  469. end
  470. key_meta:set_string("secret", minetest.parse_json(key_oldmeta).secret)
  471. item:set_metadata("")
  472. end
  473. return meta:get_string("key_lock_secret") == key_meta:get_string("secret")
  474. end
  475. return false
  476. end
  477. -- Called from bones mod to ensure the map is loaded before placing bones.
  478. -- Dunno if this has any real effect on the problem of bones disappearing.
  479. function utility.ensure_map_loaded(minp, maxp)
  480. local vm = minetest.get_voxel_manip()
  481. vm:read_from_map(minp, maxp)
  482. return vm:get_emerged_area() -- Return area actually loaded.
  483. end
  484. function table.shuffle(t, from, to, random)
  485. from = from or 1
  486. to = to or #t
  487. random = random or math_random
  488. local n = to - from + 1
  489. while n > 1 do
  490. local r = from + n-1
  491. local l = from + random(0, n-1)
  492. t[l], t[r] = t[r], t[l]
  493. n = n-1
  494. end
  495. end
  496. -- A helper for formspecs which need to show a progress image.
  497. -- Note: percent value is assumed to be an integer, but if it's a float,
  498. -- anthing less than 1 will be treated as 0!
  499. function utility.progress_image(x, y, bg, fg, percent, modifier)
  500. if not modifier then
  501. modifier = ""
  502. end
  503. if percent < 1 then
  504. -- Must handle this case specially, because otherwise Minetest will insist
  505. -- on drawing at least 1 row of pixels from the FG image, even when percent
  506. -- is zero!
  507. return "image[" .. x .. "," .. y .. ";1,1;" .. bg .. modifier .. "]"
  508. else
  509. return "image[" .. x .. "," .. y .. ";1,1;" .. bg .. "^[lowpart:" ..
  510. (percent) .. ":" .. fg .. modifier .. "]"
  511. end
  512. end
  513. minetest.register_alias("akalin:ore_mined", "akalin:ore")
  514. minetest.register_alias("alatro:ore_mined", "alatro:ore")
  515. minetest.register_alias("arol:ore_mined", "arol:ore")
  516. minetest.register_alias("chromium:ore_mined", "chromium:ore")
  517. minetest.register_alias("default:stone_with_diamond_mined", "default:stone_with_diamond")
  518. minetest.register_alias("default:stone_with_gold_mined", "default:stone_with_gold")
  519. minetest.register_alias("default:desert_stone_with_diamond_mined", "default:desert_stone_with_diamond")
  520. minetest.register_alias("default:desert_stone_with_iron_mined", "default:desert_stone_with_iron")
  521. minetest.register_alias("default:desert_stone_with_copper_mined", "default:desert_stone_with_copper")
  522. minetest.register_alias("default:stone_with_copper_mined", "default:stone_with_copper")
  523. minetest.register_alias("default:stone_with_iron_mined", "default:stone_with_iron")
  524. minetest.register_alias("default:desert_stone_with_coal_mined", "default:desert_stone_with_coal")
  525. minetest.register_alias("default:stone_with_coal_mined", "default:stone_with_coal")
  526. minetest.register_alias("rackstone:rackstone_with_meat_mined", "rackstone:rackstone_with_meat")
  527. minetest.register_alias("rackstone:rackstone_with_mese_mined", "rackstone:rackstone_with_mese")
  528. minetest.register_alias("rackstone:rackstone_with_diamond_mined", "rackstone:rackstone_with_diamond")
  529. minetest.register_alias("rackstone:rackstone_with_gold_mined", "rackstone:rackstone_with_gold")
  530. minetest.register_alias("rackstone:rackstone_with_copper_mined", "rackstone:rackstone_with_copper")
  531. minetest.register_alias("rackstone:rackstone_with_iron_mined", "rackstone:rackstone_with_iron")
  532. minetest.register_alias("rackstone:rackstone_with_coal_mined", "rackstone:rackstone_with_coal")
  533. minetest.register_alias("rackstone:redrack_with_tin_mined", "rackstone:redrack_with_tin")
  534. minetest.register_alias("rackstone:redrack_with_coal_mined", "rackstone:redrack_with_coal")
  535. minetest.register_alias("rackstone:redrack_with_copper_mined", "rackstone:redrack_with_copper")
  536. minetest.register_alias("rackstone:redrack_with_iron_mined", "rackstone:redrack_with_iron")
  537. minetest.register_alias("glowstone:luxore_mined", "glowstone:luxore")
  538. minetest.register_alias("glowstone:minerals_mined", "glowstone:minerals")
  539. minetest.register_alias("glowstone:glowstone_mined", "glowstone:glowstone")
  540. minetest.register_alias("quartz:quartz_ore_mined", "quartz:quartz_ore")
  541. minetest.register_alias("pm:quartz_ore_mined", "pm:quartz_ore")
  542. minetest.register_alias("luxore:luxore_mined", "luxore:luxore")
  543. minetest.register_alias("thorium:ore_mined", "thorium:ore")
  544. minetest.register_alias("lead:ore_mined", "lead:ore")
  545. minetest.register_alias("lapis:pyrite_ore_mined", "lapis:pyrite_ore")
  546. minetest.register_alias("kalite:ore_mined", "kalite:ore")
  547. minetest.register_alias("sulfur:ore_mined", "sulfur:ore")
  548. minetest.register_alias("titanium:ore_mined", "titanium:ore")
  549. minetest.register_alias("uranium:ore_mined", "uranium:ore")
  550. minetest.register_alias("whitestone:stone_mined", "whitestone:stone")
  551. minetest.register_alias("zinc:ore_mined", "zinc:ore")
  552. minetest.register_alias("talinite:desert_ore_mined", "talinite:desert_ore")
  553. minetest.register_alias("talinite:ore_mined", "talinite:ore")