+ Reset system now async!

+ Added tests for the map reset system
+ Fixed get_arena_by_pos()
+ Code cleaning and optimizations
- Debug messages translations
master
Giov4 2020-11-02 18:13:45 +01:00
parent f3615d3e8f
commit ad3f9b5261
12 changed files with 321 additions and 95 deletions

View File

@ -35,7 +35,7 @@ skywars_settings.player_speed = 1.5
-- true = on/false = off (case sensitive). -- true = on/false = off (case sensitive).
skywars_settings.fall_damage_disabled = true skywars_settings.fall_damage_disabled = true
-- The name of the permission to allow players to break blocks -- The name of the permission to allow players to break nodes
-- (if there's none just set it to ""). -- (if there's none just set it to "").
skywars_settings.build_permission = "build" skywars_settings.build_permission = "build"

View File

@ -15,8 +15,8 @@ an arena can have.
2) Saving the map area using: 2) Saving the map area using:
/skywars pos1 <arena name> /skywars min_pos <arena name>
/skywars pos2 <arena name> /skywars max_pos <arena name>
In order to kill players that go out of the map and to properly recognize In order to kill players that go out of the map and to properly recognize
the arena you have to define a map area; to do so, simply specify its the arena you have to define a map area; to do so, simply specify its

View File

