commands.lua 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. minetest.register_chatcommand("test_inv", {
  2. params = "",
  3. description = "Test: Modify player's inventory formspec",
  4. func = function(name, param)
  5. local player = minetest.get_player_by_name(name)
  6. if not player then
  7. return false, "No player."
  8. end
  9. player:set_inventory_formspec(
  10. "size[13,7.5]"..
  11. "image[6,0.6;1,2;player.png]"..
  12. "list[current_player;main;5,3.5;8,4;]"..
  13. "list[current_player;craft;8,0;3,3;]"..
  14. "list[current_player;craftpreview;12,1;1,1;]"..
  15. "list[detached:test_inventory;main;0,0;4,6;0]"..
  16. "button[0.5,7;2,1;button1;Button 1]"..
  17. "button_exit[2.5,7;2,1;button2;Exit Button]")
  18. return true, "Done."
  19. end,
  20. })
  21. minetest.register_chatcommand("test_bulk_set_node", {
  22. params = "",
  23. description = "Test: Bulk-set 9×9×9 stone nodes",
  24. func = function(name, param)
  25. local player = minetest.get_player_by_name(name)
  26. if not player then
  27. return false, "No player."
  28. end
  29. local pos_list = {}
  30. local ppos = player:get_pos()
  31. local i = 1
  32. for x=2,10 do
  33. for y=2,10 do
  34. for z=2,10 do
  35. pos_list[i] = {x=ppos.x + x,y = ppos.y + y,z = ppos.z + z}
  36. i = i + 1
  37. end
  38. end
  39. end
  40. minetest.bulk_set_node(pos_list, {name = "mapgen_stone"})
  41. return true, "Done."
  42. end,
  43. })
  44. -- Safeguard against too much optimization. This way the results cannot be optimized
  45. -- away, but they can be garbage collected (due to __mode = "k").
  46. _G._bench_content_ids_data = setmetatable({}, {__mode = "k"})
  47. local function bench_name2content()
  48. local t = {}
  49. _G._bench_content_ids_data[t] = true
  50. local get_content_id = minetest.get_content_id
  51. local start = minetest.get_us_time()
  52. for i = 1, 200 do
  53. for name in pairs(minetest.registered_nodes) do
  54. t[#t + 1] = get_content_id(name)
  55. end
  56. end
  57. local finish = minetest.get_us_time()
  58. return (finish - start) / 1000
  59. end
  60. local function bench_content2name()
  61. local t = {}
  62. _G._bench_content_ids_data[t] = true
  63. -- Try to estimate the highest content ID that's used
  64. -- (not accurate but good enough for this test)
  65. local n = 0
  66. for _ in pairs(minetest.registered_nodes) do
  67. n = n + 1
  68. end
  69. local get_name_from_content_id = minetest.get_name_from_content_id
  70. local start = minetest.get_us_time()
  71. for i = 1, 200 do
  72. for j = 0, n do
  73. t[#t + 1] = get_name_from_content_id(j)
  74. end
  75. end
  76. local finish = minetest.get_us_time()
  77. return (finish - start) / 1000
  78. end
  79. minetest.register_chatcommand("bench_name2content", {
  80. params = "",
  81. description = "Benchmark: Conversion from node names to content IDs",
  82. func = function(name, param)
  83. minetest.chat_send_player(name, "Benchmarking minetest.get_content_id. Warming up ...")
  84. bench_name2content()
  85. minetest.chat_send_player(name, "Warming up finished, now benchmarking ...")
  86. local time = bench_name2content()
  87. return true, ("Time: %.2f ms"):format(time)
  88. end,
  89. })
  90. minetest.register_chatcommand("bench_content2name", {
  91. params = "",
  92. description = "Benchmark: Conversion from content IDs to node names",
  93. func = function(name, param)
  94. minetest.chat_send_player(name, "Benchmarking minetest.get_name_from_content_id. Warming up ...")
  95. bench_content2name()
  96. minetest.chat_send_player(name, "Warming up finished, now benchmarking ...")
  97. local time = bench_content2name()
  98. return true, ("Time: %.2f ms"):format(time)
  99. end,
  100. })
  101. minetest.register_chatcommand("bench_bulk_set_node", {
  102. params = "",
  103. description = "Benchmark: Bulk-set 99×99×99 stone nodes",
  104. func = function(name, param)
  105. local player = minetest.get_player_by_name(name)
  106. if not player then
  107. return false, "No player."
  108. end
  109. local pos_list = {}
  110. local ppos = player:get_pos()
  111. local i = 1
  112. for x=2,100 do
  113. for y=2,100 do
  114. for z=2,100 do
  115. pos_list[i] = {x=ppos.x + x,y = ppos.y + y,z = ppos.z + z}
  116. i = i + 1
  117. end
  118. end
  119. end
  120. minetest.chat_send_player(name, "Benchmarking minetest.bulk_set_node. Warming up ...");
  121. -- warm up with stone to prevent having different callbacks
  122. -- due to different node topology
  123. minetest.bulk_set_node(pos_list, {name = "mapgen_stone"})
  124. minetest.chat_send_player(name, "Warming up finished, now benchmarking ...");
  125. local start_time = minetest.get_us_time()
  126. for i=1,#pos_list do
  127. minetest.set_node(pos_list[i], {name = "mapgen_stone"})
  128. end
  129. local middle_time = minetest.get_us_time()
  130. minetest.bulk_set_node(pos_list, {name = "mapgen_stone"})
  131. local end_time = minetest.get_us_time()
  132. local msg = string.format("Benchmark results: minetest.set_node loop: %.2f ms; minetest.bulk_set_node: %.2f ms",
  133. ((middle_time - start_time)) / 1000,
  134. ((end_time - middle_time)) / 1000
  135. )
  136. return true, msg
  137. end,
  138. })
  139. local function advance_pos(pos, start_pos, advance_z)
  140. if advance_z then
  141. pos.z = pos.z + 2
  142. pos.x = start_pos.x
  143. else
  144. pos.x = pos.x + 2
  145. end
  146. if pos.x > 30900 or pos.x - start_pos.x > 46 then
  147. pos.x = start_pos.x
  148. pos.z = pos.z + 2
  149. end
  150. if pos.z > 30900 then
  151. -- We ran out of space! Aborting
  152. aborted = true
  153. return false
  154. end
  155. return pos
  156. end
  157. local function place_nodes(param)
  158. local nodes = param.nodes
  159. local name = param.name
  160. local pos = param.pos
  161. local start_pos = param.start_pos
  162. table.sort(nodes)
  163. minetest.chat_send_player(name, "Placing nodes …")
  164. local nodes_placed = 0
  165. local aborted = false
  166. for n=1, #nodes do
  167. local itemstring = nodes[n]
  168. local def = minetest.registered_nodes[itemstring]
  169. local p2_max = 0
  170. if param.param ~= "no_param2" then
  171. -- Also test the param2 values of the nodes
  172. -- ... but we only use permissible param2 values
  173. if def.paramtype2 == "wallmounted" then
  174. p2_max = 5
  175. elseif def.paramtype2 == "facedir" then
  176. p2_max = 23
  177. elseif def.paramtype2 == "glasslikeliquidlevel" then
  178. p2_max = 63
  179. elseif def.paramtype2 == "meshoptions" and def.drawtype == "plantlike" then
  180. p2_max = 63
  181. elseif def.paramtype2 == "leveled" then
  182. p2_max = 127
  183. elseif def.paramtype2 == "degrotate" and (def.drawtype == "plantlike" or def.drawtype == "mesh") then
  184. p2_max = 239
  185. elseif def.paramtype2 == "colorfacedir" or
  186. def.paramtype2 == "colorwallmounted" or
  187. def.paramtype2 == "colordegrotate" or
  188. def.paramtype2 == "color" then
  189. p2_max = 255
  190. end
  191. end
  192. for p2 = 0, p2_max do
  193. -- Skip undefined param2 values
  194. if not ((def.paramtype2 == "meshoptions" and p2 % 8 > 4) or
  195. (def.paramtype2 == "colorwallmounted" and p2 % 8 > 5) or
  196. ((def.paramtype2 == "colorfacedir" or def.paramtype2 == "colordegrotate")
  197. and p2 % 32 > 23)) then
  198. minetest.set_node(pos, { name = itemstring, param2 = p2 })
  199. nodes_placed = nodes_placed + 1
  200. pos = advance_pos(pos, start_pos)
  201. if not pos then
  202. aborted = true
  203. break
  204. end
  205. end
  206. end
  207. if aborted then
  208. break
  209. end
  210. end
  211. if aborted then
  212. minetest.chat_send_player(name, "Not all nodes could be placed, please move further away from the world boundary. Nodes placed: "..nodes_placed)
  213. end
  214. minetest.chat_send_player(name, "Nodes placed: "..nodes_placed..".")
  215. end
  216. local function after_emerge(blockpos, action, calls_remaining, param)
  217. if calls_remaining == 0 then
  218. place_nodes(param)
  219. end
  220. end
  221. minetest.register_chatcommand("test_place_nodes", {
  222. params = "[ no_param2 ]",
  223. description = "Test: Place all non-experimental nodes and optionally their permissible param2 variants",
  224. func = function(name, param)
  225. local player = minetest.get_player_by_name(name)
  226. if not player then
  227. return false, "No player."
  228. end
  229. local pos = vector.floor(player:get_pos())
  230. pos.x = math.ceil(pos.x + 3)
  231. pos.z = math.ceil(pos.z + 3)
  232. pos.y = math.ceil(pos.y + 1)
  233. local start_pos = table.copy(pos)
  234. if pos.x > 30800 then
  235. return false, "Too close to world boundary (+X). Please move to X < 30800."
  236. end
  237. if pos.z > 30800 then
  238. return false, "Too close to world boundary (+Z). Please move to Z < 30800."
  239. end
  240. local aborted = false
  241. local nodes = {}
  242. local emerge_estimate = 0
  243. for itemstring, def in pairs(minetest.registered_nodes) do
  244. if itemstring ~= "ignore" and string.sub(itemstring, 1, 13) ~= "experimental:" then
  245. table.insert(nodes, itemstring)
  246. if def.paramtype2 == 0 then
  247. emerge_estimate = emerge_estimate + 1
  248. else
  249. emerge_estimate = emerge_estimate + 255
  250. end
  251. end
  252. end
  253. -- Emerge area to make sure that all nodes are being placed.
  254. -- Note we will emerge much more than we need to (overestimation),
  255. -- the estimation code could be improved performance-wise …
  256. local length = 16 + math.ceil(emerge_estimate / 24) * 2
  257. minetest.emerge_area(start_pos,
  258. { x = start_pos.x + 46, y = start_pos.y, z = start_pos.z + length },
  259. after_emerge, { nodes = nodes, name = name, pos = pos, start_pos = start_pos, param = param })
  260. return true, "Emerging area …"
  261. end,
  262. })
  263. core.register_on_chatcommand(function(name, command, params)
  264. minetest.log("action", "caught command '"..command.."', issued by '"..name.."'. Parameters: '"..params.."'")
  265. end)