meseportal_gui.lua 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. local reportFormspecViolation = function(submitter_name, violation)
  2. local path = minetest.get_worldpath().."/meseportals_incidents.log"
  3. local file = io.open( path, "r" )
  4. local data = ""
  5. if( file ) then
  6. data = file:read("*all")
  7. file:close()
  8. end
  9. data = data.."<"..os.date().."> "..submitter_name.." "..violation.."\n"
  10. file = io.open( path, "w" )
  11. if( file ) then
  12. file:write( data )
  13. file:close()
  14. end
  15. end
  16. local getCleanText = function(submitter_name, scan_text)
  17. if scan_text ~= nil then
  18. if string.find(scan_text, ";") or
  19. string.find(scan_text, "%[") or
  20. string.find(scan_text, "%]") or
  21. string.find(scan_text, "\\") then
  22. reportFormspecViolation(submitter_name, "sent dirty string of length "..string.len(scan_text)..": "..scan_text)
  23. --Call me paranoid. The length bit is so that someone can't get away with causing their report to line-break, and fabricating a fake report on the next line, essentially framing another player as well as themself.
  24. return ""
  25. else
  26. return scan_text
  27. end
  28. else
  29. return nil
  30. end
  31. end
  32. meseportals.searchportals = function(pos, player_name, isAdmin)
  33. meseportals_gui["players"][player_name]["own_portals"]={}
  34. meseportals_gui["players"][player_name]["public_portals"]={}
  35. local own_portals_count=0
  36. local public_portals_count=0
  37. for __,portal in ipairs(meseportals_network[player_name]) do
  38. if portal["pos"].x==pos.x and portal["pos"].y==pos.y and portal["pos"].z==pos.z then
  39. --current_portal=portals
  40. else
  41. own_portals_count=own_portals_count+1
  42. if string.find(portal["description"], meseportals_gui["players"][player_name]["query"]) then
  43. table.insert(meseportals_gui["players"][player_name]["own_portals"],portal)
  44. end
  45. end
  46. end
  47. -- get all public portals
  48. for __,tab in ipairs(meseportals["registered_players"]) do
  49. local temp=tab["player_name"]
  50. for __,portal in ipairs(meseportals_network[temp]) do
  51. if string.find(portal["description"], meseportals_gui["players"][player_name]["query"]) then
  52. if portal["type"]=="public" or portal["owner"] == player_name or isAdmin or not meseportals.allowPrivatePortals then
  53. if portal["pos"].x==pos.x and portal["pos"].y==pos.y and portal["pos"].z==pos.z then
  54. --current_portal=portals
  55. else
  56. public_portals_count=public_portals_count+1
  57. table.insert(meseportals_gui["players"][player_name]["public_portals"],portal)
  58. end
  59. end
  60. end
  61. end
  62. end
  63. meseportals_gui["players"][player_name]["own_portals_count"]=own_portals_count
  64. meseportals_gui["players"][player_name]["public_portals_count"]=public_portals_count
  65. end
  66. -- Mods can override this to restict portal connections.
  67. -- Admins ignore this.
  68. meseportals.can_connect = function(src_portal, dest_portal)
  69. return dest_portal["destination"] == nil, "Destination portal is busy."
  70. end
  71. --show formspec to player
  72. meseportals.portalFormspecHandler = function(pos, _, clicker, _)
  73. if (meseportals.findPortal(pos) ~= nil) then
  74. local player_name = clicker:get_player_name()
  75. local isAdmin = minetest.check_player_privs(clicker, {msp_admin=true})
  76. local owner=meseportals.findPortal(pos)["owner"]
  77. if meseportals.findPortal(pos)["type"] == "private" and player_name ~= owner and meseportals.allowPrivatePortals and not isAdmin then
  78. minetest.chat_send_player(clicker:get_player_name(), meseportals.findPortal(pos)["owner"] .." has set this portal to private.")
  79. return
  80. else
  81. local current_portal=meseportals.findPortal(pos)
  82. meseportals_gui["players"][player_name]["query"]=""
  83. meseportals.searchportals(pos, player_name, isAdmin)
  84. -- print(dump(meseportals_gui["players"][player_name]["public_portals"]))
  85. if current_portal == nil then
  86. print ("Portal not registered in network! Please remove it and place once again.")
  87. return nil
  88. end
  89. meseportals_gui["players"][player_name]["current_index"]=0
  90. meseportals_gui["players"][player_name]["temp_portal"]["owner"]=current_portal.owner
  91. meseportals_gui["players"][player_name]["temp_portal"]["type"]=current_portal["type"]
  92. meseportals_gui["players"][player_name]["temp_portal"]["description"]=current_portal["description"]
  93. meseportals_gui["players"][player_name]["temp_portal"]["pos"]={}
  94. meseportals_gui["players"][player_name]["temp_portal"]["pos"] = vector.new(pos)
  95. if current_portal["destination"] then
  96. meseportals_gui["players"][player_name]["temp_portal"]["destination_description"]=current_portal["destination_description"]
  97. meseportals_gui["players"][player_name]["temp_portal"]["destination_dir"]=current_portal["destination_dir"]
  98. meseportals_gui["players"][player_name]["temp_portal"]["destination"]={}
  99. meseportals_gui["players"][player_name]["temp_portal"]["destination"].x=current_portal["destination"].x
  100. meseportals_gui["players"][player_name]["temp_portal"]["destination"].y=current_portal["destination"].y
  101. meseportals_gui["players"][player_name]["temp_portal"]["destination"].z=current_portal["destination"].z
  102. else
  103. meseportals_gui["players"][player_name]["temp_portal"]["destination"]=nil
  104. end
  105. meseportals_gui["players"][player_name]["dest_type"]="all"
  106. local formspec=meseportals.get_formspec(player_name,"main")
  107. meseportals_gui["players"][player_name]["formspec"]=formspec
  108. if formspec ~=nil then minetest.show_formspec(player_name, "meseportals_main", formspec) end
  109. end
  110. else
  111. minetest.chat_send_player(clicker:get_player_name(), "This portal is broken.")
  112. end
  113. end
  114. -- get_formspec
  115. meseportals.get_formspec = function(player_name,page)
  116. if player_name==nil then return nil end
  117. meseportals_gui["players"][player_name]["current_page"]=page
  118. local temp_portal=meseportals_gui["players"][player_name]["temp_portal"]
  119. local isAdmin = minetest.check_player_privs(player_name, {msp_admin=true})
  120. local formspec = "size[14,9.8]"
  121. --background
  122. formspec = formspec .."background[-0.19,-0.25;14.38,10.6;meseportal_ui_form_bg.png]"
  123. formspec = formspec.."label[0,0.0;Mese Portal ("
  124. if meseportals.allowPrivatePortals then
  125. formspec=formspec..temp_portal["owner"]
  126. end
  127. formspec = formspec..")]"
  128. formspec = formspec.."label[0,.5;Position: ("..temp_portal["pos"].x..","..temp_portal["pos"].y..","..temp_portal["pos"].z..")]"
  129. if player_name == temp_portal["owner"] or isAdmin or not meseportals.allowPrivatePortals then
  130. if meseportals.allowPrivatePortals then
  131. formspec = formspec.."image_button[3.5,.6;.6,.6;meseportal_toggle_icon.png;toggle_type;]"
  132. formspec = formspec.."label[4,.5;Type: "..temp_portal["type"].."]"
  133. end
  134. formspec = formspec.."image_button[6.5,.6;.6,.6;meseportal_pencil_icon.png;edit_desc;]"
  135. end
  136. formspec = formspec.."label[0,1.1;Destination: ]"
  137. if temp_portal["destination"] then
  138. if meseportals.findPortal(temp_portal["destination"]) then
  139. if isAdmin or meseportals.findPortal(temp_portal["destination"])["type"] ~= "private" or player_name == meseportals.findPortal(temp_portal["destination"])["owner"] or not meseportals.allowPrivatePortals then
  140. formspec = formspec.."label[2.5,1.1;"..temp_portal["destination_description"].." ("..temp_portal["destination"].x..","..temp_portal["destination"].y..","..temp_portal["destination"].z..") "
  141. if isAdmin then
  142. formspec = formspec.."("..meseportals.findPortal(temp_portal["destination"])["type"]..")"
  143. end
  144. formspec = formspec.."]"
  145. else
  146. formspec = formspec.."label[2.5,1.1;Private Portal]"
  147. end
  148. else
  149. formspec = formspec.."label[2.5,1.1;Invalid Destination]"
  150. end
  151. formspec = formspec.."image_button[2,1.2;.6,.6;meseportal_cancel_icon.png;remove_dest;]"
  152. else
  153. formspec = formspec.."label[2,1.1;Not connected]"
  154. end
  155. formspec = formspec.."label[0,1.7;Aviable destinations:]"
  156. formspec = formspec.."image_button[3.5,1.8;.6,.6;meseportal_toggle_icon.png;toggle_dest_type;]"
  157. formspec = formspec.."label[4,1.7;Filter: "..meseportals_gui["players"][player_name]["dest_type"].."]"
  158. formspec = formspec.."image_button[12.6,1.375;.8,.8;meseportal_ui_search_icon.png;update_search_query;]"
  159. formspec = formspec.."field[9.5,1.6;3.5,1;search_box;Search...;"..meseportals_gui["players"][player_name]["query"].."]"
  160. if page=="main" then
  161. if player_name == temp_portal["owner"]or isAdmin or not meseportals.allowPrivatePortals then
  162. formspec = formspec.."image_button[6.5,.6;.6,.6;meseportal_pencil_icon.png;edit_desc;]"
  163. end
  164. formspec = formspec.."label[7,.5;Description: "..temp_portal["description"].."]"
  165. end
  166. if page=="edit_desc" then
  167. if player_name == temp_portal["owner"]or isAdmin or not meseportals.allowPrivatePortals then
  168. formspec = formspec.."image_button[6.5,.6;.6,.6;meseportal_ok_icon.png;save_desc;]"
  169. end
  170. formspec = formspec.."field[7.3,.7;5,1;desc_box;Edit portal description:;"..temp_portal["description"].."]"
  171. end
  172. local list_index=meseportals_gui["players"][player_name]["current_index"]
  173. local page=math.ceil(list_index / 24)
  174. local pagemax
  175. if meseportals_gui["players"][player_name]["dest_type"] == "own" then
  176. pagemax = math.ceil((meseportals_gui["players"][player_name]["own_portals_count"] / 24))
  177. local x,y
  178. for y=0,7,1 do
  179. for x=0,2,1 do
  180. local portal_temp=meseportals_gui["players"][player_name]["own_portals"][list_index+1]
  181. if portal_temp then
  182. formspec = formspec.."image_button["..(x*4.5)..","..(2.5+y*.87)..";.6,.6;meseportal.png;list_button"..list_index..";]"
  183. formspec = formspec.."label["..(x*4.5+.5)..","..(2.3+y*.87)..";"
  184. if portal_temp["destination"] ~= nil then
  185. formspec = formspec.."<A> "
  186. end
  187. formspec = formspec.."("..portal_temp["pos"].x..","..portal_temp["pos"].y..","..portal_temp["pos"].z..") "..portal_temp["type"].."]"
  188. formspec = formspec.."label["..(x*4.5+.5)..","..(2.7+y*.87)..";"..portal_temp["description"].."]"
  189. end
  190. list_index=list_index+1
  191. end
  192. end
  193. else
  194. pagemax = math.ceil(meseportals_gui["players"][player_name]["public_portals_count"] / 24)
  195. local x,y
  196. for y=0,7,1 do
  197. for x=0,2,1 do
  198. local portal_temp=meseportals_gui["players"][player_name]["public_portals"][list_index+1]
  199. if portal_temp then
  200. formspec = formspec.."image_button["..(x*4.5)..","..(2.5+y*.87)..";.6,.6;meseportal.png;list_button"..list_index..";]"
  201. formspec = formspec.."label["..(x*4.5+.5)..","..(2.3+y*.87)..";"
  202. if portal_temp["destination"] ~= nil then
  203. formspec = formspec.."<A> "
  204. end
  205. formspec=formspec.."("..portal_temp["pos"].x..","..portal_temp["pos"].y..","..portal_temp["pos"].z..") "..portal_temp["owner"].."]"
  206. formspec = formspec.."label["..(x*4.5+.5)..","..(2.7+y*.87)..";"..portal_temp["description"]
  207. if isAdmin then
  208. formspec = formspec.." ("..portal_temp["type"]..")"
  209. end
  210. formspec = formspec.."]"
  211. end
  212. list_index=list_index+1
  213. end
  214. end
  215. end
  216. formspec=formspec.."label[7.5,1.7;Page: "..((pagemax > 0) and (page + 1) or 0).." of "..pagemax.."]"
  217. formspec = formspec.."image_button[6.5,1.8;.6,.6;meseportal_left_icon.png;page_left;]"
  218. formspec = formspec.."image_button[6.9,1.8;.6,.6;meseportal_right_icon.png;page_right;]"
  219. if isAdmin then formspec = formspec.."image_button_exit[5.1,9.3;.8,.8;meseportal_adminlock.png;lock_and_save;]" end
  220. formspec = formspec.."image_button_exit[6.1,9.3;.8,.8;meseportal_ok_icon.png;save_changes;]"
  221. formspec = formspec.."image_button_exit[7.1,9.3;.8,.8;meseportal_cancel_icon.png;discard_changes;]"
  222. return formspec
  223. end
  224. -- register_on_player_receive_fields
  225. minetest.register_on_player_receive_fields(function(player, formname, fields)
  226. if formname ~= "meseportals_main" then return end
  227. local player_name = player:get_player_name()
  228. local isAdmin = minetest.check_player_privs(player, {msp_admin=true})
  229. local temp_portal=meseportals_gui["players"][player_name]["temp_portal"]
  230. if not temp_portal then return end
  231. local current_portal=meseportals.findPortal(meseportals_gui["players"][player_name]["temp_portal"]["pos"])
  232. local formspec
  233. if current_portal then
  234. if (player_name ~= current_portal["owner"] and temp_portal["type"] == "private" and not isAdmin) and meseportals.allowPrivatePortals then
  235. reportFormspecViolation(player_name, "accessed someone else's private portal!")
  236. return
  237. end
  238. if player_name == current_portal["owner"] or isAdmin or not meseportals.allowPrivatePortals then
  239. if fields.toggle_type then
  240. if temp_portal["type"] == "private" then
  241. temp_portal["type"] = "public"
  242. else
  243. temp_portal["type"] = "private"
  244. end
  245. meseportals_gui["players"][player_name]["current_index"]=0
  246. formspec= meseportals.get_formspec(player_name,"main")
  247. meseportals_gui["players"][player_name]["formspec"] = formspec
  248. minetest.show_formspec(player_name, "meseportals_main", formspec)
  249. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  250. return
  251. end
  252. if fields.edit_desc then
  253. formspec= meseportals.get_formspec(player_name,"edit_desc")
  254. meseportals_gui["players"][player_name]["formspec"]=formspec
  255. minetest.show_formspec(player_name, "meseportals_main", formspec)
  256. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  257. return
  258. end
  259. if fields.save_desc then
  260. temp_portal["description"]=getCleanText(player_name, fields.desc_box)
  261. formspec= meseportals.get_formspec(player_name,"main")
  262. meseportals_gui["players"][player_name]["formspec"]=formspec
  263. minetest.show_formspec(player_name, "meseportals_main", formspec)
  264. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  265. return
  266. end
  267. else
  268. if fields.toggle_type then
  269. reportFormspecViolation(player_name, "attempted to change type of someone else's portal!")
  270. end
  271. if fields.edit_desc then
  272. reportFormspecViolation(player_name, "attempted to edit description of someone else's portal!")
  273. end
  274. if fields.save_desc then
  275. reportFormspecViolation(player_name, "attempted to change description of someone else's portal!")
  276. end
  277. end
  278. if fields.toggle_dest_type then
  279. if meseportals_gui["players"][player_name]["dest_type"] == "own" then
  280. meseportals_gui["players"][player_name]["dest_type"] = "all"
  281. else meseportals_gui["players"][player_name]["dest_type"] = "own" end
  282. meseportals_gui["players"][player_name]["current_index"] = 0
  283. formspec = meseportals.get_formspec(player_name,"main")
  284. meseportals_gui["players"][player_name]["formspec"] = formspec
  285. minetest.show_formspec(player_name, "meseportals_main", formspec)
  286. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  287. return
  288. end
  289. if fields.update_search_query then
  290. meseportals_gui["players"][player_name]["query"] = getCleanText(player_name, fields.search_box)
  291. meseportals.searchportals(current_portal["pos"], player_name, isAdmin)
  292. formspec = meseportals.get_formspec(player_name,"main")
  293. meseportals_gui["players"][player_name]["formspec"] = formspec
  294. minetest.show_formspec(player_name, "meseportals_main", formspec)
  295. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  296. end
  297. -- page controls
  298. local start=math.floor(meseportals_gui["players"][player_name]["current_index"]/24 +1 )
  299. local start_i=start
  300. local pagemax
  301. if meseportals_gui["players"][player_name]["dest_type"] == "own" then
  302. pagemax = math.ceil((meseportals_gui["players"][player_name]["own_portals_count"]) / 24)
  303. else
  304. pagemax = math.ceil((meseportals_gui["players"][player_name]["public_portals_count"]) / 24)
  305. end
  306. if pagemax == 0 then pagemax = 1 end
  307. if fields.page_left then
  308. minetest.sound_play("paperflip2", {to_player=player_name, gain = 1.0})
  309. start_i = start_i - 1
  310. if start_i < 1 then start_i = 1 end
  311. if not (start_i == start) then
  312. meseportals_gui["players"][player_name]["current_index"] = (start_i-1)*24
  313. formspec = meseportals.get_formspec(player_name,"main")
  314. meseportals_gui["players"][player_name]["formspec"] = formspec
  315. minetest.show_formspec(player_name, "meseportals_main", formspec)
  316. end
  317. end
  318. if fields.page_right then
  319. minetest.sound_play("paperflip2", {to_player=player_name, gain = 1.0})
  320. start_i = start_i + 1
  321. if start_i > pagemax then start_i = pagemax end
  322. if not (start_i == start) then
  323. meseportals_gui["players"][player_name]["current_index"] = (start_i-1)*24
  324. formspec = meseportals.get_formspec(player_name,"main")
  325. meseportals_gui["players"][player_name]["formspec"] = formspec
  326. minetest.show_formspec(player_name, "meseportals_main", formspec)
  327. end
  328. end
  329. if fields.discard_changes then
  330. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  331. end
  332. if current_portal.admin_lock and not isAdmin then
  333. minetest.chat_send_player(player_name, "This portal has been locked by an admin.")
  334. return
  335. end
  336. if fields.remove_dest then
  337. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  338. temp_portal["destination"]=nil
  339. temp_portal["destination_description"]=nil
  340. formspec = meseportals.get_formspec(player_name,"main")
  341. meseportals_gui["players"][player_name]["formspec"] = formspec
  342. minetest.show_formspec(player_name, "meseportals_main", formspec)
  343. end
  344. if fields.save_changes or fields.lock_and_save then
  345. minetest.sound_play("click", {to_player=player_name, gain = 0.5})
  346. if player_name == current_portal["owner"] or isAdmin or not meseportals.allowPrivatePortals then
  347. if fields.desc_box ~= nil then
  348. temp_portal["description"]=getCleanText(player_name, fields.desc_box)
  349. end
  350. current_portal["type"]=temp_portal["type"]
  351. current_portal["description"]=temp_portal["description"]
  352. end
  353. if temp_portal["destination"] then
  354. local dest_portal = meseportals.findPortal(temp_portal["destination"])
  355. if dest_portal then
  356. if isAdmin then
  357. current_portal.admin_lock = fields.lock_and_save
  358. dest_portal.admin_lock = fields.lock_and_save
  359. elseif fields.lock_and_save then
  360. reportFormspecViolation(player_name, "attempted to admin-lock a portal while missing msp_admin privilege!")
  361. end
  362. if dest_portal["type"] ~= "private" or dest_portal["owner"] == player_name or isAdmin then
  363. if current_portal["destination"] ~= nil then
  364. current_portal["destination_deactivate"] = vector.new(current_portal["destination"])
  365. end
  366. current_portal["destination"]={}
  367. current_portal["destination"]=vector.new(temp_portal["destination"])
  368. current_portal["destination_description"]=temp_portal["destination_description"]
  369. current_portal["destination_dir"]=temp_portal["destination_dir"]
  370. else
  371. reportFormspecViolation(player_name, "attempted to connect to private portal at "..minetest.pos_to_string(dest_portal.pos).." from "..minetest.pos_to_string(current_portal.pos))
  372. end
  373. else
  374. minetest.chat_send_player(player_name, "The destination portal seems to have vanished while you were in the menu...")
  375. end
  376. else
  377. if current_portal["destination"] ~= nil then
  378. current_portal["destination_deactivate"] = vector.new(current_portal["destination"])
  379. meseportals.deactivatePortal(current_portal.pos)
  380. end
  381. end
  382. if current_portal["destination_deactivate"] ~= nil then
  383. if not temp_portal["destination"] then
  384. current_portal.admin_lock = nil
  385. end
  386. if meseportals.findPortal(current_portal["destination_deactivate"]) then
  387. meseportals.findPortal(current_portal["destination_deactivate"]).admin_lock = nil
  388. meseportals.deactivatePortal (current_portal["destination_deactivate"])
  389. current_portal["destination_deactivate"] = nil
  390. end
  391. end
  392. if meseportals.findPortal(current_portal["destination"]) then
  393. local dest_portal = meseportals.findPortal(current_portal["destination"])
  394. local can_connect, fail_reason = meseportals.can_connect(table.copy(current_portal), table.copy(dest_portal))
  395. if can_connect or isAdmin then
  396. dest_portal.admin_lock = current_portal.admin_lock
  397. -- Connecting to a portal, its locked state becomes the same as this portal.
  398. if dest_portal["destination"] then --Admin can interrupt any existing connection
  399. meseportals.deactivatePortal(dest_portal["destination"])
  400. end
  401. meseportals.activatePortal (current_portal.pos)
  402. dest_portal["destination"] = current_portal["pos"]
  403. dest_portal["destination_description"] = current_portal["description"]
  404. dest_portal["destination_dir"] = current_portal["dir"]
  405. meseportals.activatePortal (dest_portal.pos)
  406. current_portal["time"] = meseportals.close_after
  407. else
  408. if fail_reason then
  409. minetest.chat_send_player(player_name, "Connection failed: " .. fail_reason)
  410. else
  411. minetest.chat_send_player(player_name, "Connection failed.")
  412. end
  413. meseportals.deactivatePortal (current_portal["pos"])
  414. end
  415. else
  416. meseportals.deactivatePortal (current_portal["pos"])
  417. end
  418. if meseportals.save_data(current_portal["owner"])==nil then
  419. print ("[meseportals] Couldnt update network file!")
  420. end
  421. end
  422. local list_index=meseportals_gui["players"][player_name]["current_index"]
  423. local i
  424. for i=0,23,1 do
  425. local button="list_button"..i+list_index
  426. if fields[button] then
  427. minetest.sound_play("click", {to_player=player_name, gain = 1.0})
  428. local portal=meseportals_gui["players"][player_name]["temp_portal"]
  429. local dest_portal
  430. if meseportals_gui["players"][player_name]["dest_type"] == "own" then
  431. dest_portal=meseportals_gui["players"][player_name]["own_portals"][list_index+i+1]
  432. else
  433. dest_portal=meseportals_gui["players"][player_name]["public_portals"][list_index+i+1]
  434. end
  435. portal["destination"]=vector.new(dest_portal["pos"])
  436. portal["destination_description"]=dest_portal["description"]
  437. portal["destination_dir"]=dest_portal["dir"]
  438. formspec = meseportals.get_formspec(player_name,"main")
  439. meseportals_gui["players"][player_name]["formspec"] = formspec
  440. minetest.show_formspec(player_name, "meseportals_main", formspec)
  441. end
  442. end
  443. end
  444. end)