// Copyright Shacraft contributors. MIT OR Apache-2.0. // Generate our own tiny world metadata and validate files using public Java26.2 // APIs. Does not start a server, open sockets, or read/accept an EULA. import java.nio.file.*; import java.io.*; import java.util.*; import com.mojang.serialization.*; import net.minecraft.SharedConstants; import net.minecraft.server.Bootstrap; import net.minecraft.nbt.*; import net.minecraft.core.*; import net.minecraft.core.registries.*; import net.minecraft.data.registries.VanillaRegistries; import net.minecraft.world.level.*; import net.minecraft.world.level.block.*; import net.minecraft.world.level.chunk.*; import net.minecraft.world.level.chunk.storage.*; import net.minecraft.world.level.levelgen.*; import net.minecraft.world.level.levelgen.flat.*; import net.minecraft.world.level.levelgen.presets.*; import net.minecraft.world.level.storage.*; import net.minecraft.world.level.gamerules.*; import net.minecraft.world.level.biome.*; class compat_java { static final NbtAccounter BUDGET=NbtAccounter.create(16*1024*1024); static void generate(Path out, HolderLookup.Provider lookup) throws Exception { Files.createDirectories(out); var settings=new LevelSettings("Shacraft template",GameType.CREATIVE,LevelSettings.DifficultySettings.DEFAULT,true,WorldDataConfiguration.DEFAULT); var level=new PrimaryLevelData(settings,PrimaryLevelData.SpecialWorldProperty.FLAT,Lifecycle.stable()); level.setInitialized(true); level.setSpawn(LevelData.RespawnData.of(Level.OVERWORLD,new BlockPos(0,80,0),0,0)); var root=new CompoundTag();root.put("Data",level.createTag(null)); NbtIo.writeCompressed(root,out.resolve("level.dat")); var flat=new FlatLevelGeneratorSettings(Optional.of(HolderSet.direct()),lookup.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.PLAINS),List.of()); flat.getLayersInfo().add(new FlatLayerInfo(1,Blocks.AIR));flat.updateLayers(); var dims=lookup.lookupOrThrow(Registries.WORLD_PRESET).getOrThrow(WorldPresets.FLAT).value().createWorldDimensions().replaceOverworldGenerator(lookup,new FlatLevelSource(flat)); var worldgen=new WorldGenSettings(new WorldOptions(0,false,false),dims); var encoded=WorldGenSettings.CODEC.encodeStart(lookup.createSerializationContext(NbtOps.INSTANCE),worldgen).getOrThrow(); var data=new CompoundTag();data.put("data",encoded);NbtUtils.addCurrentDataVersion(data); Path gen=WorldGenSettings.TYPE.id().withSuffix(".dat").resolveAgainst(out.resolve("data")); Files.createDirectories(gen.getParent());NbtIo.writeCompressed(data,gen); var rules=new GameRules(level.enabledFeatures());rules.set(GameRules.SPAWN_MOBS,false,null);rules.set(GameRules.ADVANCE_TIME,false,null); LevelStorageSource.writeGameRules(level,out,rules); System.out.println("Generated metadata with public Java26.2 APIs: "+out); } static PalettedContainerFactory factory(HolderLookup.Provider lookup) { var biomeRegistry=new MappedRegistry(Registries.BIOME,Lifecycle.stable()); lookup.lookupOrThrow(Registries.BIOME).listElements().forEach(h->biomeRegistry.register(h.key(),h.value(),RegistrationInfo.BUILT_IN)); biomeRegistry.freeze(); return PalettedContainerFactory.create(new RegistryAccess.ImmutableRegistryAccess(List.of(biomeRegistry))); } static void fixture(Path out,HolderLookup.Provider lookup) throws Exception { generate(out,lookup); var factory=factory(lookup); var section=new LevelChunkSection(factory); section.setBlockState(15,15,15,Blocks.CHEST.defaultBlockState()); section.setBlockState(14,15,15,Blocks.OAK_STAIRS.defaultBlockState()); section.setBlockState(13,15,15,Blocks.STONE.defaultBlockState()); var chest=new CompoundTag();chest.putString("id","minecraft:chest");chest.putInt("x",-1);chest.putInt("y",-1);chest.putInt("z",31); var item=new CompoundTag();item.putByte("Slot",(byte)0);item.putString("id","minecraft:diamond");item.putInt("count",3); var inventory=new ListTag();inventory.add(item);chest.put("Items",inventory);chest.putLong("unknown_inventory_tag",12345678901234567L); var chunk=new SerializableChunkData(factory,new ChunkPos(-1,1),-4,0,0,net.minecraft.world.level.chunk.status.ChunkStatus.FULL, null,null,UpgradeData.EMPTY,null,Map.of(),new ChunkAccess.PackedTicks(List.of(),List.of()), new it.unimi.dsi.fastutil.shorts.ShortList[24],false, List.of(new SerializableChunkData.SectionData(-1,section,null,null)),List.of(),List.of(chest),new CompoundTag()); var tag=chunk.write();var unknown=new CompoundTag();unknown.putByte("Byte",(byte)-128);unknown.putShort("Short",(short)-32768); unknown.putLong("Long",Long.MIN_VALUE);unknown.putString("Unicode","Привет🌍\u0000");unknown.putIntArray("UUID",new int[]{1,2,3,4});tag.put("UnknownRoot",unknown); Files.createDirectories(out.resolve("region")); try(var region=new RegionFile(new RegionStorageInfo("compat-fixture",Level.OVERWORLD,"chunk"),out.resolve("region/r.-1.0.mca"),out.resolve("region"),false)) { try(var output=region.getChunkDataOutputStream(new ChunkPos(-1,1))){NbtIo.write(tag,output);} } var entity=new CompoundTag();entity.putString("id","minecraft:armor_stand");entity.putIntArray("UUID",new int[]{1,2,3,4}); var pos=new ListTag();pos.add(DoubleTag.valueOf(-0.5));pos.add(DoubleTag.valueOf(0));pos.add(DoubleTag.valueOf(31.5));entity.put("Pos",pos);entity.putBoolean("NoGravity",true); var entities=new ListTag();entities.add(entity);var root=new CompoundTag();root.putInt("DataVersion",4903);root.putIntArray("Position",new int[]{-1,1});root.put("Entities",entities); Files.createDirectories(out.resolve("entities")); try(var region=new RegionFile(new RegionStorageInfo("compat-fixture",Level.OVERWORLD,"entities"),out.resolve("entities/r.-1.0.mca"),out.resolve("entities"),false)) { try(var output=region.getChunkDataOutputStream(new ChunkPos(-1,1))){NbtIo.write(root,output);} } Files.writeString(out.resolve("custom-metadata.txt"),"own fixture; retain unknown file\n"); } static void validate(Path world,HolderLookup.Provider lookup) throws Exception { var levelRoot=NbtIo.readCompressed(world.resolve("level.dat"),NbtAccounter.create(16*1024*1024)); var level=levelRoot.getCompoundOrEmpty("Data"); if(level.getIntOr("DataVersion",-1)!=4903)throw new AssertionError("DataVersion"); var dynamic=new Dynamic<>(NbtOps.INSTANCE,level); var config=LevelStorageSource.readDataConfig(dynamic); var settings=LevelSettings.parse(dynamic,config); var parsed=PrimaryLevelData.parse(dynamic,settings,PrimaryLevelData.SpecialWorldProperty.FLAT,Lifecycle.stable()); Path gen=WorldGenSettings.TYPE.id().withSuffix(".dat").resolveAgainst(world.resolve("data")); var encoded=NbtIo.readCompressed(gen,NbtAccounter.create(16*1024*1024)).getCompoundOrEmpty("data"); var worldgen=WorldGenSettings.CODEC.parse(lookup.createSerializationContext(NbtOps.INSTANCE),encoded).getOrThrow(); if(worldgen.dimensions().dimensions().size()!=3)throw new AssertionError("dimensions"); var factory=factory(lookup);int chunks=0,sections=0,entities=0;long nonair=0; try(var files=Files.walk(world)) { for(Path path:files.filter(p->p.toString().endsWith(".mca")&&Set.of("region","entities").contains(p.getParent().getFileName().toString())&&!p.toString().contains("source-sidecar")).toList()) { boolean entityRegion=path.getParent().getFileName().toString().equals("entities"); String[] parts=path.getFileName().toString().split("\\.");int rx=Integer.parseInt(parts[1]),rz=Integer.parseInt(parts[2]); try(var region=new RegionFile(new RegionStorageInfo("compat-check",Level.OVERWORLD,"chunk"),path,path.getParent(),false)) { for(int i=0;i<1024;i++) { var pos=new ChunkPos(rx*32+i%32,rz*32+i/32); if(!region.hasChunk(pos))continue; try(var input=region.getChunkDataInputStream(pos)) { var tag=NbtIo.read(input,NbtAccounter.create(16*1024*1024)); if(entityRegion) { int[] coordinates=tag.getIntArray("Position").orElseThrow(); if(coordinates.length!=2||coordinates[0]!=pos.x()||coordinates[1]!=pos.z())throw new AssertionError("entity chunk Position"); for(var value:tag.getListOrEmpty("Entities")) { var entity=(CompoundTag)value; if(entity.getIntArray("UUID").orElseThrow().length!=4)throw new AssertionError("entity UUID"); if(entity.getListOrEmpty("Pos").size()!=3)throw new AssertionError("entity Pos"); if(!BuiltInRegistries.ENTITY_TYPE.containsKey(net.minecraft.resources.Identifier.parse(entity.getString("id").orElseThrow())))throw new AssertionError("unknown vanilla entity type"); entities++; } continue; } var chunk=SerializableChunkData.parse(LevelHeightAccessor.create(-64,384),factory,tag); if(chunk==null||!chunk.chunkPos().equals(pos))throw new AssertionError("missing/misplaced chunk "+pos); for(var section:chunk.sectionData()) { if(section.chunkSection()!=null){sections++;for(int y=0;y<16;y++)for(int z=0;z<16;z++)for(int x=0;x<16;x++)if(!section.chunkSection().getBlockState(x,y,z).isAir())nonair++;} } chunks++; } } } } } System.out.println("{\"java26_2_verified\":true,\"chunks\":"+chunks+",\"sections\":"+sections+",\"entities\":"+entities+",\"nonair_blocks\":"+nonair+",\"level_name\":\""+parsed.getLevelName()+"\",\"scope\":\"NbtIo,RegionFile,SerializableChunkData,PrimaryLevelData,WorldGenSettings codecs; no server simulation\"}"); } public static void main(String[] args) throws Exception { SharedConstants.tryDetectVersion();Bootstrap.bootStrap();var lookup=VanillaRegistries.createLookup(); if(args[0].equals("generate"))generate(Path.of(args[1]),lookup); else if(args[0].equals("fixture"))fixture(Path.of(args[1]),lookup); else validate(Path.of(args[1]),lookup); } }