Several improvements to portal behavior, optimizations, new features

master
Piezo_ 2019-01-25 17:48:21 -08:00
parent 3da01e5e28
commit 3b3678d8dd
6 changed files with 163 additions and 104 deletions

View File

@ -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_

View File

@ -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"]={}

View File

@ -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)

View File

@ -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

View File

@ -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