chatcommands.lua 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. ------------------------------------------------------------------------------
  2. -- This file is registered as reloadable.
  3. ------------------------------------------------------------------------------
  4. reload = reload or {}
  5. reload.impl = reload.impl or {}
  6. -- This function expects only to be called from the chatcommands that this mod registers!
  7. reload.impl.dofile = function(name, path)
  8. local PREFIX = reload.chat_prefix
  9. local FILEPATH = path
  10. if type(path) == "string" and type(name) == "string" then
  11. if path == "" then
  12. reload.chat_send_player(name, PREFIX .. "No filepath provided.")
  13. return false
  14. end
  15. -- Log this action.
  16. reload.log("action", "[Mod Reload] Player <" .. name .. "> attempts to execute Lua source file '" .. FILEPATH .. "'.")
  17. -- A bit of security.
  18. if string.find(path, "%.%.") then
  19. reload.chat_send_player(name, PREFIX .. "Filepath cannot include '..' tokens.")
  20. return false
  21. end
  22. -- Attempt to load and execute the Lua file.
  23. local func, err = loadfile(FILEPATH)
  24. if not func then -- Syntax error.
  25. reload.chat_send_player(name, PREFIX .. "Could not load file. Received error message: '" .. err .. "'.")
  26. return false
  27. end
  28. local good, err = pcall(func)
  29. if not good then -- Runtime error.
  30. reload.chat_send_player(name, PREFIX .. "Could not execute file. Received error message: '" .. err .. "'.")
  31. return false
  32. end
  33. reload.chat_send_player(name, PREFIX .. "File '" .. FILEPATH .. "' successfully executed.")
  34. return true
  35. else
  36. reload.chat_send_player(name, PREFIX .. "Invalid arguments.")
  37. return false
  38. end
  39. end
  40. -- This function expects only to be called from the chatcommands that this mod registers!
  41. reload.impl.reload = function(name, param)
  42. local PREFIX = reload.chat_prefix
  43. local ROOT = reload.root_path .. "/"
  44. if param == "list" then
  45. for k, v in pairs(reload.impl.files) do
  46. local count = 30
  47. count = count - string.len(k)
  48. if count < 0 then count = 0 end
  49. local spaces = string.rep(" ", count)
  50. local len = string.len(ROOT)
  51. local p = string.sub(v, len+1)
  52. reload.chat_send_player(name, PREFIX .. "<" .. k .. ">, " .. spaces .. "'" .. p .. "'.")
  53. end
  54. reload.chat_send_player(name, PREFIX .. "End of list.")
  55. return true
  56. else
  57. if not param or param == "" then
  58. reload.chat_send_player(name, PREFIX .. "No file ID provided.")
  59. return false
  60. end
  61. local file = reload.impl.files[param]
  62. if file then
  63. return reload.impl.dofile(name, file)
  64. end
  65. reload.chat_send_player(name, PREFIX .. "Invalid file ID.")
  66. return false
  67. end
  68. end
  69. reload.impl.execute = function(name, path)
  70. local path2 = reload.root_path .. "/" .. path
  71. return reload.impl.dofile(name, path2)
  72. end
  73. reload.impl.dostring = function(name, str)
  74. local PREFIX = reload.chat_prefix
  75. if not str or str == "" then
  76. reload.chat_send_player(name, PREFIX .. "No argument provided.")
  77. reload.chat_send_player(name, PREFIX .. "Note: available custom variables are: me, mypos, player(name), print(text).")
  78. return false
  79. end
  80. -- Code injection.
  81. local ci = "do " .. -- Begin new block.
  82. "local me=minetest.get_player_by_name(\"" .. name .. "\") " ..
  83. "local mypos=me:get_pos() " ..
  84. "local function player(pname) return minetest.get_player_by_name(pname) end " ..
  85. "local function print(text) minetest.chat_send_player(\"" .. name .. "\", \"# Server: \" .. text) end " ..
  86. str .. " end" -- User code & end of block.
  87. local func, err = loadstring(ci)
  88. if not func then -- Syntax error.
  89. reload.chat_send_player(name, PREFIX .. "Could not compile string. Received error message: '" .. err .. "'.")
  90. return false
  91. end
  92. local good, err = pcall(func)
  93. if not good then -- Runtime error.
  94. reload.chat_send_player(name, PREFIX .. "Could not execute string. Received error message: '" .. err .. "'.")
  95. return false
  96. end
  97. reload.chat_send_player(name, PREFIX .. "Code executed successfully!")
  98. return true
  99. end
  100. -- Don't register the chat commands more than once, even if this file is reloaded.
  101. if not reload.chat_registered then
  102. minetest.register_chatcommand("reload", {
  103. params = "<fileid> | list",
  104. description = "Reload a registered source file at runtime.",
  105. -- Player must have server priviliges.
  106. privs = {server=true},
  107. func = function(...) return reload.impl.reload(...) end,
  108. })
  109. minetest.register_chatcommand("exec", {
  110. params = "<filepath>",
  111. description = "Load and execute an arbitrary Lua source file.",
  112. -- Player must have server priviliges.
  113. privs = {server=true},
  114. func = function(...) return reload.impl.execute(...) end,
  115. })
  116. minetest.register_chatcommand("run", {
  117. params = "<filepath>",
  118. description = "Load and execute an arbitrary Lua source file.",
  119. -- Player must have server priviliges.
  120. privs = {server=true},
  121. func = function(...) return reload.impl.execute(...) end,
  122. })
  123. minetest.register_chatcommand("dofile", {
  124. params = "<filepath>",
  125. description = "Load and execute an arbitrary Lua source file.",
  126. -- Player must have server priviliges.
  127. privs = {server=true},
  128. func = function(...) return reload.impl.execute(...) end,
  129. })
  130. -- Alias name. Some people (like me) keep wanting to spell it out.
  131. minetest.register_chatcommand("execute", {
  132. params = "<filepath>",
  133. description = "Load and execute an arbitrary Lua source file.",
  134. -- Player must have server priviliges.
  135. privs = {server=true},
  136. func = function(...) return reload.impl.execute(...) end,
  137. })
  138. minetest.register_chatcommand("dostring", {
  139. params = "<code>",
  140. description = "Execute a statement in Lua.",
  141. -- Player must have server priviliges.
  142. privs = {server=true},
  143. func = function(...) return reload.impl.dostring(...) end,
  144. })
  145. minetest.register_chatcommand("lua", {
  146. params = "<code>",
  147. description = "Execute a statement in Lua.",
  148. -- Player must have server priviliges.
  149. privs = {server=true},
  150. func = function(...) return reload.impl.dostring(...) end,
  151. })
  152. minetest.register_chatcommand("dolua", {
  153. params = "<code>",
  154. description = "Execute a statement in Lua.",
  155. -- Player must have server priviliges.
  156. privs = {server=true},
  157. func = function(...) return reload.impl.dostring(...) end,
  158. })
  159. reload.chat_registered = true
  160. end