From 8afe1ab07cf7cea1634facc6e7b96f4babf262c6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 5 Feb 2019 10:48:27 +0200 Subject: [PATCH] Rewrote the villager texture cache. It won't attempt to verify textures every time one is retrieved now. That should improve performance. --- .../render/ponies/RenderPonyVillager.java | 27 +++++---- .../ponies/RenderPonyZombieVillager.java | 26 +++++---- .../VillagerProfessionTextureCache.java | 57 +++++++++++-------- .../util/render/FormattedTextureSupplier.java | 23 ++++++++ .../util/render/IntStringMapper.java | 42 ++++++++++++++ 5 files changed, 129 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/minelittlepony/util/render/FormattedTextureSupplier.java create mode 100644 src/main/java/com/minelittlepony/util/render/IntStringMapper.java diff --git a/src/main/java/com/minelittlepony/render/ponies/RenderPonyVillager.java b/src/main/java/com/minelittlepony/render/ponies/RenderPonyVillager.java index cf9a7ada..90a0ea16 100644 --- a/src/main/java/com/minelittlepony/render/ponies/RenderPonyVillager.java +++ b/src/main/java/com/minelittlepony/render/ponies/RenderPonyVillager.java @@ -2,7 +2,9 @@ package com.minelittlepony.render.ponies; import com.minelittlepony.model.PMAPI; import com.minelittlepony.render.RenderPonyMob; +import com.minelittlepony.util.render.FormattedTextureSupplier; import com.minelittlepony.util.render.ITextureSupplier; +import com.minelittlepony.util.render.IntStringMapper; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.entity.RenderManager; @@ -11,17 +13,18 @@ import net.minecraft.util.ResourceLocation; public class RenderPonyVillager extends RenderPonyMob { - private static final ITextureSupplier PROFESSIONS = new VillagerProfessionTextureCache( - "textures/entity/villager/%d_pony.png", - new ResourceLocation("minelittlepony", "textures/entity/villager/farmer_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/villager/librarian_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/villager/priest_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/villager/smith_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/villager/butcher_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/villager/villager_pony.png") - ); - private static final ResourceLocation EGG = new ResourceLocation("minelittlepony", "textures/entity/villager/silly_pony.png"); - private static final ResourceLocation EGG_2 = new ResourceLocation("minelittlepony", "textures/entity/villager/tiny_silly_pony.png"); + /** + * Key mapping from a villager profession id to a human readable name + */ + public static final IntStringMapper MAPPER = new IntStringMapper("farmer", "librarian", "priest", "smith", "butcher", "villager"); + + private static final ITextureSupplier FORMATTER = new FormattedTextureSupplier("minelittlepony", "textures/entity/villager/%s_pony.png"); + + private static final ResourceLocation DEFAULT = FORMATTER.supplyTexture("villager"); + private static final ResourceLocation EGG = FORMATTER.supplyTexture("silly"); + private static final ResourceLocation EGG_2 = FORMATTER.supplyTexture("tiny_silly"); + + private static final ITextureSupplier PROFESSIONS = new VillagerProfessionTextureCache(FORMATTER, MAPPER, DEFAULT); public RenderPonyVillager(RenderManager manager) { super(manager, PMAPI.villager); @@ -30,7 +33,7 @@ public class RenderPonyVillager extends RenderPonyMob { @Override public void preRenderCallback(EntityVillager villager, float ticks) { super.preRenderCallback(villager, ticks); - GlStateManager.scale(0.9375F, 0.9375F, 0.9375F); + GlStateManager.scale(BASE_MODEL_SCALE, BASE_MODEL_SCALE, BASE_MODEL_SCALE); } @Override diff --git a/src/main/java/com/minelittlepony/render/ponies/RenderPonyZombieVillager.java b/src/main/java/com/minelittlepony/render/ponies/RenderPonyZombieVillager.java index 31aa7ee5..dc98e5d4 100644 --- a/src/main/java/com/minelittlepony/render/ponies/RenderPonyZombieVillager.java +++ b/src/main/java/com/minelittlepony/render/ponies/RenderPonyZombieVillager.java @@ -2,7 +2,9 @@ package com.minelittlepony.render.ponies; import com.minelittlepony.model.PMAPI; import com.minelittlepony.render.RenderPonyMob; +import com.minelittlepony.util.render.FormattedTextureSupplier; import com.minelittlepony.util.render.ITextureSupplier; +import com.minelittlepony.util.render.IntStringMapper; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.entity.monster.EntityZombieVillager; @@ -10,17 +12,19 @@ import net.minecraft.util.ResourceLocation; public class RenderPonyZombieVillager extends RenderPonyMob { - private static final ITextureSupplier PROFESSIONS = new VillagerProfessionTextureCache( - "textures/entity/zombie_villager/zombie_%d_pony.png", - new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_farmer_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_librarian_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_priest_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_smith_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_butcher_pony.png"), - new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_villager_pony.png") - ); - private static final ResourceLocation EGG = new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_silly_pony.png"); - private static final ResourceLocation EGG_2 = new ResourceLocation("minelittlepony", "textures/entity/zombie_villager/zombie_tiny_silly_pony.png"); + /** + * Ditto. + * @see RenderPonyVillager.MAPPER + */ + public static final IntStringMapper MAPPER = new IntStringMapper("farmer", "librarian", "priest", "smith", "butcher", "villager"); + + private static final ITextureSupplier FORMATTER = new FormattedTextureSupplier("minelittlepony", "textures/entity/zombie_villager/zombie_%s_pony.png"); + + private static final ResourceLocation DEFAULT = FORMATTER.supplyTexture("villager"); + private static final ResourceLocation EGG = FORMATTER.supplyTexture("silly"); + private static final ResourceLocation EGG_2 = FORMATTER.supplyTexture("tiny_silly"); + + private static final ITextureSupplier PROFESSIONS = new VillagerProfessionTextureCache(FORMATTER, MAPPER, DEFAULT); public RenderPonyZombieVillager(RenderManager manager) { super(manager, PMAPI.zombieVillager); diff --git a/src/main/java/com/minelittlepony/render/ponies/VillagerProfessionTextureCache.java b/src/main/java/com/minelittlepony/render/ponies/VillagerProfessionTextureCache.java index 6aff9870..99e0fa6e 100644 --- a/src/main/java/com/minelittlepony/render/ponies/VillagerProfessionTextureCache.java +++ b/src/main/java/com/minelittlepony/render/ponies/VillagerProfessionTextureCache.java @@ -3,46 +3,57 @@ package com.minelittlepony.render.ponies; import net.minecraft.client.Minecraft; import net.minecraft.util.ResourceLocation; +import com.minelittlepony.MineLittlePony; import com.minelittlepony.util.render.ITextureSupplier; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; +/** + * Cached pool of villager textures. + */ class VillagerProfessionTextureCache implements ITextureSupplier { - private final ResourceLocation[] pool; - private final String path; + private final ITextureSupplier formatter; + + private final Function keyMapper; + + private final ResourceLocation fallback; private final Map cache = new HashMap<>(); - public VillagerProfessionTextureCache(String path, ResourceLocation... pool) { - this.path = path; - this.pool = pool; + /** + * Creates a new profession cache + * + * @param formatter Formatter used when creating new textures + * @param keyMapper Mapper to convert integer ids into a string value for format insertion + * @param fallback The default if any generated textures fail to load. This is stored in place of failing textures. + */ + public VillagerProfessionTextureCache(ITextureSupplier formatter, Function keyMapper, ResourceLocation fallback) { + this.formatter = formatter; + this.fallback = fallback; + this.keyMapper = keyMapper; } @Override public ResourceLocation supplyTexture(Integer profession) { - ResourceLocation texture = getVillagerTexture(profession); - - try { - Minecraft.getMinecraft().getResourceManager().getResource(texture); - } catch (IOException e) { - return pool[pool.length - 1]; - } - - return texture; - } - - private ResourceLocation getVillagerTexture(int profession) { - if (profession >= pool.length) { - return cache.computeIfAbsent(profession, this::getModProfessionResource); - } - - return pool[profession]; + return cache.computeIfAbsent(profession, this::getModProfessionResource); } private ResourceLocation getModProfessionResource(int professionId) { - return new ResourceLocation("minelittlepony", String.format(path, professionId)); + ResourceLocation generated = formatter.supplyTexture(keyMapper.apply(professionId)); + + try { + Minecraft.getMinecraft().getResourceManager().getResource(generated); + } catch (IOException e) { + MineLittlePony.logger.error("Error loading villager texture `" + generated + "`.", e); + + // if texture loading fails, use the fallback. + return fallback; + } + + return generated; } } diff --git a/src/main/java/com/minelittlepony/util/render/FormattedTextureSupplier.java b/src/main/java/com/minelittlepony/util/render/FormattedTextureSupplier.java new file mode 100644 index 00000000..bf8fc7e2 --- /dev/null +++ b/src/main/java/com/minelittlepony/util/render/FormattedTextureSupplier.java @@ -0,0 +1,23 @@ +package com.minelittlepony.util.render; + +import net.minecraft.util.ResourceLocation; + +/** + * Supplies new resource locations based on a pre-defined domain and formatted path. + */ +public class FormattedTextureSupplier implements ITextureSupplier { + + private final String domain; + private final String path; + + public FormattedTextureSupplier(String domain, String path) { + this.domain = domain; + this.path = path; + } + + @Override + public ResourceLocation supplyTexture(String key) { + return new ResourceLocation(domain, String.format(path, key)); + } + +} diff --git a/src/main/java/com/minelittlepony/util/render/IntStringMapper.java b/src/main/java/com/minelittlepony/util/render/IntStringMapper.java new file mode 100644 index 00000000..5dcda33a --- /dev/null +++ b/src/main/java/com/minelittlepony/util/render/IntStringMapper.java @@ -0,0 +1,42 @@ +package com.minelittlepony.util.render; + +import com.google.common.collect.Maps; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; + +/** + * Simple mapping from an integer index to a pre-defined set of strings. + * Returns the string representation of the index if no value was found. + */ +public class IntStringMapper implements Function { + + private final HashMap values = Maps.newHashMap(); + + /** + * Creates a new string mapper pre-populated with the provided values by index. + */ + public IntStringMapper(String...values) { + for (int i = 0; i < values.length; i++) { + this.values.put(i, Objects.requireNonNull(values[i])); + } + } + + /** + * Return the values. So you can actually modify it. + * I mean, if you want to @modders... + */ + public Map getValues() { + return values; + } + + @Override + public String apply(Integer t) { + if (values.containsKey(t)) { + return values.get(t); + } + return String.valueOf(t); + } +}