add modgen

This commit is contained in:
Bruno Rybársky 2022-08-15 08:18:56 +02:00
parent 55c97761ca
commit af2207ea40
20 changed files with 499 additions and 0 deletions

View File

@ -0,0 +1,58 @@
local import_mod = ...
local function get_mod_chunk_mtime(chunk_pos)
local _,_,mtime = import_mod.read_chunk_header(chunk_pos)
return mtime
end
local function get_world_chunk_mtime(chunk_pos)
local mtime = import_mod.storage:get_int(minetest.pos_to_string(chunk_pos))
if mtime == 0 then
return nil
else
return mtime
end
end
local cache = {}
local function check_player_pos(player)
local ppos = player:get_pos()
local chunk_pos = import_mod.get_chunkpos(ppos)
-- cache access
local cache_key = minetest.pos_to_string(chunk_pos)
if cache[cache_key] then
return
end
cache[cache_key] = true
-- retrieve timestamps
local mod_mtime = get_mod_chunk_mtime(chunk_pos)
local world_mtime = get_world_chunk_mtime(chunk_pos)
if not mod_mtime then
-- the chunk isn't available in the mod
return
end
if world_mtime and world_mtime >= mod_mtime then
-- world chunk is same or newer (?) than the one in the mod
return
end
local mapblock_min, mapblock_max = import_mod.get_mapblock_bounds_from_chunk(chunk_pos)
local min = import_mod.get_mapblock_bounds_from_mapblock(mapblock_min)
local _, max = import_mod.get_mapblock_bounds_from_mapblock(mapblock_max)
minetest.delete_area(min, max)
end
local function check_players()
for _, player in ipairs(minetest.get_connected_players()) do
check_player_pos(player)
end
minetest.after(1, check_players)
end
print("[modgen] map auto-update enabled")
minetest.after(1, check_players)

View File

@ -0,0 +1,20 @@
local import_mod = ...
function import_mod.decode_uint16(str, ofs)
ofs = ofs or 0
local a, b = string.byte(str, ofs + 1, ofs + 2)
return a + b * 0x100
end
local function lshift(x, by)
return x * 2 ^ by
end
function import_mod.decode_uint32(data, offset)
return (
string.byte(data,1+offset) +
lshift(string.byte(data,2+offset), 8) +
lshift(string.byte(data,3+offset), 16) +
lshift(string.byte(data,4+offset), 24)
)
end

View File

@ -0,0 +1,52 @@
local import_mod = ...
function import_mod.deserialize(data, mapblock_pos)
local pos1 = vector.multiply(mapblock_pos, 16)
local pos2 = vector.add(pos1, 15) -- inclusive
local manip = minetest.get_voxel_manip()
local e1, e2 = manip:read_from_map(pos1, pos2)
local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
local node_data = manip:get_data()
local param1 = manip:get_light_data()
local param2 = manip:get_param2_data()
local j = 1
for z=pos1.z,pos2.z do
for x=pos1.x,pos2.x do
for y=pos1.y,pos2.y do
local i = area:index(x,y,z)
node_data[i] = data.node_ids[j]
param1[i] = data.param1[j]
param2[i] = data.param2[j]
j = j + 1
end
end
end
manip:set_data(node_data)
manip:set_light_data(param1)
manip:set_param2_data(param2)
manip:write_to_map(false)
-- deserialize metadata
if data.metadata and data.metadata.meta then
for pos_str, md in pairs(data.metadata.meta) do
local relative_pos = minetest.string_to_pos(pos_str)
local absolute_pos = vector.add(pos1, relative_pos)
minetest.get_meta(absolute_pos):from_table(md)
end
end
-- deserialize node timers
if data.metadata and data.metadata.timers then
for pos_str, timer_data in pairs(data.metadata.timers) do
local relative_pos = minetest.string_to_pos(pos_str)
local absolute_pos = vector.add(pos1, relative_pos)
minetest.get_node_timer(absolute_pos):set(timer_data.timeout, timer_data.elapsed)
end
end
end

View File

