// Copyright Shacraft contributors. MIT OR Apache-2.0. // Public API calls only: extract factual registries and collision measurements. // Run by catalog_generate.py; never starts a server or accepts an EULA. import java.nio.file.*; import java.util.*; import com.google.gson.*; import net.minecraft.SharedConstants; import net.minecraft.server.Bootstrap; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.DefaultAttributes; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; class catalog_extract { static JsonArray boxes(VoxelShape shape) { var result = new JsonArray(); for (var b : shape.toAabbs()) { var box = new JsonArray(); for (double x : new double[]{b.minX,b.minY,b.minZ,b.maxX,b.maxY,b.maxZ}) box.add(x); result.add(box); } return result; } static class SampleWorld implements BlockGetter { final BlockState center, other; SampleWorld(BlockState center, BlockState other) { this.center=center; this.other=other; } public BlockEntity getBlockEntity(BlockPos pos) { return null; } public BlockState getBlockState(BlockPos pos) { return pos.equals(BlockPos.ZERO)?center:other; } public FluidState getFluidState(BlockPos pos) { return getBlockState(pos).getFluidState(); } public int getHeight() { return 384; } public int getMinY() { return -64; } } public static void main(String[] args) throws Exception { SharedConstants.tryDetectVersion(); Bootstrap.bootStrap(); var root = new JsonObject(); var states = new JsonObject(); var entities = new JsonObject(); var air = Block.stateById(0); var stone = BuiltInRegistries.BLOCK.getValue(net.minecraft.resources.Identifier.parse("minecraft:stone")).defaultBlockState(); int errors=0, contextual=0; for (var block : BuiltInRegistries.BLOCK) for (var state : block.getStateDefinition().getPossibleStates()) { var out = new JsonObject(); var world = new SampleWorld(state,air); try { var shape = boxes(state.getCollisionShape(world,BlockPos.ZERO,CollisionContext.empty())); out.add("collision",shape); boolean context = !shape.equals(boxes(state.getCollisionShape(new SampleWorld(state,stone),BlockPos.ZERO,CollisionContext.empty()))) || !shape.equals(boxes(state.getCollisionShape(world,BlockPos.ZERO,CollisionContext.positionContext(10)))) || !shape.equals(boxes(state.getCollisionShape(world,BlockPos.ZERO,CollisionContext.positionContext(-10)))); out.addProperty("sample_context_dependent",context); if(context)contextual++; out.addProperty("air",state.isAir()); out.addProperty("light",state.getLightEmission()); out.addProperty("hardness",state.getDestroySpeed(world,BlockPos.ZERO)); } catch (Throwable e) { out.addProperty("error",e.toString()); errors++; } states.add(Integer.toString(Block.getId(state)),out); } for(var entity : BuiltInRegistries.ENTITY_TYPE) { var out = new JsonObject(); out.addProperty("width",entity.getWidth()); out.addProperty("height",entity.getHeight()); out.addProperty("eye_height",entity.getDimensions().eyeHeight()); out.addProperty("fixed_dimensions",entity.getDimensions().fixed()); out.addProperty("category",entity.getCategory().getName()); out.addProperty("summonable",entity.canSummon()); out.addProperty("serializable",entity.canSerialize()); out.addProperty("fire_immune",entity.fireImmune()); out.addProperty("tracking_range",entity.clientTrackingRange()); out.addProperty("update_interval",entity.updateInterval()); out.addProperty("peaceful_allowed",entity.isAllowedInPeaceful()); var attrs = new JsonObject(); if(DefaultAttributes.hasSupplier(entity)) { var supplier = DefaultAttributes.getSupplier((EntityType)entity); for(var holder : BuiltInRegistries.ATTRIBUTE.listElements().toList()) if(supplier.hasAttribute(holder)) attrs.addProperty(holder.unwrapKey().get().identifier().toString(),supplier.getBaseValue(holder)); } out.add("attributes",attrs); entities.add(EntityType.getKey(entity).toString(),out); } root.add("states",states); root.add("entities",entities); root.addProperty("errors",errors); root.addProperty("context_dependent_samples",contextual); Files.writeString(Path.of(args[0]),new GsonBuilder().create().toJson(root)); System.out.println("Extracted "+states.size()+" states, "+entities.size()+" entities, "+errors+" errors, "+contextual+" contextual sample differences"); if(errors!=0)System.exit(2); } }