Skip to content

Commit

Permalink
Handle FMLRenderAccessLibrary obfuscation properly (#663)
Browse files Browse the repository at this point in the history
* Handle FMLRenderAccessLibrary obfuscation properly

* Add a comment explaining jankness
  • Loading branch information
Cleptomania authored Oct 17, 2024
1 parent 6cf119d commit fd78f63
Showing 1 changed file with 35 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import com.gtnewhorizons.angelica.AngelicaMod;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import cpw.mods.fml.client.registry.RenderingRegistry;
import me.jellysquid.mods.sodium.client.SodiumClientMod;
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.src.FMLRenderAccessLibrary;
import net.minecraft.world.IBlockAccess;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
Expand All @@ -32,17 +32,48 @@ private void renderingByTypeDisable(CallbackInfoReturnable<Boolean> ci) {
this.isRenderingByType = false;
}

/**
* This mixin and the one below(wrapRenderWorldBlockDeobfuscated) achieve the same goal. The goal is to wrap ISBRH rendering in a try/catch
* to ignore NPE, as mods commonly like to not null-guard the tile entity casting, and Sodium introduces a race condition where when a block
* is broken, the TE can be removed from the world before the render thread gets to it, but the block data is deep copied to the thread, so
* it still tries to render the block.
* The reason there's two mixins to the same thing for this, is because FMLRenderAccessLibrary is an old Forge remnant of Optifine compat
* whereby they provided this class for Optifine to be able to access Forge's rendering methods. For some reason, in a deobfuscated environment,
* that class lives in net.minecraft.src.FMLRenderAccessLibrary. However in an obfuscated prod environment, it gets moved into the root unnamed
* package. So basically, only one of these two redirects will actually end up getting applied, and the other will fail, based on what environment
* you're running in.
*/
@Redirect(
method = "renderBlockByRenderType",
at = @At(
value = "INVOKE",
target = "LFMLRenderAccessLibrary;renderWorldBlock(Lnet/minecraft/client/renderer/RenderBlocks;Lnet/minecraft/world/IBlockAccess;IIILnet/minecraft/block/Block;I)Z",
remap = false
),
expect = 0
)
private boolean wrapRenderWorldBlockObfuscated(RenderBlocks rb, IBlockAccess world, int x, int y, int z, Block block, int modelId) {
try {
return RenderingRegistry.instance().renderWorldBlock(rb, world, x, y, z, block, modelId);
} catch (NullPointerException ignored) {
rb.renderStandardBlock(AngelicaMod.blockError, x, y, z);
}
return false;
}

@Redirect(
method = "renderBlockByRenderType",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/src/FMLRenderAccessLibrary;renderWorldBlock(Lnet/minecraft/client/renderer/RenderBlocks;Lnet/minecraft/world/IBlockAccess;IIILnet/minecraft/block/Block;I)Z",
remap = false
)
),
expect = 0
)
private boolean wrapRenderWorldBlock(RenderBlocks rb, IBlockAccess world, int x, int y, int z, Block block, int modelId) {
private boolean wrapRenderWorldBlockDeobfuscated(RenderBlocks rb, IBlockAccess world, int x, int y, int z, Block block, int modelId) {
try {
return FMLRenderAccessLibrary.renderWorldBlock(rb, world, x, y, z, block, modelId);
return RenderingRegistry.instance().renderWorldBlock(rb, world, x, y, z, block, modelId);
} catch (NullPointerException ignored) {
rb.renderStandardBlock(AngelicaMod.blockError, x, y, z);
}
Expand Down

0 comments on commit fd78f63

Please sign in to comment.