fix glow for 1.21.11

This commit is contained in:
seb
2026-05-11 03:03:40 +02:00
parent 19a85628f2
commit cf97ebe11b
5 changed files with 166 additions and 61 deletions

View File

@@ -3,7 +3,7 @@ import java.time.format.DateTimeFormatter
import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaLanguageVersion
plugins { plugins {
id("dev.isxander.modstitch.base") version "0.8.4" id("dev.isxander.modstitch.base") version "0.8.5"
id("com.modrinth.minotaur") version "2.+" id("com.modrinth.minotaur") version "2.+"
} }
@@ -84,6 +84,12 @@ stonecutter {
"forge" to loader.equals("forge", ignoreCase = true), "forge" to loader.equals("forge", ignoreCase = true),
"vanilla" to loader.equals("vanilla", ignoreCase = true), "vanilla" to loader.equals("vanilla", ignoreCase = true),
"mc26" to (minecraft == "26.1.2"), "mc26" to (minecraft == "26.1.2"),
// TraderHighlightRenderer: MC 26 uses Fabric LevelRenderEvents; 1.21.x uses WorldRenderEvents (v1.world).
"traderWireframeRender" to (minecraft == "26.1.2" || minecraft == "1.21.11" || minecraft == "1.21.10"),
"traderWireframeMc26" to (minecraft == "26.1.2"),
"traderWireframe121" to (minecraft == "1.21.10" || minecraft == "1.21.11"),
"traderWireframe12110" to (minecraft == "1.21.10"),
"traderWireframe12111" to (minecraft == "1.21.11"),
"npcSplit" to (minecraft == "26.1.2" || minecraft == "1.21.11"), "npcSplit" to (minecraft == "26.1.2" || minecraft == "1.21.11"),
"npcFlat" to (minecraft == "1.21.10"), "npcFlat" to (minecraft == "1.21.10"),
) )

View File