@ -0,0 +1,46 @@
--- Modgen import mod
-- writes the mapblocks back to the world
-- hard-dependency- and global-free
-- mod name and path
local modname = minetest.get_current_modname()
local MP = minetest.get_modpath(modname)
local import_mod = {
-- storage
storage = minetest.get_mod_storage()
}
-- local functions/helpers
loadfile(MP .. "/decode.lua")(import_mod)
loadfile(MP .. "/util.lua")(import_mod)
loadfile(MP .. "/load_chunk.lua")(import_mod)
loadfile(MP .. "/register_mapgen.lua")(import_mod)
loadfile(MP .. "/read_manifest.lua")(import_mod)
loadfile(MP .. "/nodename_check.lua")(import_mod)
loadfile(MP .. "/uid_check.lua")(import_mod)
loadfile(MP .. "/localize_nodeids.lua")(import_mod)
loadfile(MP .. "/deserialize.lua")(import_mod)
local manifest = import_mod.read_manifest()
-- check world uid
import_mod.uid_check(manifest)
-- check if the nodes are available in the current world
minetest.register_on_mods_loaded(function()
import_mod.nodename_check(manifest)
end)
-- initialize mapgen
import_mod.register_mapgen(manifest)
if minetest.get_modpath("modgen") then
-- modgen available, make it aware of the loaded import_mod
modgen.register_import_mod(manifest, MP)
end
-- check if the auto-update feature is enabled
if minetest.settings:get_bool("import_mod.auto_update.enabled") then
loadfile(MP .. "/auto_update.lua")(import_mod)
end

View File

@ -0,0 +1,78 @@
local import_mod = ...
local modname = minetest.get_current_modname()
local MP = minetest.get_modpath(modname)
local function get_chunk_name(chunk_pos)
return MP .. "/map/chunk_" .. chunk_pos.x .. "_" .. chunk_pos.y .. "_" .. chunk_pos.z .. ".bin"
end
function import_mod.read_chunk_header(chunk_pos)
local filename = get_chunk_name(chunk_pos)
local file = io.open(filename, "rb")
if file then
local version = string.byte(file:read(1))
local mapblock_count = string.byte(file:read(1))
local mtime = import_mod.decode_uint32(file:read(4), 0)
return version, mapblock_count, mtime
end
end
local function read_chunkdata(chunk_pos)
local filename = get_chunk_name(chunk_pos)
local file = io.open(filename, "rb")
if file then
local version = string.byte(file:read(1))
local mapblock_count = string.byte(file:read(1))
local mtime = import_mod.decode_uint32(file:read(4), 0)
local data = file:read("*all")
return version, mapblock_count, mtime, minetest.decompress(data, "deflate"), #data
end
end
-- local vars for faster access
local insert, byte, decode_uint16 = table.insert, string.byte, import_mod.decode_uint16
function import_mod.load_chunk(chunk_pos, manifest)
local version, mapblock_count, _, chunk_data = read_chunkdata(chunk_pos)
if not chunk_data then
-- write current os.time to modstorage
import_mod.storage:set_int(minetest.pos_to_string(chunk_pos), os.time())
return
end
if version ~= manifest.version then
error("couldn't load chunk " .. minetest.pos_to_string(chunk_pos) ..
" serialization-version: " .. version)
end
local manifest_offset = 1 + (4096 * 4 * mapblock_count)
local chunk_manifest = minetest.parse_json(string.sub(chunk_data, manifest_offset))
for mbi=1, mapblock_count do
local mapblock_manifest = chunk_manifest.mapblocks[mbi]
local mapblock = {
node_ids = {},
param1 = {},
param2 = {},
metadata = mapblock_manifest.metadata
}
for i=1,4096 do
local node_id = decode_uint16(chunk_data, ((mbi-1) * 4096 * 2) + (i * 2) - 2)
local param1 = byte(chunk_data, (4096 * 2 * mapblock_count) + ((mbi-1) * 4096) + i)
local param2 = byte(chunk_data, (4096 * 3 * mapblock_count) + ((mbi-1) * 4096) + i)
insert(mapblock.node_ids, node_id)
insert(mapblock.param1, param1)
insert(mapblock.param2, param2)
end
import_mod.localize_nodeids(manifest.node_mapping, mapblock.node_ids)
import_mod.deserialize(mapblock, mapblock_manifest.pos)
end
if chunk_manifest.mtime then
-- write emerge chunk mtime to modstorage
import_mod.storage:set_int(minetest.pos_to_string(chunk_pos), chunk_manifest.mtime)
end
end

View File

@ -0,0 +1,32 @@
local import_mod = ...
local air_content_id = minetest.get_content_id("air")
-- local nodename->id cache
local local_nodename_to_id_mapping = {} -- name -> id
function import_mod.localize_nodeids(node_mapping, node_ids)
local foreign_nodeid_to_name_mapping = {} -- id -> name
for k, v in pairs(node_mapping) do
foreign_nodeid_to_name_mapping[v] = k
end
for i, node_id in ipairs(node_ids) do
local node_name = foreign_nodeid_to_name_mapping[node_id]
local local_node_id = local_nodename_to_id_mapping[node_name]
if not local_node_id then
if minetest.registered_nodes[node_name] then
-- node is locally available
local_node_id = minetest.get_content_id(node_name)
else
-- node is not available here
-- TODO: make replacements configurable
local_node_id = air_content_id
end
local_nodename_to_id_mapping[node_name] = local_node_id
end
node_ids[i] = local_node_id
end
end

