diff --git a/src/Formats.c b/src/Formats.c index b9275383c..d4ccd2e2f 100644 --- a/src/Formats.c +++ b/src/Formats.c @@ -421,6 +421,18 @@ static ReturnCode Nbt_ReadTag(uint8_t typeId, bool readTagName, struct Stream* s /*########################################################################################################################* *--------------------------------------------------ClassicWorld format----------------------------------------------------* *#########################################################################################################################*/ +static void* Cw_GetBlocks(struct NbtTag* tag) { + void* ptr; + if (NbtTag_IsSmall(tag)) { + ptr = Mem_Alloc(tag->DataSize, 1, ".cw map blocks"); + Mem_Copy(ptr, tag->Value.Small, tag->DataSize); + } else { + ptr = tag->Value.Big; + tag->Value.Big = NULL; /* So Nbt_ReadTag doesn't call Mem_Free on World.Blocks */ + } + return ptr; +} + static void Cw_Callback_1(struct NbtTag* tag) { if (IsTag(tag, "X")) { World.Width = NbtTag_U16(tag); return; } if (IsTag(tag, "Y")) { World.Height = NbtTag_U16(tag); return; } @@ -434,17 +446,14 @@ static void Cw_Callback_1(struct NbtTag* tag) { if (IsTag(tag, "BlockArray")) { World.Volume = tag->DataSize; - if (NbtTag_IsSmall(tag)) { - World.Blocks = Mem_Alloc(World.Volume, 1, ".cw map blocks"); - Mem_Copy(World.Blocks, tag->Value.Small, tag->DataSize); - } else { - World.Blocks = tag->Value.Big; - tag->Value.Big = NULL; /* So Nbt_ReadTag doesn't call Mem_Free on World.Blocks */ - } + World.Blocks = Cw_GetBlocks(tag); #ifdef EXTENDED_BLOCKS World.Blocks2 = World.Blocks; #endif } +#ifdef EXTENDED_BLOCKS + if (IsTag(tag, "BlockArray2")) World_SetMapUpper(Cw_GetBlocks(tag)); +#endif } static void Cw_Callback_2(struct NbtTag* tag) { @@ -892,6 +901,9 @@ NBT_DICT, 0,12, 'C','l','a','s','s','i','c','W','o','r','l','d', NBT_END, NBT_I8S, 0,10, 'B','l','o','c','k','A','r','r','a','y', 0,0,0,0, }; +static uint8_t cw_map2[18] = { + NBT_I8S, 0,11, 'B','l','o','c','k','A','r','r','a','y','2', 0,0,0,0, +}; static uint8_t cw_meta_cpe[303] = { NBT_DICT, 0,8, 'M','e','t','a','d','a','t','a', NBT_DICT, 0,3, 'C','P','E', @@ -1016,9 +1028,17 @@ ReturnCode Cw_Save(struct Stream* stream) { tmp[107] = Math_Deg2Packed(p->SpawnRotY); tmp[112] = Math_Deg2Packed(p->SpawnHeadX); } - if ((res = Stream_Write(stream, tmp, sizeof(cw_begin)))) return res; + if ((res = Stream_Write(stream, tmp, sizeof(cw_begin)))) return res; if ((res = Stream_Write(stream, World.Blocks, World.Volume))) return res; + if (World.Blocks != World.Blocks2) { + Mem_Copy(tmp, cw_map2, sizeof(cw_map2)); + Stream_SetU32_BE(&tmp[14], World.Volume); + + if ((res = Stream_Write(stream, tmp, sizeof(cw_map2)))) return res; + if ((res = Stream_Write(stream, World.Blocks2, World.Volume))) return res; + } + Mem_Copy(tmp, cw_meta_cpe, sizeof(cw_meta_cpe)); { Stream_SetU16_BE(&tmp[44], (uint16_t)(LocalPlayer_Instance.ReachDistance * 32)); diff --git a/src/PacketHandlers.c b/src/PacketHandlers.c index e07332aa7..6bae704b6 100644 --- a/src/PacketHandlers.c +++ b/src/PacketHandlers.c @@ -510,10 +510,9 @@ static void Classic_LevelFinalise(uint8_t* data) { World_SetNewMap(map_blocks, width, height, length); #ifdef EXTENDED_BLOCKS - if (cpe_extBlocks) { - /* defer allocation of scond map array if possible */ - World.Blocks2 = map2_blocks ? map2_blocks : map_blocks; - Block_SetUsedCount(map2_blocks ? 768 : 256); + /* defer allocation of second map array if possible */ + if (cpe_extBlocks && map2_blocks) { + World_SetMapUpper(map2_blocks); } #endif diff --git a/src/Program.c b/src/Program.c index f4e4bc8fb..fe49e758f 100644 --- a/src/Program.c +++ b/src/Program.c @@ -105,8 +105,8 @@ int main(int argc, char** argv) { argsCount = Platform_GetCommandLineArgs(argc, argv, args); /* NOTE: Make sure to comment this out before pushing a commit */ /* String rawArgs = String_FromConst("UnknownShadow200 fffff 127.0.0.1 25565"); */ - /* String rawArgs = String_FromConst("UnknownShadow200"); */ - /* argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4); */ + String rawArgs = String_FromConst("UnknownShadow200"); + argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4); if (argsCount == 0) { Launcher_Run(); diff --git a/src/World.c b/src/World.c index 8b8639f19..2e8ee8bb2 100644 --- a/src/World.c +++ b/src/World.c @@ -53,7 +53,11 @@ void World_SetNewMap(BlockRaw* blocks, int width, int height, int length) { if (!World.Volume) World.Blocks = NULL; #ifdef EXTENDED_BLOCKS - World.Blocks2 = World.Blocks; + /* .cw maps may have set this to a non-NULL when importing */ + if (!World.Blocks2) { + World.Blocks2 = World.Blocks; + Block_SetUsedCount(256); + } #endif if (Env_EdgeHeight == -1) { @@ -74,6 +78,13 @@ CC_NOINLINE void World_SetDimensions(int width, int height, int length) { World.MaxZ = length - 1; } +#ifdef EXTENDED_BLOCKS +void World_SetMapUpper(BlockRaw* blocks) { + World.Blocks2 = blocks; + Block_SetUsedCount(768); +} +#endif + #ifdef EXTENDED_BLOCKS void World_SetBlock(int x, int y, int z, BlockID block) { diff --git a/src/World.h b/src/World.h index 0d0fb8c53..8777f71f2 100644 --- a/src/World.h +++ b/src/World.h @@ -47,6 +47,8 @@ CC_NOINLINE void World_SetDimensions(int width, int height, int length); #ifdef EXTENDED_BLOCKS extern int Block_IDMask; +/* Sets World.Blocks2 and updates internal state for more than 256 blocks. */ +void World_SetMapUpper(BlockRaw* blocks); /* Gets the block at the given coordinates. */ /* NOTE: Does NOT check that the coordinates are inside the map. */