minecraft-src/net/minecraft/client/renderer/block/model/BlockElement.java
2025-07-04 03:45:38 +03:00

174 lines
6.1 KiB
Java

package net.minecraft.client.renderer.block.model;
import com.google.common.collect.Maps;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import java.lang.reflect.Type;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.core.Direction;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import org.joml.Vector3fc;
@Environment(EnvType.CLIENT)
public record BlockElement(
Vector3fc from, Vector3fc to, Map<Direction, BlockElementFace> faces, @Nullable BlockElementRotation rotation, boolean shade, int lightEmission
) {
private static final boolean DEFAULT_RESCALE = false;
private static final float MIN_EXTENT = -16.0F;
private static final float MAX_EXTENT = 32.0F;
public BlockElement(Vector3fc from, Vector3fc to, Map<Direction, BlockElementFace> faces) {
this(from, to, faces, null, true, 0);
}
@Environment(EnvType.CLIENT)
protected static class Deserializer implements JsonDeserializer<BlockElement> {
private static final boolean DEFAULT_SHADE = true;
private static final int DEFAULT_LIGHT_EMISSION = 0;
public BlockElement deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
Vector3f vector3f = this.getFrom(jsonObject);
Vector3f vector3f2 = this.getTo(jsonObject);
BlockElementRotation blockElementRotation = this.getRotation(jsonObject);
Map<Direction, BlockElementFace> map = this.getFaces(context, jsonObject);
if (jsonObject.has("shade") && !GsonHelper.isBooleanValue(jsonObject, "shade")) {
throw new JsonParseException("Expected shade to be a Boolean");
} else {
boolean bl = GsonHelper.getAsBoolean(jsonObject, "shade", true);
int i = 0;
if (jsonObject.has("light_emission")) {
boolean bl2 = GsonHelper.isNumberValue(jsonObject, "light_emission");
if (bl2) {
i = GsonHelper.getAsInt(jsonObject, "light_emission");
}
if (!bl2 || i < 0 || i > 15) {
throw new JsonParseException("Expected light_emission to be an Integer between (inclusive) 0 and 15");
}
}
return new BlockElement(vector3f, vector3f2, map, blockElementRotation, bl, i);
}
}
@Nullable
private BlockElementRotation getRotation(JsonObject json) {
BlockElementRotation blockElementRotation = null;
if (json.has("rotation")) {
JsonObject jsonObject = GsonHelper.getAsJsonObject(json, "rotation");
Vector3f vector3f = this.getVector3f(jsonObject, "origin");
vector3f.mul(0.0625F);
Direction.Axis axis = this.getAxis(jsonObject);
float f = this.getAngle(jsonObject);
boolean bl = GsonHelper.getAsBoolean(jsonObject, "rescale", false);
blockElementRotation = new BlockElementRotation(vector3f, axis, f, bl);
}
return blockElementRotation;
}
private float getAngle(JsonObject json) {
float f = GsonHelper.getAsFloat(json, "angle");
if (f != 0.0F && Mth.abs(f) != 22.5F && Mth.abs(f) != 45.0F) {
throw new JsonParseException("Invalid rotation " + f + " found, only -45/-22.5/0/22.5/45 allowed");
} else {
return f;
}
}
private Direction.Axis getAxis(JsonObject json) {
String string = GsonHelper.getAsString(json, "axis");
Direction.Axis axis = Direction.Axis.byName(string.toLowerCase(Locale.ROOT));
if (axis == null) {
throw new JsonParseException("Invalid rotation axis: " + string);
} else {
return axis;
}
}
private Map<Direction, BlockElementFace> getFaces(JsonDeserializationContext context, JsonObject json) {
Map<Direction, BlockElementFace> map = this.filterNullFromFaces(context, json);
if (map.isEmpty()) {
throw new JsonParseException("Expected between 1 and 6 unique faces, got 0");
} else {
return map;
}
}
private Map<Direction, BlockElementFace> filterNullFromFaces(JsonDeserializationContext context, JsonObject json) {
Map<Direction, BlockElementFace> map = Maps.newEnumMap(Direction.class);
JsonObject jsonObject = GsonHelper.getAsJsonObject(json, "faces");
for (Entry<String, JsonElement> entry : jsonObject.entrySet()) {
Direction direction = this.getFacing((String)entry.getKey());
map.put(direction, (BlockElementFace)context.deserialize((JsonElement)entry.getValue(), BlockElementFace.class));
}
return map;
}
private Direction getFacing(String name) {
Direction direction = Direction.byName(name);
if (direction == null) {
throw new JsonParseException("Unknown facing: " + name);
} else {
return direction;
}
}
private Vector3f getTo(JsonObject json) {
Vector3f vector3f = this.getVector3f(json, "to");
if (!(vector3f.x() < -16.0F)
&& !(vector3f.y() < -16.0F)
&& !(vector3f.z() < -16.0F)
&& !(vector3f.x() > 32.0F)
&& !(vector3f.y() > 32.0F)
&& !(vector3f.z() > 32.0F)) {
return vector3f;
} else {
throw new JsonParseException("'to' specifier exceeds the allowed boundaries: " + vector3f);
}
}
private Vector3f getFrom(JsonObject json) {
Vector3f vector3f = this.getVector3f(json, "from");
if (!(vector3f.x() < -16.0F)
&& !(vector3f.y() < -16.0F)
&& !(vector3f.z() < -16.0F)
&& !(vector3f.x() > 32.0F)
&& !(vector3f.y() > 32.0F)
&& !(vector3f.z() > 32.0F)) {
return vector3f;
} else {
throw new JsonParseException("'from' specifier exceeds the allowed boundaries: " + vector3f);
}
}
private Vector3f getVector3f(JsonObject json, String memberName) {
JsonArray jsonArray = GsonHelper.getAsJsonArray(json, memberName);
if (jsonArray.size() != 3) {
throw new JsonParseException("Expected 3 " + memberName + " values, found: " + jsonArray.size());
} else {
float[] fs = new float[3];
for (int i = 0; i < fs.length; i++) {
fs[i] = GsonHelper.convertToFloat(jsonArray.get(i), memberName + "[" + i + "]");
}
return new Vector3f(fs[0], fs[1], fs[2]);
}
}
}
}