Skip to content

Commit

Permalink
killswitches for various rendering-related things for performance rea…
Browse files Browse the repository at this point in the history
…sons (see: #5)
  • Loading branch information
quat1024 committed May 28, 2019
1 parent a5fc056 commit 1361c39
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 87 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ apply plugin: 'net.minecraftforge.gradle.forge'
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.


version = "1.2.0"
version = "1.2.1"
group = "quaternary.simpletrophies" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "simpletrophies"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.color.BlockColors;
import net.minecraft.client.renderer.color.ItemColors;
import net.minecraft.client.resources.SimpleReloadableResourceManager;
import net.minecraft.item.Item;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
Expand All @@ -20,6 +23,7 @@
import quaternary.simpletrophies.client.tesr.RenderItemStackSimpleTrophy;
import quaternary.simpletrophies.client.tesr.RenderTileSimpleTrophy;
import quaternary.simpletrophies.common.block.SimpleTrophiesBlocks;
import quaternary.simpletrophies.common.config.SimpleTrophiesConfig;
import quaternary.simpletrophies.common.etc.TrophyHelpers;
import quaternary.simpletrophies.common.item.SimpleTrophiesItems;
import quaternary.simpletrophies.common.tile.TileSimpleTrophy;
Expand All @@ -30,8 +34,23 @@ public class ClientGameEvents {
public static void models(ModelRegistryEvent e) {
setSimpleItemModel(SimpleTrophiesItems.TROPHY);

ClientRegistry.bindTileEntitySpecialRenderer(TileSimpleTrophy.class, new RenderTileSimpleTrophy());
SimpleTrophiesItems.TROPHY.setTileEntityItemStackRenderer(new RenderItemStackSimpleTrophy());
if(SimpleTrophiesConfig.NO_TEISR) {
if(!SimpleTrophiesConfig.SKIP_ITEM_BASES) {
ModelLoader.setCustomMeshDefinition(SimpleTrophiesItems.TROPHY, stack ->
RenderItemStackSimpleTrophy.baseLocations.get(TrophyHelpers.getDisplayedVariant(stack))
);

//this used to work...fuck it, doesnt seem to now though
ModelLoader.registerItemVariants(SimpleTrophiesItems.TROPHY, new ResourceLocation(SimpleTrophies.MODID, "trophy"));
}
} else {
SimpleTrophiesItems.TROPHY.setTileEntityItemStackRenderer(new RenderItemStackSimpleTrophy());
((SimpleReloadableResourceManager) Minecraft.getMinecraft().getResourceManager()).registerReloadListener(resourceManager -> RenderItemStackSimpleTrophy.dumpCache());
}

if(!SimpleTrophiesConfig.NO_TESR) {
ClientRegistry.bindTileEntitySpecialRenderer(TileSimpleTrophy.class, new RenderTileSimpleTrophy());
}
}

private static void setSimpleItemModel(Item e) {
Expand All @@ -51,6 +70,16 @@ public static void blockColors(ColorHandlerEvent.Block e) {
}, SimpleTrophiesBlocks.TROPHY);
}

@SubscribeEvent
public static void itemColors(ColorHandlerEvent.Item e) {
//Has no effect unless skipTeisr is on, btw
ItemColors ic = e.getItemColors();
ic.registerItemColorHandler((stack, tintIndex) -> {
if(tintIndex != 0) return 0xFFFFFF;
else return TrophyHelpers.getCombinedColor(stack);
}, SimpleTrophiesItems.TROPHY);
}

private static long ticksInGame = 0;
private static boolean paused = false;
private static float lastNonPausedPartialTicks = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,124 +2,132 @@

import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockModelRenderer;
import net.minecraft.client.renderer.BlockModelShapes;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ModelManager;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.renderer.texture.ITextureObject;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import org.lwjgl.opengl.GL11;
import quaternary.simpletrophies.SimpleTrophies;
import quaternary.simpletrophies.client.ClientGameEvents;
import quaternary.simpletrophies.common.block.BlockSimpleTrophy;
import quaternary.simpletrophies.common.config.SimpleTrophiesConfig;
import quaternary.simpletrophies.common.etc.EnumTrophyVariant;
import quaternary.simpletrophies.common.etc.TrophyHelpers;
import quaternary.simpletrophies.common.item.ItemSimpleTrophy;

import java.util.EnumMap;

public class RenderItemStackSimpleTrophy extends TileEntityItemStackRenderer {
static final ModelResourceLocation[] baseModels;
public static final EnumMap<EnumTrophyVariant, ModelResourceLocation> baseLocations;
static final EnumMap<EnumTrophyVariant, IBakedModel> baseModels;

static {
baseModels = new ModelResourceLocation[EnumTrophyVariant.VALUES.length];
baseLocations = new EnumMap<>(EnumTrophyVariant.class);
PropertyEnum<EnumTrophyVariant> propVariant = BlockSimpleTrophy.PROP_VARIANT;
String variantName = propVariant.getName();
for(int i = 0; i < EnumTrophyVariant.VALUES.length; i++) {
EnumTrophyVariant var = EnumTrophyVariant.VALUES[i];
baseModels[i] = new ModelResourceLocation(new ResourceLocation(SimpleTrophies.MODID, "trophy"), variantName + '=' + propVariant.getName(var));

for(EnumTrophyVariant var : EnumTrophyVariant.VALUES) {
baseLocations.put(var, new ModelResourceLocation(new ResourceLocation(SimpleTrophies.MODID, "trophy"), variantName + '=' + propVariant.getName(var)));
}

baseModels = new EnumMap<>(EnumTrophyVariant.class);
}

public static void dumpCache() {
baseModels.clear();
}

int recursionDepth = 0;

@Override
public void renderByItem(ItemStack stack) {
if(!(stack.getItem() instanceof ItemSimpleTrophy)) return;
if(SimpleTrophiesConfig.NO_TEISR || !(stack.getItem() instanceof ItemSimpleTrophy)) return;

//Render the base
int variantID = TrophyHelpers.getDisplayedVariant(stack).ordinal();
BlockRendererDispatcher brd = Minecraft.getMinecraft().getBlockRendererDispatcher();
ModelManager mm = brd.getBlockModelShapes().getModelManager();
int color = TrophyHelpers.getCombinedColor(stack);
float red = ((color & 0xFF0000) >> 16) / 255f;
float green = ((color & 0x00FF00) >> 8) / 255f;
float blue = (color & 0x0000FF) / 255f;
brd.getBlockModelRenderer().renderModelBrightnessColor(mm.getModel(baseModels[variantID]), 1f, red, green, blue);

//Render the item
ItemStack displayedStack = TrophyHelpers.getDisplayedStack(stack);

if(!displayedStack.isEmpty()) {
float ticks = ClientGameEvents.getPauseAdjustedTicksAndPartialTicks();

GlStateManager.pushMatrix();
GlStateManager.translate(.5, .55, .5);
if(!Minecraft.getMinecraft().getRenderItem().getItemModelWithOverrides(displayedStack, Minecraft.getMinecraft().world, null).isGui3d()) {
GlStateManager.translate(0, 0.1, 0);
}
if(!SimpleTrophiesConfig.SKIP_ITEM_BASES) {
EnumTrophyVariant baseVariant = TrophyHelpers.getDisplayedVariant(stack);
IBakedModel baseModel = baseModels.computeIfAbsent(baseVariant, (var) ->
brd.getBlockModelShapes().getModelManager().getModel(baseLocations.get(var))
);

GlStateManager.rotate(ticks * 2.5f, 0, 1, 0);
GlStateManager.scale(2, 2, 2);

//Fix flickering leaves issue on old Forges
//Without this line:
//RenderItem#renderItem is called on this item
// -> calls setBlurMipmap(false, false) which saves old blur/mipmap values (A)
// -> finds and calls this TEISR
// -> -> I call renderItem#renderItem
// -> -> -> calls setBlurMipmap(false, false) which destroys old values (!!!) (B)
// -> -> -> item rendering happens
// -> -> -> calls restoreLastBlurMipmap() which restores the (false, false) saved in A
// -> calls restoreLastBlurMipmap() which restores (false, false) from B
//values saved in A have now been overwritten with (false, false) - stateleak!
//
//With this line:
//RenderItem#renderItem is called on this item
// -> calls setBlurMipmap(false, false) which saves old blur/mipmap values (A)
// -> finds and calls this TEISR
// -> -> I call restoreLastBlurMipmap() which restores old values saved in A
// -> -> I call renderItem#renderItem
// -> -> -> calls setBlurMipmap(false, false) which saves old blur/mipmap values (B)
// -> -> -> item rendering happens
// -> -> -> calls restoreLastBlurMipmap() which restores the old values saved in A (saved again in B)
// -> calls restoreLastBlurMipmap() (but the saved values match the real values so nothing happens)
//values saved in A are now preserved - no stateleak
//
//Flickering leaves were fixed in https://github.com/MinecraftForge/MinecraftForge/pull/4997
//But it still stateleaks technically, you just can't see it on leaves.
Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).restoreLastBlurMipmap();

//Too many nested pushmatrixes can cause severe render glitching on my pc.
//Nobody's going to actually hand out trophies of trophies of trophies of trophies of trophies of trophies anyways.
//No, that's not a challenge, stop it.
//And you can't even see it anyways it's so small.
recursionDepth++;
int color = TrophyHelpers.getCombinedColor(stack);
float red = ((color & 0xFF0000) >> 16) / 255f;
float green = ((color & 0x00FF00) >> 8) / 255f;
float blue = (color & 0x0000FF) / 255f;
brd.getBlockModelRenderer().renderModelBrightnessColor(baseModel, 1f, red, green, blue);
}

//Render the item
if(!SimpleTrophiesConfig.SKIP_ITEM_ITEMS) {
ItemStack displayedStack = TrophyHelpers.getDisplayedStack(stack);

if(recursionDepth < 5) {
try {
Minecraft.getMinecraft().getRenderItem().renderItem(displayedStack, ItemCameraTransforms.TransformType.GROUND);
} catch(Exception oof) {
SimpleTrophies.LOG.error("Problem rendering item on a trophy TEISR", oof);
if(!displayedStack.isEmpty()) {
float ticks = ClientGameEvents.getPauseAdjustedTicksAndPartialTicks();

GlStateManager.pushMatrix();
GlStateManager.translate(.5, .55, .5);
if(!Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getItemModel(displayedStack).isGui3d()) {
GlStateManager.translate(0, 0.1, 0);
}

GlStateManager.rotate(ticks * 2.5f, 0, 1, 0);
GlStateManager.scale(2, 2, 2);

//Fix flickering leaves issue on old Forges
//Without this line:
//RenderItem#renderItem is called on this item
// -> calls setBlurMipmap(false, false) which saves old blur/mipmap values (A)
// -> finds and calls this TEISR
// -> -> I call renderItem#renderItem
// -> -> -> calls setBlurMipmap(false, false) which destroys old values (!!!) (B)
// -> -> -> item rendering happens
// -> -> -> calls restoreLastBlurMipmap() which restores the (false, false) saved in A
// -> calls restoreLastBlurMipmap() which restores (false, false) from B
//values saved in A have now been overwritten with (false, false) - stateleak!
//
//With this line:
//RenderItem#renderItem is called on this item
// -> calls setBlurMipmap(false, false) which saves old blur/mipmap values (A)
// -> finds and calls this TEISR
// -> -> I call restoreLastBlurMipmap() which restores old values saved in A
// -> -> I call renderItem#renderItem
// -> -> -> calls setBlurMipmap(false, false) which saves old blur/mipmap values (B)
// -> -> -> item rendering happens
// -> -> -> calls restoreLastBlurMipmap() which restores the old values saved in A (saved again in B)
// -> calls restoreLastBlurMipmap() (but the saved values match the real values so nothing happens)
//values saved in A are now preserved - no stateleak
//
//Flickering leaves were fixed in https://github.com/MinecraftForge/MinecraftForge/pull/4997
//But it still stateleaks technically, you just can't see it on leaves.
Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).restoreLastBlurMipmap();

//Too many nested pushmatrixes can cause severe render glitching on my pc.
//Nobody's going to actually hand out trophies of trophies of trophies of trophies of trophies of trophies anyways.
//No, that's not a challenge, stop it.
//And you can't even see it anyways it's so small.
recursionDepth++;

if(recursionDepth < 5) {
try {
Minecraft.getMinecraft().getRenderItem().renderItem(displayedStack, ItemCameraTransforms.TransformType.GROUND);
} catch(Exception oof) {
SimpleTrophies.LOG.error("Problem rendering item on a trophy TEISR", oof);
}
}

recursionDepth--;

GlStateManager.enableBlend(); //fix a stateleak

GlStateManager.popMatrix();
}

recursionDepth--;

GlStateManager.enableBlend(); //fix a stateleak

GlStateManager.popMatrix();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
public class RenderTileSimpleTrophy extends TileEntitySpecialRenderer<TileSimpleTrophy> {
@Override
public void render(TileSimpleTrophy te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
if(te == null) return;
if(te == null || SimpleTrophiesConfig.NO_TESR) return;

ItemStack displayedStack = te.displayedStack;

if(!displayedStack.isEmpty()) {
if(!SimpleTrophiesConfig.SKIP_BLOCK_ITEMS && !displayedStack.isEmpty()) {
float ticks = ClientGameEvents.getPauseAdjustedTicksAndPartialTicks();

//spread out animations a little bit.
Expand All @@ -36,7 +36,7 @@ public void render(TileSimpleTrophy te, double x, double y, double z, float part

GlStateManager.translate(x + .5, y + .6 + Math.sin(ticks / 25f) / 7f, z + .5);

if(!Minecraft.getMinecraft().getRenderItem().getItemModelWithOverrides(displayedStack, getWorld(), null).isGui3d()) {
if(!Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getItemModel(displayedStack).isGui3d()) {
GlStateManager.translate(0, 0.2, 0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public class SimpleTrophiesConfig {

public static List<NBTTagCompound> CREATIVETAB_TAGS;

public static boolean SKIP_ITEM_BASES;
public static boolean SKIP_ITEM_ITEMS;
public static boolean SKIP_BLOCK_ITEMS;
public static boolean NO_TEISR;
public static boolean NO_TESR;

public static String DEFAULT_CREATIVETAB_STR = "{TrophyName:\"Add your own trophies here in the config!\",TrophyVariant:\"classic\",TrophyItem:{id:\"minecraft:diamond_axe\",Count:1b,Damage:0s},TrophyColorRed:65,TrophyColorGreen:205,TrophyColorBlue:52}";
public static NBTTagCompound DEFAULT_CREATIVETAB_TAG = SimpleTrophiesUtil.swallowError(() -> JsonToNBT.getTagFromJson(DEFAULT_CREATIVETAB_STR));

Expand All @@ -49,6 +55,16 @@ private static void load() {
}
}

SKIP_BLOCK_ITEMS = config.getBoolean("skipBlockItems", "client.perf", false, "Don't show the items on top of trophies placed in the world. Saves on performance.");

SKIP_ITEM_ITEMS = config.getBoolean("skipItemItems", "client.perf", false, "Don't show the items on top of trophies in your inventory and on other GUIs. Saves on performance.");

SKIP_ITEM_BASES = config.getBoolean("skipItemBases", "client.perf", false, "Don't show trophy bases on trophies in your inventory and on other GUIs. Saves on performance.");

NO_TESR = config.getBoolean("noTileEntitySpecialRenderer", "client.perf", false, "Emergency killswitch for the tile entity renderer. Enable in cases of extreme performance issues or client rendering-related crashes.\n(Requires a game restart in some cases.)");

NO_TEISR = config.getBoolean("noTileEntityItemStackRenderer", "client.perf", false, "Emergency killswitch for the in-inventory trophy renderer. Enable in cases of extreme performance issues or client rendering-related crashes.\n(Requires a game restart in some cases.)\nIf this option is enabled, and skipItemBases is not, trophy item bases will render using a 'fast path' that is about as expensive as rendering a grass block item. This fast path is not compatible with the fancy trophy TEISR, to my knowledge.");

if(config.hasChanged()) config.save();
}

Expand Down

0 comments on commit 1361c39

Please sign in to comment.