add modgen

This commit is contained in:
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
}

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

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