minecraft-src/net/minecraft/client/renderer/block/model/BlockModelDefinition.java
2025-07-04 01:41:11 +03:00

176 lines
5.9 KiB
Java

package net.minecraft.client.renderer.block.model;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
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.io.Reader;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.block.model.multipart.MultiPart;
import net.minecraft.client.renderer.block.model.multipart.Selector;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class BlockModelDefinition {
private final Map<String, MultiVariant> variants = Maps.<String, MultiVariant>newLinkedHashMap();
private MultiPart multiPart;
public static BlockModelDefinition fromStream(BlockModelDefinition.Context context, Reader reader) {
return GsonHelper.fromJson(context.gson, reader, BlockModelDefinition.class);
}
public static BlockModelDefinition fromJsonElement(BlockModelDefinition.Context context, JsonElement json) {
return context.gson.fromJson(json, BlockModelDefinition.class);
}
public BlockModelDefinition(Map<String, MultiVariant> variants, MultiPart multiPart) {
this.multiPart = multiPart;
this.variants.putAll(variants);
}
public BlockModelDefinition(List<BlockModelDefinition> modelDefinitions) {
BlockModelDefinition blockModelDefinition = null;
for (BlockModelDefinition blockModelDefinition2 : modelDefinitions) {
if (blockModelDefinition2.isMultiPart()) {
this.variants.clear();
blockModelDefinition = blockModelDefinition2;
}
this.variants.putAll(blockModelDefinition2.variants);
}
if (blockModelDefinition != null) {
this.multiPart = blockModelDefinition.multiPart;
}
}
@VisibleForTesting
public boolean hasVariant(String key) {
return this.variants.get(key) != null;
}
@VisibleForTesting
public MultiVariant getVariant(String key) {
MultiVariant multiVariant = (MultiVariant)this.variants.get(key);
if (multiVariant == null) {
throw new BlockModelDefinition.MissingVariantException();
} else {
return multiVariant;
}
}
public boolean equals(Object object) {
if (this == object) {
return true;
} else if (object instanceof BlockModelDefinition blockModelDefinition && this.variants.equals(blockModelDefinition.variants)) {
return this.isMultiPart() ? this.multiPart.equals(blockModelDefinition.multiPart) : !blockModelDefinition.isMultiPart();
} else {
return false;
}
}
public int hashCode() {
return 31 * this.variants.hashCode() + (this.isMultiPart() ? this.multiPart.hashCode() : 0);
}
public Map<String, MultiVariant> getVariants() {
return this.variants;
}
@VisibleForTesting
public Set<MultiVariant> getMultiVariants() {
Set<MultiVariant> set = Sets.<MultiVariant>newHashSet(this.variants.values());
if (this.isMultiPart()) {
set.addAll(this.multiPart.getMultiVariants());
}
return set;
}
public boolean isMultiPart() {
return this.multiPart != null;
}
public MultiPart getMultiPart() {
return this.multiPart;
}
@Environment(EnvType.CLIENT)
public static final class Context {
protected final Gson gson = new GsonBuilder()
.registerTypeAdapter(BlockModelDefinition.class, new BlockModelDefinition.Deserializer())
.registerTypeAdapter(Variant.class, new Variant.Deserializer())
.registerTypeAdapter(MultiVariant.class, new MultiVariant.Deserializer())
.registerTypeAdapter(MultiPart.class, new MultiPart.Deserializer(this))
.registerTypeAdapter(Selector.class, new Selector.Deserializer())
.create();
private StateDefinition<Block, BlockState> definition;
public StateDefinition<Block, BlockState> getDefinition() {
return this.definition;
}
public void setDefinition(StateDefinition<Block, BlockState> stateContainer) {
this.definition = stateContainer;
}
}
@Environment(EnvType.CLIENT)
public static class Deserializer implements JsonDeserializer<BlockModelDefinition> {
public BlockModelDefinition deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
Map<String, MultiVariant> map = this.getVariants(context, jsonObject);
MultiPart multiPart = this.getMultiPart(context, jsonObject);
if (!map.isEmpty() || multiPart != null && !multiPart.getMultiVariants().isEmpty()) {
return new BlockModelDefinition(map, multiPart);
} else {
throw new JsonParseException("Neither 'variants' nor 'multipart' found");
}
}
protected Map<String, MultiVariant> getVariants(JsonDeserializationContext context, JsonObject json) {
Map<String, MultiVariant> map = Maps.<String, MultiVariant>newHashMap();
if (json.has("variants")) {
JsonObject jsonObject = GsonHelper.getAsJsonObject(json, "variants");
for (Entry<String, JsonElement> entry : jsonObject.entrySet()) {
map.put((String)entry.getKey(), (MultiVariant)context.deserialize((JsonElement)entry.getValue(), MultiVariant.class));
}
}
return map;
}
@Nullable
protected MultiPart getMultiPart(JsonDeserializationContext context, JsonObject json) {
if (!json.has("multipart")) {
return null;
} else {
JsonArray jsonArray = GsonHelper.getAsJsonArray(json, "multipart");
return context.deserialize(jsonArray, MultiPart.class);
}
}
}
@Environment(EnvType.CLIENT)
protected class MissingVariantException extends RuntimeException {
}
}