@@ -11,6 +11,7 @@ import java.util.List;
import java.util.Vector; import java.util.Vector;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.client.gui.screens.inventory.ContainerScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.client.gui.screens.inventory.MerchantScreen;
import net.minecraft.client.gui.screens.inventory.ShulkerBoxScreen; import net.minecraft.client.gui.screens.inventory.ShulkerBoxScreen;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -48,7 +49,6 @@ final class AutoTradeClientTick {
private final Vector<Entity> villagersInRange = new Vector<>(); private final Vector<Entity> villagersInRange = new Vector<>();
private int villagerActive = 0; private int villagerActive = 0;
private boolean state = false;
private boolean inputInRange = false; private boolean inputInRange = false;
private boolean inputOpened = false; private boolean inputOpened = false;
private boolean outputInRange = false; private boolean outputInRange = false;
@@ -68,6 +68,7 @@ final class AutoTradeClientTick {
private int inputContainerHighlightTicks = 0; private int inputContainerHighlightTicks = 0;
private int outputContainerHighlightTicks = 0; private int outputContainerHighlightTicks = 0;
private int postMerchantInventorySyncTicks = 0;
/** /**
* Entity to draw in-world highlight for; {@code null} when inactive or unknown * Entity to draw in-world highlight for; {@code null} when inactive or unknown
@@ -102,7 +103,14 @@ final class AutoTradeClientTick {
if (containerDelay > 0) { if (containerDelay > 0) {
containerDelay--; containerDelay--;
} }
if (!Configs.Generic.ENABLED.getBooleanValue() || mc.player == null) { if (mc.player == null) {
return;
}
if (postMerchantInventorySyncTicks > 0) {
postMerchantInventorySyncTicks--;
ContainerIoHelper.syncPlayerInventoryAfterMerchant(mc);
}
if (!Configs.Generic.ENABLED.getBooleanValue()) {
return; return;
} }
Inventory plInv = mc.player.getInventory(); Inventory plInv = mc.player.getInventory();
@@ -158,9 +166,9 @@ final class AutoTradeClientTick {
//?} else { //?} else {
mc.gameMode.interact(mc.player, entity, InteractionHand.MAIN_HAND); mc.gameMode.interact(mc.player, entity, InteractionHand.MAIN_HAND);
//?} //?}
postMerchantInventorySyncTicks = 0;
voidDelay = Configs.Generic.VOID_TRADING_DELAY.getIntegerValue(); voidDelay = Configs.Generic.VOID_TRADING_DELAY.getIntegerValue();
villagerActive = entity.getId(); villagerActive = entity.getId();
state = false;
break; break;
} }
} }
@@ -296,64 +304,101 @@ final class AutoTradeClientTick {
} }
private void tickMerchantScreen(Minecraft mc, MerchantScreen screen) { private void tickMerchantScreen(Minecraft mc, MerchantScreen screen) {
if (!state) { MerchantMenu menu = screen.getMenu();
String sellItemStr = Configs.Generic.SELL_ITEM.getStringValue(); MerchantOffers offers = menu.getOffers();
String buyItemStr = Configs.Generic.BUY_ITEM.getStringValue();
state = true;
MerchantMenu menu = screen.getMenu();
MerchantOffers offers = menu.getOffers();
// Cache offers for the in-world trade overlay. Entity activeEntity = findEntityById(mc, villagerActive);
Entity activeEntity = findEntityById(mc, villagerActive); if (activeEntity != null && offers != null && !offers.isEmpty()) {
if (activeEntity != null && offers != null && !offers.isEmpty()) { VillagerTradeCache.put(activeEntity.getUUID(), offers);
VillagerTradeCache.put(activeEntity.getUUID(), offers); }
}
for (int i = 0; i < offers.size(); i++) { if (tryExecuteOneMerchantTrade(mc, screen)) {
MerchantOffer offer = offers.get(i); ContainerIoHelper.syncPlayerInventoryAfterMerchant(mc);
int tradesLeft = offer.getMaxUses() - offer.getUses(); return;
if (TradeItemSpec.matches(offer.getResult(), buyItemStr) && Configs.Generic.ENABLE_BUY.getBooleanValue() }
&& offer.getResult().getCount() <= Configs.Generic.BUY_LIMIT.getIntegerValue()) {
if (tradesLeft > 0 && playerHasMerchantCosts(mc.player, offer)) { finishMerchantSession(mc, screen);
Slot slot = menu.getSlot(2); }
menu.setSelectionHint(i);
mc.player.connection.send(new ServerboundSelectTradePacket(i)); /**
AutoTrade.bought += offer.getMaxUses(); * Runs at most <strong>one</strong> trade per tick so the server can answer before the next
InfoUtils.showGuiOrInGameMessage(Message.MessageType.INFO, "autotrade.message.trade_bought", * packet — avoids inventory slot ghosts from batched select-trade + shift-clicks.
formatItemCountNameForTrades(offer.getResult(), tradesLeft), */
formatOfferPriceForTrades(offer, tradesLeft)); private boolean tryExecuteOneMerchantTrade(Minecraft mc, MerchantScreen screen) {
try { MerchantMenu menu = screen.getMenu();
ContainerIoHelper.quickMoveResultSlot(mc, menu, slot.index); MerchantOffers offers = menu.getOffers();
} catch (Exception e) { if (offers == null || offers.isEmpty()) {
System.out.println("err " + e); return false;
} }
String sellItemStr = Configs.Generic.SELL_ITEM.getStringValue();
String buyItemStr = Configs.Generic.BUY_ITEM.getStringValue();
for (int i = 0; i < offers.size(); i++) {
MerchantOffer offer = offers.get(i);
int tradesLeft = offer.getMaxUses() - offer.getUses();
if (TradeItemSpec.matches(offer.getResult(), buyItemStr) && Configs.Generic.ENABLE_BUY.getBooleanValue()
&& offer.getResult().getCount() <= Configs.Generic.BUY_LIMIT.getIntegerValue()) {
if (tradesLeft > 0 && playerHasMerchantCosts(mc.player, offer)) {
Slot slot = menu.getSlot(2);
menu.setSelectionHint(i);
mc.player.connection.send(new ServerboundSelectTradePacket(i));
AutoTrade.bought += offer.getMaxUses();
showTradeNotice(mc, "autotrade.message.trade_bought",
Component.literal(formatItemCountNameForTrades(offer.getResult(), tradesLeft)),
Component.literal(formatOfferPriceForTrades(offer, tradesLeft)));
try {
ContainerIoHelper.quickMoveResultSlot(mc, menu, slot.index);
} catch (Exception e) {
System.out.println("err " + e);
} }
return true;
} }
if (TradeItemSpec.matches(offer.getCostA(), sellItemStr) }
&& Configs.Generic.ENABLE_SELL.getBooleanValue()
&& offer.getCostA().getCount() <= Configs.Generic.SELL_LIMIT.getIntegerValue()) { if (TradeItemSpec.matches(offer.getCostA(), sellItemStr)
if (tradesLeft > 0 && playerHasMerchantCosts(mc.player, offer)) { && Configs.Generic.ENABLE_SELL.getBooleanValue()
Slot slot = menu.getSlot(2); && offer.getCostA().getCount() <= Configs.Generic.SELL_LIMIT.getIntegerValue()) {
menu.setSelectionHint(i); if (tradesLeft > 0 && playerHasMerchantCosts(mc.player, offer)) {
AutoTrade.sold += offer.getMaxUses(); Slot slot = menu.getSlot(2);
mc.player.connection.send(new ServerboundSelectTradePacket(i)); menu.setSelectionHint(i);
InfoUtils.showGuiOrInGameMessage(Message.MessageType.INFO, "autotrade.message.trade_sold", mc.player.connection.send(new ServerboundSelectTradePacket(i));
formatItemCountNameForTrades(offer.getCostA(), tradesLeft) AutoTrade.sold += offer.getMaxUses();
+ formatOptionalSecondCostForTrades(offer, tradesLeft), showTradeNotice(mc, "autotrade.message.trade_sold",
formatItemCountNameForTrades(offer.getResult(), tradesLeft)); Component.literal(formatItemCountNameForTrades(offer.getCostA(), tradesLeft)
try { + formatOptionalSecondCostForTrades(offer, tradesLeft)),
ContainerIoHelper.quickMoveResultSlot(mc, menu, slot.index); Component.literal(formatItemCountNameForTrades(offer.getResult(), tradesLeft)));
} catch (Exception e) { try {
System.out.println("err " + e); ContainerIoHelper.quickMoveResultSlot(mc, menu, slot.index);
} } catch (Exception e) {
System.out.println("err " + e);
} }
return true;
} }
} }
} }
return false;
}
private void finishMerchantSession(Minecraft mc, MerchantScreen screen) {
ContainerIoHelper.syncPlayerInventoryAfterMerchant(mc);
screen.onClose(); screen.onClose();
ContainerIoHelper.syncPlayerInventoryAfterMerchant(mc); ContainerIoHelper.syncPlayerInventoryAfterMerchant(mc);
postMerchantInventorySyncTicks = 15;
startTraderGlow(mc, villagerActive); startTraderGlow(mc, villagerActive);
} }
/**
* Malilib's {@code showGuiOrInGameMessage} routes to multiple HUD targets; trade spam looked like 3× duplication.
* Vanilla overlay is a single on-screen line (same idea as vanilla toast-adjacent hints).
*/
private static void showTradeNotice(Minecraft mc, String translationKey, Component arg1, Component arg2) {
if (mc.gui == null) {
return;
}
mc.gui.setOverlayMessage(Component.translatable(translationKey, arg1, arg2), false);
}
private void tickTraderGlow(Minecraft mc) { private void tickTraderGlow(Minecraft mc) {
if (mc.level == null || traderGlowTicksRemaining <= 0) { if (mc.level == null || traderGlowTicksRemaining <= 0) {
return; return;

View File

@@ -1,16 +1,13 @@
package com.github.sebseb7.autotrade.render; package com.github.sebseb7.autotrade.render;
//? if mc26 { //? if traderWireframeRender {
import com.github.sebseb7.autotrade.config.Configs; import com.github.sebseb7.autotrade.config.Configs;
import com.github.sebseb7.autotrade.event.KeybindCallbacks; import com.github.sebseb7.autotrade.event.KeybindCallbacks;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderEvents;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.ShapeRenderer; import net.minecraft.client.renderer.ShapeRenderer;
import net.minecraft.client.renderer.rendertype.RenderTypes;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
@@ -18,6 +15,20 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.Shapes;
//?} //?}
//? if traderWireframeMc26 {
import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderEvents;
//?}
//? if traderWireframe121 {
import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents;
//?}
//? if traderWireframe12110 {
import net.minecraft.client.renderer.RenderType;
//?}
//? if traderWireframeMc26 || traderWireframe12111 {
import net.minecraft.client.renderer.rendertype.RenderTypes;
//?}
/** /**
* Client wireframe highlights: last-traded villager, and input/output container * Client wireframe highlights: last-traded villager, and input/output container
@@ -30,21 +41,27 @@ public final class TraderHighlightRenderer {
} }
public static void register() { public static void register() {
//? if mc26 { //? if traderWireframeMc26 {
LevelRenderEvents.AFTER_SOLID_FEATURES.register(TraderHighlightRenderer::renderLevel); LevelRenderEvents.AFTER_SOLID_FEATURES.register(TraderHighlightRenderer::renderLevelMc26);
//?}
//? if traderWireframe121 {
WorldRenderEvents.END_MAIN.register(TraderHighlightRenderer::renderWorld121);
//?} //?}
} }
//? if mc26 { //? if traderWireframeRender {
private static final ShapeRenderer SHAPE_RENDERER = new ShapeRenderer(); private static final ShapeRenderer SHAPE_RENDERER = new ShapeRenderer();
private static final int TRADER_OUTLINE_COLOR = 0xFF66FF66; private static final int TRADER_OUTLINE_COLOR = 0xFF66FF66;
private static final int INPUT_CONTAINER_COLOR = 0xFFFF6666; private static final int INPUT_CONTAINER_COLOR = 0xFFFF6666;
private static final int OUTPUT_CONTAINER_COLOR = 0xFF6666FF; private static final int OUTPUT_CONTAINER_COLOR = 0xFF6666FF;
//? if traderWireframeMc26 || traderWireframe12111 {
private static final float LINE_WIDTH = 2.5F; private static final float LINE_WIDTH = 2.5F;
//?}
private static void renderLevel(LevelRenderContext context) { //? if traderWireframeMc26 {
private static void renderLevelMc26(LevelRenderContext context) {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
if (mc.level == null) { if (mc.level == null) {
return; return;
@@ -65,6 +82,38 @@ public final class TraderHighlightRenderer {
renderBoxes(mc, drawPose, consumer, camera, tickDelta, trader, inTicks, outTicks); renderBoxes(mc, drawPose, consumer, camera, tickDelta, trader, inTicks, outTicks);
} }
//?}
//? if traderWireframe121 {
private static void renderWorld121(WorldRenderContext context) {
Minecraft mc = Minecraft.getInstance();
if (mc.level == null) {
return;
}
KeybindCallbacks kb = KeybindCallbacks.getInstance();
Entity trader = kb.getTraderHighlightEntity(mc);
int inTicks = kb.getInputContainerHighlightTicks();
int outTicks = kb.getOutputContainerHighlightTicks();
if (trader == null && inTicks <= 0 && outTicks <= 0) {
return;
}
var vertexConsumers = context.consumers();
PoseStack drawPose = new PoseStack();
Vec3 camera = mc.gameRenderer.getMainCamera().position();
float tickDelta = mc.getDeltaTracker().getGameTimeDeltaPartialTick(true);
final VertexConsumer consumer;
//? if traderWireframe12110 {
consumer = vertexConsumers.getBuffer(RenderType.lines());
//?}
//? if traderWireframe12111 {
consumer = vertexConsumers.getBuffer(RenderTypes.lines());
//?}
renderBoxes(mc, drawPose, consumer, camera, tickDelta, trader, inTicks, outTicks);
}
//?}
private static void renderBoxes(Minecraft mc, PoseStack drawPose, VertexConsumer consumer, Vec3 camera, private static void renderBoxes(Minecraft mc, PoseStack drawPose, VertexConsumer consumer, Vec3 camera,
float tickDelta, Entity trader, int inTicks, int outTicks) { float tickDelta, Entity trader, int inTicks, int outTicks) {
@@ -100,8 +149,13 @@ public final class TraderHighlightRenderer {
} }
private static void renderShape(PoseStack drawPose, VertexConsumer consumer, AABB cameraRelative, int color) { private static void renderShape(PoseStack drawPose, VertexConsumer consumer, AABB cameraRelative, int color) {
//? if traderWireframe12110 {
SHAPE_RENDERER.renderShape(drawPose, consumer, Shapes.create(cameraRelative), 0.0D, 0.0D, 0.0D, color);
//?}
//? if traderWireframeMc26 || traderWireframe12111 {
SHAPE_RENDERER.renderShape(drawPose, consumer, Shapes.create(cameraRelative), 0.0D, 0.0D, 0.0D, color, SHAPE_RENDERER.renderShape(drawPose, consumer, Shapes.create(cameraRelative), 0.0D, 0.0D, 0.0D, color,
LINE_WIDTH); LINE_WIDTH);
//?}
} }
//?} //?}
} }

View File

@@ -1,7 +1,7 @@
modstitch.platform=fabric-loom-remap modstitch.platform=fabric-loom-remap
deps.minecraft=1.21.10 deps.minecraft=1.21.10
fabric_loader_version=0.19.2 fabric_loader_version=0.18.3
fabric_api_version=0.138.4+1.21.10 fabric_api_version=0.138.4+1.21.10
malilib_version=0.26.8 malilib_version=0.26.8
mod_menu_version=16.0.1 mod_menu_version=16.0.1

View File

@@ -2,7 +2,7 @@ modstitch.platform=fabric-loom-remap
deps.minecraft=1.21.11 deps.minecraft=1.21.11
fabric_loader_version=0.19.2 fabric_loader_version=0.19.2
fabric_api_version=0.136.0+1.21.11 fabric_api_version=0.141.3+1.21.11
malilib_version=0.27.3 malilib_version=0.27.9
mod_menu_version=17.0.0 mod_menu_version=17.0.0
minecraft_version_min=1.21.11 minecraft_version_min=1.21.11