Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ Available in flavors [**Cleanroom**](https://www.curseforge.com/minecraft/modpac
* **Mob Despawning Improvement:** Mobs carrying picked up items will despawn properly (and optionally drop their equipment)
* **Mob Griefing:** Controls mob griefing through customizable lists
* **Mob Spawning Light Level:** Sets the maximum light level for hostile mobs to spawn
* * **Modern Debug Render:** Aligns the chunk border (F3+G) and hitbox (F3+B) overlays with Minecraft 1.21.1+
* **Modern Knockback:** Backports 1.16+ knockback to 1.12: Knockback resistance is now a scale instead of a probability
* **More Banner Layers:** Sets the amount of applicable pattern layers for banners
* **Music Control:** Enables various music playback control tweaks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,11 @@ public static class MiscCategory
})
public int utLinearXP = 0;

@Config.RequiresMcRestart
@Config.Name("Modern Debug Render")
@Config.Comment("Aligns the chunk border (F3+G) and hitbox (F3+B) overlays with Minecraft 1.21.1+")
public boolean utModernDebugRenderToggle = true;

@Config.RequiresMcRestart
@Config.Name("More Banner Layers")
@Config.Comment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ public class UTLoadingPlugin implements IFMLLoadingPlugin, IEarlyMixinLoader
put("mixins/tweaks/mixins.misc.hotbarscroll.json", c -> UTConfigTweaks.MISC.utDisableHotbarScrollWrapping);
put("mixins/tweaks/mixins.misc.lightning.flash.json", c -> UTConfigTweaks.MISC.LIGHTNING.utLightningFlashToggle);
put("mixins/tweaks/mixins.misc.gui.mainmenu.json", c -> UTConfigTweaks.MISC.utReturnToMainMenu);
put("mixins/tweaks/mixins.misc.moderndebugrender.json", c -> UTConfigTweaks.MISC.utModernDebugRenderToggle);
put("mixins/tweaks/mixins.misc.music.json", c -> UTConfigTweaks.MISC.MUSIC.utMusicControlToggle);
put("mixins/tweaks/mixins.misc.narrator.json", c -> UTConfigTweaks.MISC.utDisableNarratorToggle);
put("mixins/tweaks/mixins.misc.narratorkeybind.json", c -> UTConfigTweaks.MISC.utUseCustomNarratorKeybind);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender;

import javax.annotation.Nullable;

import org.lwjgl.opengl.GL11;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;

