Fix crash when in replay with Optifine 1.12.2 DX (fixes #120)

Re-creating the RenderChunk lost any custom data Optifine had in them which
resulted in NPEs.
The reason we re-create the RenderChunks is because otherwise, once it's
assigned an empty chunk once, it's not getting any further update even when
moving back to filled chunks. Since just calling setNeedsUpdate works as well,
this commit changes the whole mixin to doing that instead.
This commit is contained in:
Jonas Herzig
2018-06-09 23:45:22 +02:00
parent efaa5b7c41
commit 62d2ce4b37

View File

@@ -1,17 +1,11 @@
//#if MC>=10800 //#if MC>=10800
package com.replaymod.replay.mixin; package com.replaymod.replay.mixin;
import com.replaymod.replay.ReplayModReplay;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.ViewFrustum; import net.minecraft.client.renderer.ViewFrustum;
import net.minecraft.client.renderer.chunk.IRenderChunkFactory;
import net.minecraft.client.renderer.chunk.RenderChunk; import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//#if MC>=10904 //#if MC>=10904
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@@ -19,77 +13,24 @@ import net.minecraft.util.math.BlockPos;
//$$ import net.minecraft.util.BlockPos; //$$ import net.minecraft.util.BlockPos;
//#endif //#endif
import static com.replaymod.core.versions.MCVer.*;
@Mixin(ViewFrustum.class) @Mixin(ViewFrustum.class)
public abstract class MixinViewFrustum { public abstract class MixinViewFrustum {
private IRenderChunkFactory renderChunkFactory; @Redirect(method = "updateChunkPositions", at=@At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/chunk/RenderChunk;setPosition(III)V"))
private void replayModReplay_updatePositionAndMarkForUpdate(RenderChunk renderChunk, int x, int y, int z) {
@Shadow protected RenderGlobal renderGlobal; BlockPos pos = new BlockPos(x, y, z);
@Shadow protected World world; if (!pos.equals(renderChunk.getPosition())) {
@Shadow protected int countChunksY; //#if MC>=10904
@Shadow protected int countChunksX; //#if MC>=11100
@Shadow protected int countChunksZ; renderChunk.setPosition(x, y, z);
@Shadow public RenderChunk[] renderChunks; //#else
//$$ renderChunk.setOrigin(x, y, z);
@Inject(method = "<init>", at = @At("RETURN")) //#endif
private void setRenderChunkFactory(World a1, int a2, RenderGlobal a3, IRenderChunkFactory rcf, CallbackInfo ci) { renderChunk.setNeedsUpdate(false);
this.renderChunkFactory = rcf; //#else
} //$$ renderChunk.setPosition(pos);
//$$ renderChunk.setNeedsUpdate(true);
/** //#endif
* Instead of updating its position, we recreate the render chunk
* which seems to solve the problem that chunks are invisible when you leave an area and return
* to it.
* Any better fixes are welcome.
* Note: Most of this code is copied from {@link ViewFrustum#updateChunkPositions(double, double)}
*/
@Inject(method = "updateChunkPositions", at = @At("HEAD"), cancellable = true)
public void fixedUpdateChunkPositions(double viewEntityX, double viewEntityZ, CallbackInfo ci) {
if (ReplayModReplay.instance.getReplayHandler() == null) {
return;
} }
int i = floor(viewEntityX) - 8;
int j = floor(viewEntityZ) - 8;
int k = this.countChunksX * 16;
for (int l = 0; l < this.countChunksX; ++l) {
int i1 = this.getBaseCoordinate(i, k, l);
for (int j1 = 0; j1 < this.countChunksZ; ++j1) {
int k1 = this.getBaseCoordinate(j, k, j1);
for (int l1 = 0; l1 < this.countChunksY; ++l1) {
int i2 = l1 * 16;
RenderChunk renderchunk = this.renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l];
BlockPos blockpos = new BlockPos(i1, i2, k1);
if (!blockpos.equals(renderchunk.getPosition())) {
// Recreate render chunk instead of setting its position
//#if MC>=10904
(renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l] =
renderChunkFactory.create(world, renderGlobal, 0)
//#if MC>= 11100
).setPosition(blockpos.getX(), blockpos.getY(), blockpos.getZ());
//#else
//$$ ).setOrigin(blockpos.getX(), blockpos.getY(), blockpos.getZ());
//#endif
//#else
//$$ renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l] =
//$$ renderChunkFactory.makeRenderChunk(world, renderGlobal, blockpos, 0);
//#endif
}
}
}
}
ci.cancel();
} }
//#if MC>=10904
@Shadow abstract int getBaseCoordinate(int p_178157_1_, int p_178157_2_, int p_178157_3_);
//#else
//$$ private int getBaseCoordinate(int p_178157_1_, int p_178157_2_, int p_178157_3_) {
//$$ return func_178157_a(p_178157_1_, p_178157_2_, p_178157_3_);
//$$ }
//$$ @Shadow abstract int func_178157_a(int p_178157_1_, int p_178157_2_, int p_178157_3_);
//#endif
} }
//#endif //#endif