Several improvements to portal behavior, optimizations, new features
parent
3da01e5e28
commit
3b3678d8dd
|
@ -1,7 +1,7 @@
|
|||
Media:
|
||||
|
||||
Portal, item and controller textures: CC BY-SA (4.0) by Piezo_
|
||||
GUI Elements: See <https://github.com/minetest-mods/unified_inventory/blob/master/README.md>
|
||||
Portal, item, and controller textures: CC BY-SA (4.0) by Piezo_
|
||||
textures/meseportal_adminlock.png: CC BY-SA (4.0) by Piezo_
|
||||
Other GUI Elements: See <https://github.com/minetest-mods/unified_inventory/blob/master/README.md>
|
||||
Models: CC BY-SA (4.0) by Piezo_
|
||||
Sounds:
|
||||
Portal noises (meseportal_open, meseportal_close): CC BY-SA (4.0) by Piezo_
|
||||
|
|
5
init.lua
5
init.lua
|
@ -1,12 +1,11 @@
|
|||
-- Minetest 0.4.5 : meseportals
|
||||
|
||||
--data tables definitions
|
||||
meseportals={}
|
||||
meseportals_network = {}
|
||||
meseportals_gui = {}
|
||||
|
||||
meseportals.allowPrivatePortals = true
|
||||
meseportals.maxPlayerPortals = 14 --Set to 0 or lower to restrict portal placement to those with msp_unlimited privilege
|
||||
meseportals.maxPlayerPortals = 14 -- Set to 0 or lower to restrict portal placement to only players with msp_unlimited privilege
|
||||
meseportals.close_after = 120 -- Automatically close portals after a while (default: 2 min)
|
||||
|
||||
meseportals.default_page = "main"
|
||||
meseportals_gui["players"]={}
|
||||
|
|
|
@ -53,7 +53,7 @@ meseportals.searchportals = function(pos, player_name, isAdmin)
|
|||
local temp=tab["player_name"]
|
||||
for __,portals in ipairs(meseportals_network[temp]) do
|
||||
if string.find(portals["description"], meseportals_gui["players"][player_name]["query"]) then
|
||||
if portals["type"]=="public" or isAdmin or not meseportals.allowPrivatePortals then
|
||||
if portals["type"]=="public" or portal["owner"] == player_name or isAdmin or not meseportals.allowPrivatePortals then
|
||||
if portals["pos"].x==pos.x and portals["pos"].y==pos.y and portals["pos"].z==pos.z then
|
||||
--current_portal=portals
|
||||
else
|
||||
|
@ -177,10 +177,10 @@ meseportals.get_formspec = function(player_name,page)
|
|||
end
|
||||
|
||||
local list_index=meseportals_gui["players"][player_name]["current_index"]
|
||||
local page=math.floor(list_index / 24 + 1)
|
||||
local page=math.ceil(list_index / 24)
|
||||
local pagemax
|
||||
if meseportals_gui["players"][player_name]["dest_type"] == "own" then
|
||||
pagemax = math.floor((meseportals_gui["players"][player_name]["own_portals_count"] / 24) + 1)
|
||||
pagemax = math.ceil((meseportals_gui["players"][player_name]["own_portals_count"] / 24))
|
||||
local x,y
|
||||
for y=0,7,1 do
|
||||
for x=0,2,1 do
|
||||
|
@ -198,7 +198,7 @@ meseportals.get_formspec = function(player_name,page)
|
|||
end
|
||||
end
|
||||
else
|
||||
pagemax = math.floor(meseportals_gui["players"][player_name]["public_portals_count"] / 24 + 1)
|
||||
pagemax = math.ceil(meseportals_gui["players"][player_name]["public_portals_count"] / 24)
|
||||
local x,y
|
||||
for y=0,7,1 do
|
||||
for x=0,2,1 do
|
||||
|
@ -223,6 +223,7 @@ meseportals.get_formspec = function(player_name,page)
|
|||
formspec=formspec.."label[7.5,1.7;Page: "..page.." of "..pagemax.."]"
|
||||
formspec = formspec.."image_button[6.5,1.8;.6,.6;meseportal_left_icon.png;page_left;]"
|
||||
formspec = formspec.."image_button[6.9,1.8;.6,.6;meseportal_right_icon.png;page_right;]"
|
||||
if isAdmin then formspec = formspec.."image_button_exit[5.1,9.3;.8,.8;meseportal_adminlock.png;lock_and_save;]" end
|
||||
formspec = formspec.."image_button_exit[6.1,9.3;.8,.8;meseportal_ok_icon.png;save_changes;]"
|
||||
formspec = formspec.."image_button_exit[7.1,9.3;.8,.8;meseportal_cancel_icon.png;discard_changes;]"
|
||||
return formspec
|
||||
|
@ -234,9 +235,14 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
local player_name = player:get_player_name()
|
||||
local isAdmin = minetest.check_player_privs(player, {msp_admin=true})
|
||||
local temp_portal=meseportals_gui["players"][player_name]["temp_portal"]
|
||||
if not temp_portal then return end
|
||||
local current_portal=meseportals.findPortal(meseportals_gui["players"][player_name]["temp_portal"]["pos"])
|
||||
local formspec
|
||||
if current_portal then
|
||||
if (player_name ~= current_portal["owner"] and temp_portal["type"] == "private" and not isAdmin) and meseportals.allowPrivatePortals then
|
||||
reportFormspecViolation(player_name, "accessed someone else's private portal!")
|
||||
return
|
||||
end
|
||||
if player_name == current_portal["owner"] or isAdmin or not meseportals.allowPrivatePortals then
|
||||
if fields.toggle_type then
|
||||
if temp_portal["type"] == "private" then
|
||||
|
@ -330,7 +336,19 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
minetest.show_formspec(player_name, "meseportals_main", formspec)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if fields.discard_changes then
|
||||
minetest.sound_play("click", {to_player=player_name, gain = 0.5})
|
||||
end
|
||||
|
||||
if current_portal.admin_lock and not isAdmin then
|
||||
minetest.chat_send_player(player_name, "This portal has been locked by an admin.")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if fields.remove_dest then
|
||||
minetest.sound_play("click", {to_player=player_name, gain = 0.5})
|
||||
temp_portal["destination"]=nil
|
||||
|
@ -340,10 +358,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
minetest.show_formspec(player_name, "meseportals_main", formspec)
|
||||
end
|
||||
|
||||
if fields.save_changes then
|
||||
if fields.save_changes or fields.lock_and_save then
|
||||
minetest.sound_play("click", {to_player=player_name, gain = 0.5})
|
||||
local meta = minetest.get_meta(temp_portal["pos"])
|
||||
local infotext=""
|
||||
if player_name == current_portal["owner"] or isAdmin or not meseportals.allowPrivatePortals then
|
||||
if fields.desc_box ~= nil then
|
||||
temp_portal["description"]=getCleanText(player_name, fields.desc_box)
|
||||
|
@ -351,10 +367,16 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
current_portal["type"]=temp_portal["type"]
|
||||
current_portal["description"]=temp_portal["description"]
|
||||
end
|
||||
current_portal["dest"]=temp_portal["dest"]
|
||||
if temp_portal["destination"] then
|
||||
local dest_portal = meseportals.findPortal(temp_portal["destination"])
|
||||
if dest_portal then
|
||||
if isAdmin then
|
||||
current_portal.admin_lock = fields.lock_and_save
|
||||
dest_portal.admin_lock = fields.lock_and_save
|
||||
|
||||
elseif fields.lock_and_save then
|
||||
reportFormspecViolation(player_name, "attempted to admin-lock a portal while missing msp_admin privilege!")
|
||||
end
|
||||
if dest_portal["type"] ~= "private" or dest_portal["owner"] == player_name or isAdmin then
|
||||
if current_portal["destination"] ~= nil then
|
||||
current_portal["destination_deactivate"] = vector.new(current_portal["destination"])
|
||||
|
@ -367,7 +389,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
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))
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(player_name, "The portal seems to have vanished while you were still in the menu...")
|
||||
minetest.chat_send_player(player_name, "The destination portal seems to have vanished while you were in the menu...")
|
||||
end
|
||||
else
|
||||
if current_portal["destination"] ~= nil then
|
||||
|
@ -377,15 +399,22 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
end
|
||||
|
||||
if current_portal["destination_deactivate"] ~= nil then
|
||||
if not temp_portal["destination"] then
|
||||
current_portal.admin_lock = nil
|
||||
end
|
||||
if meseportals.findPortal(current_portal["destination_deactivate"]) then
|
||||
meseportals.findPortal(current_portal["destination_deactivate"]).admin_lock = nil
|
||||
meseportals.deactivatePortal (current_portal["destination_deactivate"])
|
||||
current_portal["destination_deactivate"] = nil
|
||||
end
|
||||
end
|
||||
|
||||
if meseportals.findPortal(current_portal["destination"]) then
|
||||
local dest_portal = meseportals.findPortal(current_portal["destination"])
|
||||
if dest_portal["destination"] == nil or isAdmin then
|
||||
if dest_portal["destination"] then --Admin can interrupt an existing connection
|
||||
dest_portal.admin_lock = current_portal.admin_lock
|
||||
-- Connecting to a portal, its locked state becomes the same as this portal.
|
||||
if dest_portal["destination"] then --Admin can interrupt any existing connection
|
||||
meseportals.deactivatePortal(dest_portal["destination"])
|
||||
end
|
||||
meseportals.activatePortal (current_portal.pos)
|
||||
|
@ -393,6 +422,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
dest_portal["destination_description"] = current_portal["description"]
|
||||
dest_portal["destination_dir"] = current_portal["dir"]
|
||||
meseportals.activatePortal (dest_portal.pos)
|
||||
current_portal["time"] = meseportals.close_after
|
||||
else
|
||||
minetest.chat_send_player(player_name, "Connection failed: Portal is busy.")
|
||||
meseportals.deactivatePortal (current_portal["pos"])
|
||||
|
@ -400,39 +430,32 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
else
|
||||
meseportals.deactivatePortal (current_portal["pos"])
|
||||
end
|
||||
|
||||
|
||||
if meseportals.save_data(current_portal["owner"])==nil then
|
||||
print ("[meseportals] Couldnt update network file!")
|
||||
end
|
||||
end
|
||||
|
||||
if fields.discard_changes then
|
||||
minetest.sound_play("click", {to_player=player_name, gain = 0.5})
|
||||
end
|
||||
|
||||
local list_index=meseportals_gui["players"][player_name]["current_index"]
|
||||
local i
|
||||
for i=0,23,1 do
|
||||
local button="list_button"..i+list_index
|
||||
if fields[button] then
|
||||
minetest.sound_play("click", {to_player=player_name, gain = 1.0})
|
||||
local portal=meseportals_gui["players"][player_name]["temp_portal"]
|
||||
local dest_portal
|
||||
if meseportals_gui["players"][player_name]["dest_type"] == "own" then
|
||||
dest_portal=meseportals_gui["players"][player_name]["own_portals"][list_index+i+1]
|
||||
else
|
||||
dest_portal=meseportals_gui["players"][player_name]["public_portals"][list_index+i+1]
|
||||
local button="list_button"..i+list_index
|
||||
if fields[button] then
|
||||
minetest.sound_play("click", {to_player=player_name, gain = 1.0})
|
||||
local portal=meseportals_gui["players"][player_name]["temp_portal"]
|
||||
local dest_portal
|
||||
if meseportals_gui["players"][player_name]["dest_type"] == "own" then
|
||||
dest_portal=meseportals_gui["players"][player_name]["own_portals"][list_index+i+1]
|
||||
else
|
||||
dest_portal=meseportals_gui["players"][player_name]["public_portals"][list_index+i+1]
|
||||
end
|
||||
portal["destination"]=vector.new(dest_portal["pos"])
|
||||
portal["destination_description"]=dest_portal["description"]
|
||||
portal["destination_dir"]=dest_portal["dir"]
|
||||
formspec = meseportals.get_formspec(player_name,"main")
|
||||
meseportals_gui["players"][player_name]["formspec"] = formspec
|
||||
minetest.show_formspec(player_name, "meseportals_main", formspec)
|
||||
end
|
||||
portal["destination"]={}
|
||||
portal["destination"].x=dest_portal["pos"].x
|
||||
portal["destination"].y=dest_portal["pos"].y
|
||||
portal["destination"].z=dest_portal["pos"].z
|
||||
portal["destination_description"]=dest_portal["description"]
|
||||
portal["destination_dir"]=dest_portal["dir"]
|
||||
formspec = meseportals.get_formspec(player_name,"main")
|
||||
meseportals_gui["players"][player_name]["formspec"] = formspec
|
||||
minetest.show_formspec(player_name, "meseportals_main", formspec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -38,15 +38,27 @@ minetest.register_globalstep(function(dtime)
|
|||
for __, portal in pairs(skip) do
|
||||
if portal then
|
||||
pos = portal["pos"]
|
||||
if portal["time"] and not portal["admin_lock"] then -- Close portals automatically after a while
|
||||
if portal["time"] > 0 then
|
||||
portal["time"] = portal["time"] - dtime
|
||||
else
|
||||
portal["time"] = nil
|
||||
if portal["destination"] then
|
||||
meseportals.deactivatePortal(portal["destination"])
|
||||
end
|
||||
meseportals.deactivatePortal(pos)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if minetest.get_node_or_nil(pos) then -- Check and update node
|
||||
if minetest.get_node(pos).name ~= "meseportals:portalnode_off" and minetest.get_node(pos).name ~= "meseportals:portalnode_on" then --Portal broke
|
||||
if minetest.get_node_or_nil(pos) then -- Do the complicated stuff only if the portal is loaded
|
||||
if minetest.get_node(pos).name ~= "meseportals:portalnode_off"
|
||||
and minetest.get_node(pos).name ~= "meseportals:portalnode_on"
|
||||
then --Portal broke
|
||||
if portal["destination"] then
|
||||
meseportals.deactivatePortal(portal["destination"])
|
||||
end
|
||||
meseportals.unregisterPortal(pos)
|
||||
elseif portal["updateme"] then
|
||||
elseif portal["updateme"] then -- Node needs to update
|
||||
if portal["destination"] == nil then
|
||||
if minetest.get_node(pos).name ~= "meseportals:portalnode_off" then
|
||||
minetest.sound_play("meseportal_close", {pos = pos, gain=0.6, max_hear_distance = 40})
|
||||
|
@ -64,7 +76,7 @@ minetest.register_globalstep(function(dtime)
|
|||
else
|
||||
infotext=(portal["description"])
|
||||
if meseportals.allowPrivatePortals then
|
||||
infotext=infotext.." (Public Portal)\n".."Owned by "..portal["owner"]
|
||||
infotext=infotext.." ("..portal["owner"].."'s Public Portal)"
|
||||
end
|
||||
dest_portal = meseportals.findPortal(portal["destination"])
|
||||
if dest_portal then
|
||||
|
@ -75,69 +87,86 @@ minetest.register_globalstep(function(dtime)
|
|||
end
|
||||
end
|
||||
end
|
||||
if portal.admin_lock then
|
||||
infotext=infotext.."\nAdmin connection (Can not be closed)"
|
||||
end
|
||||
meta:set_string("infotext",infotext)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--Teleport players
|
||||
dest_portal=meseportals.findPortal(portal["destination"])
|
||||
if dest_portal then
|
||||
pos1 = vector.new(dest_portal["pos"])
|
||||
dir = portal.dir
|
||||
dir1 = portal.destination_dir
|
||||
hdiff = nil
|
||||
for _,object in pairs(core.get_objects_inside_radius({x = pos.x, y = pos.y, z = pos.z}, 2)) do
|
||||
if dir == 1
|
||||
or dir == 3 then
|
||||
if math.floor(object:get_pos().x + 0.5) == pos.x then
|
||||
hdiff = (object:get_pos().z - pos.z)
|
||||
|
||||
--Teleport players
|
||||
dest_portal=meseportals.findPortal(portal["destination"])
|
||||
if dest_portal then
|
||||
pos1 = vector.new(dest_portal["pos"])
|
||||
dir = portal.dir
|
||||
dir1 = portal.destination_dir
|
||||
for _,object in pairs(core.get_objects_inside_radius({x = pos.x, y = pos.y, z = pos.z}, 2)) do
|
||||
hdiff = nil
|
||||
if dir == 1
|
||||
or dir == 3 then
|
||||
if math.floor(object:get_pos().x + 0.5) == pos.x then
|
||||
hdiff = (object:get_pos().z - pos.z)
|
||||
end
|
||||
else
|
||||
if math.floor(object:get_pos().z + 0.5) == pos.z then
|
||||
hdiff = (object:get_pos().x - pos.x)
|
||||
end
|
||||
end
|
||||
else
|
||||
if math.floor(object:get_pos().z + 0.5) == pos.z then
|
||||
hdiff = (object:get_pos().x - pos.x)
|
||||
if hdiff then
|
||||
pos1.y = pos1.y + (object:get_pos().y - pos.y) + 0.2
|
||||
local dest_angle = ((dir1 - 2) * -90)
|
||||
|
||||
dest_angle = ((object:get_look_horizontal() or object:get_yaw()) + math.pi) + ((dir1 - dir) * -(math.pi/2))
|
||||
|
||||
if dir == 1 or dir == 2 then
|
||||
hdiff = -hdiff
|
||||
end
|
||||
--hdiff = -1
|
||||
if dir1 == 0 then --ALL CORRECT
|
||||
pos1.z = pos1.z-1.25
|
||||
pos1.x = pos1.x - hdiff
|
||||
elseif dir1 == 1 then
|
||||
pos1.x = pos1.x-1.25
|
||||
pos1.z = pos1.z + hdiff
|
||||
elseif dir1 == 2 then
|
||||
pos1.z=pos1.z+1.25
|
||||
pos1.x = pos1.x + hdiff
|
||||
elseif dir1 == 3 then
|
||||
pos1.x = pos1.x+1.25
|
||||
pos1.z = pos1.z - hdiff
|
||||
end
|
||||
object:set_pos(pos1)
|
||||
local vel = object:get_velocity() or object:get_player_velocity()
|
||||
vel.x = -vel.x
|
||||
local magnitude = math.sqrt((vel.x*vel.x) + (vel.z*vel.z))
|
||||
if math.abs(vel.z) < 0.01 then
|
||||
vel.z = 0.01
|
||||
end
|
||||
local direction = math.atan(vel.x/vel.z)
|
||||
-- Direction of velocity plus the change in look direction
|
||||
if vel.z < 0 then
|
||||
direction = direction + math.pi
|
||||
end
|
||||
direction = direction + math.pi + ((dir1 - dir) * -(math.pi/2))
|
||||
vel.x = magnitude * -math.sin(direction)
|
||||
vel.z = magnitude * math.cos(direction)
|
||||
if object:is_player() then
|
||||
--player:set_player_velocity(vel) -- TODO: Bother the devs more about this
|
||||
object:set_look_horizontal(dest_angle)
|
||||
minetest.sound_play("meseportal_warp", {to_player=object:get_player_name(), gain=0.6, max_hear_distance=15})
|
||||
else
|
||||
object:set_velocity(vel)
|
||||
object:set_yaw(dest_angle)
|
||||
end
|
||||
minetest.sound_play("meseportal_warp", {pos = pos, gain=0.6, max_hear_distance=15})
|
||||
minetest.sound_play("meseportal_warp", {pos = pos1, gain=0.6, max_hear_distance=15})
|
||||
end
|
||||
end
|
||||
if hdiff then
|
||||
pos1.y = pos1.y + (object:get_pos().y - pos.y) + 0.2
|
||||
local dest_angle = ((dir1 - 2) * -90)
|
||||
|
||||
if object:get_look_horizontal() then
|
||||
dest_angle = (math.deg(object:get_look_horizontal()) + 180) + ((dir1 - dir) * -90)
|
||||
end
|
||||
|
||||
if dir == 1 or dir == 2 then
|
||||
hdiff = -hdiff
|
||||
end
|
||||
--hdiff = -1
|
||||
if dir1 == 0 then --ALL CORRECT
|
||||
pos1.z = pos1.z-1.25
|
||||
pos1.x = pos1.x - hdiff
|
||||
elseif dir1 == 1 then
|
||||
pos1.x = pos1.x-1.25
|
||||
pos1.z = pos1.z + hdiff
|
||||
elseif dir1 == 2 then
|
||||
pos1.z=pos1.z+1.25
|
||||
pos1.x = pos1.x + hdiff
|
||||
elseif dir1 == 3 then
|
||||
pos1.x = pos1.x+1.25
|
||||
pos1.z = pos1.z - hdiff
|
||||
end
|
||||
object:moveto(pos1,false)
|
||||
object:set_look_horizontal(math.rad(dest_angle))
|
||||
if object:is_player() then
|
||||
minetest.sound_play("meseportal_warp", {to_player=object:get_player_name(), gain=0.6, max_hear_distance=15})
|
||||
end
|
||||
minetest.sound_play("meseportal_warp", {pos = pos, gain=0.6, max_hear_distance=15})
|
||||
minetest.sound_play("meseportal_warp", {pos = pos1, gain=0.6, max_hear_distance=15})
|
||||
else
|
||||
if portal["destination"] then --Destination portal broke/vanished
|
||||
meseportals.deactivatePortal(pos)
|
||||
end
|
||||
end
|
||||
else
|
||||
if portal["destination"] then --Destination portal broke/vanished
|
||||
meseportals.deactivatePortal(pos)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,6 +12,8 @@ end
|
|||
|
||||
minetest.register_node("meseportals:portal_collider",{
|
||||
drawtype = "airlike",
|
||||
on_blast = function() end,
|
||||
drop = "",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
sunlight_propagates = true,
|
||||
can_dig = false,
|
||||
|
@ -230,7 +232,6 @@ minetest.register_node("meseportals:portalnode_on",{
|
|||
on_rightclick=meseportals.portalFormspecHandler,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_node("meseportals:portalnode_off",{
|
||||
description = "Mese Portal (Sneak+Place = Buried)",
|
||||
inventory_image = "meseportal.png",
|
||||
|
@ -313,10 +314,17 @@ minetest.is_protected = function(pos, player, ...) --Protect the bottom of the p
|
|||
end
|
||||
end
|
||||
portal = meseportals.findPortal(pos)
|
||||
if portal and portal.owner ~= player and not minetest.check_player_privs(player, {msp_admin=true}) then
|
||||
minetest.chat_send_player(player, "This portal belongs to " ..portal["owner"] .."!")
|
||||
return true
|
||||
if portal and not minetest.check_player_privs(player, {msp_admin=true}) then
|
||||
if portal.owner ~= player then
|
||||
minetest.chat_send_player(player, "This portal belongs to " ..portal["owner"] .."!")
|
||||
return true
|
||||
end
|
||||
if portal.admin_lock then
|
||||
minetest.chat_send_player(player, "This portal has been locked by an admin.")
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return old_protected(pos, player, ...)
|
||||
end
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Loading…
Reference in New Issue