init.lua 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. --------------------------------------------------------------------------------
  2. -- Mapfix, MTS version.
  3. -- Authored by MustTest.
  4. -- License: MIT.
  5. --------------------------------------------------------------------------------
  6. -- Mod is reloadable.
  7. mapfix = mapfix or {}
  8. mapfix.players = mapfix.players or {}
  9. mapfix.modpath = minetest.get_modpath("mapfix")
  10. -- Configurable settings.
  11. local MIN_TIMEOUT = 15
  12. local DEFAULT_RADIUS = 40
  13. local MAX_RADIUS = 60
  14. local function work(minp, maxp)
  15. local vm = minetest.get_voxel_manip(minp, maxp)
  16. vm:update_liquids()
  17. vm:write_to_map(true) -- Fix lighting while you're at it.
  18. return vm:get_emerged_area()
  19. end
  20. -- Export this function publicly.
  21. mapfix.work = work
  22. -- Public API function. May be called from other mods.
  23. function mapfix.execute(pos, radius)
  24. pos = vector.round(pos)
  25. radius = math.floor(radius)
  26. local minp = vector.subtract(pos, radius)
  27. local maxp = vector.add(pos, radius)
  28. work(minp, maxp)
  29. end
  30. -- Chat-command callback function.
  31. -- Handles minimum timeout and required privileges.
  32. -- Called by KoC.
  33. mapfix.command = function(pname, param)
  34. -- Profile function execution time.
  35. local t1 = os.clock()
  36. local player = minetest.get_player_by_name(pname)
  37. if not player or not player:is_player() then
  38. return
  39. end
  40. -- Determine radius.
  41. local radius = DEFAULT_RADIUS
  42. if param and param ~= "" then
  43. radius = tonumber(param:trim())
  44. if not radius then
  45. minetest.chat_send_player(pname, "# Server: Usage: /mapfix [<radius>].")
  46. return
  47. end
  48. end
  49. -- Check timeout delay for this user.
  50. if mapfix.players[pname] then
  51. local tnow = os.time()
  52. local prev = mapfix.players[pname]
  53. local diff = tnow - prev
  54. -- Check if function was called too soon.
  55. if diff < MIN_TIMEOUT then
  56. local remain = math.ceil(MIN_TIMEOUT - diff)
  57. -- Grammar adjustment.
  58. local str = "seconds"
  59. if remain == 1 then
  60. str = "second"
  61. end
  62. minetest.chat_send_player(pname,
  63. "# Server: Too soon to run /mapfix again! Wait " .. remain ..
  64. " more " .. str .. ".")
  65. return
  66. end
  67. -- Store time of last call to this function.
  68. mapfix.players[pname] = tnow
  69. else
  70. -- Store time of last call to this function.
  71. mapfix.players[pname] = os.time()
  72. end
  73. local pos = vector.round(player:get_pos())
  74. radius = math.floor(radius)
  75. -- Check privs.
  76. if radius > MAX_RADIUS then
  77. local privs = minetest.check_player_privs(pname, {mapfix=true})
  78. if not privs then
  79. minetest.chat_send_player(pname,
  80. "# Server: You cannot exceed radius " .. MAX_RADIUS ..
  81. "! Your privileges are insufficient.")
  82. return
  83. end
  84. elseif radius < 0 then
  85. minetest.chat_send_player(pname, "# Server: Radius cannot be negative!")
  86. return
  87. end
  88. local minp = vector.subtract(pos, radius)
  89. local maxp = vector.add(pos, radius)
  90. minetest.log("action",
  91. "Player <" .. pname .. "> executed /mapfix with radius " .. radius ..
  92. " at " .. minetest.pos_to_string(pos) .. ".")
  93. minp, maxp = work(minp, maxp)
  94. -- Calculate elapsed time.
  95. local t2 = os.clock()
  96. local totalms = math.ceil((t2 - t1) * 1000)
  97. minetest.chat_send_player(pname,
  98. "# Server: Liquid & light recalculation finished! Extents: " ..
  99. rc.pos_to_namestr(minp) .. " to " .. rc.pos_to_namestr(maxp) ..
  100. ". Radius: " .. radius .. ". Took " .. totalms .. " milliseconds.")
  101. end
  102. if not mapfix.registered then
  103. -- Privilege required in order to execute /mapfix for very large areas.
  104. minetest.register_privilege("mapfix", {
  105. description = "Player may execute /mapfix with an arbitrary radius.",
  106. give_to_singleplayer = false,
  107. })
  108. -- Allow players to use command from chat console.
  109. -- No privs required.
  110. minetest.register_chatcommand("mapfix", {
  111. params = "[<radius>]",
  112. description = "Request a recalculation of nearby liquids and light.",
  113. func = function(...)
  114. mapfix.command(...)
  115. end,
  116. })
  117. -- Register mod as reloadable.
  118. local c = "mapfix:core"
  119. local f = mapfix.modpath .. "/init.lua"
  120. reload.register_file(c, f, false)
  121. mapfix.registered = true
  122. end