123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937 |
- --[[
- Advanced Portals (advanced_portals), A minetest add-on that allows certain users to create and place portals on their minetest world.
- Copyright (c) 2020 Genshin <emperor_genshin@hotmail.com>
- License: GPLv3
- --]]
- minetest.register_privilege("portals_admin", {"Grants the ability to configure any portal owned by players", give_to_singleplayer = false})
- minetest.register_privilege("portals", {"Grants the ability to place and configure their own portals", give_to_singleplayer = false})
- local storage = minetest.get_mod_storage()
- local footer = "Version 1.0 - By: Genshin"
- local from_node_metadata = {}
- local previous_input_data = {} --Previous Input Data stored to be reused during active portal placement on the map via on_construct
- local saved_input_data = {} --Previous Input Data stored to be reused when active portal is being right_clicked
- local portal_list_changes = {}
- local previous_portal_ids = {}
- local debug = minetest.settings:get_bool("enable_portals_debug") or false
- portal_list_changes = {}
- --[Local Function] Convert CSV (String list with commas) to a Table Array
- local function convert_csv_to_table_array(s)
- local result = {}
- s = s .. ','
- local t = {}
- local fieldstart = 1
- repeat
- if string.find(s, '^"', fieldstart) then
- local a, c
- local i = fieldstart
- repeat
- a, i, c = string.find(s, '"("?)', i+1)
- until c ~= '"'
- if not i then return result end
- local f = string.sub(s, fieldstart+1, i-1)
- table.insert(t, (string.gsub(f, '""', '"')))
- fieldstart = string.find(s, ',', i) + 1
- else
- local nexti = string.find(s, ',', fieldstart)
- table.insert(t, string.sub(s, fieldstart, nexti-1))
- fieldstart = nexti + 1
- end
- until fieldstart > string.len(s)
- for k,v in pairs(t) do
- result[#result+1] = string.gsub(v, "%s+", "")
- end
- return result
- end
- --[Local Function] Convert CSV (Comma separated values) to XYZ Coordinates
- local function convert_csv_to_xyz(s)
- local result = {}
- local cancel = false
- s = s .. ','
- local t = {}
- local fieldstart = 1
- repeat
- if string.find(s, '^"', fieldstart) then
- local a, c
- local i = fieldstart
- repeat
- a, i, c = string.find(s, '"("?)', i+1)
- until c ~= '"'
- if not i then return result end
- local f = string.sub(s, fieldstart+1, i-1)
- table.insert(t, (string.gsub(f, '""', '"')))
- fieldstart = string.find(s, ',', i) + 1
- else
- local nexti = string.find(s, ',', fieldstart)
- table.insert(t, string.sub(s, fieldstart, nexti-1))
- fieldstart = nexti + 1
- end
- until fieldstart > string.len(s)
- --Convert Table into Coordinates
- for k,v in pairs(t) do
- local number = k
- local value = string.gsub(v, "%s+", "")
- if string.match(v, "%d+") then
- if number == 1 then
- result["x"] = tonumber(value)
- elseif number == 2 then
- result["y"] = tonumber(value)
- elseif number == 3 then
- result["z"] = tonumber(value)
- elseif number > 3 then
- break
- end
- else
- cancel = true
- end
- end
- if cancel == true then
- return {}
- end
- return result
- end
- --[Local Function] Show Portal Configuration Menu
- local function show_portal_configuration_menu(name, meta)
- if minetest.check_player_privs(name, {portals_admin=true}) or minetest.check_player_privs(name, {portals=true}) then
- local owner = meta:get_string("owner")
- --Debug Stuff to see and verify if local owner is being called
- if debug == true then
- minetest.chat_send_player(name, "<[DEBUG]: Owner = "..tostring(owner)..">")
- print("<[DEBUG]: Owner = "..tostring(owner)..">")
- end
- if name ~= owner or (name ~= owner and minetest.check_player_privs(name, {portals_admin=false})) then
- minetest.chat_send_player(name, "You are not authorized to configure this portal!")
- goto end_portal_config
- elseif name == owner or (name ~= owner and minetest.check_player_privs(name, {portals_admin=true})) then
- goto show_portals_form
- end
- ::show_portals_form::
- --Load Previous Inputs
- local status = meta:get_string("status")
- local facedir = meta:get_string("facedir")
- local portal_name = meta:get_string("portal_name")
- local portal_nametag = meta:get_string("nametag")
- local node = meta:get_string("portal_node_name")
- local linked_portal_name = meta:get_string("linked_portal")
- local portal_pos = minetest.deserialize(meta:get_string("portal_pos"))
- local private = meta:get_string("private")
- local linked = meta:get_string("linked")
- local coordinates = meta:get_string("coordinates")
- local whitelist = meta:get_string("whitelist")
- local private_int = nil
- local linked_int = nil
- local status_color = nil
- local formspec = nil
- from_node_metadata[name] = {
- ["nametag"] = portal_nametag,
- ["owner"] = owner,
- ["status"] = status,
- ["facedir"] = facedir,
- ["portal_name"] = portal_name,
- ["portal_node_name"] = node,
- ["portal_pos"] = portal_pos,
- ["node"] = node,
- ["linked_portal_name"] = linked_portal_name,
- ["private"] = private,
- ["linked"] = linked,
- ["coordinates"] = coordinates,
- ["whitelist"] = whitelist
- }
- --Debug Stuff to see and verify if local metadata strings are being stored in table "from_node_metadata" correctly.
- if debug == true then
- minetest.chat_send_player(name, "<[DEBUG]: "..tostring(minetest.serialize(from_node_metadata[name]))..">")
- print("<[DEBUG]: "..tostring(minetest.serialize(from_node_metadata[name]))..">")
- end
- if private == "Yes" then
- private_int = 1
- elseif private == "No" then
- private_int = 2
- end
- if linked == "Yes" then
- linked_int = 1
- elseif linked == "No" then
- linked_int = 2
- end
- if status == "Inactive" then
- status_color = "#e8484a"
- elseif status == "Active" then
- status_color = "#00f03c"
- end
- if portal_name == "" then
- formspec = {
- "size[8,8]",
- "background[-0.30,-0.34;8.5,8.5;portals_gui_bg.png;true]",
- "image[0,-0.85;3.1,3.5;portals_gui_logo.png]",
- "label[3,0.10;Portal Configuration Menu]",
- "label[3,0.55;"..minetest.colorize("#cacaca", "Status: ")..minetest.colorize(status_color, status).."]",
- "label[3,0.80;"..minetest.colorize("#cacaca", "Owner: ")..minetest.colorize("#fff0a2", owner).."]",
- "image[6.60,2.90;0.70,2.43;portals_gui_linked.png]",
- "field[1.95,1.90;5.25,0.8;portal_name;"..minetest.colorize("#ff0004", "* ").."Portal ID;"..portal_name.."]",
- "field[1.95,2.90;5.25,0.8;set_coords;"..minetest.colorize("#ff0004", "* ").."Destination (If not Linked);"..minetest.formspec_escape(coordinates).."]",
- "field[1.95,3.90;4.25,0.8;whitelist; Who else can use this portal? (If Private);"..whitelist.."]",
- "label[5.70,3.23;"..minetest.colorize("#ffe44b", "Private?").."]",
- "dropdown[5.70,3.59;1,1;private;Yes,No;"..private_int.."]",
- "field[1.95,4.90;4.25,0.8;linked_portal;"..minetest.colorize("#ff0004", "* ").."Linked Portal (If Linked);"..linked_portal_name.."]",
- "label[5.70,4.22;"..minetest.colorize("#ffe44b", "Linked?").."]",
- "dropdown[5.70,4.58;1,1;linked;Yes,No;"..linked_int.."]",
- "field[1.95,5.90;4.25,0.8;portal_nametag; Portal Tag;"..portal_nametag.."]",
- "image_button_exit[2.5,6.70;1.5,0.8;portals_gui_button.png;apply;Set]",
- "image_button_exit[4.0,6.70;1.5,0.8;portals_gui_button.png;cancel;Cancel]",
- "label[0,7.90;"..minetest.colorize("#acacac", minetest.formspec_escape(footer)).."]"
- }
- else
- formspec = {
- "size[8,8]",
- "background[-0.30,-0.34;8.5,8.5;portals_gui_bg.png;true]",
- "image[0,-0.85;3.1,3.5;portals_gui_logo.png]",
- "label[3,0.10;Portal Configuration Menu]",
- "label[3,0.55;"..minetest.colorize("#cacaca", "Status: ")..minetest.colorize(status_color, status).."]",
- "label[3,0.80;"..minetest.colorize("#cacaca", "Owner: ")..minetest.colorize("#fff0a2", owner).."]",
- "image[6.60,2.90;0.70,2.43;portals_gui_linked.png]",
- "label[1.80,1.50;Portal ID]",
- "label[1.85,1.80;"..minetest.formspec_escape(portal_name).."]",
- "field[1.95,2.90;5.25,0.8;set_coords;"..minetest.colorize("#ff0004", "* ").."Destination (If not Linked);"..minetest.formspec_escape(coordinates).."]",
- "field[1.95,3.90;4.25,0.8;whitelist; Who else can use this portal? (If Private);"..whitelist.."]",
- "label[5.70,3.23;"..minetest.colorize("#ffe44b", "Private?").."]",
- "dropdown[5.70,3.59;1,1;private;Yes,No;"..private_int.."]",
- "field[1.95,4.90;4.25,0.8;linked_portal;"..minetest.colorize("#ff0004", "* ").."Linked Portal (If Linked);"..linked_portal_name.."]",
- "label[5.70,4.22;"..minetest.colorize("#ffe44b", "Linked?").."]",
- "dropdown[5.70,4.58;1,1;linked;Yes,No;"..linked_int.."]",
- "field[1.95,5.90;4.25,0.8;portal_nametag; Portal Tag;"..portal_nametag.."]",
- "image_button_exit[2.5,6.70;1.5,0.8;portals_gui_button.png;apply;Set]",
- "image_button_exit[4.0,6.70;1.5,0.8;portals_gui_button.png;cancel;Cancel]",
- "label[0,7.90;"..minetest.colorize("#acacac", minetest.formspec_escape(footer)).."]"
- }
- end
- minetest.show_formspec(name, "portals:configuration_menu", table.concat(formspec, ""))
- end
- ::end_portal_config::
- return
- end
- --[Function] Get portal data
- function get_portal_data(portal)
- if not portal then
- return nil
- end
- return minetest.deserialize(storage:get_string(portal))
- end
- --[Function] Get portal data
- function get_portal_data(portal)
- if not portal then
- return nil
- end
- return minetest.deserialize(storage:get_string(portal))
- end
- --[Function] Get portal particle values - TODO
- function get_portal_particle_values(portal, valuetype)
- local bool = storage:get_string(portal.."_activation_particles") or false
- local texture = storage:get_string(portal.."_activation_particle_texture")
- local interval = storage:get_string(portal.."_activation_particles_interval")
- local radius = storage:get_int(portal.."_activation_particle_spread")
- if valuetype == "flag" then
- return bool
- elseif valuetype == "texture" then
- return texture
- elseif valuetype == "delay" then
- return interval
- elseif valuetype == "spread" then
- return radius
- end
- if not portal or not texture or not interval or not radius then
- return nil
- end
- return minetest.deserialize(storage:get_string(portal))
- end
- function get_portal_handler_origin_height(portal, class)
- if class == "warp_handler" then
- return storage:get_int(portal.."_warp_handler_height")
- elseif class == "nametag" then
- return storage:get_int(portal.."_nametag_height")
- end
- return nil
- end
- --[Function] Get Portal Handler Sound by type
- function get_portal_handler_sounds(portal, soundtype)
- local sounds_list = storage:get_string(portal.."_sounds")
- local distance = storage:get_int(portal.."_sound_distance")
- if sounds_list then
- sounds_list = minetest.deserialize(sounds_list)
- if soundtype == "portal_activate" then
- return sounds_list.activate
- elseif soundtype == "portal_ambiance" then
- return sounds_list.portal_ambiance
- elseif soundtype == "portal_warp" then
- return sounds_list.portal_warp
- elseif soundtype == "sound_distance" then
- return distance
- else
- return nil
- end
- return nil
- end
- return nil
- end
- --[Function] Register Portal Node
- function register_portal(name, def)
- --Temporary Data
- local groups_data = {}
- local tmp = {}
- --generate a separate groups table for active portals
- if def.groups then
- for k,v in pairs(def.groups) do
- local group = k
- local group_value = v
- groups_data[group] = group_value
- end
- end
- local active_portal_groups = groups_data
- --Clear temporary data
- groups_data = {}
- --for active portal nodes, make sure they are hidden away from the inventory so they can be swapped silently, also make sure no one can place it either
- active_portal_groups["not_in_creative_inventory"] = 1
- --Inactive Portal
- minetest.register_node("advanced_portals:"..name.."_inactive",{
- description = def.description.." (Inactive)",
- drawtype = "mesh",
- mesh = def.mesh,
- inventory_image = def.inventory_image or nil,
- light_source = def.light_source or nil,
- tiles = {def.tiles[1], "portal_deactivated.png"},
- use_texture_alpha = true,
- groups = def.groups,
- paramtype2 = "facedir",
- selection_box = def.selection_box,
- drop = "advanced_portals:"..name.."_inactive",
- sounds = def.sounds or nil,
- collision_box = def.collision_box,
- on_rotate = screwdriver.rotate_simple,
- after_place_node = function(pos, placer, itemstack, pointed_thing)
- local pname = placer:get_player_name()
- if minetest.check_player_privs(pname, {portals_admin = true}) or minetest.check_player_privs(pname, {portals = true}) then
- local meta = minetest.get_meta(pos)
- local node = minetest.get_node(pos)
- meta:set_string("portal_name", tostring(""))
- meta:set_string("owner", tostring(pname)) --The owner of the portal
- meta:set_string("portal_node_name", name) --The node name of the portal
- meta:set_string("facedir", node.param2)
- meta:set_string("status", "Inactive")
- meta:set_string("facedir", node.param2) --The face direction of the portal, it's needed for swapping nodes
- meta:set_string("owner", tostring(pname)) --The owner of the portal
- meta:set_string("status", "Inactive") --[Flag] Is the portal active or not?
- meta:set_string("portal_pos", minetest.serialize(pos)) --The exact location of the portal
- meta:set_string("private", "No") --[Flag] is this portal private accessible?
- meta:set_string("linked", "No") ----[Flag] is this portal linked to another portal?
- else
- minetest.chat_send_player(pname, "**You are not authorized to place portals on the map!")
- minetest.remove_node(pos)
- return itemstack
- end
- end,
- on_rightclick = function(pos, node, player, itemstack, pointed_thing)
- local pname = player:get_player_name()
- local meta = minetest.get_meta(pos)
- local owner = meta:get_string("owner")
- show_portal_configuration_menu(pname, meta)
- return itemstack
- end
-
- })
- --Active Portal
- minetest.register_node("advanced_portals:"..name.."_active",{
- description = def.description.." (Inactive)\n "..minetest.colorize("#ff0004","*You shouldn't have this!"),
- drawtype = "mesh",
- mesh = def.mesh,
- is_portal = true,
- inventory_image = def.inventory_image or nil,
- light_source = 30,
- tiles = {
- def.tiles[1],
- {
- name = def.activation_sprite,
- animation = {
- type = "vertical_frames",
- aspect_w = 16,
- aspect_h = 16,
- length = 0.3,
- },
- backface_culling = true,
- },
- },
-
- use_texture_alpha = true,
- groups = active_portal_groups,
- paramtype2 = "facedir",
- selection_box = def.selection_box,
- drop = "advanced_portals:"..name.."_inactive",
- sounds = def.sounds or nil,
- collision_box = def.collision_box,
- on_rotate = screwdriver.rotate_simple,
- on_construct = function(pos)
-
- local meta = minetest.get_meta(pos)
- local old_data = previous_input_data
- if old_data == nil then else
- meta:set_string("portal_name", old_data.portal_name)
- meta:set_string("portal_node_name", old_data.portal_node_name)
- meta:set_string("facedir", old_data.facedir)
- meta:set_string("owner", old_data.owner)
- meta:set_string("portal_pos", minetest.serialize(old_data.portal_pos))
- meta:set_string("private", old_data.private)
- meta:set_string("linked", old_data.linked)
- meta:set_string("linked_portal", old_data.linked_portal)
- meta:set_string("coordinates", old_data.coordinates)
- meta:set_string("whitelist", old_data.whitelist)
- meta:set_string("status", old_data.status)
- --Debug Stuff to see and verify if local owner is being called
- if debug == true then
- minetest.chat_send_player(old_data.owner, "<[DEBUG]: Active portal successfully set old metadata at on_construct >")
- print("<[DEBUG]: Active portal successfully set old metadata at on_construct >")
- end
- previous_input_data = nil
- end
- end,
- on_place = function(itemstack, placer, pointed_thing)
- local pname = placer:get_player_name()
- minetest.log("warning", pname.." attempt to place a illegal node on the map. kicking user "..pname.." from the server due to possible exploitation attempts.")
- minetest.chat_send_all(minetest.colorize("#ff8c00", "[EXPLOITATION PREVENTION]:"..pname.." attempted to place unobtainable blocks on the map. kicking user "..pname.." from the server due to possible exploitation attempts."))
- minetest.kick_player(pname, "[Exploitation Attempts] Attempt to place unobtainable illegal blocks on the map. This incident will be reported to the server\'s host!")
- return
- end,
- --Clear Data
- on_destruct = function(pos)
- local meta = minetest.get_meta(pos)
- local portal_name = meta:get_string("portal_name")
- local portals_list = storage:get_string("portals_list")
- storage:set_string(portal_name, "")
- if not (portals_list == nil or portals_list == "") then
- portals_list = minetest.deserialize(portals_list)
- portal_list_changes = portals_list
- if portals_list[portal_name] then
- portal_list_changes[portal_name] = nil
- storage:set_string("portals_list", minetest.serialize(portal_list_changes))
- end
- portal_list_changes = {}
- end
- end,
- on_rightclick = function(pos, node, player, itemstack, pointed_thing)
- local pname = player:get_player_name()
- local meta = minetest.get_meta(pos)
- local owner = meta:get_string("owner")
- local portal_name = meta:get_string("portal_name")
- local old_data = saved_input_data[portal_name]
- if old_data == nil then else
- meta:set_string("nametag", old_data.nametag)
- meta:set_string("portal_name", old_data.portal_name)
- meta:set_string("portal_node_name", old_data.portal_node_name)
- meta:set_string("facedir", old_data.facedir)
- meta:set_string("owner", old_data.owner)
- meta:set_string("portal_pos", minetest.serialize(old_data.portal_pos))
- meta:set_string("private", old_data.private)
- meta:set_string("linked", old_data.linked)
- meta:set_string("linked_portal", old_data.linked_portal)
- meta:set_string("coordinates", old_data.coordinates)
- meta:set_string("whitelist", old_data.whitelist)
- meta:set_string("status", old_data.status)
- saved_input_data[portal_name] = nil
- --Debug Stuff to see and verify if local owner is being called
- if debug == true then
- minetest.chat_send_player(pname, "<[DEBUG]: Active portal successfully set information changes to its metadata via on_rightckick >")
- print("<[DEBUG]: Active portal successfully set information changes to its metadata via on_rightckick >")
- end
- end
- show_portal_configuration_menu(pname, meta)
- return itemstack
- end
-
- })
- --Set dynamic intergers
- if minetest.registered_nodes["advanced_portals:"..name.."_active"] then
- storage:set_int(name.."_warp_handler_height", def.warp_handler_height)
- storage:set_int(name.."_nametag_height", def.nametag_height)
- storage:set_int(name.."_teleport_radius", def.teleport_radius)
- storage:set_int(name.."_warp_height", def.warp_height)
- storage:set_string(name.."_sounds", minetest.serialize(def.portal_sounds))
- storage:set_int(name.."_sound_distance", def.portal_sound_distance)
- storage:set_string(name.."_activation_particles", tostring(def.activation_particles))
- storage:set_string(name.."_activation_particle_texture", def.activation_particle_texture)
- storage:set_int(name.."_activation_particle_interval", def.activation_particle_interval)
- storage:set_int(name.."_activation_particle_spread", def.activation_particle_spread)
- return
- end
- end
- --[Fields Handler] Portal Configuration Menu Handler
- minetest.register_on_player_receive_fields(function(player, formname, fields)
- if formname == "portals:configuration_menu" then
- --[Local Function] Update Portal Config
- if fields.apply then
- goto portal_config_fields
- else
- return
- end
- ::portal_config_fields::
- local pname = player:get_player_name()
- local from_meta = from_node_metadata[pname]
- local portal_name = from_meta.portal_name
- --Debug Stuff to see and verify if portal name is being called
- if debug == true then
- minetest.chat_send_all("1) "..tostring(fields.portal_name)..", "..tostring(portal_name))
- end
- if fields.portal_name and portal_name == "" then
- portal_name = fields.portal_name
- --Debug Stuff to see and verify if portal name is being called
- if debug == true then
- minetest.chat_send_all("2) "..tostring(fields.portal_name)..", "..tostring(portal_name))
- end
- elseif not fields.portal_name and portal_name ~= "" then
- fields.portal_name = portal_name
- --Debug Stuff to see and verify if portal name is being called
- if debug == true then
- minetest.chat_send_all("3) "..tostring(fields.portal_name)..", "..tostring(portal_name))
- end
- end
- if (fields.portal_name == nil or fields.portal_name == "") and portal_name == "" then
- --Debug Stuff to see and verify if portal name is being called
- if debug == true then
- minetest.chat_send_all(tostring(fields.portal_name)..", "..tostring(portal_name))
- end
- minetest.chat_send_player(pname, "**You must give a ID to this portal!")
- return
- else
- local dir = from_meta.facedir
- local node = tostring(from_meta.portal_node_name)
- local owner = tostring(from_meta.owner)
- local status = tostring(from_meta.status)
- local portal_pos = from_meta.portal_pos
- local private_int = nil
- local linked_int = nil
- local is_private = nil
- local is_linked = nil
- local coordinates = {x = 0, y = 0, z = 0}
- local handler_ent = nil
- local nametag_ent = nil
- local handler = nil
- local nametag = nil
- local portal_data = storage:get_string(fields.portal_name)
- local portals_list = storage:get_string("portals_list")
- --Debug Stuff to see and verify if local metadata strings exists in table "from_node_metadata".
- if debug == true then
- minetest.chat_send_all("<[DEBUG]: "..tostring(minetest.serialize(from_meta))..">")
- print("<[DEBUG]: "..tostring(minetest.serialize(from_meta))..">")
- end
- if portal_data == nil or portal_data == "" then else
- portal_data = minetest.deserialize(portal_data)
- end
- if portals_list == nil or portals_list == "" then
- storage:set_string("portals_list", minetest.serialize(portal_list_changes))
- --Debug Stuff to see and verify if portal list changes are present
- if debug == true then
- minetest.chat_send_player(pname, "<[DEBUG]: "..tostring(minetest.serialize(portal_list_changes))..">")
- end
-
- else
-
- portals_list = minetest.deserialize(storage:get_string("portals_list"))
- portal_list_changes = portals_list
- --Debug Stuff to see and verify if portal list changes are present
- if debug == true then
- minetest.chat_send_player(pname, "<[DEBUG]: "..tostring(minetest.serialize(portal_list_changes))..">")
- end
- end
- --update previous portal name and clear it's old data if name does not match with the old portal name
- if portal_name == nil or portal_name == "" then
-
- elseif portal_name ~= fields.portal_name then
- storage:set_string(portal_name, "")
-
- --clear old portal name from the list
- if portals_list[portal_name] then
-
- portal_list_changes[portal_name] = nil
- previous_portal_ids[portal_name] = fields.portal_name
- storage:set_string("previous_portal_ids", minetest.serialize(previous_portal_ids))
- end
- end
- --Check if portal ID exists on the list, if it does, thenn cancel activation.
- if not portals_list[fields.portal_name] then
-
- portal_list_changes[fields.portal_name] = true
- elseif portals_list[fields.portal_name] and portal_name == fields.portal_name then
- elseif portals_list[fields.portal_name] then
- minetest.chat_send_player(pname, "**Unable to change Portal\'s ID, Portal ID \""..fields.portal_name.."\" already exist!")
- return
- end
- if fields.private == "Yes" then
- private_int = 1
- is_private = true
- elseif fields.private == "No" then
- private_int = 2
- is_private = false
- end
- if fields.linked == "Yes" then
- linked_int = 1
- is_linked = true
- elseif fields.linked == "No" then
- linked_int = 2
- is_linked = false
- end
- if is_linked == false then
- coordinates = convert_csv_to_xyz(fields.set_coords)
- if next(coordinates) == nil then
- minetest.chat_send_player(pname, "**You must enter proper XYZ coordinates for the destination!")
- return
- end
-
- elseif is_linked == true then
- local linked_portal_data = storage:get_string(fields.linked_portal)
- --Debug Stuff to see and verify if linked portal data from mod storage has successfully loaded
- if debug == true then
- minetest.chat_send_player(pname, "<[DEBUG]: Linked Portal Data = "..tostring(linked_portal_data).." >")
- print("<[DEBUG]: Linked Portal Data = "..tostring(linked_portal_data).." >")
- end
- if linked_portal_data == nil or linked_portal_data == "" then
- minetest.chat_send_player(pname, "**You must type a existing portal in order to link this portal with another one!")
- return
- else
- linked_portal_data = minetest.deserialize(linked_portal_data)
- local target_portal = linked_portal_data["portal_name"]
- if target_portal ~= fields.linked_portal then
- minetest.chat_send_player(pname, "**You must type a existing portal in order to link this portal with another one!")
- return
- elseif target_portal == fields.portal_name then
- minetest.chat_send_player(pname, "**You can\'t link a portal to itself!")
- return
- end
- end
- end
- local whitelist = convert_csv_to_table_array(fields.whitelist)
- --Debug Stuff to see and verify if local metadata strings are being stored in table "from_node_metadata" correctly.
- if debug == true then
- minetest.chat_send_player(pname, "<[DEBUG]: "..fields.private..", "..fields.linked..", "..tostring(coordinates)..", "..tostring(whitelist)..">")
- minetest.chat_send_player(pname, "<[DEBUG]: "..tostring(minetest.serialize(portal_list_changes))..">")
- print("<[DEBUG]: "..fields.private..", "..fields.linked..", "..tostring(coordinates)..", "..tostring(whitelist)..">")
- print("<[DEBUG]: "..tostring(minetest.serialize(portal_list_changes))..">")
- end
- storage:set_string("portals_list", minetest.serialize(portal_list_changes))
- --Store data so portal entity can use it to do it's thing
- storage:set_string(fields.portal_name, minetest.serialize({
- ["nametag"] = fields.portal_nametag or "",
- ["portal_name"] = fields.portal_name,
- ["facedir"] = dir,
- ["portal_node_name"] = node,
- ["location"] = portal_pos,
- ["owner"] = owner,
- ["private"] = is_private,
- ["linked"] = is_linked,
- ["linked_portal"] = fields.linked_portal,
- ["coordinates"] = coordinates,
- ["status"] = "Active",
- ["whitelist"] = whitelist,
- }))
- --Stored Context Data for later use
- previous_input_data = {
- ["nametag"] = fields.portal_nametag or "",
- ["portal_name"] = fields.portal_name,
- ["facedir"] = dir,
- ["portal_node_name"] = node,
- ["owner"] = owner,
- ["portal_pos"] = portal_pos,
- ["private"] = fields.private,
- ["linked"] = fields.linked,
- ["linked_portal"] = fields.linked_portal,
- ["coordinates"] = fields.set_coords,
- ["whitelist"] = fields.whitelist,
- ["status"] = "Active"
- }
- saved_input_data[fields.portal_name] = {
- ["nametag"] = fields.portal_nametag or "",
- ["portal_name"] = fields.portal_name,
- ["facedir"] = dir,
- ["portal_node_name"] = node,
- ["owner"] = owner,
- ["portal_pos"] = portal_pos,
- ["private"] = fields.private,
- ["linked"] = fields.linked,
- ["linked_portal"] = fields.linked_portal,
- ["coordinates"] = fields.set_coords,
- ["whitelist"] = fields.whitelist,
- ["status"] = "Active"
- }
- --minetest.chat_send_player(pname, "<[DEBUG] "..tostring(storage:get_string(fields.portal_name)..">"))
- if status == "Inactive" then
- local portal_sounds = storage:get_string(node.."_sounds")
- sound_distance = storage:get_string(node.."_sounds_distance") or 20
- local sound = ""
- --Debug Stuff to see and verify if portal sounds list are being called
- if debug == true then
- minetest.chat_send_player(pname, "<[DEBUG] "..tostring(portal_sounds)..">")
- end
- if portal_sounds then
- portal_sounds = minetest.deserialize(portal_sounds)
- sound = portal_sounds.portal_activate
- --Debug Stuff to see and verify if portal activation sound is being called
- if debug == true then
- minetest.chat_send_player(pname, "<[DEBUG] "..tostring(portal_sounds.portal_activate)..">")
- end
- end
- minetest.sound_play(sound, {
- pos = portal_pos,
- max_hear_distance = sound_distance,
- gain = 10.0,
- })
-
- --The entity that will handle teleportation behavior
- handler_ent = minetest.add_entity({x = portal_pos.x, y = portal_pos.y + storage:get_int(node.."_warp_handler_height"), z = portal_pos.z}, "advanced_portals:portal_handler")
- handler = handler_ent:get_luaentity()
- handler.portal_owner = owner
- handler.scan_radius = storage:get_int(node.."_teleport_radius")
- handler.origin_height = storage:get_int(node.."_warp_handler_height")
- handler.portal = fields.portal_name
- handler.portal_node = tostring("advanced_portals:"..node.."_active")
- handler.portal_nodename = node
- handler.emit_particles = storage:get_string(node.."_activation_particles")
- --The enitiy that acts as the portal's nametag
- nametag_ent = minetest.add_entity({x = portal_pos.x, y = portal_pos.y + storage:get_int(node.."_nametag_height"), z = portal_pos.z}, "advanced_portals:portal_nametag")
- nametag = nametag_ent:get_luaentity()
- nametag.origin_height = storage:get_int(node.."_nametag_height")
- nametag.portal = fields.portal_name
- nametag.portal_node = tostring("advanced_portals:"..node.."_active")
- nametag.portal_nodename = node
- nametag.tag = fields.portal_nametag
- --Swaps node to make it look like if it activated
- minetest.set_node(portal_pos, {name="advanced_portals:"..node.."_active", param2 = dir})
- end
- minetest.chat_send_player(pname, "**Portal \""..fields.portal_name.."\" configuration has been successfully updated!")
- from_node_metadata[pname] = {}
- return
- end
- portal_list_changes = {}
- previous_portal_ids = {}
- from_node_metadata[pname] = {}
- end
- end)
- --Clear data
- minetest.register_on_leaveplayer(function(player)
- local name = player:get_player_name()
- if from_node_metadata[name] then
- from_node_metadata[name] = nil
- end
- end)
|