public class UTModernDebugRender
{
public static final float STROKE_WIDTH = 2.5F;
public static final float THICK_WIDTH = 4.0F;
public static final float THIN_WIDTH = 1.0F;

@Nullable
public static Vec3d cameraPos(float partialTicks)
{
Entity camera = Minecraft.getMinecraft().getRenderViewEntity();
if (camera == null) return null;
return new Vec3d(
camera.lastTickPosX + (camera.posX - camera.lastTickPosX) * partialTicks,
camera.lastTickPosY + (camera.posY - camera.lastTickPosY) * partialTicks,
camera.lastTickPosZ + (camera.posZ - camera.lastTickPosZ) * partialTicks);
}

// Start of the 16 block cell the coordinate falls into, relative to the coordinate itself
public static double sectionOrigin(double coord)
{
return (MathHelper.floor(coord) >> 4 << 4) - coord;
}

public static void drawArrowHead(Vec3d start, Vec3d end, float red, float green, float blue)
{
Vec3d shaft = end.subtract(start);
double length = shaft.length();
if (length < 1.0E-5D) return;

Vec3d forward = shaft.scale(1.0D / length);
double barb = MathHelper.clamp(length * 0.1D, 0.1D, 1.0D);
// The seed only has to be non-parallel to the shaft to yield a usable perpendicular
Vec3d seed = Math.abs(forward.y) > 0.999D ? new Vec3d(1.0D, 0.0D, 0.0D) : new Vec3d(0.0D, 1.0D, 0.0D);
Vec3d sideA = forward.crossProduct(seed).normalize().scale(barb);
// forward is unit length and perpendicular to sideA, so this product is already barb long
Vec3d sideB = forward.crossProduct(sideA);
Vec3d base = end.subtract(forward.scale(barb));

Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
addLine(buffer, base.add(sideA), end, red, green, blue);
addLine(buffer, base.subtract(sideA), end, red, green, blue);
addLine(buffer, base.add(sideB), end, red, green, blue);
addLine(buffer, base.subtract(sideB), end, red, green, blue);
tessellator.draw();
}

public static void drawPoint(double x, double y, double z, float red, float green, float blue)
{
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
GL11.glPointSize(2.0F);
buffer.begin(GL11.GL_POINTS, DefaultVertexFormats.POSITION_COLOR);
buffer.pos(x, y, z).color(red, green, blue, 1.0F).endVertex();
tessellator.draw();
GL11.glPointSize(1.0F);
}

private static void addLine(BufferBuilder buffer, Vec3d start, Vec3d end, float red, float green, float blue)
{
buffer.pos(start.x, start.y, start.z).color(red, green, blue, 1.0F).endVertex();
buffer.pos(end.x, end.y, end.z).color(red, green, blue, 1.0F).endVertex();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender.mixin;

import org.lwjgl.opengl.GL11;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.debug.DebugRendererChunkBorder;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;

import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalDoubleRef;
import mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender.UTModernDebugRender;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;

@Mixin(DebugRendererChunkBorder.class)
public abstract class UTChunkBorderMixin
{
// Interpolated camera Y. The X and Z it is derived from are dead once the two origins below are stored.
@ModifyVariable(method = "render", at = @At("STORE"), ordinal = 1)
private double utCameraY(double original, @Local(argsOnly = true) float partialTicks, @Share("utCameraY") LocalDoubleRef shared)
{
Vec3d camera = UTModernDebugRender.cameraPos(partialTicks);
double value = camera == null ? original : camera.y;
shared.set(value);
return value;
}

@ModifyVariable(method = "render", at = @At("STORE"), ordinal = 5)
private double utOriginX(double original, @Local(argsOnly = true) float partialTicks, @Share("utOriginX") LocalDoubleRef shared)
{
Vec3d camera = UTModernDebugRender.cameraPos(partialTicks);
double value = camera == null ? original : UTModernDebugRender.sectionOrigin(camera.x);
shared.set(value);
return value;
}

@ModifyVariable(method = "render", at = @At("STORE"), ordinal = 6)
private double utOriginZ(double original, @Local(argsOnly = true) float partialTicks, @Share("utOriginZ") LocalDoubleRef shared)
{
Vec3d camera = UTModernDebugRender.cameraPos(partialTicks);
double value = camera == null ? original : UTModernDebugRender.sectionOrigin(camera.z);
shared.set(value);
return value;
}

@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;disableBlend()V"))
private void utKeepBlend()
{
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
}

// Colour calls 0-19 belong to the vertical grids, 20 onwards to the rings and the major lines.
// Only the yellow ones are ours to recolour, so the red and blue passes need no further slicing.
@ModifyArgs(method = "render",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/BufferBuilder;color(FFFF)Lnet/minecraft/client/renderer/BufferBuilder;"),
slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/BufferBuilder;color(FFFF)Lnet/minecraft/client/renderer/BufferBuilder;", ordinal = 19)))
private void utGridCell(Args args, @Local(ordinal = 0) int coord)
{
if (coord % 4 == 0) utCellColor(args);
}

@ModifyArgs(method = "render",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/BufferBuilder;color(FFFF)Lnet/minecraft/client/renderer/BufferBuilder;"),
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/BufferBuilder;color(FFFF)Lnet/minecraft/client/renderer/BufferBuilder;", ordinal = 20)))
private void utRingCell(Args args, @Local(ordinal = 0) int coord)
{
if (coord % 8 == 0) utCellColor(args);
}

@ModifyArg(method = "render",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;glLineWidth(F)V"),
slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;glLineWidth(F)V", ordinal = 1)))
private float utPassWidth(float width)
{
return UTModernDebugRender.THICK_WIDTH;
}

@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/BufferBuilder;pos(DDD)Lnet/minecraft/client/renderer/BufferBuilder;", ordinal = 4), require = 1)
private void utSplitGridBatch(float partialTicks, long finishTimeNano, CallbackInfo ci, @Local(ordinal = 0) Tessellator tess, @Local(ordinal = 0) BufferBuilder buffer)
{
tess.draw();
GlStateManager.glLineWidth(UTModernDebugRender.THIN_WIDTH);
buffer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION_COLOR);
}

@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;draw()V", ordinal = 1, shift = At.Shift.AFTER), require = 1)
private void utCameraSection(float partialTicks, long finishTimeNano, CallbackInfo ci, @Share("utCameraY") LocalDoubleRef cameraY, @Share("utOriginX") LocalDoubleRef originX, @Share("utOriginZ") LocalDoubleRef originZ)
{
double x = originX.get();
double z = originZ.get();
double y = UTModernDebugRender.sectionOrigin(cameraY.get());
GlStateManager.glLineWidth(UTModernDebugRender.THIN_WIDTH);
GlStateManager.disableDepth();
RenderGlobal.drawSelectionBoundingBox(new AxisAlignedBB(x, y, z, x + 16.0D, y + 16.0D, z + 16.0D), 0.25F, 0.25F, 1.0F, 1.0F);
GlStateManager.enableDepth();
}

@Unique
private static void utCellColor(Args args)
{
if ((float) args.get(0) != 1.0F || (float) args.get(1) != 1.0F || (float) args.get(2) != 0.0F) return;
args.set(0, 0.0F);
args.set(1, 155.0F / 255.0F);
args.set(2, 155.0F / 255.0F);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender.mixin;

import java.util.List;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.debug.DebugRendererCollisionBox;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender.UTModernDebugRender;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;

@Mixin(DebugRendererCollisionBox.class)
public abstract class UTCollisionBoxMixin
{
@Shadow
private double renderPosX;
@Shadow
private double renderPosY;
@Shadow
private double renderPosZ;

@Unique
private long utLastUpdate;

@Unique
private List<AxisAlignedBB> utShapes;

@WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getCollisionBoxes(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/AxisAlignedBB;)Ljava/util/List;"))
private List<AxisAlignedBB> utCacheShapes(World world, Entity entity, AxisAlignedBB box, Operation<List<AxisAlignedBB>> original)
{
long now = System.nanoTime();
// null rather than a timestamp sentinel, because nanoTime has no defined origin to compare against
if (this.utShapes == null || now - this.utLastUpdate > 100_000_000L)
{
this.utLastUpdate = now;
Entity camera = Minecraft.getMinecraft().getRenderViewEntity();
this.utShapes = camera == null ? original.call(world, entity, box) : original.call(world, camera, camera.getEntityBoundingBox().grow(6.0D));
}
return this.utShapes;
}

// The shapes arrive offset by the player position, which is not the camera while spectating
@ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBoundingBox(Lnet/minecraft/util/math/AxisAlignedBB;FFFF)V"), index = 0)
private AxisAlignedBB utCameraOffset(AxisAlignedBB box, @Local(argsOnly = true) float partialTicks)
{
Vec3d camera = UTModernDebugRender.cameraPos(partialTicks);
return camera == null ? box : box.offset(this.renderPosX - camera.x, this.renderPosY - camera.y, this.renderPosZ - camera.z);
}

@ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;glLineWidth(F)V"))
private float utStrokeWidth(float width)
{
return UTModernDebugRender.STROKE_WIDTH;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender.mixin;

import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;

import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalFloatRef;
import mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender.UTModernDebugRender;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArgs;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;

@Mixin(RenderManager.class)
public abstract class UTEntityHitboxMixin
{
// The lines are unlit, so the entity brightness is swapped for full bright and restored afterwards
@Inject(method = "renderDebugBoundingBox", at = @At("HEAD"))
private void utStrokeWidth(Entity entity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci, @Share("utBrightnessX") LocalFloatRef brightnessX, @Share("utBrightnessY") LocalFloatRef brightnessY)
{
GlStateManager.glLineWidth(UTModernDebugRender.STROKE_WIDTH);
brightnessX.set(OpenGlHelper.lastBrightnessX);
brightnessY.set(OpenGlHelper.lastBrightnessY);
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240.0F, 240.0F);
}

// Use the actual box for eye pos calculation
@ModifyArgs(method = "renderDebugBoundingBox", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawBoundingBox(DDDDDDFFFF)V", ordinal = 2))
private void utEyeBox(Args args, @Local(argsOnly = true, ordinal = 0) Entity entity, @Local(argsOnly = true, ordinal = 0) double x, @Local(argsOnly = true, ordinal = 1) double y, @Local(argsOnly = true, ordinal = 2) double z, @Local(ordinal = 0) AxisAlignedBB box)
{
double eyeY = y + box.minY - entity.posY + entity.getEyeHeight();
args.set(0, box.minX - entity.posX + x);
args.set(1, eyeY - 0.01D);
args.set(2, box.minZ - entity.posZ + z);
args.set(3, box.maxX - entity.posX + x);
args.set(4, eyeY + 0.01D);
args.set(5, box.maxZ - entity.posZ + z);
}

// The only draw in this method is the view vector, so afterwards the arrow head can be appended
// while texturing and depth writes are still off.
@Inject(method = "renderDebugBoundingBox", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/Tessellator;draw()V", shift = At.Shift.AFTER))
private void utArrowHeadAndCentre(Entity entity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci, @Share("utBrightnessX") LocalFloatRef brightnessX, @Share("utBrightnessY") LocalFloatRef brightnessY)
{
Vec3d eye = new Vec3d(x, y + entity.getEyeHeight(), z);
UTModernDebugRender.drawArrowHead(eye, eye.add(entity.getLook(partialTicks).scale(2.0D)), 0.0F, 0.0F, 1.0F);
UTModernDebugRender.drawPoint(x, y, z, 1.0F, 1.0F, 1.0F);
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, brightnessX.get(), brightnessY.get());
GlStateManager.glLineWidth(UTModernDebugRender.THIN_WIDTH);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"package": "mod.acgaming.universaltweaks.tweaks.misc.moderndebugrender.mixin",
"refmap": "universaltweaks.refmap.json",
"minVersion": "0.8",
"compatibilityLevel": "JAVA_8",
"client": ["UTChunkBorderMixin", "UTCollisionBoxMixin", "UTEntityHitboxMixin"]
}
Loading