package slimeknights.tconstruct.library.client.model;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemTransformVec3f;
import net.minecraft.client.renderer.block.model.ModelBlock;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.commons.io.IOUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Map;
import slimeknights.tconstruct.library.client.deserializer.ItemCameraTransformsDeserializer;
import slimeknights.tconstruct.library.client.deserializer.ItemTransformVec3fDeserializer;
import slimeknights.tconstruct.library.client.model.format.AmmoPosition;
import slimeknights.tconstruct.library.client.model.format.ModelTextureDeserializer;
import slimeknights.tconstruct.library.client.model.format.Offset;
import slimeknights.tconstruct.library.client.model.format.ToolModelOverride;
import slimeknights.tconstruct.library.client.model.format.TransformDeserializer;
import slimeknights.tconstruct.shared.client.BakedColoredItemModel;
@SideOnly(Side.CLIENT)
public class ModelHelper extends slimeknights.mantle.client.ModelHelper {
public static final EnumFacing[] MODEL_SIDES = new EnumFacing[]{null, EnumFacing.DOWN, EnumFacing.UP, EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.EAST};
private static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(ModelTextureDeserializer.TYPE, ModelTextureDeserializer.INSTANCE)
.registerTypeAdapter(Offset.OffsetDeserializer.TYPE, Offset.OffsetDeserializer.INSTANCE)
.registerTypeAdapter(TransformDeserializer.TYPE, TransformDeserializer.INSTANCE)
//.registerTypeAdapter(ImmutableMap.class, JsonUtils.ImmutableMapTypeAdapter.INSTANCE)
.registerTypeAdapter(ItemCameraTransforms.class, ItemCameraTransformsDeserializer.INSTANCE)
.registerTypeAdapter(ItemTransformVec3f.class, ItemTransformVec3fDeserializer.INSTANCE)
//.registerTypeAdapter(TRSRTransformation.class, ForgeBlockStateV1.TRSRDeserializer.INSTANCE)
.registerTypeAdapter(ToolModelOverride.ToolModelOverrideListDeserializer.TYPE, ToolModelOverride.ToolModelOverrideListDeserializer.INSTANCE)
.registerTypeAdapter(AmmoPosition.AmmoPositionDeserializer.TYPE, AmmoPosition.AmmoPositionDeserializer.INSTANCE)
.create();
public static IBakedModel getBakedModelForItem(ItemStack stack, World world, EntityLivingBase entity) {
IBakedModel model = Minecraft.getMinecraft().getRenderItem().getItemModelWithOverrides(stack, world, entity);
if(model == null || model.isBuiltInRenderer()) {
// missing model so people don't go paranoid when their chests go missing
model = Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getModelManager().getMissingModel();
}
else {
// take color into account
model = new BakedColoredItemModel(stack, model);
}
return model;
}
public static Reader getReaderForResource(ResourceLocation location) throws IOException {
return getReaderForResource(location, Minecraft.getMinecraft().getResourceManager());
}
public static Reader getReaderForResource(ResourceLocation location, IResourceManager resourceManager) throws IOException {
ResourceLocation file = new ResourceLocation(location.getResourceDomain(), location.getResourcePath() + ".json");
IResource iresource = resourceManager.getResource(file);
return new BufferedReader(new InputStreamReader(iresource.getInputStream(), Charsets.UTF_8));
}
public static Map<String, String> loadTexturesFromJson(ResourceLocation location) throws IOException {
Reader reader = getReaderForResource(location);
try {
return GSON.fromJson(reader, ModelTextureDeserializer.TYPE);
} finally {
IOUtils.closeQuietly(reader);
}
}
public static Offset loadOffsetFromJson(ResourceLocation location) throws IOException {
Reader reader = getReaderForResource(location);
try {
return GSON.fromJson(reader, Offset.OffsetDeserializer.TYPE);
} finally {
IOUtils.closeQuietly(reader);
}
}
public static AmmoPosition loadAmmoPositionFromJson(ResourceLocation location) throws IOException {
Reader reader = getReaderForResource(location);
try {
return GSON.fromJson(reader, AmmoPosition.AmmoPositionDeserializer.TYPE);
} finally {
IOUtils.closeQuietly(reader);
}
}
public static ImmutableList<ToolModelOverride> loadToolModelOverridesFromJson(ResourceLocation location) throws IOException {
Reader reader = getReaderForResource(location);
try {
return GSON.fromJson(reader, ToolModelOverride.ToolModelOverrideListDeserializer.TYPE);
} finally {
IOUtils.closeQuietly(reader);
}
}
public static ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> loadTransformFromJson(ResourceLocation location)
throws IOException {
return loadTransformFromJson(location, "display");
}
public static ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> loadTransformFromJson(ResourceLocation location, String tag)
throws IOException {
Reader reader = getReaderForResource(location);
try {
TransformDeserializer.tag = tag;
ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transforms = GSON.fromJson(reader, TransformDeserializer.TYPE);
// filter out missing/identity entries
ImmutableMap.Builder<ItemCameraTransforms.TransformType, TRSRTransformation> builder = ImmutableMap.builder();
for(Map.Entry<ItemCameraTransforms.TransformType, TRSRTransformation> entry : transforms.entrySet()) {
if(!entry.getValue().equals(TRSRTransformation.identity())) {
builder.put(entry.getKey(), entry.getValue());
}
}
return builder.build();
} finally {
IOUtils.closeQuietly(reader);
}
}
public static ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> loadTransformFromJsonBackup(ResourceLocation location)
throws IOException {
Reader reader = getReaderForResource(location);
try {
// we abuse ModelBlock because all the deserializers are not accessible..
ModelBlock modelBlock = ModelBlock.deserialize(reader);
ItemCameraTransforms itemCameraTransforms = modelBlock.getAllTransforms();
ImmutableMap.Builder<ItemCameraTransforms.TransformType, TRSRTransformation> builder = ImmutableMap.builder();
for(ItemCameraTransforms.TransformType type : ItemCameraTransforms.TransformType.values()) {
if(itemCameraTransforms.getTransform(type) != ItemTransformVec3f.DEFAULT) {
builder.put(type, new TRSRTransformation(itemCameraTransforms.getTransform(type)));
}
}
return builder.build();
} finally {
IOUtils.closeQuietly(reader);
}
}
public static ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> getTransforms(IPerspectiveAwareModel model) {
ImmutableMap.Builder<ItemCameraTransforms.TransformType, TRSRTransformation> builder = ImmutableMap.builder();
for(ItemCameraTransforms.TransformType type : ItemCameraTransforms.TransformType.values()) {
TRSRTransformation transformation = new TRSRTransformation(model.handlePerspective(type).getRight());
if(!transformation.equals(TRSRTransformation.identity())) {
builder.put(type, TRSRTransformation.blockCenterToCorner(transformation));
}
}
return builder.build();
}
public static ImmutableList<ResourceLocation> loadTextureListFromJson(ResourceLocation location) throws IOException {
ImmutableList.Builder<ResourceLocation> builder = ImmutableList.builder();
for(String s : loadTexturesFromJson(location).values()) {
builder.add(new ResourceLocation(s));
}
return builder.build();
}
public static Float[] loadLayerRotations(ResourceLocation location) throws IOException {
JsonReader reader = new JsonReader(getReaderForResource(location));
try {
reader.beginObject();
while(reader.hasNext()) {
if("layerrotation".equals(reader.nextName())) {
return GSON.fromJson(reader, Float[].class);
}
else {
reader.skipValue();
}
}
} finally {
IOUtils.closeQuietly(reader);
}
return new Float[0];
}
public static ResourceLocation getModelLocation(ResourceLocation location) {
return new ResourceLocation(location.getResourceDomain(), "models/" + location.getResourcePath() + ".json");
}
}