@ -1,6 +1,6 @@
local function add_privs() end local function add_privs() end
local function remove_privs() end local function remove_privs() end
local function create_glass_cage()end local function create_glass_cage() end
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
@ -10,7 +10,7 @@ end)
arena_lib.on_load("skywars", function(arena) arena_lib.on_load("skywars", function(arena)
skywars.load_map_mapblocks(arena) skywars.load_mapblocks(arena)
skywars.reset_map(arena) skywars.reset_map(arena)
for pl_name in pairs(arena.players) do for pl_name in pairs(arena.players) do
@ -65,6 +65,8 @@ arena_lib.on_end("skywars", function(arena, players)
skywars.remove_armor(player) skywars.remove_armor(player)
skywars.block_enderpearl(player, arena) skywars.block_enderpearl(player, arena)
end end
skywars.reset_map(arena)
end) end)
@ -130,7 +132,7 @@ arena_lib.on_enable("skywars", function(arena, pl_name)
elseif arena.chests[1] == nil then elseif arena.chests[1] == nil then
skywars.print_error(pl_name, skywars.T("You didn't set the chests!")) skywars.print_error(pl_name, skywars.T("You didn't set the chests!"))
return false return false
elseif arena.pos1.x == nil or arena.pos2.x == nil then elseif arena.min_pos.x == nil or arena.max_pos.x == nil then
skywars.print_error(pl_name, skywars.T("You didn't set the map corners!")) skywars.print_error(pl_name, skywars.T("You didn't set the map corners!"))
return false return false
end end
@ -159,7 +161,7 @@ function add_privs(pl_name)
local privs = minetest.get_player_privs(pl_name) local privs = minetest.get_player_privs(pl_name)
local player = minetest.get_player_by_name(pl_name) local player = minetest.get_player_by_name(pl_name)
-- preventing players with noclip to fall when placing blocks -- preventing players with noclip to fall when placing nodes
if privs.noclip then if privs.noclip then
player:get_meta():set_string("sw_can_noclip", "true") player:get_meta():set_string("sw_can_noclip", "true")
privs.noclip = nil privs.noclip = nil
@ -200,7 +202,7 @@ end
function create_glass_cage(player) function create_glass_cage(player)
minetest.after(0.1, function() minetest.after(0.1, function()
local pl_pos = player:get_pos() local pl_pos = player:get_pos()
local glass_blocks = { local glass_nodes = {
{x = 0, y = -1, z = 0}, {x = 0, y = -1, z = 0},
{x = 0, y = -2, z = 0}, {x = 0, y = -2, z = 0},
{x = 1, y = 1, z = 0}, {x = 1, y = 1, z = 0},
@ -213,7 +215,7 @@ function create_glass_cage(player)
player:set_physics_override({gravity=0, jump=0}) player:set_physics_override({gravity=0, jump=0})
player:add_player_velocity(vector.multiply(player:get_player_velocity(), -1)) player:add_player_velocity(vector.multiply(player:get_player_velocity(), -1))
for _, relative_pos in pairs(glass_blocks) do for _, relative_pos in pairs(glass_nodes) do
local node_pos = vector.round(vector.add(pl_pos, relative_pos)) local node_pos = vector.round(vector.add(pl_pos, relative_pos))
if minetest.get_node(node_pos).name == "air" then if minetest.get_node(node_pos).name == "air" then
minetest.add_node(node_pos, {name="default:glass"}) minetest.add_node(node_pos, {name="default:glass"})
@ -224,5 +226,8 @@ function create_glass_cage(player)
minetest.after(1, function() minetest.after(1, function()
player:set_pos(pl_pos) player:set_pos(pl_pos)
end) end)
minetest.after(2, function()
player:set_pos(pl_pos)
end)
end) end)
end end

View File

@ -18,7 +18,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local arena = arena_lib.get_arena_by_player(pl_name) local arena = arena_lib.get_arena_by_player(pl_name)
local kits = skywars.load_table("kits") local kits = skywars.load_table("kits")
-- if the pressed button name is equal to one of the kits in the arena then select it -- If the pressed button name is equal to one of the kits in the arena then select it.
for i = 1, #arena.kits do for i = 1, #arena.kits do
local kit_name = arena.kits[i] local kit_name = arena.kits[i]
if fields[kit_name] then if fields[kit_name] then
@ -60,7 +60,7 @@ function create_formspec(arena)
local offset_y = 0 local offset_y = 0
local kits = skywars.load_table("kits") local kits = skywars.load_table("kits")
-- generates the formspec buttons -- Generates the formspec buttons.
for i=1, #arena.kits do for i=1, #arena.kits do
local kit_name = arena.kits[i] local kit_name = arena.kits[i]
local kit = kits[kit_name] local kit = kits[kit_name]
@ -77,7 +77,7 @@ function create_formspec(arena)
end end
if kit.items and kit.items[1] then if kit.items and kit.items[1] then
-- if offset_x has reached its maximum amount then reset it and increase offset_y -- If offset_x has reached its maximum amount then reset it and increase offset_y.
if offset_x == distance_x * (buttons_per_row-1) then if offset_x == distance_x * (buttons_per_row-1) then
offset_y = offset_y + distance_y offset_y = offset_y + distance_y
offset_x = 0 offset_x = 0
@ -85,11 +85,11 @@ function create_formspec(arena)
offset_x = offset_x + distance_x offset_x = offset_x + distance_x
end end
-- generating the kit description (a list of all the items in the kit) -- Generating the kit description (a list of all the items in the kit).
for j = 1, #kit.items do for j = 1, #kit.items do
local item_name = kit.items[j].name local item_name = kit.items[j].name
-- if the string is "mod:item_name" it becomes "item name" -- If the string is "mod:item_name" it becomes "item name".
if string.match(item_name, ":") then if string.match(item_name, ":") then
local split_name = string.split(item_name, ":") local split_name = string.split(item_name, ":")
item_name = string.gsub(split_name[2], "_", " ") item_name = string.gsub(split_name[2], "_", " ")

View File

@ -1,40 +1,19 @@
local function save_block() end local function save_block() end
local function delete_drops() end
local function async_reset_map() end
function skywars.load_mapblocks(arena)
function skywars.load_map_mapblocks(arena) minetest.load_area(arena.min_pos, arena.max_pos)
minetest.load_area(arena.pos1, arena.pos2) minetest.emerge_area(arena.min_pos, arena.max_pos)
minetest.emerge_area(arena.pos1, arena.pos2)
end end
function skywars.reset_map(arena) function skywars.reset_map(arena, debug, debug_data)
local maps = skywars.load_table("maps") if not arena.enabled or arena.is_resetting then return end
local pos1, pos2 = reorder_positions(arena.pos1, arena.pos2)
local distance_from_center = vector.distance(pos1, pos2) / 2
local map_center = {x = (pos1.x+pos2.x) / 2, y = (pos1.y+pos2.y) / 2, z = (pos1.z+pos2.z) / 2}
-- deleting drops delete_drops(arena)
for i, obj in pairs(minetest.get_objects_inside_radius(map_center, distance_from_center)) do async_reset_map(arena, debug, debug_data)
if not obj:is_player() then
local props = obj:get_properties()
local entity_texture = props.textures[1]
if props.automatic_rotate > 0 and ItemStack(entity_texture):is_known() then
obj:remove()
end
end
end
if not maps or maps == "" or not maps[arena.name] or not maps[arena.name].blocks then
return
end
for serialized_pos, node in pairs(maps[arena.name].blocks) do
local pos = minetest.deserialize(serialized_pos)
minetest.add_node(pos, node)
end
maps[arena.name].blocks = {}
skywars.overwrite_table("maps", maps)
end end
@ -43,7 +22,7 @@ function skywars.kill_players_out_map(arena)
for pl_name in pairs(arena.players) do for pl_name in pairs(arena.players) do
local player = minetest.get_player_by_name(pl_name) local player = minetest.get_player_by_name(pl_name)
local pl_pos = player:get_pos() local pl_pos = player:get_pos()
local map_area = VoxelArea:new{MinEdge = arena.pos1, MaxEdge = arena.pos2} local map_area = VoxelArea:new{MinEdge = arena.min_pos, MaxEdge = arena.max_pos}
if map_area:contains(pl_pos.x, pl_pos.y, pl_pos.z) == false then if map_area:contains(pl_pos.x, pl_pos.y, pl_pos.z) == false then
player:set_hp(0) player:set_hp(0)
@ -81,13 +60,15 @@ end)
-- minetest.set_node override -- minetest.set_node override.
local set_node = minetest.set_node local set_node = minetest.set_node
function minetest.set_node(pos, node) function minetest.set_node(pos, node)
local arena = skywars.get_arena_by_pos(pos) local arena = skywars.get_arena_by_pos(pos)
local oldnode = minetest.get_node(pos) local oldnode = minetest.get_node(pos)
if arena and arena.enabled then save_block(arena, pos, oldnode) end if arena and arena.enabled then
save_block(arena, pos, oldnode)
end
return set_node(pos, node) return set_node(pos, node)
end end
@ -107,11 +88,101 @@ function save_block(arena, pos, node)
if not arena then return end if not arena then return end
if not maps then maps = {} end if not maps then maps = {} end
if not maps[arena.name] then maps[arena.name] = {} end if not maps[arena.name] then maps[arena.name] = {} end
if not maps[arena.name].blocks then maps[arena.name].blocks = {} end if not maps[arena.name].nodes then maps[arena.name].nodes = {} end
-- if this block has not been changed yet then save it -- If this block has not been changed yet then save it.
if maps[arena.name].blocks[serialized_pos] == nil then if maps[arena.name].nodes[serialized_pos] == nil then
maps[arena.name].blocks[serialized_pos] = node maps[arena.name].nodes[serialized_pos] = node
skywars.overwrite_table("maps", maps) skywars.overwrite_table("maps", maps)
end end
end
function delete_drops(arena)
local min_pos, max_pos = skywars.reorder_positions(arena.min_pos, arena.max_pos)
local distance_from_center = vector.distance(min_pos, max_pos) / 2
local map_center = {
x = (min_pos.x + max_pos.x) / 2,
y = (min_pos.y + max_pos.y) / 2,
z = (min_pos.z + max_pos.z) / 2
}
for i, obj in pairs(minetest.get_objects_inside_radius(map_center, distance_from_center)) do
if not obj:is_player() then
local props = obj:get_properties()
local entity_texture = props.textures[1]
if props.automatic_rotate > 0 and ItemStack(entity_texture):is_known() then
obj:remove()
end
end
end
end
function async_reset_map(arena, debug, recursive_data)
recursive_data = recursive_data or {}
-- When the function gets called again it uses the same maps table.
local original_maps = recursive_data.original_maps or skywars.load_table("maps")
if not original_maps[arena.name] or not original_maps[arena.name].nodes then
return
end
-- The indexes are useful to count the reset nodes.
debug = debug or false
local current_index = 1
local original_map_nodes = original_maps[arena.name].nodes
local last_index = recursive_data.last_index or 0
local nodes_per_tick = recursive_data.nodes_per_tick or 30
local current_cycle = recursive_data.current_cycle or 1
local initial_time = recursive_data.initial_time or minetest.get_us_time()
local nodes_to_reset = nodes_per_tick * current_cycle
-- Resets a node if it hasn't been reset yet and, if it reset more than "nodes_per_tick"
-- nodes, it invokes this function again after one step.
arena.is_resetting = true
for serialized_pos, node in pairs(original_map_nodes) do
if current_index > last_index then
local pos = minetest.deserialize(serialized_pos)
minetest.add_node(pos, node)
end
if current_index >= nodes_to_reset then
minetest.after(0, function()
async_reset_map(arena, debug, {
last_index = current_index,
nodes_per_tick = nodes_per_tick,
original_maps = original_maps,
current_cycle = current_cycle+1,
initial_time = initial_time
})
end)
return
end
current_index = current_index + 1
end
arena.is_resetting = false
-- Removing the original map nodes from the actual map to preserve eventual changes made
-- to the latter during the reset.
local actual_maps = skywars.load_table("maps")
if not actual_maps[arena.name] or not actual_maps[arena.name].nodes then
return
end
local actual_map_nodes = actual_maps[arena.name].nodes
for serialized_pos, node in pairs(actual_map_nodes) do
if original_map_nodes[serialized_pos] then
actual_map_nodes[serialized_pos] = nil
end
end
skywars.overwrite_table("maps", actual_maps)
if debug then
local duration = minetest.get_us_time() - initial_time
minetest.log("[Skywars Reset Debug] The reset took " .. duration/1000000 .. " seconds!")
end
end end

106
_tests/map_reset.lua Normal file
View File

@ -0,0 +1,106 @@
local function test_not_async_reset() end
local function test_async_reset() end
local function place_nodes_at_arena_edges() end
local function get_nodes_at_arena_edges() end
function skywars.map_reset_test(arena)
return test_not_async_reset(arena) and test_async_reset(arena)
end
function skywars.test_async_speed(arena)
skywars.reorder_positions(arena.min_pos, arena.max_pos)
skywars.load_mapblocks(arena)
local max_pos = arena.max_pos
local min_pos = arena.min_pos
local area_size = 10
max_pos = vector.add(min_pos, area_size)
for x = 1, max_pos.x - min_pos.x do
for y = 1, max_pos.y - min_pos.y do
for z = 1, max_pos.z - min_pos.z do
local node_pos = {
x = min_pos.x+x,
y = min_pos.y+y,
z = min_pos.z+z
}
minetest.set_node(node_pos, {name="skywars:test_node"})
end
end
end
minetest.after(1, function() skywars.reset_map(arena, true) end)
end
function test_not_async_reset(arena)
place_nodes_at_arena_edges(arena)
skywars.reset_map(arena)
local node1, node2 = get_nodes_at_arena_edges(arena)
local did_nodes_reset = (node1.name ~= "skywars:test_node" and node2.name ~= "skywars:test_node")
if not did_nodes_reset then
minetest.log("[Skywars Test] Reset system doesn't work")
return false
end
return true
end
function test_async_reset(arena)
place_nodes_at_arena_edges(arena)
skywars.reset_map(arena, true, {nodes_per_tick = 1})
local node1, node2 = get_nodes_at_arena_edges(arena)
local did_just_one_node_reset = (node1.name ~= node2.name)
if not did_just_one_node_reset then
minetest.log("[Skywars Test] Async reset system doesn't work")
return false
end
return true
end
function place_nodes_at_arena_edges(arena)
skywars.reorder_positions(arena.min_pos, arena.max_pos)
skywars.load_mapblocks(arena)
local node1, node2 = get_nodes_at_arena_edges(arena)
if node1.name == "skywars:test_node" then minetest.remove_node(arena.min_pos) end
if node2.name == "skywars:test_node" then minetest.remove_node(arena.max_pos) end
skywars.overwrite_table("maps", {})
minetest.set_node(arena.min_pos, {name="skywars:test_node"})
minetest.set_node(arena.max_pos, {name="skywars:test_node"})
node1 = minetest.get_node(arena.min_pos)
node2 = minetest.get_node(arena.max_pos)
end
function get_nodes_at_arena_edges(arena)
local node1 = minetest.get_node(arena.min_pos)
local node2 = minetest.get_node(arena.max_pos)
return node1, node2
end
minetest.register_node("skywars:test_node", {
description = "Skywars test block, don't use it!",
groups = {crumbly=1, soil=1},
tiles = {"test_node.png"},
})

View File

@ -748,8 +748,8 @@ ChatCmdBuilder.new("skywars", function(cmd)
return return
end end
arena.pos1 = player:get_pos() arena.min_pos = player:get_pos()
arena_lib.change_arena_property(sender, "skywars", arena.name, "pos1", arena.pos1) arena_lib.change_arena_property(sender, "skywars", arena.name, "min_pos", arena.min_pos)
skywars.print_msg(sender, skywars.T("Position saved!")) skywars.print_msg(sender, skywars.T("Position saved!"))
end) end)
@ -765,24 +765,14 @@ ChatCmdBuilder.new("skywars", function(cmd)
return return
end end
arena.pos2 = player:get_pos() arena.max_pos = player:get_pos()
arena_lib.change_arena_property(sender, "skywars", arena.name, "pos2", arena.pos2) arena_lib.change_arena_property(sender, "skywars", arena.name, "max_pos", arena.max_pos)
skywars.print_msg(sender, skywars.T("Position saved!")) skywars.print_msg(sender, skywars.T("Position saved!"))
end) end)
cmd:sub("getpos",
function(sender)
local pos = minetest.get_player_by_name(sender):get_pos()
local readable_pos = "[X Y Z] " .. minetest.pos_to_string(pos, 1)
skywars.print_msg(sender, readable_pos)
end)
cmd:sub("reset :arena", cmd:sub("reset :arena",
function(sender, arena_name) function(sender, arena_name)
local player = minetest.get_player_by_name(sender) local player = minetest.get_player_by_name(sender)
@ -802,10 +792,60 @@ ChatCmdBuilder.new("skywars", function(cmd)
--------------------
-- ! DEBUG CMDS ! --
--------------------
cmd:sub("clearmapstable", cmd:sub("clearmapstable",
function(sender) function(sender)
skywars.overwrite_table("maps", {}) skywars.overwrite_table("maps", {})
skywars.print_msg(sender, skywars.T("Maps table reset!")) skywars.print_msg(sender, "Maps table reset!")
end)
cmd:sub("getpos",
function(sender)
local pos = minetest.get_player_by_name(sender):get_pos()
local readable_pos = "[X Y Z] " .. minetest.pos_to_string(pos, 1)
skywars.print_msg(sender, readable_pos)
end)
cmd:sub("test reset :arena",
function(sender, arena_name)
local player = minetest.get_player_by_name(sender)
local arena, arena_name = get_valid_arena(arena_name, sender)
if not arena then return end
if arena.enabled then
local result = skywars.map_reset_test(arena)
if result then skywars.print_msg(sender, "Reset system working!")
else skywars.print_error(sender, "Reset system doesn't work!") end
else
skywars.print_error(sender, skywars.T("@1 must be enabled!", arena_name))
end
end)
cmd:sub("test asyncspeed :arena",
function(sender, arena_name)
local player = minetest.get_player_by_name(sender)
local arena, arena_name = get_valid_arena(arena_name, sender)
if not arena then return end
skywars.print_msg(sender, "Placing 1000 nodes, the server may lag...")
if arena.enabled then
skywars.test_async_speed(arena)
skywars.print_msg(sender, "Nodes placed at " .. minetest.pos_to_string(arena.min_pos, 0) .. "!")
else
skywars.print_error(sender, skywars.T("@1 must be enabled!", arena_name))
end
end) end)
end, { end, {
@ -850,8 +890,8 @@ end, {
- additem hand <kit name> - additem hand <kit name>
- removeitem <kit name> <item> - removeitem <kit name> <item>
- removeitem hand <kit name> - removeitem hand <kit name>
- arenakit add <arena> <kit name> - arenakit add <arena name> <kit name>
- arenakit remove <arena> <kit name> - arenakit remove <arena name> <kit name>
- getkits - getkits
- resetkit <kit name> - resetkit <kit name>
- getitems <kit name> - getitems <kit name>
@ -860,8 +900,12 @@ end, {
Debug (don't use them if you don't know what you're doing): Debug (don't use them if you don't know what you're doing):
- clearmapstable: clears the changed blocks table of each map without resetting them - clearmapstable: clears the changed nodes table of each map without resetting them
- getpos - getpos
- test reset <arena name>: tests the reset system, make sure your map is properly reset
before using it, 'cause it will clear the maps table first
- test asyncspeed <arena name>: places a 10x10 area full of nodes, useful to test the
async reset system speed (read the server logs to know the reset speed)
]], ]],
privs = { skywars_admin = true } privs = { skywars_admin = true }
}) })

