Complete local voxel MVP with server, client, MCP, packages and world interchange
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user