Compare commits

...
6 Commits
12 changed files with 225 additions and 23 deletions

No files matched your search

@@ -1991,7 +1991,9 @@ public class GLStateManager {
}
RENDER_BACKEND.bindTexture(GL11.GL_TEXTURE_2D, id);
RENDER_BACKEND.texParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, 0);
suspendPixelUnpackBuffer();
RENDER_BACKEND.texImage2D(GL11.GL_TEXTURE_2D, 0, GL30.GL_R8, 1, 1, 0, GL11.GL_RED, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null);
restorePixelUnpackBuffer();
// Restore previous binding on active unit
RENDER_BACKEND.bindTexture(GL11.GL_TEXTURE_2D, savedBinding == id ? 0 : savedBinding);
@@ -4964,25 +4966,25 @@ public class GLStateManager {
RENDER_BACKEND.bindBuffer(target, buffer);
}
private static void suspendPixelUnpackBuffer() {
static void suspendPixelUnpackBuffer() {
if (boundPixelUnpackBuffer != 0) {
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
}
}
private static void restorePixelUnpackBuffer() {
static void restorePixelUnpackBuffer() {
if (boundPixelUnpackBuffer != 0) {
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, boundPixelUnpackBuffer);
}
}
private static void suspendPixelPackBuffer() {
static void suspendPixelPackBuffer() {
if (boundPixelPackBuffer != 0) {
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
}
}
private static void restorePixelPackBuffer() {
static void restorePixelPackBuffer() {
if (boundPixelPackBuffer != 0) {
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_PACK_BUFFER, boundPixelPackBuffer);
}
@@ -156,7 +156,9 @@ public class RenderSystem {
public static void texImage2D(int texture, int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable ByteBuffer pixels) {
GLStateManager.glBindTexture(target, texture);
GLStateManager.suspendPixelUnpackBuffer();
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
GLStateManager.restorePixelUnpackBuffer();
if (target == GL11.GL_TEXTURE_2D && level == 0) {
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
}
@@ -225,29 +227,41 @@ public class RenderSystem {
}
public static void textureImage2D(int texture, int target, int level, int internalformat, int width, int height, int border, int format, int type, ByteBuffer pixels) {
GLStateManager.suspendPixelUnpackBuffer();
dsaState.textureImage2D(texture, target, level, internalformat, width, height, border, format, type, pixels);
GLStateManager.restorePixelUnpackBuffer();
}
public static void textureImage2D(int texture, int target, int level, int internalformat, int width, int height, int border, int format, int type, IntBuffer pixels) {
GLStateManager.suspendPixelUnpackBuffer();
dsaState.textureImage2D(texture, target, level, internalformat, width, height, border, format, type, pixels);
GLStateManager.restorePixelUnpackBuffer();
}
public static void textureSubImage2D(int texture, int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer pixels) {
GLStateManager.suspendPixelUnpackBuffer();
dsaState.textureSubImage2D(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);
GLStateManager.restorePixelUnpackBuffer();
}
public static void textureSubImage2D(int texture, int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer pixels) {
GLStateManager.suspendPixelUnpackBuffer();
dsaState.textureSubImage2D(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);
GLStateManager.restorePixelUnpackBuffer();
}
public static void texImage1D(int texture, int target, int level, int internalformat, int width, int border, int format, int type, ByteBuffer pixels) {
RENDER_BACKEND.bindTexture(target, texture);
GLStateManager.suspendPixelUnpackBuffer();
RENDER_BACKEND.texImage1D(target, level, internalformat, width, border, format, type, pixels);
GLStateManager.restorePixelUnpackBuffer();
}
public static void texImage3D(int texture, int target, int level, int internalformat, int width, int height, int depth, int border, int format, int type, ByteBuffer pixels) {
RENDER_BACKEND.bindTexture(target, texture);
GLStateManager.suspendPixelUnpackBuffer();
RENDER_BACKEND.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
GLStateManager.restorePixelUnpackBuffer();
}
public static String getProgramInfoLog(int program) {
@@ -271,7 +285,9 @@ public class RenderSystem {
}
public static void readPixels(int x, int y, int width, int height, int format, int type, FloatBuffer pixels) {
GLStateManager.suspendPixelPackBuffer();
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
GLStateManager.restorePixelPackBuffer();
}
public static void bufferData(int target, FloatBuffer data, int usage) {
@@ -7,6 +7,7 @@ import com.gtnewhorizons.angelica.glsm.states.LightState;
import com.gtnewhorizons.angelica.glsm.states.MaterialState;
import com.gtnewhorizons.angelica.glsm.states.TexGenState;
import com.gtnewhorizons.angelica.glsm.hooks.GLSMConfig;
import org.joml.Math;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector4f;
@@ -42,8 +43,8 @@ public class Uniforms {
private final org.joml.Vector3f tempVec3 = new org.joml.Vector3f();
// Pre-computed constants for fog params (Mesa STATE_FOG_PARAMS_OPTIMIZED)
private static final double LN2 = Math.log(2.0);
private static final double SQRT_LN2 = Math.sqrt(LN2);
private static final double LN2 = java.lang.Math.log(2.0);
private static final double SQRT_LN2 = java.lang.Math.sqrt(LN2);
// Dirty tracking: last-uploaded generation per category + program ID.
// Program change forces full re-upload since uniform locations differ.
@@ -315,10 +316,10 @@ public class Uniforms {
// Upload the current color from GLSM
final var color = GLStateManager.getColor();
vec4Buf.clear();
vec4Buf.put(color.getRed());
vec4Buf.put(color.getGreen());
vec4Buf.put(color.getBlue());
vec4Buf.put(color.getAlpha());
vec4Buf.put(Math.clamp(0f, 1f, color.getRed()));
vec4Buf.put(Math.clamp(0f, 1f, color.getGreen()));
vec4Buf.put(Math.clamp(0f, 1f, color.getBlue()));
vec4Buf.put(Math.clamp(0f, 1f, color.getAlpha()));
vec4Buf.flip();
RENDER_BACKEND.uniform4(program.locCurrentColor, vec4Buf);
}
@@ -8,7 +8,6 @@ import com.gtnewhorizons.angelica.loading.fml.compat.handlers.ThaumcraftCompatHa
import com.gtnewhorizons.angelica.loading.fml.compat.handlers.ThaumicHorizonsCompatHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
@@ -45,20 +44,19 @@ public enum CompatHandlers {
/**
* Returns extra transformers as well as the main transformer.
* Returns an empty list if no handlers registered.
*/
public static List<String> getTransformers() {
final List<ICompatHandler> handlers = getHandlers();
if (handlers.isEmpty()) {
return Collections.emptyList();
}
List<String> transformers = new ArrayList<>();
List<String> transformers = new ArrayList<>();
for (ICompatHandler handler : handlers) {
if (handler.extraTransformers() != null) {
transformers.addAll(handler.extraTransformers());
}
}
transformers.add("com.gtnewhorizons.angelica.loading.fml.transformers.GenericCompatTransformer");
if (!handlers.isEmpty()) {
transformers.add("com.gtnewhorizons.angelica.loading.fml.transformers.GenericCompatTransformer");
}
transformers.add("com.gtnewhorizons.angelica.loading.fml.transformers.IsbrhTessellatorAbuseClassTransformer");
return transformers;
}
}
@@ -0,0 +1,93 @@
package com.gtnewhorizons.angelica.loading.fml.transformers;
import com.gtnewhorizons.angelica.loading.AngelicaClientTweaker;
import com.gtnewhorizons.angelica.loading.shared.AngelicaClassDump;
import net.minecraft.launchwrapper.IClassTransformer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
public class IsbrhTessellatorAbuseClassTransformer implements IClassTransformer {
private static final Logger LOGGER = LogManager.getLogger("IsbrhTessellatorAbuse");
private static final String ISBRH = "cpw/mods/fml/client/registry/ISimpleBlockRenderingHandler";
private static final String TESSELLATOR = "net/minecraft/client/renderer/Tessellator";
private static final String RENDER_WORLD_BLOCK_DESC = "(Lnet/minecraft/world/IBlockAccess;IIILnet/minecraft/block/Block;ILnet/minecraft/client/renderer/RenderBlocks;)Z";
private final String draw;
private final String startDrawingQuads;
private final String startDrawing;
public IsbrhTessellatorAbuseClassTransformer() {
this(AngelicaClientTweaker.isObfEnv());
}
public IsbrhTessellatorAbuseClassTransformer(boolean isObf) {
this.draw = isObf ? "func_78381_a" : "draw";
this.startDrawingQuads = isObf ? "func_78382_b" : "startDrawingQuads";
this.startDrawing = isObf ? "func_78371_b" : "startDrawing";
}
public boolean shouldTransform(byte[] classBytes) {
final ClassReader cr = new ClassReader(classBytes);
for (String iface : cr.getInterfaces()) {
if (ISBRH.equals(iface)) return true;
}
return false;
}
public boolean transformClassNode(String transformedName, ClassNode cn) {
boolean changed = false;
for (MethodNode mn : cn.methods) {
if (!"renderWorldBlock".equals(mn.name) || !RENDER_WORLD_BLOCK_DESC.equals(mn.desc)) continue;
for (AbstractInsnNode insn : mn.instructions.toArray()) {
if (!(insn instanceof MethodInsnNode min) || min.getOpcode() != Opcodes.INVOKEVIRTUAL || !TESSELLATOR.equals(min.owner)) continue;
final int popOp;
final boolean pushIntResult;
if (min.name.equals(draw) && "()I".equals(min.desc)) {
popOp = Opcodes.POP;
pushIntResult = true;
} else if (min.name.equals(startDrawingQuads) && "()V".equals(min.desc)) {
popOp = Opcodes.POP;
pushIntResult = false;
} else if (min.name.equals(startDrawing) && "(I)V".equals(min.desc)) {
popOp = Opcodes.POP2;
pushIntResult = false;
} else {
continue;
}
mn.instructions.insertBefore(insn, new InsnNode(popOp));
if (pushIntResult) mn.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_0));
mn.instructions.remove(insn);
LOGGER.info("Stripped Tessellator.{} from {}#renderWorldBlock", min.name, cn.name);
changed = true;
}
}
return changed;
}
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if (basicClass == null || !shouldTransform(basicClass)) return basicClass;
final ClassReader cr = new ClassReader(basicClass);
final ClassNode cn = new ClassNode();
cr.accept(cn, 0);
if (!transformClassNode(transformedName, cn)) return basicClass;
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
final byte[] bytes = cw.toByteArray();
AngelicaClassDump.dumpClass(transformedName, basicClass, bytes, this);
return bytes;
}
}
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.loading.rfb;
import com.gtnewhorizons.angelica.loading.rfb.transformers.RFBAngelicaRedirector;
import com.gtnewhorizons.angelica.loading.rfb.transformers.RFBCeleritasBlockTransformer;
import com.gtnewhorizons.angelica.loading.rfb.transformers.RFBIsbrhTessellatorAbuseTransformer;
import com.gtnewhorizons.retrofuturabootstrap.api.PluginContext;
import com.gtnewhorizons.retrofuturabootstrap.api.RetroFuturaBootstrap;
import com.gtnewhorizons.retrofuturabootstrap.api.RfbClassTransformer;
@@ -28,7 +29,8 @@ public class AngelicaRfbPlugin implements RfbPlugin {
final boolean isObf = RetroFuturaBootstrap.API.launchClassLoader().findClassMetadata("net.minecraft.world.World") == null;
return new RfbClassTransformer[] {
new RFBAngelicaRedirector(),
new RFBCeleritasBlockTransformer(isObf)
new RFBCeleritasBlockTransformer(isObf),
new RFBIsbrhTessellatorAbuseTransformer(isObf)
};
}
}
@@ -0,0 +1,54 @@
package com.gtnewhorizons.angelica.loading.rfb.transformers;
import com.gtnewhorizons.angelica.loading.fml.transformers.IsbrhTessellatorAbuseClassTransformer;
import com.gtnewhorizons.angelica.loading.shared.AngelicaClassDump;
import com.gtnewhorizons.retrofuturabootstrap.api.ClassNodeHandle;
import com.gtnewhorizons.retrofuturabootstrap.api.ExtensibleClassLoader;
import com.gtnewhorizons.retrofuturabootstrap.api.RfbClassTransformer;
import org.intellij.lang.annotations.Pattern;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.jar.Manifest;
/** RfbClassTransformer wrapper for {@link IsbrhTessellatorAbuseClassTransformer} */
public class RFBIsbrhTessellatorAbuseTransformer implements RfbClassTransformer {
private final IsbrhTessellatorAbuseClassTransformer inner;
public RFBIsbrhTessellatorAbuseTransformer(boolean isObf) {
inner = new IsbrhTessellatorAbuseClassTransformer(isObf);
}
@Pattern("[a-z0-9-]+")
@Override
public @NotNull String id() {
return "isbrh-tessellator-abuse";
}
@Override
public @NotNull String @Nullable [] sortAfter() {
return new String[] {"*", "mixin:mixin"};
}
@Override
public @NotNull String @Nullable [] sortBefore() {
return new String[] {"lwjgl3ify:redirect"};
}
@Override
public boolean shouldTransformClass(@NotNull ExtensibleClassLoader classLoader,
@NotNull RfbClassTransformer.Context context, @Nullable Manifest manifest, @NotNull String className,
@NotNull ClassNodeHandle classNode) {
if (!classNode.isPresent()) return false;
return inner.shouldTransform(classNode.getOriginalBytes());
}
@Override
public void transformClass(@NotNull ExtensibleClassLoader classLoader, @NotNull RfbClassTransformer.Context context,
@Nullable Manifest manifest, @NotNull String className, @NotNull ClassNodeHandle classNode) {
if (inner.transformClassNode(className, classNode.getNode())) {
classNode.computeMaxs();
AngelicaClassDump.dumpRFBClass(className, classNode, this);
}
}
}
@@ -38,6 +38,7 @@ public enum Mixins implements IMixins {
, "angelica.MixinMinecraftServer"
, "angelica.bugfixes.MixinItemRenderer_EdgeDepth"
, "angelica.bugfixes.MixinModelCreeper_AuraBodyInflate"
, "angelica.bugfixes.MixinModelSkeleton_LegPelvisZFight"
, "angelica.bugfixes.MixinModelWither_ArmorCentering"
, "angelica.bugfixes.MixinRenderBlocks_CrossedSquaresNormal"
, "angelica.bugfixes.MixinRenderCreeper_AuraDepth"
@@ -33,6 +33,9 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
public class ReeseSodiumVideoOptionsScreen extends SodiumOptionsGUI {
private static final float ASPECT_RATIO = 5f / 4f;
private static final int MINIMUM_WIDTH = 550;
@Nullable
private Element focused;
@@ -88,10 +91,10 @@ public class ReeseSodiumVideoOptionsScreen extends SodiumOptionsGUI {
protected BasicFrame.Builder parentFrameBuilder() {
final BasicFrame.Builder basicFrameBuilder;
// Calculates if resolution exceeds 16:9 ratio, force 16:9
// Clamp width on wide screens
int newWidth = this.width;
if ((float) this.width / (float) this.height > 1.77777777778) {
newWidth = (int) (this.height * 1.77777777778);
if (this.width > MINIMUM_WIDTH && (float) this.width / (float) this.height > ASPECT_RATIO) {
newWidth = Math.max(MINIMUM_WIDTH, (int) (this.height * ASPECT_RATIO));
}
final Dim2i basicFrameDim = new Dim2i((this.width - newWidth) / 2, 0, newWidth, this.height);
@@ -0,0 +1,31 @@
package com.gtnewhorizons.angelica.mixins.early.angelica.bugfixes;
import net.minecraft.client.model.ModelSkeleton;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Prevents z-fighting between the skeleton's leg tops and the pelvis (bipedBody) bottom face.
*/
@Mixin(ModelSkeleton.class)
public class MixinModelSkeleton_LegPelvisZFight {
@Unique
private static final float LEG_PIVOT_Y = Float.intBitsToFloat(Float.floatToIntBits(12.0F) + 128);
@Inject(
method = "setRotationAngles(FFFFFFLnet/minecraft/entity/Entity;)V",
at = @At("TAIL")
)
private void angelica$nudgeLegsBelowPelvis(float swing, float swingAmount, float ticks,
float headYaw, float headPitch, float scale,
Entity entity, CallbackInfo ci) {
final ModelSkeleton self = (ModelSkeleton) (Object) this;
self.bipedRightLeg.rotationPointY = LEG_PIVOT_Y;
self.bipedLeftLeg.rotationPointY = LEG_PIVOT_Y;
}
}
@@ -19,8 +19,9 @@ public class MixinEntityRenderer {
private void updateDynamicLights(float p_78471_1_, long p_78471_2_, CallbackInfo ci) {
IDynamicLightWorldRenderer renderer = DynamicLights.getActiveRenderer();
if (renderer != null && renderer.isActive()) {
mc.mcProfiler.endStartSection("angelica_dynamic_lighting");
mc.mcProfiler.startSection("angelica_dynamic_lighting");
DynamicLights.get().updateAll(renderer);
mc.mcProfiler.endSection();
}
}
}
@@ -151,7 +151,7 @@ public abstract class MixinRenderBlocks {
private boolean handleISBRHException(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 | ArrayIndexOutOfBoundsException e) {
} catch (Exception e) {
CTMUtils.clearCurrentCompact();
// Render Error Block
int meta = exceptionErrorBlockMap.getOrDefault(e.getClass(), 0);