mirror of
https://github.com/GTNewHorizons/Draconic-Evolution.git
synced 2026-11-13 16:54:18 +00:00
Reduce render load of DE placed items (#108)
This commit is contained in:
1 parent
6f183b615e
commit
fedee1ba43
5 files changed
+238
-8
No files matched your search
@@ -18,4 +18,5 @@ dependencies {
|
||||
|
||||
compileOnly('curse.maven:automagy-222153:2285272')
|
||||
compileOnly('com.github.GTNewHorizons:EnderIO:2.10.25:dev')
|
||||
runtimeOnly("com.github.GTNewHorizons:NotEnoughItems:2.8.118-GTNH:dev")
|
||||
}
|
||||
+10
-4
@@ -15,6 +15,12 @@ import com.brandon3055.draconicevolution.common.utils.LogHelper;
|
||||
|
||||
public class RenderMobSoul implements IItemRenderer {
|
||||
|
||||
public static volatile boolean applyTimeRotation = true;
|
||||
|
||||
public static float getRotationAngle() {
|
||||
return (float) (Minecraft.getSystemTime() / -10);
|
||||
}
|
||||
|
||||
private final Minecraft mc;
|
||||
private final String[] randomEntities = new String[] { "Pig", "Sheep", "Enderman", "Zombie", "Creeper", "Cow",
|
||||
"Chicken", "Ozelot", "Witch", "Wolf", "MushroomCow", "Squid", "EntityHorse", "Spider", "Skeleton", "Blaze",
|
||||
@@ -58,7 +64,7 @@ public class RenderMobSoul implements IItemRenderer {
|
||||
GL11.glScalef(13F, 13F, 13F);
|
||||
GL11.glTranslated(1.2, 2.2, 0);
|
||||
GL11.glRotatef(180F, 1F, 0F, 0F);
|
||||
GL11.glRotatef(mc.getSystemTime() / -10, 0F, 1F, 0F);
|
||||
if (applyTimeRotation) GL11.glRotatef(getRotationAngle(), 0F, 1F, 0F);
|
||||
GL11.glRotatef(-20F, 1F, 0F, 0F);
|
||||
RenderManager.instance.renderEntityWithPosYaw(mob, 0, 0, 0, 0F, 1F);
|
||||
GL11.glPopMatrix();
|
||||
@@ -67,7 +73,7 @@ public class RenderMobSoul implements IItemRenderer {
|
||||
GL11.glScalef(0.8F, 0.8F, 0.8F);
|
||||
GL11.glTranslated(2, 0.5, 0);
|
||||
GL11.glRotatef(20F, 0F, 0F, 1F);
|
||||
GL11.glRotatef(mc.getSystemTime() / -10, 0F, 1F, 0F);
|
||||
if (applyTimeRotation) GL11.glRotatef(getRotationAngle(), 0F, 1F, 0F);
|
||||
GL11.glRotatef(-20F, 1F, 0F, 0F);
|
||||
RenderManager.instance.renderEntityWithPosYaw(mob, 0, 0, 0, 0F, 1F);
|
||||
GL11.glPopMatrix();
|
||||
@@ -76,14 +82,14 @@ public class RenderMobSoul implements IItemRenderer {
|
||||
GL11.glScalef(0.8F, 0.8F, 0.8F);
|
||||
GL11.glTranslated(1, 0.5, 0);
|
||||
GL11.glRotatef(20F, 0F, 0F, 1F);
|
||||
GL11.glRotatef(mc.getSystemTime() / -10, 0F, 1F, 0F);
|
||||
if (applyTimeRotation) GL11.glRotatef(getRotationAngle(), 0F, 1F, 0F);
|
||||
GL11.glRotatef(-20F, 1F, 0F, 0F);
|
||||
RenderManager.instance.renderEntityWithPosYaw(mob, 0, 0, 0, 0F, 1F);
|
||||
GL11.glPopMatrix();
|
||||
} else {
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScalef(1.5F, 1.5F, 1.5F);
|
||||
GL11.glRotatef(mc.getSystemTime() / -10, 0F, 1F, 0F);
|
||||
if (applyTimeRotation) GL11.glRotatef(getRotationAngle(), 0F, 1F, 0F);
|
||||
GL11.glRotatef(-20F, 1F, 0F, 0F);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
package com.brandon3055.draconicevolution.client.render.tile;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.RenderItem;
|
||||
import net.minecraft.client.renderer.texture.ITickable;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.brandon3055.draconicevolution.client.render.item.RenderMobSoul;
|
||||
import com.brandon3055.draconicevolution.common.items.MobSoul;
|
||||
import com.brandon3055.draconicevolution.common.tileentities.TilePlacedItem;
|
||||
import com.brandon3055.draconicevolution.common.utils.ItemNBTHelper;
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
public class PlacedItemDisplayListCache {
|
||||
|
||||
private static final long GLINT_TTL_MS = 33L;
|
||||
private static final long ANIMATED_TTL_MS = 50L;
|
||||
private static final long MOBSOUL_TTL_MS = 1000L;
|
||||
private static final long PRUNE_INTERVAL_MS = 1000L;
|
||||
|
||||
private final Map<TilePlacedItem, CacheEntry> displayListCache = new HashMap<>();
|
||||
private int atlasVersion;
|
||||
private long nextPruneMs;
|
||||
|
||||
public PlacedItemDisplayListCache() {
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
public CacheEntry getOrCompile(TilePlacedItem tile, ItemStack stack, int meta, Runnable renderBody) {
|
||||
CacheEntry entry = displayListCache.get(tile);
|
||||
if (entry == null || !entry.isValid(stack, meta, tile.rotation, atlasVersion) || entry.needsRefresh()) {
|
||||
dispose(tile);
|
||||
entry = compile(tile, stack, meta, renderBody);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
private CacheEntry compile(TilePlacedItem tile, ItemStack stack, int meta, Runnable renderBody) {
|
||||
int listId = GL11.glGenLists(1);
|
||||
boolean mobSoul = stack.getItem() instanceof MobSoul;
|
||||
boolean previousRotationFlag = RenderMobSoul.applyTimeRotation;
|
||||
GL11.glNewList(listId, GL11.GL_COMPILE);
|
||||
try {
|
||||
if (mobSoul) RenderMobSoul.applyTimeRotation = false;
|
||||
renderBody.run();
|
||||
GL11.glEndList();
|
||||
} catch (RuntimeException | Error t) {
|
||||
GL11.glEndList();
|
||||
GL11.glDeleteLists(listId, 1);
|
||||
RenderItem.renderInFrame = false;
|
||||
throw t;
|
||||
} finally {
|
||||
RenderMobSoul.applyTimeRotation = previousRotationFlag;
|
||||
}
|
||||
CacheEntry entry = new CacheEntry(
|
||||
listId,
|
||||
stack,
|
||||
stack.stackSize,
|
||||
meta,
|
||||
tile.rotation,
|
||||
getTTL(stack, mobSoul),
|
||||
mobSoul,
|
||||
atlasVersion);
|
||||
displayListCache.put(tile, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
private long getTTL(ItemStack stack, boolean mobSoul) {
|
||||
if (mobSoul) {
|
||||
// "Any" soul swaps mob every second while named souls only need per-frame rotation outside the list
|
||||
return isAnyMobSoul(stack) ? MOBSOUL_TTL_MS : Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
if (stack.hasEffect()) return GLINT_TTL_MS; // Glint scroll (~30 fps)
|
||||
if (stack.getItem().getIconIndex(stack) instanceof ITickable) return ANIMATED_TTL_MS; // 20 Hz sprite ticks
|
||||
return Long.MAX_VALUE; // static (event-invalidated)
|
||||
}
|
||||
|
||||
private boolean isAnyMobSoul(ItemStack stack) {
|
||||
return "Any".equals(ItemNBTHelper.getString(stack, "Name", "Pig"));
|
||||
}
|
||||
|
||||
public void dispose(TilePlacedItem tile) {
|
||||
CacheEntry entry = displayListCache.remove(tile);
|
||||
if (entry != null) GL11.glDeleteLists(entry.listId, 1);
|
||||
}
|
||||
|
||||
private void pruneInvalidEntries() {
|
||||
if (displayListCache.isEmpty()) return;
|
||||
long now = Minecraft.getSystemTime();
|
||||
if (now < nextPruneMs) return;
|
||||
nextPruneMs = now + PRUNE_INTERVAL_MS;
|
||||
|
||||
Iterator<Map.Entry<TilePlacedItem, CacheEntry>> it = displayListCache.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<TilePlacedItem, CacheEntry> entry = it.next();
|
||||
TilePlacedItem tile = entry.getKey();
|
||||
if (tile.isInvalid() || tile.getWorldObj() == null || tile.getStack() == null) {
|
||||
GL11.glDeleteLists(entry.getValue().listId, 1);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAll() {
|
||||
for (CacheEntry entry : displayListCache.values()) {
|
||||
GL11.glDeleteLists(entry.listId, 1);
|
||||
}
|
||||
displayListCache.clear();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderWorldLast(RenderWorldLastEvent event) {
|
||||
pruneInvalidEntries();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onTextureStitch(TextureStitchEvent.Post event) {
|
||||
atlasVersion++;
|
||||
clearAll();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onChunkUnload(ChunkEvent.Unload event) {
|
||||
if (!event.world.isRemote) return;
|
||||
Chunk chunk = event.getChunk();
|
||||
Iterator<Map.Entry<TilePlacedItem, CacheEntry>> it = displayListCache.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<TilePlacedItem, CacheEntry> e = it.next();
|
||||
TilePlacedItem tile = e.getKey();
|
||||
if ((tile.xCoord >> 4) == chunk.xPosition && (tile.zCoord >> 4) == chunk.zPosition) {
|
||||
GL11.glDeleteLists(e.getValue().listId, 1);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldUnload(WorldEvent.Unload event) {
|
||||
if (!event.world.isRemote) return;
|
||||
clearAll();
|
||||
}
|
||||
|
||||
public static class CacheEntry {
|
||||
|
||||
public final int listId;
|
||||
public final ItemStack stack;
|
||||
public final int stackSize;
|
||||
public final int meta;
|
||||
public final float rotation;
|
||||
public final long ttlMs;
|
||||
public final boolean mobSoul;
|
||||
public final int atlasVersion;
|
||||
private long lastCompileMs;
|
||||
|
||||
private CacheEntry(int listId, ItemStack stack, int stackSize, int meta, float rotation, long ttlMs,
|
||||
boolean mobSoul, int atlasVersion) {
|
||||
this.listId = listId;
|
||||
this.stack = stack;
|
||||
this.stackSize = stackSize;
|
||||
this.meta = meta;
|
||||
this.rotation = rotation;
|
||||
this.ttlMs = ttlMs;
|
||||
this.mobSoul = mobSoul;
|
||||
this.atlasVersion = atlasVersion;
|
||||
this.lastCompileMs = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private boolean isValid(ItemStack stack, int meta, float rotation, int atlasVersion) {
|
||||
// checking the pointer of the stack is enough
|
||||
return this.stack == stack && this.stackSize == stack.stackSize
|
||||
&& this.meta == meta
|
||||
&& this.rotation == rotation
|
||||
&& this.atlasVersion == atlasVersion;
|
||||
}
|
||||
|
||||
private boolean needsRefresh() {
|
||||
return ttlMs != Long.MAX_VALUE && System.currentTimeMillis() - lastCompileMs >= ttlMs;
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-4
@@ -14,6 +14,8 @@ import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.brandon3055.draconicevolution.client.render.item.RenderMobSoul;
|
||||
import com.brandon3055.draconicevolution.client.render.tile.PlacedItemDisplayListCache.CacheEntry;
|
||||
import com.brandon3055.draconicevolution.common.items.MobSoul;
|
||||
import com.brandon3055.draconicevolution.common.tileentities.TilePlacedItem;
|
||||
|
||||
@@ -22,16 +24,33 @@ import com.brandon3055.draconicevolution.common.tileentities.TilePlacedItem;
|
||||
*/
|
||||
public class RenderTilePlacedItem extends TileEntitySpecialRenderer {
|
||||
|
||||
private static final float MOBSOUL_CENTER_X = 0.5F;
|
||||
private static final float MOBSOUL_CENTER_Y = 0.3F;
|
||||
private static final float MOBSOUL_CENTER_Z = 0.5F;
|
||||
|
||||
private final EntityItem cachedEntity = new EntityItem(null, 0, 0, 0, new ItemStack(Items.apple));
|
||||
private final PlacedItemDisplayListCache displayListCache = new PlacedItemDisplayListCache();
|
||||
|
||||
@Override
|
||||
public void renderTileEntityAt(TileEntity te, double x, double y, double z, float timeSinceLastTick) {
|
||||
if (!(te instanceof TilePlacedItem tile)) return;
|
||||
if (tile.getStack() == null) return;
|
||||
ItemStack stack = tile.getStack();
|
||||
if (stack == null) {
|
||||
displayListCache.dispose(tile);
|
||||
return;
|
||||
}
|
||||
if (tile.getWorldObj() == null) return;
|
||||
int meta = tile.getWorldObj().getBlockMetadata(tile.xCoord, tile.yCoord, tile.zCoord);
|
||||
CacheEntry entry = displayListCache.getOrCompile(tile, stack, meta, () -> renderItem(tile));
|
||||
GL11.glPushMatrix();
|
||||
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
|
||||
GL11.glTranslated(x, y, z);
|
||||
renderItem(tile);
|
||||
if (entry.mobSoul) {
|
||||
GL11.glTranslated(MOBSOUL_CENTER_X, MOBSOUL_CENTER_Y, MOBSOUL_CENTER_Z);
|
||||
GL11.glRotatef(RenderMobSoul.getRotationAngle(), 0F, 1F, 0F);
|
||||
GL11.glTranslated(-MOBSOUL_CENTER_X, -MOBSOUL_CENTER_Y, -MOBSOUL_CENTER_Z);
|
||||
}
|
||||
GL11.glCallList(entry.listId);
|
||||
GL11.glPopAttrib();
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
@@ -39,7 +58,6 @@ public class RenderTilePlacedItem extends TileEntitySpecialRenderer {
|
||||
public void renderItem(TilePlacedItem tile) {
|
||||
ItemStack stack = tile.getStack();
|
||||
int meta = tile.getWorldObj().getBlockMetadata(tile.xCoord, tile.yCoord, tile.zCoord);
|
||||
// itemEntity.getEntityItem().stackSize = 1;
|
||||
final Item item = stack.getItem();
|
||||
boolean is3D = item.isFull3D();
|
||||
boolean isBlock = item instanceof ItemBlock;
|
||||
@@ -58,7 +76,7 @@ public class RenderTilePlacedItem extends TileEntitySpecialRenderer {
|
||||
GL11.glRotatef(tile.rotation, 0F, 0F, 1F);
|
||||
GL11.glTranslatef(0.0F, -0.21F, 0.0F);
|
||||
} else if (item instanceof MobSoul) {
|
||||
GL11.glTranslatef(0.5F, 0.3F, 0.5F);
|
||||
GL11.glTranslatef(MOBSOUL_CENTER_X, MOBSOUL_CENTER_Y, MOBSOUL_CENTER_Z);
|
||||
} else {
|
||||
GL11.glRotatef(90F, -1F, 0F, 0F);
|
||||
GL11.glTranslatef(0.5F, -0.65F, 0.02F);
|
||||
|
||||
+11
@@ -7,6 +7,7 @@ import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.Vec3;
|
||||
|
||||
import com.brandon3055.draconicevolution.common.ModBlocks;
|
||||
@@ -20,6 +21,16 @@ public class TilePlacedItem extends TileEntity {
|
||||
public ItemStack stack;
|
||||
public float rotation = 0F;
|
||||
private boolean hasUpdated = false;
|
||||
private AxisAlignedBB renderBoundingBox;
|
||||
|
||||
@Override
|
||||
public AxisAlignedBB getRenderBoundingBox() {
|
||||
if (renderBoundingBox == null) {
|
||||
renderBoundingBox = AxisAlignedBB
|
||||
.getBoundingBox(xCoord - 2, yCoord - 2, zCoord - 2, xCoord + 2, yCoord + 2, zCoord + 2);
|
||||
}
|
||||
return renderBoundingBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEntity() {
|
||||
|
||||
Reference in new issue
Block a user