Use ASM instead of inheritance to override methods in RenderGlobal
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package eu.crushedpixel.replaymod.renderer;
|
||||
|
||||
import eu.crushedpixel.replaymod.utils.JailingQueue;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RegionRenderCacheBuilder;
|
||||
import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator;
|
||||
@@ -12,31 +11,23 @@ import net.minecraft.client.renderer.culling.ICamera;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class ChunkLoadingRenderGlobal extends RenderGlobal {
|
||||
public static void install(Minecraft mc) {
|
||||
RenderGlobal org = mc.renderGlobal;
|
||||
if (org instanceof ChunkLoadingRenderGlobal) {
|
||||
((ChunkLoadingRenderGlobal) org).uninstall();
|
||||
}
|
||||
mc.renderGlobal = new ChunkLoadingRenderGlobal(mc);
|
||||
}
|
||||
public class ChunkLoadingRenderGlobal {
|
||||
|
||||
private final RenderGlobal originalRenderGlobal;
|
||||
private final RenderGlobal hooked;
|
||||
private final ChunkRenderDispatcher renderDispatcher;
|
||||
private final JailingQueue<?> workerJailingQueue;
|
||||
private final CustomChunkRenderWorker renderWorker;
|
||||
private int frame;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ChunkLoadingRenderGlobal(Minecraft mc) {
|
||||
super(mc);
|
||||
this.originalRenderGlobal = mc.renderGlobal;
|
||||
public ChunkLoadingRenderGlobal(RenderGlobal renderGlobal) {
|
||||
this.hooked = renderGlobal;
|
||||
this.renderDispatcher = renderGlobal.renderDispatcher;
|
||||
this.renderWorker = new CustomChunkRenderWorker(renderDispatcher, new RegionRenderCacheBuilder());
|
||||
if (mc.theWorld != null) {
|
||||
setWorldAndLoadRenderers(mc.theWorld);
|
||||
}
|
||||
|
||||
int workerThreads = renderDispatcher.listThreadedWorkers.size();
|
||||
BlockingQueue<Object> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
|
||||
@@ -49,27 +40,35 @@ public class ChunkLoadingRenderGlobal extends RenderGlobal {
|
||||
}
|
||||
workerJailingQueue.jail(workerThreads);
|
||||
renderDispatcher.queueChunkUpdates = queueChunkUpdates;
|
||||
|
||||
try {
|
||||
Field hookField = RenderGlobal.class.getField("hook");
|
||||
hookField.set(hooked, this);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new Error(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unused") // Method called by ASM hook
|
||||
public void setupTerrain(Entity viewEntity, double partialTicks, ICamera camera, int frameCount, boolean playerSpectator) {
|
||||
// There has to be a better way to force minecraft into queueing all chunks at once
|
||||
// Someone should probably find and implement it!
|
||||
do {
|
||||
super.setupTerrain(viewEntity, partialTicks, camera, frame++, playerSpectator);
|
||||
} while (displayListEntitiesDirty);
|
||||
original_setupTerrain(viewEntity, partialTicks, camera, frame++, playerSpectator);
|
||||
} while (hooked.displayListEntitiesDirty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPositionInRenderChunk(BlockPos p_174983_1_, RenderChunk p_174983_2_) {
|
||||
@SuppressWarnings("unused") // Method called by ASM hook
|
||||
public boolean isPositionInRenderChunk(BlockPos pos, RenderChunk chunk) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "unused"}) // Method called by ASM hook
|
||||
public void updateChunks(long finishTimeNano) {
|
||||
while (renderDispatcher.runChunkUploads(0)) {
|
||||
displayListEntitiesDirty = true;
|
||||
hooked.displayListEntitiesDirty = true;
|
||||
}
|
||||
|
||||
while (!renderDispatcher.queueChunkUpdates.isEmpty()) {
|
||||
@@ -78,7 +77,7 @@ public class ChunkLoadingRenderGlobal extends RenderGlobal {
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
|
||||
Iterator<RenderChunk> iterator = chunksToUpdate.iterator();
|
||||
Iterator<RenderChunk> iterator = hooked.chunksToUpdate.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
RenderChunk renderchunk = iterator.next();
|
||||
|
||||
@@ -89,9 +88,33 @@ public class ChunkLoadingRenderGlobal extends RenderGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void original_setupTerrain(Entity viewEntity, double partialTicks, ICamera camera, int frameCount, boolean playerSpectator) {
|
||||
// Method body generated by ASM
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private boolean original_isPositionInRenderChunk(BlockPos pos, RenderChunk chunk) {
|
||||
// Method body generated by ASM
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void original_updateChunks(long finishTimeNano) {
|
||||
// Method body generated by ASM
|
||||
}
|
||||
|
||||
public void uninstall() {
|
||||
workerJailingQueue.freeAll();
|
||||
Minecraft.getMinecraft().renderGlobal = originalRenderGlobal;
|
||||
|
||||
try {
|
||||
Field hookField = RenderGlobal.class.getField("hook");
|
||||
hookField.set(hooked, null);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new Error(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user