View File

@ -21,10 +21,11 @@ arena_lib.register_minigame("skywars", {
}, },
properties = { properties = {
chests = {}, chests = {},
treasures = {}, -- items to put in the chests treasures = {}, -- Items to put in the chests.
pos1 = {}, min_pos = {},
pos2 = {}, max_pos = {},
kits = {} kits = {},
is_resetting = false
}, },
time_mode = 2, time_mode = 2,
disabled_damage_types = disabled_damage_types_ disabled_damage_types = disabled_damage_types_
@ -34,6 +35,7 @@ arena_lib.register_minigame("skywars", {
dofile(minetest.get_modpath("skywars") .. "/chatcmdbuilder.lua") dofile(minetest.get_modpath("skywars") .. "/chatcmdbuilder.lua")
dofile(minetest.get_modpath("skywars") .. "/utils.lua") dofile(minetest.get_modpath("skywars") .. "/utils.lua")
dofile(minetest.get_modpath("skywars") .. "/_tests/map_reset.lua")
dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/enderpearl/init_enderpearl.lua") dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/enderpearl/init_enderpearl.lua")
dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/3d_armor/init_3d_armor.lua") dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/3d_armor/init_3d_armor.lua")
dofile(minetest.get_modpath("skywars") .. "/_storage/storage_manager.lua") dofile(minetest.get_modpath("skywars") .. "/_storage/storage_manager.lua")

