package slimeknights.tconstruct.library.client.material; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; 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 com.google.gson.reflect.TypeToken; import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManagerReloadListener; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StringUtils; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.LoaderState; import net.minecraftforge.fml.common.ModContainer; import org.apache.logging.log4j.Logger; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import slimeknights.tconstruct.library.TinkerRegistry; import slimeknights.tconstruct.library.Util; import slimeknights.tconstruct.library.client.MaterialRenderInfo; import slimeknights.tconstruct.library.client.model.ModelHelper; import slimeknights.tconstruct.library.materials.Material; public class MaterialRenderInfoLoader implements IResourceManagerReloadListener { public static final MaterialRenderInfoLoader INSTANCE = new MaterialRenderInfoLoader(); private static Logger log = Util.getLogger("RenderInfoLoader"); private static final Type TYPE = new TypeToken<IMaterialRenderInfoDeserializer>() {}.getType(); private static final Gson GSON = new GsonBuilder() .registerTypeAdapter(TYPE, new MaterialInfoDeserializerDeserializer()) .create(); private IResourceManager resourceManager; static Map<String, Class<? extends IMaterialRenderInfoDeserializer>> renderInfoDeserializers = Maps.newHashMap(); public static void addRenderInfo(String id, Class<? extends IMaterialRenderInfoDeserializer> clazz) { renderInfoDeserializers.put(id, clazz); } // we load from mods resource locations, in this order: // <mod that registered the material> -> tconstruct -> minecraft public void loadRenderInfo() { if(!Loader.instance().hasReachedState(LoaderState.POSTINITIALIZATION)) { return; } for(Material material : TinkerRegistry.getAllMaterials()) { // check if info exists in the form of json // if not, check if there already is data // if no data exists and no json is present, fill it with textcolor default List<String> domains = Lists.newArrayList(); ModContainer registeredBy = TinkerRegistry.getTrace(material); if(!Util.MODID.equals(registeredBy.getModId())) { domains.add(registeredBy.getModId().toLowerCase()); } domains.add(Util.MODID); domains.add("minecraft"); for(String domain : domains) { ResourceLocation location = new ResourceLocation(domain, "materials/" + material.getIdentifier()); try { Reader reader = ModelHelper.getReaderForResource(location, resourceManager); IMaterialRenderInfoDeserializer deserializer = GSON.fromJson(reader, TYPE); if(deserializer != null) { material.renderInfo = deserializer.getMaterialRenderInfo(); material.renderInfo.setTextureSuffix(deserializer.getSuffix()); } } catch(FileNotFoundException e) { // set default if nothing is present if(material.renderInfo == null) { material.renderInfo = new MaterialRenderInfo.Default(material.materialTextColor); log.warn("Material " + material.getIdentifier() + " has no rendering info. Substituting default"); } } catch(IOException | JsonParseException e) { log.error("Exception when loading render info for material " + material.getIdentifier() + " from file " + location.toString(), e); } } } } @Override public void onResourceManagerReload(IResourceManager resourceManager) { this.resourceManager = resourceManager; loadRenderInfo(); } private static class MaterialInfoDeserializerDeserializer implements JsonDeserializer<IMaterialRenderInfoDeserializer> { @Override public IMaterialRenderInfoDeserializer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); String type = jsonObject.get("type").getAsString(); Class<? extends IMaterialRenderInfoDeserializer> deserializerClass = renderInfoDeserializers.get(type); if(deserializerClass == null) { throw new JsonParseException("Unknown material texture type: " + type); } JsonElement parameters = jsonObject.get("parameters"); IMaterialRenderInfoDeserializer deserializer = GSON.fromJson(parameters, deserializerClass); if(deserializer != null && jsonObject.has("suffix")) { deserializer.setSuffix(jsonObject.get("suffix").getAsString()); } return deserializer; } } }