diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index ad40f4c6..b6315127 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -153,8 +153,122 @@ function mcl_maps.load_map(id) return texture end +local function encode_item_meta(input) + return minetest.encode_base64( + minetest.compress( + input, + "deflate", + 9 + ) + ) +end + +local function decode_item_meta(input) + return minetest.decompress( + minetest.decode_base64(input), + "deflate", + 9 + ) +end + +result_original = "foo\0\01\02\x03\n\rbar" +result_roundtrip = decode_item_meta( + encode_item_meta(result_original) +) +assert( + result_original == result_roundtrip, + "mcl_maps: mismatch between encode_item_meta() and decode_item_meta()" +) + function mcl_maps.load_map_item(itemstack) - return mcl_maps.load_map(itemstack:get_meta():get_string("mcl_maps:id")) + local meta = itemstack:get_meta() + local map_id = meta:get_string("mcl_maps:id") + + if "" == map_id or creating_maps[map_id] then + -- wait for map content to be created + return + end + + if loaded_maps[map_id] then + -- texture has already been sent + return mcl_maps.load_map(map_id) + end + + local texture_file_name = "mcl_maps_map_texture_" .. map_id .. ".tga" + local texture_file_path = map_textures_path .. texture_file_name + + -- does the texture file exist? + local texture_file_handle_read = io.open( + texture_file_path, + "rb" + ) + local texture_file_exists = true + local texture_data_from_file + if nil == texture_file_handle_read then + texture_file_exists = false + else + texture_data_from_file = texture_file_handle_read:read("*a") + texture_file_handle_read:close() + end + + -- does the texture item meta exist? + local tga_deflate_base64 = meta:get_string("mcl_maps:tga_deflate_base64") + local texture_item_meta_exists = true + if "" == tga_deflate_base64 then + texture_item_meta_exists = false + end + + if texture_file_exists and nil ~= texture_data_from_file then + if texture_item_meta_exists then + -- sanity check: do we have the same textures? + -- if server-side texture has changed, take it + if decode_item_meta(tga_deflate_base64) ~= texture_data_from_file then + minetest.log( + "action", + "mcl_maps: update item meta from file content for map " .. map_id + ) + meta:set_string( + "mcl_maps:tga_deflate_base64", + encode_item_meta(texture_data_from_file) + ) + end + else + -- probably an older map from mcl2 or mcl5, so + -- we now write the file contents to item meta + minetest.log( + "action", + "mcl_maps: create item meta from file content for map " .. map_id + ) + meta:set_string( + "mcl_maps:tga_deflate_base64", + encode_item_meta(texture_data_from_file) + ) + end + else + -- no texture file → could be a world download + -- so we look for missing texture in item meta + -- and write that to the map texture file here + if texture_item_meta_exists then + minetest.log( + "action", + "mcl_maps: create file content from item meta for map " .. map_id + ) + assert( + minetest.safe_file_write( + texture_file_path, + decode_item_meta(tga_deflate_base64) + ) + ) + else + minetest.log( + "error", + "no data for map " .. map_id + ) + return + end + end + + return mcl_maps.load_map(map_id) end local function fill_map(itemstack, placer, pointed_thing)