View File

@ -0,0 +1,110 @@
{
"bounds" :
{
"max" :
{
"x" : -1.0,
"y" : 1.0,
"z" : 0.0
},
"min" :
{
"x" : -1.0,
"y" : 1.0,
"z" : 0.0
}
},
"chunks" : 6.0,
"mtime" : 1660543987.0,
"next_id" : 84.0,
"node_mapping" :
{
"air" : 0.0,
"an_televator:televator" : 24.0,
"mesecons:wire_00000000_off" : 58.0,
"mesecons:wire_00010000_off" : 51.0,
"mesecons:wire_00010000_on" : 37.0,
"mesecons:wire_00010001_on" : 41.0,
"mesecons:wire_00100000_off" : 56.0,
"mesecons:wire_00100010_off" : 9.0,
"mesecons:wire_00100010_on" : 71.0,
"mesecons:wire_00110000_off" : 19.0,
"mesecons:wire_00110001_off" : 29.0,
"mesecons:wire_00110010_on" : 44.0,
"mesecons:wire_01000000_off" : 11.0,
"mesecons:wire_01000000_on" : 35.0,
"mesecons:wire_01000100_off" : 59.0,
"mesecons:wire_01000100_on" : 62.0,
"mesecons:wire_01010000_off" : 17.0,
"mesecons:wire_01010000_on" : 40.0,
"mesecons:wire_01010001_off" : 82.0,
"mesecons:wire_01010001_on" : 36.0,
"mesecons:wire_01010101_on" : 39.0,
"mesecons:wire_01100000_off" : 27.0,
"mesecons:wire_01100000_on" : 34.0,
"mesecons:wire_01100010_off" : 81.0,
"mesecons:wire_01100100_off" : 10.0,
"mesecons:wire_01110000_off" : 16.0,
"mesecons:wire_01110000_on" : 70.0,
"mesecons:wire_01110011_off" : 80.0,
"mesecons:wire_01110100_on" : 77.0,
"mesecons:wire_01110111_on" : 76.0,
"mesecons:wire_10000000_off" : 49.0,
"mesecons:wire_10001000_off" : 21.0,
"mesecons:wire_10010000_off" : 47.0,
"mesecons:wire_10010000_on" : 42.0,
"mesecons:wire_10010001_off" : 50.0,
"mesecons:wire_10011000_off" : 48.0,
"mesecons:wire_10011000_on" : 72.0,
"mesecons:wire_10100000_off" : 13.0,
"mesecons:wire_10100000_on" : 33.0,
"mesecons:wire_10100010_off" : 23.0,
"mesecons:wire_10100010_on" : 75.0,
"mesecons:wire_10101000_off" : 7.0,
"mesecons:wire_10101000_on" : 73.0,
"mesecons:wire_10101010_off" : 6.0,
"mesecons:wire_10110000_off" : 67.0,
"mesecons:wire_10110000_on" : 74.0,
"mesecons:wire_10110001_off" : 28.0,
"mesecons:wire_11000000_off" : 46.0,
"mesecons:wire_11000000_on" : 68.0,
"mesecons:wire_11000100_off" : 22.0,
"mesecons:wire_11001000_on" : 31.0,
"mesecons:wire_11010000_off" : 15.0,
"mesecons:wire_11010000_on" : 38.0,
"mesecons:wire_11100000_off" : 66.0,
"mesecons:wire_11100100_off" : 8.0,
"mesecons:wire_11101010_off" : 79.0,
"mesecons:wire_11110000_off" : 55.0,
"mesecons:wire_11110000_on" : 43.0,
"mesecons:wire_11111110_off" : 63.0,
"mesecons:wire_11111111_off" : 65.0,
"mesecons_commandblock:commandblock_off" : 4.0,
"mesecons_detector:object_detector_off" : 25.0,
"mesecons_extrawires:vertical_bottom_off" : 52.0,
"mesecons_extrawires:vertical_off" : 53.0,
"mesecons_extrawires:vertical_top_off" : 57.0,
"mesecons_gates:not_on" : 45.0,
"mesecons_gates:or_off" : 78.0,
"mesecons_gates:or_on" : 69.0,
"mesecons_lightstone:lightstone_white_off" : 61.0,
"mesecons_lightstone:lightstone_white_on" : 64.0,
"mesecons_pistons:piston_pusher_sticky" : 32.0,
"mesecons_pistons:piston_sticky_off" : 5.0,
"mesecons_pistons:piston_sticky_on" : 30.0,
"mesecons_powerplant:power_plant" : 12.0,
"mesecons_torch:mesecon_torch_on" : 83.0,
"portalgun:autocheckpoint" : 18.0,
"portalgun:cplps3" : 20.0,
"portalgun:plantform_nu1" : 14.0,
"portalgun:testblock" : 1.0,
"portalgun:testblocks" : 60.0,
"portalgun:toxwater_1" : 3.0,
"portalgun:toxwater_2" : 2.0,
"portalgun:turretgun_spawner" : 54.0,
"portalgun:wscspawner5" : 26.0
},
"size" : 48642.0,
"uid" : "278350",
"version" : 4.0
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
optional_depends = modgen, technic_worldgen

View File

@ -0,0 +1,25 @@
local import_mod = ...
function import_mod.nodename_check(manifest)
-- assemble node-list from registered lbm's
local lbm_nodes = {}
for _, lbm in ipairs(minetest.registered_lbms) do
if type(lbm.nodenames) == "string" then
-- duh, list as string
lbm_nodes[lbm.nodenames] = true
else
-- proper list, add all regardless if they are a "group:*"
for _, nodename in ipairs(lbm.nodenames) do
lbm_nodes[nodename] = true
end
end
end
for nodename in pairs(manifest.node_mapping) do
if not minetest.registered_nodes[nodename]
and not minetest.registered_aliases[nodename]
and not lbm_nodes[nodename] then
error("node not found and not aliased: " .. nodename)
end
end
end

View File

@ -0,0 +1,12 @@
local import_mod = ...
local modname = minetest.get_current_modname()
local MP = minetest.get_modpath(modname)
function import_mod.read_manifest()
local infile = io.open(MP .. "/manifest.json", "r")
local instr = infile:read("*a")
infile:close()
return minetest.parse_json(instr or "{}")
end

View File

@ -0,0 +1,6 @@
## Modgen import mod
**This folder and its contents are autogenerated, do not edit directly**
For more infos, see: https://github.com/Buckaroobanzay/modgen

View File

@ -0,0 +1,7 @@
local import_mod = ...
function import_mod.register_mapgen(manifest)
minetest.register_on_generated(function(minp)
import_mod.load_chunk(import_mod.get_chunkpos(minp), manifest)
end)
end

View File

@ -0,0 +1,12 @@
local import_mod = ...
function import_mod.uid_check(manifest)
local world_uid = import_mod.storage:get_string("uid")
if world_uid ~= "" and world_uid ~= manifest.uid then
-- abort if the uids don't match, something fishy might be going on
error("modgen uids don't match, aborting for your safety!")
end
-- write modgen uid to world-storage
import_mod.storage:set_string("uid", manifest.uid)
end

View File

@ -0,0 +1,40 @@
local import_mod = ...
function import_mod.get_mapblock_pos(pos)
return vector.floor( vector.divide(pos, 16))
end
function import_mod.get_mapblock(pos)
return vector.floor( vector.divide(pos, 16))
end
function import_mod.get_chunkpos(pos)
local mapblock_pos = import_mod.get_mapblock_pos(pos)
local aligned_mapblock_pos = vector.add(mapblock_pos, 2)
return vector.floor( vector.divide(aligned_mapblock_pos, 5) )
end
function import_mod.get_mapblock_bounds_from_chunk(chunk_pos)
local min = vector.subtract( vector.multiply(chunk_pos, 5), 2)
local max = vector.add(min, 4)
return min, max
end
function import_mod.get_chunk_bounds(pos)
local chunk_pos = import_mod.get_chunkpos(pos)
local mapblock_min, mapblock_max = import_mod.get_mapblock_bounds_from_chunk(chunk_pos)
local min = import_mod.get_mapblock_bounds(mapblock_min)
local _, max = import_mod.get_mapblock_bounds(mapblock_max)
return min, max
end
function import_mod.get_mapblock_bounds_from_mapblock(mapblock)
local min = vector.multiply(mapblock, 16)
local max = vector.add(min, 15)
return min, max
end
function import_mod.get_mapblock_bounds(pos)
local mapblock = import_mod.get_mapblock(pos)
return import_mod.get_mapblock_bounds_from_mapblock(mapblock)
end