load_chunk.lua 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. local import_mod = ...
  2. local modname = minetest.get_current_modname()
  3. local MP = minetest.get_modpath(modname)
  4. local function get_chunk_name(chunk_pos)
  5. return MP .. "/map/chunk_" .. chunk_pos.x .. "_" .. chunk_pos.y .. "_" .. chunk_pos.z .. ".bin"
  6. end
  7. function import_mod.read_chunk_header(chunk_pos)
  8. local filename = get_chunk_name(chunk_pos)
  9. local file = io.open(filename, "rb")
  10. if file then
  11. local version = string.byte(file:read(1))
  12. local mapblock_count = string.byte(file:read(1))
  13. local mtime = import_mod.decode_uint32(file:read(4), 0)
  14. return version, mapblock_count, mtime
  15. end
  16. end
  17. local function read_chunkdata(chunk_pos)
  18. local filename = get_chunk_name(chunk_pos)
  19. local file = io.open(filename, "rb")
  20. if file then
  21. local version = string.byte(file:read(1))
  22. local mapblock_count = string.byte(file:read(1))
  23. local mtime = import_mod.decode_uint32(file:read(4), 0)
  24. local data = file:read("*all")
  25. return version, mapblock_count, mtime, minetest.decompress(data, "deflate"), #data
  26. end
  27. end
  28. -- local vars for faster access
  29. local insert, byte, decode_uint16 = table.insert, string.byte, import_mod.decode_uint16
  30. function import_mod.load_chunk(chunk_pos, manifest)
  31. local version, mapblock_count, _, chunk_data = read_chunkdata(chunk_pos)
  32. if not chunk_data then
  33. -- write current os.time to modstorage
  34. import_mod.storage:set_int(minetest.pos_to_string(chunk_pos), os.time())
  35. return
  36. end
  37. if version ~= manifest.version then
  38. error("couldn't load chunk " .. minetest.pos_to_string(chunk_pos) ..
  39. " serialization-version: " .. version)
  40. end
  41. local manifest_offset = 1 + (4096 * 4 * mapblock_count)
  42. local chunk_manifest = minetest.parse_json(string.sub(chunk_data, manifest_offset))
  43. for mbi=1, mapblock_count do
  44. local mapblock_manifest = chunk_manifest.mapblocks[mbi]
  45. local mapblock = {
  46. node_ids = {},
  47. param1 = {},
  48. param2 = {},
  49. metadata = mapblock_manifest.metadata
  50. }
  51. for i=1,4096 do
  52. local node_id = decode_uint16(chunk_data, ((mbi-1) * 4096 * 2) + (i * 2) - 2)
  53. local param1 = byte(chunk_data, (4096 * 2 * mapblock_count) + ((mbi-1) * 4096) + i)
  54. local param2 = byte(chunk_data, (4096 * 3 * mapblock_count) + ((mbi-1) * 4096) + i)
  55. insert(mapblock.node_ids, node_id)
  56. insert(mapblock.param1, param1)
  57. insert(mapblock.param2, param2)
  58. end
  59. import_mod.localize_nodeids(manifest.node_mapping, mapblock.node_ids)
  60. import_mod.deserialize(mapblock, mapblock_manifest.pos)
  61. end
  62. if chunk_manifest.mtime then
  63. -- write emerge chunk mtime to modstorage
  64. import_mod.storage:set_int(minetest.pos_to_string(chunk_pos), chunk_manifest.mtime)
  65. end
  66. end