View File

@ -41,5 +41,4 @@ x@1 @2 added to @3!=x@1 @2 aggiunto a @3!
@1 kits have been copied to @2!=I kit di @1 sono stati copiati in @2! @1 kits have been copied to @2!=I kit di @1 sono stati copiati in @2!
Time is out, the match is over!=Tempo terminato, la partita è finita! Time is out, the match is over!=Tempo terminato, la partita è finita!
Nobody=Nessuno Nobody=Nessuno
Nobody must be in the editor!=Nessuno deve essere nell'editor! Nobody must be in the editor!=Nessuno deve essere nell'editor!
Maps table reset!=Tabella mappe resettata!

View File

@ -41,5 +41,4 @@ x@1 @2 added to @3!=
@1 kits have been copied to @2!= @1 kits have been copied to @2!=
Time is out, the match is over!= Time is out, the match is over!=
Nobody= Nobody=
Nobody must be in the editor!= Nobody must be in the editor!=
Maps table reset!=

BIN
textures/test_node.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

View File

@ -12,10 +12,10 @@ end
function skywars.get_arena_by_pos(pos) function skywars.get_arena_by_pos(pos)
for i, arena in pairs(arena_lib.mods["skywars"].arenas) do for i, arena in pairs(arena_lib.mods["skywars"].arenas) do
if arena.pos1.x == nil or arena.pos2.x == nil then goto continue end if arena.min_pos.x == nil or arena.max_pos.x == nil then goto continue end
reorder_positions(arena.pos1, arena.pos2) skywars.reorder_positions(arena.min_pos, arena.max_pos)
local map_area = VoxelArea:new{MinEdge = arena.pos1, MaxEdge = arena.pos2} local map_area = VoxelArea:new{MinEdge = arena.min_pos, MaxEdge = arena.max_pos}
if map_area:contains(pos.x, pos.y, pos.z) then if map_area:contains(pos.x, pos.y, pos.z) then
return arena return arena
@ -27,27 +27,27 @@ end
-- reordering the corners positions so that pos1 is smaller than pos2 -- reordering the corners positions so that min_pos is smaller than max_pos
function reorder_positions(pos1, pos2) function skywars.reorder_positions(min_pos, max_pos)
local temp local temp
if pos1.z > pos2.z then if min_pos.z > max_pos.z then
temp = pos1.z temp = min_pos.z
pos1.z = pos2.z min_pos.z = max_pos.z
pos2.z = temp max_pos.z = temp
end end
if pos1.y > pos2.y then if min_pos.y > max_pos.y then
temp = pos1.y temp = min_pos.y
pos1.y = pos2.y min_pos.y = max_pos.y
pos2.y = temp max_pos.y = temp
end end
if pos1.x > pos2.x then if min_pos.x > max_pos.x then
temp = pos1.x temp = min_pos.x
pos1.x = pos2.x min_pos.x = max_pos.x
pos2.x = temp max_pos.x = temp
end end
return pos1, pos2 return min_pos, max_pos
end end