Box creation & entry demo, quite hacky for now

This commit is contained in:
Ekdohibs 2017-01-26 18:54:21 +01:00
parent bc24c621d7
commit 1a4b209fde
4 changed files with 212 additions and 5 deletions

BIN
mods/boxes/box.box Normal file

Binary file not shown.

BIN
mods/boxes/entry.box Normal file

Binary file not shown.

BIN
mods/boxes/exit.box Normal file

Binary file not shown.

View File

@ -1,7 +1,7 @@
boxes = {} boxes = {}
local function bytes_to_string(bytes) local function bytes_to_string(bytes)
s = {} local s = {}
for i = 1, #bytes do for i = 1, #bytes do
s[i] = string.char(bytes[i]) s[i] = string.char(bytes[i])
end end
@ -9,7 +9,7 @@ local function bytes_to_string(bytes)
end end
local function string_to_bytes(str) local function string_to_bytes(str)
s = {} local s = {}
for i = 1, string.len(str) do for i = 1, string.len(str) do
s[i] = string.byte(str, i) s[i] = string.byte(str, i)
end end
@ -423,9 +423,180 @@ function boxes.vfree(minp)
update_alloc_sizes(node.parent) update_alloc_sizes(node.parent)
end end
function boxes.read_box(box_data)
local data_index = 1
local function read_u8()
local c = string.byte(box_data, data_index)
data_index = data_index + 1
return c
end
local function read_u16()
local a = read_u8()
local b = read_u8()
return 256 * a + b
end
local function read_pos()
local x = read_u16()
local y = read_u16()
local z = read_u16()
return {x = x, y = y, z = z}
end
local size = read_pos()
local entry = read_pos()
local exit = read_pos()
return {
size = size,
entry = entry,
exit = exit,
data = string.sub(box_data, data_index)
}
end
function boxes.write_box(box)
local data_index = 1
local data = {}
local function write_u8(x)
data[data_index] = x
data_index = data_index + 1
end
local function write_u16(x)
write_u8(math.floor(x / 256))
write_u8(x % 256)
end
local function write_pos(p)
write_u16(p.x)
write_u16(p.y)
write_u16(p.z)
end
write_pos(box.size)
write_pos(box.entry)
write_pos(box.exit)
return bytes_to_string(data) .. box.data
end
function vector.min(a, b)
return {
x = math.min(a.x, b.x),
y = math.min(a.y, b.y),
z = math.min(a.z, b.z),
}
end
function vector.max(a, b)
return {
x = math.max(a.x, b.x),
y = math.max(a.y, b.y),
z = math.max(a.z, b.z),
}
end
local players_in_boxes = {}
local function read_file(filename)
local file = io.open(filename, "r")
if file ~= nil then
local file_content = file:read("*all")
io.close(file)
return file_content
end
return ""
end
local function write_file(filename, data)
local file, err = io.open(filename, "w")
if file then
file:write(data)
io.close(file)
else
error(err)
end
end
local entry_lobby_data = read_file(minetest.get_modpath(minetest.get_current_modname()) .. "/entry.box")
local exit_lobby_data = read_file(minetest.get_modpath(minetest.get_current_modname()) .. "/exit.box")
local box_data = read_file(minetest.get_modpath(minetest.get_current_modname()) .. "/box.box")
local function pop_node(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local r = {pos = pos, node = node, meta = meta:to_table()}
minetest.remove_node(pos)
return r
end
local function unpop_node(data)
minetest.set_node(data.pos, data.node)
local meta = minetest.get_meta(data.pos)
meta:from_table(data.meta)
end
local function open_door(player, pos)
local nds = {
pop_node(pos),
pop_node(vector.add(pos, {x = -1, y = 0, z = 0})),
pop_node(vector.add(pos, {x = 0, y = 1, z = 0})),
pop_node(vector.add(pos, {x = -1, y = 1, z = 0})),
}
local od = players_in_boxes[player:get_player_name()].open_doors
od[#od + 1] = { minx = pos.x + 0.5, nodes = nds }
end
minetest.register_globalstep(function(dtime)
for playername, info in pairs(players_in_boxes) do
local i = 1
local player = minetest.get_player_by_name(playername)
local pos = player:get_pos()
local od = info.open_doors
local n = #od
while od[i] do
if pos.x >= od[i].minx then
for _, dt in ipairs(od[i].nodes) do
unpop_node(dt)
end
od[i] = od[n]
n = n - 1
else
i = i + 1
end
end
end
end)
function boxes.start_box(player, box_data)
local name = player:get_player_name()
assert(players_in_boxes[name] == nil)
local box = boxes.read_box(box_data)
local lobby_spawn = boxes.read_box(entry_lobby_data)
local lobby_exit = boxes.read_box(exit_lobby_data)
local lobby_spawn_offset = vector.subtract(box.entry, lobby_spawn.exit)
local lobby_exit_offset = vector.subtract(box.exit, lobby_exit.entry)
local pmin = vector.min({x = 0, y = 0, z = 0}, vector.min(lobby_spawn_offset,
lobby_exit_offset))
local box_offset = {x = -pmin.x, y = -pmin.y, z = -pmin.z}
local spawn_offset = vector.add(box_offset, lobby_spawn_offset)
local exit_offset = vector.add(box_offset, lobby_exit_offset)
local pmax = vector.max(vector.add(box_offset, box.size),
vector.max(vector.add(spawn_offset, lobby_spawn.size),
vector.add(exit_offset, lobby_exit.size)))
local request_size = math.max(pmax.x, pmax.z)
local minp = boxes.valloc(request_size)
boxes.load(vector.add(minp, box_offset), box.data)
boxes.load(vector.add(minp, spawn_offset), lobby_spawn.data)
boxes.load(vector.add(minp, exit_offset), lobby_exit.data)
player:set_pos(vector.add(minp, vector.add(spawn_offset, lobby_spawn.entry)))
players_in_boxes[name] = {
minp = minp,
open_doors = {},
}
open_door(player, vector.add(minp, vector.add(box_offset, box.entry)))
open_door(player, vector.add(minp, vector.add(box_offset, box.exit)))
end
-- test code -- test code
--[[
minetest.after(5, function() minetest.after(5, function()
--[[
local data = boxes.save({x = -1, y = -4, z = -1}, local data = boxes.save({x = -1, y = -4, z = -1},
{x = 1, y = -2, z = 1}) {x = 1, y = -2, z = 1})
print(string.len(data)) print(string.len(data))
@ -437,6 +608,42 @@ minetest.after(5, function()
print(dump(boxes_tree)) print(dump(boxes_tree))
boxes.vfree(minp) boxes.vfree(minp)
print(dump(boxes_tree)) print(dump(boxes_tree))
end)
]] ]]
--[[
local data_spawn = boxes.save({x = -35, y = -32, z = 56},
{x = -33, y = -29, z = 64})
local data_exit = boxes.save({x = -10, y = -32, z = 53},
{x = -8, y = -29, z = 61})
local sp = {
size = boxes.extent(data_spawn),
entry = {x = 0, y = 2, z = 4},
exit = {x = 3, y = 1, z = 4},
data = data_spawn,
}
local ex = {
size = boxes.extent(data_exit),
entry = {x = 0, y = 1, z = 4},
exit = {x = 3, y = 1, z = 4},
data = data_exit,
}
local data_box = boxes.save({x = -32, y = -32, z = 48},
{x = -11, y = -27, z = 69})
local bx = {
size = boxes.extent(data_box),
entry = {x = 0, y = 1, z = 10},
exit = {x = 22, y = 1, z = 10},
data = data_box,
}
local path = minetest.get_worldpath()
write_file(path .. "/entry.box", boxes.write_box(sp))
write_file(path .. "/exit.box", boxes.write_box(ex))
write_file(path .. "/box.box", boxes.write_box(bx))
]]
local player = minetest.get_player_by_name("singleplayer")
boxes.start_box(player, box_data)
end)