update_travelnet.lua 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. local S = minetest.get_translator("travelnet")
  2. return function (node_info, fields, player)
  3. local pos = node_info.pos
  4. local meta = node_info.meta
  5. local player_name = player:get_player_name()
  6. if not pos or not fields or not meta or not player_name then
  7. return false, S("Invalid data or node.")
  8. end
  9. local owner_name = node_info.props.owner_name
  10. local station_network = node_info.props.station_network
  11. local station_name = node_info.props.station_name
  12. local description = node_info.props.description
  13. local new_owner_name, new_station_network, new_station_name
  14. if not description then
  15. return false, S("Unknown node.")
  16. end
  17. if owner_name == fields.owner_name
  18. and station_network == fields.station_network
  19. and station_name == fields.station_name
  20. then
  21. return true, { formspec = travelnet.formspecs.primary }
  22. end
  23. -- sanitize inputs
  24. local error_message = ''
  25. if travelnet.is_falsey_string(fields.station_name) then
  26. error_message = S('Please provide a station name.')
  27. end
  28. if travelnet.is_falsey_string(fields.station_network) then
  29. error_message = error_message .. ' '
  30. ..S('Please provide a network name.')
  31. end
  32. if travelnet.is_falsey_string(fields.owner_name) then
  33. error_message = error_message .. ' '
  34. ..S('Please provide an owner.')
  35. end
  36. if '' ~= error_message then
  37. return false, error_message
  38. end
  39. -- players with travelnet_remove priv can dig the station
  40. if not minetest.get_player_privs(player_name)[travelnet.remove_priv]
  41. -- the function travelnet.allow_dig(..) may allow additional digging
  42. and not travelnet.allow_dig(player_name, owner_name, station_network, pos)
  43. -- the owner can remove the station
  44. and owner_name ~= player_name
  45. -- stations without owner can be removed/edited by anybody
  46. and owner_name ~= ""
  47. then
  48. return false, S("This @1 belongs to @2. You can't edit it.",
  49. description,
  50. tostring(owner_name)
  51. )
  52. end
  53. -- abort if protected by another mod
  54. if minetest.is_protected(pos, player_name)
  55. and not minetest.check_player_privs(player_name, { protection_bypass = true })
  56. then
  57. minetest.record_protection_violation(pos, player_name)
  58. return false, S("This @1 belongs to @2. You can't edit it.",
  59. description,
  60. tostring(owner_name)
  61. )
  62. end
  63. local timestamp = os.time()
  64. if owner_name ~= fields.owner_name then
  65. if not minetest.get_player_privs(player_name)[travelnet.attach_priv]
  66. and not travelnet.allow_attach(player_name, owner_name, fields.station_network) then
  67. minetest.record_protection_violation(pos, player_name)
  68. return false, S("You don't have permission to change the owner of this travelnet")
  69. end
  70. -- new owner -> remove station from old network then add to new owner
  71. -- but only if there is space on the network
  72. -- get the new network
  73. local old_travelnets = travelnet.get_travelnets(owner_name)
  74. local new_travelnets = travelnet.get_travelnets(fields.owner_name)
  75. local new_network = new_travelnets[fields.station_network]
  76. if not new_network then
  77. new_network = {}
  78. new_travelnets[fields.station_network] = new_network
  79. end
  80. -- does a station with the new name already exist?
  81. if new_network[fields.station_name] then
  82. return false, S('Station "@1" already exists on network "@2" of player "@3".',
  83. fields.station_name, fields.station_network, fields.owner_name)
  84. end
  85. -- does the new network have space at all?
  86. if travelnet.MAX_STATIONS_PER_NETWORK ~= 0 and 1 + #new_network > travelnet.MAX_STATIONS_PER_NETWORK then
  87. return false,
  88. S('Network "@1", already contains the maximum number (@2) of '
  89. .. 'allowed stations per network. Please choose a '
  90. .. 'different network name.', fields.station_network,
  91. travelnet.MAX_STATIONS_PER_NETWORK)
  92. end
  93. -- get the old network
  94. local old_network = old_travelnets[station_network]
  95. if not old_network then
  96. print("TRAVELNET: failed to get old network when re-owning "
  97. .. "travelnet/elevator at pos " .. minetest.pos_to_string(pos))
  98. return false, S("Station does not have network.")
  99. end
  100. -- remove old station from old network
  101. old_network[station_name] = nil
  102. -- add new station to new network
  103. new_network[fields.station_name] = { pos = pos, timestamp = timestamp }
  104. -- update meta
  105. meta:set_string("station_name", fields.station_name)
  106. meta:set_string("station_network", fields.station_network)
  107. meta:set_string("owner", fields.owner_name)
  108. meta:set_int ("timestamp", timestamp)
  109. minetest.chat_send_player(player_name,
  110. S('Station "@1" has been renamed to "@2", '
  111. .. 'moved from network "@3" to network "@4" '
  112. .. 'and from owner "@5" to owner "@6".',
  113. station_name, fields.station_name,
  114. station_network, fields.station_network,
  115. owner_name, fields.owner_name))
  116. new_owner_name = fields.owner_name
  117. new_station_network = fields.station_network
  118. new_station_name = fields.station_name
  119. travelnet.log("action", "changed station '" .. station_name .. "' to '" .. fields.station_name ..
  120. "' moved network from '" .. station_network .. "' to '" .. fields.station_network .. "'" ..
  121. "' from player '" .. owner_name .. "' to '" .. fields.owner_name .. "'")
  122. travelnet.set_travelnets(owner_name, old_travelnets)
  123. travelnet.set_travelnets(fields.owner_name, new_travelnets)
  124. elseif station_network ~= fields.station_network then
  125. -- same owner but different network -> remove station from old network
  126. -- but only if there is space on the new network and no other station with that name
  127. -- get the new network
  128. local travelnets = travelnet.get_travelnets(owner_name)
  129. local network = travelnets[fields.station_network]
  130. if not network then
  131. network = {}
  132. travelnets[fields.station_network] = network
  133. end
  134. -- does a station with the new name already exist?
  135. if network[fields.station_name] then
  136. return false, S('Station "@1" already exists on network "@2".',
  137. fields.station_name, fields.station_network)
  138. end
  139. -- does the new network have space at all?
  140. if travelnet.MAX_STATIONS_PER_NETWORK ~= 0 and 1 + #network > travelnet.MAX_STATIONS_PER_NETWORK then
  141. return false,
  142. S('Network "@1", already contains the maximum number (@2) of '
  143. .. 'allowed stations per network. Please choose a '
  144. .. 'different network name.', fields.station_network,
  145. travelnet.MAX_STATIONS_PER_NETWORK)
  146. end
  147. -- get the old network
  148. local old_network = travelnets[station_network]
  149. if not old_network then
  150. print("TRAVELNET: failed to get old network when re-networking "
  151. .. "travelnet/elevator at pos " .. minetest.pos_to_string(pos))
  152. return false, S("Station does not have network.")
  153. end
  154. -- remove old station from old network
  155. old_network[station_name] = nil
  156. -- add new station to new network
  157. network[fields.station_name] = { pos = pos, timestamp = timestamp }
  158. -- update meta
  159. meta:set_string("station_name", fields.station_name)
  160. meta:set_string("station_network", fields.station_network)
  161. meta:set_int ("timestamp", timestamp)
  162. minetest.chat_send_player(player_name,
  163. S('Station "@1" has been renamed to "@2" and moved '
  164. .. 'from network "@3" to network "@4".',
  165. station_name, fields.station_name,
  166. station_network, fields.station_network))
  167. new_station_network = fields.station_network
  168. new_station_name = fields.station_name
  169. travelnet.log("action", "changed station '" .. station_name .. "' to '" .. fields.station_name ..
  170. "' moved network from '" .. station_network .. "' to '" .. fields.station_network .. "'" ..
  171. "' for player '" .. owner_name .. "'")
  172. travelnet.set_travelnets(owner_name, travelnets)
  173. else
  174. -- only name changed -> change name but keep timestamp to preserve order
  175. local travelnets = travelnet.get_travelnets(owner_name)
  176. local network = travelnets[station_network]
  177. if not network then
  178. network = {}
  179. travelnets[station_network] = network
  180. end
  181. -- does a station with the new name already exist?
  182. if network[fields.station_name] then
  183. return false, S('Station "@1" already exists on network "@2".',
  184. fields.station_name, station_network)
  185. end
  186. -- get the old station table
  187. local old_station = network[station_name]
  188. if not old_station then
  189. return false, S("Station does exist.")
  190. end
  191. -- apply the old table to the new station
  192. network[fields.station_name] = old_station
  193. -- remove old station
  194. network[station_name] = nil
  195. -- update station name in node meta
  196. meta:set_string("station_name", fields.station_name)
  197. minetest.chat_send_player(player_name,
  198. S('Station "@1" has been renamed to "@2" on network "@3".',
  199. station_name, fields.station_name, station_network))
  200. new_station_name = fields.station_name
  201. travelnet.log("action", "changed station '" .. station_name .. "' to '" .. fields.station_name ..
  202. "' on network '" .. station_network .. "'" ..
  203. "' for player '" .. owner_name .. "'")
  204. travelnet.set_travelnets(owner_name, travelnets)
  205. end
  206. meta:set_string("infotext",
  207. S("Station '@1'" .. " " ..
  208. "on network '@2' (owned by @3)" .. " " ..
  209. "ready for usage.",
  210. tostring(new_station_name or station_name),
  211. tostring(new_station_network or station_network),
  212. tostring(new_owner_name or owner_name)
  213. ))
  214. return true, { formspec = travelnet.formspecs.primary, options = {
  215. station_name = new_station_name or station_name,
  216. station_network = new_station_network or station_network,
  217. owner_name = new_owner_name or owner_name
  218. } }
  219. end