feat:
1.制作中打开供应器高亮对应样板 2.优化高亮工具类
This commit is contained in:
parent
247081939f
commit
f254da43f4
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.extendedae_plus.content;
|
||||||
|
|
||||||
|
import appeng.api.crafting.IPatternDetails;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
public final class PatternHighlightStore {
|
||||||
|
// 使用同步的 WeakHashMap 存储高亮状态,键为 IPatternDetails,值为 Boolean
|
||||||
|
private static final Map<IPatternDetails, Boolean> HIGHLIGHTS = Collections.synchronizedMap(new WeakHashMap<>());
|
||||||
|
|
||||||
|
// 私有构造方法,防止实例化
|
||||||
|
private PatternHighlightStore() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置指定 details 的高亮状态。
|
||||||
|
* @param details 需要设置的 IPatternDetails 实例
|
||||||
|
* @param highlighted 是否高亮
|
||||||
|
*/
|
||||||
|
public static void setHighlight(IPatternDetails details, boolean highlighted) {
|
||||||
|
if (details == null) return;
|
||||||
|
if (highlighted) {
|
||||||
|
HIGHLIGHTS.put(details, Boolean.TRUE); // 设置为高亮
|
||||||
|
} else {
|
||||||
|
HIGHLIGHTS.remove(details); // 移除高亮
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定 details 的高亮状态。
|
||||||
|
* @param details 需要查询的 IPatternDetails 实例
|
||||||
|
* @return 是否高亮
|
||||||
|
*/
|
||||||
|
public static boolean getHighlight(IPatternDetails details) {
|
||||||
|
if (details == null) return false;
|
||||||
|
Boolean v = HIGHLIGHTS.get(details);
|
||||||
|
return v != null && v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空所有高亮状态(在供应器界面关闭时调用)。
|
||||||
|
*/
|
||||||
|
public static void clearAll() {
|
||||||
|
HIGHLIGHTS.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.extendedae_plus.mixin.ae2.client.gui;
|
package com.extendedae_plus.mixin.ae2.client.gui;
|
||||||
|
|
||||||
|
import appeng.api.crafting.PatternDetailsHelper;
|
||||||
import appeng.api.stacks.AEKey;
|
import appeng.api.stacks.AEKey;
|
||||||
import appeng.client.Point;
|
import appeng.client.Point;
|
||||||
import appeng.client.gui.AEBaseScreen;
|
import appeng.client.gui.AEBaseScreen;
|
||||||
|
|
@ -12,12 +13,14 @@ import appeng.client.gui.style.Text;
|
||||||
import appeng.client.gui.style.TextAlignment;
|
import appeng.client.gui.style.TextAlignment;
|
||||||
import appeng.menu.slot.AppEngSlot;
|
import appeng.menu.slot.AppEngSlot;
|
||||||
import com.extendedae_plus.api.ExPatternPageAccessor;
|
import com.extendedae_plus.api.ExPatternPageAccessor;
|
||||||
|
import com.extendedae_plus.content.PatternHighlightStore;
|
||||||
import com.extendedae_plus.network.CraftingMonitorJumpC2SPacket;
|
import com.extendedae_plus.network.CraftingMonitorJumpC2SPacket;
|
||||||
import com.extendedae_plus.network.CraftingMonitorOpenProviderC2SPacket;
|
import com.extendedae_plus.network.CraftingMonitorOpenProviderC2SPacket;
|
||||||
import com.extendedae_plus.network.ModNetwork;
|
import com.extendedae_plus.network.ModNetwork;
|
||||||
import com.extendedae_plus.util.GuiUtil;
|
import com.extendedae_plus.util.GuiUtil;
|
||||||
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
|
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.Font;
|
import net.minecraft.client.gui.Font;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
import net.minecraft.client.renderer.Rect2i;
|
import net.minecraft.client.renderer.Rect2i;
|
||||||
|
|
@ -150,40 +153,49 @@ public abstract class AEBaseScreenMixin {
|
||||||
@Inject(method = "renderSlot", at = @At("TAIL"))
|
@Inject(method = "renderSlot", at = @At("TAIL"))
|
||||||
private void eap$renderSlotAmounts(GuiGraphics guiGraphics, Slot s, CallbackInfo ci) {
|
private void eap$renderSlotAmounts(GuiGraphics guiGraphics, Slot s, CallbackInfo ci) {
|
||||||
Object self = this;
|
Object self = this;
|
||||||
|
|
||||||
// 只处理AppEngSlot类型的槽位
|
// 只处理AppEngSlot类型的槽位
|
||||||
if (!(s instanceof AppEngSlot appEngSlot)) {
|
if (!(s instanceof AppEngSlot appEngSlot)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查槽位是否可见且有效
|
// 检查槽位是否可见且有效
|
||||||
if (!appEngSlot.isActive() || !appEngSlot.isSlotEnabled()) {
|
if (!appEngSlot.isActive() || !appEngSlot.isSlotEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取槽位中的物品
|
// 获取槽位中的物品
|
||||||
var itemStack = appEngSlot.getItem();
|
var itemStack = appEngSlot.getItem();
|
||||||
if (itemStack.isEmpty()) {
|
if (itemStack.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用GuiUtil的格式化方法获取数量文本
|
// 使用GuiUtil的格式化方法获取数量文本
|
||||||
String amountText = GuiUtil.getPatternOutputText(itemStack);
|
String amountText = GuiUtil.getPatternOutputText(itemStack);
|
||||||
if (amountText.isEmpty()) {
|
if (amountText.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在槽位右下角绘制数量文本
|
// 在槽位右下角绘制数量文本
|
||||||
Font font = eap$getFont(self);
|
Font font = eap$getFont(self);
|
||||||
GuiUtil.drawAmountText(guiGraphics, font, amountText, appEngSlot.x, appEngSlot.y, 0.6f);
|
GuiUtil.drawAmountText(guiGraphics, font, amountText, appEngSlot.x, appEngSlot.y, 0.6f);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var details = PatternDetailsHelper.decodePattern(itemStack, Minecraft.getInstance().level, false);
|
||||||
|
if (PatternHighlightStore.getHighlight(details)) {
|
||||||
|
try {
|
||||||
|
GuiUtil.drawSlotRainbowHighlight(guiGraphics, s.x, s.y);
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
}
|
||||||
|
} catch (Throwable ignore) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在 AEBaseScreen.drawText 完成某个文本绘制后,若该文本为“样板”标签,则紧接着绘制页码。
|
// 在 AEBaseScreen.drawText 完成某个文本绘制后,若该文本为“样板”标签,则紧接着绘制页码。
|
||||||
@Inject(method = "drawText", at = @At("TAIL"), remap = false)
|
@Inject(method = "drawText", at = @At("TAIL"), remap = false)
|
||||||
private void eap$appendPageAfterPatternsLabel(GuiGraphics guiGraphics,
|
private void eap$appendPageAfterPatternsLabel(GuiGraphics guiGraphics,
|
||||||
Text text,
|
Text text,
|
||||||
@Nullable TextOverride override,
|
@Nullable TextOverride override,
|
||||||
CallbackInfo ci) {
|
CallbackInfo ci) {
|
||||||
Object self = this;
|
Object self = this;
|
||||||
if (!(self instanceof GuiExPatternProvider)) {
|
if (!(self instanceof GuiExPatternProvider)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -237,8 +249,10 @@ public abstract class AEBaseScreenMixin {
|
||||||
if (!isPatterns) {
|
if (!isPatterns) {
|
||||||
String label = content.getString();
|
String label = content.getString();
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
if (label.equals(Component.translatable("gui.pattern_provider.patterns").getString())) isPatterns = true;
|
if (label.equals(Component.translatable("gui.pattern_provider.patterns").getString()))
|
||||||
else if (label.equals(Component.translatable("gui.extendedae.patterns").getString())) isPatterns = true;
|
isPatterns = true;
|
||||||
|
else if (label.equals(Component.translatable("gui.extendedae.patterns").getString()))
|
||||||
|
isPatterns = true;
|
||||||
else if (label.equals(Component.translatable("gui.ae2.patterns").getString())) isPatterns = true;
|
else if (label.equals(Component.translatable("gui.ae2.patterns").getString())) isPatterns = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,16 +277,18 @@ public abstract class AEBaseScreenMixin {
|
||||||
if (v instanceof Integer i) {
|
if (v instanceof Integer i) {
|
||||||
max = Math.max(1, i);
|
max = Math.max(1, i);
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
String pageText = "第"+cur+"页" + "/" + max + "页";
|
String pageText = "第" + cur + "页" + "/" + max + "页";
|
||||||
|
|
||||||
ScreenStyle style = eap$getStyle(self);
|
ScreenStyle style = eap$getStyle(self);
|
||||||
int color = 0xFFFFFFFF;
|
int color = 0xFFFFFFFF;
|
||||||
if (style != null) {
|
if (style != null) {
|
||||||
try {
|
try {
|
||||||
color = style.getColor(PaletteColor.DEFAULT_TEXT_COLOR).toARGB();
|
color = style.getColor(PaletteColor.DEFAULT_TEXT_COLOR).toARGB();
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int padding = 4;
|
int padding = 4;
|
||||||
if (scale == 1.0f) {
|
if (scale == 1.0f) {
|
||||||
|
|
@ -284,6 +300,7 @@ public abstract class AEBaseScreenMixin {
|
||||||
guiGraphics.drawString(font, pageText, lineWidth + padding, 0, color, false);
|
guiGraphics.drawString(font, pageText, lineWidth + padding, 0, color, false);
|
||||||
guiGraphics.pose().popPose();
|
guiGraphics.pose().popPose();
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {}
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.extendedae_plus.mixin.ae2.client.gui;
|
||||||
|
|
||||||
|
import appeng.client.gui.implementations.PatternProviderScreen;
|
||||||
|
import com.extendedae_plus.content.PatternHighlightStore;
|
||||||
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
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.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(value = AbstractContainerScreen.class, remap = false)
|
||||||
|
public class PatternProviderCloseMixin {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
protected AbstractContainerMenu menu;
|
||||||
|
|
||||||
|
@Inject(method = "removed", at = @At("HEAD"))
|
||||||
|
private void onRemoved(CallbackInfo ci) {
|
||||||
|
try {
|
||||||
|
if (((Object) this) instanceof PatternProviderScreen) {
|
||||||
|
PatternHighlightStore.clearAll();
|
||||||
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,6 @@ import appeng.api.crafting.PatternDetailsHelper;
|
||||||
import appeng.client.gui.AEBaseScreen;
|
import appeng.client.gui.AEBaseScreen;
|
||||||
import appeng.client.gui.Icon;
|
import appeng.client.gui.Icon;
|
||||||
import appeng.client.gui.me.patternaccess.PatternContainerRecord;
|
import appeng.client.gui.me.patternaccess.PatternContainerRecord;
|
||||||
import appeng.client.gui.me.patternaccess.PatternSlot;
|
|
||||||
import appeng.client.gui.style.ScreenStyle;
|
import appeng.client.gui.style.ScreenStyle;
|
||||||
import appeng.client.gui.widgets.AETextField;
|
import appeng.client.gui.widgets.AETextField;
|
||||||
import appeng.client.gui.widgets.IconButton;
|
import appeng.client.gui.widgets.IconButton;
|
||||||
|
|
@ -13,6 +12,7 @@ import com.extendedae_plus.config.ModConfigs;
|
||||||
import com.extendedae_plus.mixin.extendedae.accessor.GuiExPatternTerminalAccessor;
|
import com.extendedae_plus.mixin.extendedae.accessor.GuiExPatternTerminalAccessor;
|
||||||
import com.extendedae_plus.network.ModNetwork;
|
import com.extendedae_plus.network.ModNetwork;
|
||||||
import com.extendedae_plus.network.OpenProviderUiC2SPacket;
|
import com.extendedae_plus.network.OpenProviderUiC2SPacket;
|
||||||
|
import com.extendedae_plus.util.GuiUtil;
|
||||||
import com.glodblock.github.extendedae.client.gui.GuiExPatternTerminal;
|
import com.glodblock.github.extendedae.client.gui.GuiExPatternTerminal;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
|
@ -76,41 +76,6 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
||||||
super(menu, playerInventory, title, style);
|
super(menu, playerInventory, title, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
|
||||||
private static int eap$withAlpha(int rgb, int alpha255) {
|
|
||||||
return ((alpha255 & 0xFF) << 24) | (rgb & 0x00FFFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将 HSV 转换为 RGB(返回 0xRRGGBB,不含 alpha)。
|
|
||||||
* h: 0.0~1.0,s: 0.0~1.0,v: 0.0~1.0
|
|
||||||
*/
|
|
||||||
@Unique
|
|
||||||
private static int eap$hsvToRgb(float h, float s, float v) {
|
|
||||||
if (s <= 0.0f) {
|
|
||||||
int g = Math.round(v * 255.0f);
|
|
||||||
return (g << 16) | (g << 8) | g;
|
|
||||||
}
|
|
||||||
float hh = (h - (float) Math.floor(h)) * 6.0f;
|
|
||||||
int sector = (int) Math.floor(hh);
|
|
||||||
float f = hh - sector;
|
|
||||||
float p = v * (1.0f - s);
|
|
||||||
float q = v * (1.0f - s * f);
|
|
||||||
float t = v * (1.0f - s * (1.0f - f));
|
|
||||||
float r, g, b;
|
|
||||||
switch (sector) {
|
|
||||||
case 0: r = v; g = t; b = p; break;
|
|
||||||
case 1: r = q; g = v; b = p; break;
|
|
||||||
case 2: r = p; g = v; b = t; break;
|
|
||||||
case 3: r = p; g = q; b = v; break;
|
|
||||||
case 4: r = t; g = p; b = v; break;
|
|
||||||
default: r = v; g = p; b = q; break;
|
|
||||||
}
|
|
||||||
int ri = Math.round(r * 255.0f);
|
|
||||||
int gi = Math.round(g * 255.0f);
|
|
||||||
int bi = Math.round(b * 255.0f);
|
|
||||||
return (ri << 16) | (gi << 8) | bi;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前选择的样板供应器ID
|
* 获取当前选择的样板供应器ID
|
||||||
|
|
@ -579,53 +544,9 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 彩虹色的流转:基于时间在 HSV 色环上循环(4 秒为一周期)
|
// 使用 GuiUtil 的通用绘制方法绘制槽位高亮(包含彩虹流转效果)
|
||||||
long now = System.currentTimeMillis();
|
GuiUtil.drawPatternSlotHighlights(guiGraphics, this.menu.slots, this.matchedStack, this.matchedProvider);
|
||||||
final long rainbowPeriodMs = 4000L;
|
|
||||||
float hue = (now % rainbowPeriodMs) / (float) rainbowPeriodMs; // 0.0 ~ 1.0
|
|
||||||
int rainbowRgb = eap$hsvToRgb(hue, 1.0f, 1.0f);
|
|
||||||
|
|
||||||
for (Slot slot : this.menu.slots) {
|
|
||||||
if (!(slot instanceof PatternSlot ps)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sx = slot.x;
|
|
||||||
int sy = slot.y;
|
|
||||||
|
|
||||||
boolean isMatchedSlot = this.matchedStack != null && this.matchedStack.contains(slot.getItem());
|
|
||||||
boolean isMatchedProvider = false;
|
|
||||||
try {
|
|
||||||
PatternContainerRecord container = ps.getMachineInv();
|
|
||||||
isMatchedProvider = this.matchedProvider != null && this.matchedProvider.contains(container);
|
|
||||||
} catch (Throwable ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// 依据命中状态选择颜色方案
|
|
||||||
int borderColor;
|
|
||||||
int backgroundColor;
|
|
||||||
|
|
||||||
if (isMatchedSlot) {
|
|
||||||
// 命中槽位:使用彩虹色边框与浅底色(固定透明度,呈现色相流转效果)
|
|
||||||
borderColor = eap$withAlpha(rainbowRgb, 0xA0);
|
|
||||||
backgroundColor = eap$withAlpha(rainbowRgb, 0x3C);
|
|
||||||
} else if (!isMatchedProvider) {
|
|
||||||
borderColor = eap$withAlpha(0xFFFFFF, 0x40);
|
|
||||||
backgroundColor = eap$withAlpha(0x000000, 0x18);
|
|
||||||
} else {
|
|
||||||
borderColor = eap$withAlpha(0xFFFFFF, 0x30);
|
|
||||||
backgroundColor = eap$withAlpha(0xFFFFFF, 0x14);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 绘制 18x18 边框(1px 宽)
|
|
||||||
eap$fill(guiGraphics, new Rect2i(sx - 1, sy - 1, 18, 1), borderColor);
|
|
||||||
eap$fill(guiGraphics, new Rect2i(sx - 1, sy + 16, 18, 1), borderColor);
|
|
||||||
eap$fill(guiGraphics, new Rect2i(sx - 1, sy, 1, 16), borderColor);
|
|
||||||
eap$fill(guiGraphics, new Rect2i(sx + 16, sy, 1, 16), borderColor);
|
|
||||||
|
|
||||||
// 绘制 16x16 浅底色(半透明,叠加在槽位上方)
|
|
||||||
eap$fill(guiGraphics, new Rect2i(sx, sy, 16, 16), backgroundColor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unique
|
@Unique
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import appeng.menu.AEBaseMenu;
|
||||||
import appeng.menu.locator.MenuLocators;
|
import appeng.menu.locator.MenuLocators;
|
||||||
import appeng.menu.me.crafting.CraftingCPUMenu;
|
import appeng.menu.me.crafting.CraftingCPUMenu;
|
||||||
import appeng.parts.AEBasePart;
|
import appeng.parts.AEBasePart;
|
||||||
|
import com.extendedae_plus.content.PatternHighlightStore;
|
||||||
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor;
|
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor;
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
@ -99,6 +100,9 @@ public class CraftingMonitorOpenProviderC2SPacket {
|
||||||
} else {
|
} else {
|
||||||
host.openMenu(player, MenuLocators.forBlockEntity(pbe));
|
host.openMenu(player, MenuLocators.forBlockEntity(pbe));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PatternHighlightStore.setHighlight(pattern, true);
|
||||||
|
|
||||||
context.setPacketHandled(true);
|
context.setPacketHandled(true);
|
||||||
return;
|
return;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,17 @@ package com.extendedae_plus.util;
|
||||||
|
|
||||||
import appeng.api.crafting.PatternDetailsHelper;
|
import appeng.api.crafting.PatternDetailsHelper;
|
||||||
import appeng.api.stacks.GenericStack;
|
import appeng.api.stacks.GenericStack;
|
||||||
|
import appeng.client.gui.me.patternaccess.PatternContainerRecord;
|
||||||
|
import appeng.client.gui.me.patternaccess.PatternSlot;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.Font;
|
import net.minecraft.client.gui.Font;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.world.inventory.Slot;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GUI工具类,提供样板获取、绘制等通用功能
|
* GUI工具类,提供样板获取、绘制等通用功能
|
||||||
|
|
@ -77,4 +83,105 @@ public class GuiUtil {
|
||||||
guiGraphics.drawString(font, text, (int)(textX / scale), (int)(textY / scale), 0xFFFFFFFF, true);
|
guiGraphics.drawString(font, text, (int)(textX / scale), (int)(textY / scale), 0xFFFFFFFF, true);
|
||||||
guiGraphics.pose().popPose();
|
guiGraphics.pose().popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper: add alpha channel to RGB (rgb is 0xRRGGBB)
|
||||||
|
private static int withAlpha(int rgb, int alpha255) {
|
||||||
|
return ((alpha255 & 0xFF) << 24) | (rgb & 0x00FFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HSV -> RGB (returns 0xRRGGBB)
|
||||||
|
private static int hsvToRgb(float h, float s, float v) {
|
||||||
|
if (s <= 0.0f) {
|
||||||
|
int g = Math.round(v * 255.0f);
|
||||||
|
return (g << 16) | (g << 8) | g;
|
||||||
|
}
|
||||||
|
float hh = (h - (float) Math.floor(h)) * 6.0f;
|
||||||
|
int sector = (int) Math.floor(hh);
|
||||||
|
float f = hh - sector;
|
||||||
|
float p = v * (1.0f - s);
|
||||||
|
float q = v * (1.0f - s * f);
|
||||||
|
float t = v * (1.0f - s * (1.0f - f));
|
||||||
|
float r, g, b;
|
||||||
|
switch (sector) {
|
||||||
|
case 0: r = v; g = t; b = p; break;
|
||||||
|
case 1: r = q; g = v; b = p; break;
|
||||||
|
case 2: r = p; g = v; b = t; break;
|
||||||
|
case 3: r = p; g = q; b = v; break;
|
||||||
|
case 4: r = t; g = p; b = v; break;
|
||||||
|
default: r = v; g = p; b = q; break;
|
||||||
|
}
|
||||||
|
int ri = Math.round(r * 255.0f);
|
||||||
|
int gi = Math.round(g * 255.0f);
|
||||||
|
int bi = Math.round(b * 255.0f);
|
||||||
|
return (ri << 16) | (gi << 8) | bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回当前时间对应的彩虹色(0xRRGGBB),周期固定为 4000ms
|
||||||
|
private static int getRainbowRgb() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
final long rainbowPeriodMs = 4000L;
|
||||||
|
float hue = (now % rainbowPeriodMs) / (float) rainbowPeriodMs; // 0.0 ~ 1.0
|
||||||
|
return hsvToRgb(hue, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在给定槽位坐标绘制 1px 边框(18x18)和 16x16 半透明背景
|
||||||
|
private static void drawSlotBox(GuiGraphics guiGraphics, int sx, int sy, int borderColor, int backgroundColor) {
|
||||||
|
guiGraphics.fill(sx - 1, sy - 1, sx + 17, sy, borderColor);
|
||||||
|
guiGraphics.fill(sx - 1, sy + 16, sx + 17, sy + 17, borderColor);
|
||||||
|
guiGraphics.fill(sx - 1, sy, sx, sy + 16, borderColor);
|
||||||
|
guiGraphics.fill(sx + 16, sy, sx + 17, sy + 16, borderColor);
|
||||||
|
guiGraphics.fill(sx, sy, sx + 16, sy + 16, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在槽位上绘制彩色流转的高亮和浅底色
|
||||||
|
*/
|
||||||
|
public static void drawPatternSlotHighlights(GuiGraphics guiGraphics, List<Slot> slots, Set<ItemStack> matchedStack, Set<PatternContainerRecord> matchedProvider) {
|
||||||
|
if (slots == null) return;
|
||||||
|
|
||||||
|
int rainbowRgb = getRainbowRgb();
|
||||||
|
|
||||||
|
for (Slot slot : slots) {
|
||||||
|
if (!(slot instanceof PatternSlot ps)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sx = slot.x;
|
||||||
|
int sy = slot.y;
|
||||||
|
|
||||||
|
boolean isMatchedSlot = matchedStack != null && matchedStack.contains(slot.getItem());
|
||||||
|
boolean isMatchedProvider = false;
|
||||||
|
try {
|
||||||
|
PatternContainerRecord container = ps.getMachineInv();
|
||||||
|
isMatchedProvider = matchedProvider != null && matchedProvider.contains(container);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int borderColor;
|
||||||
|
int backgroundColor;
|
||||||
|
|
||||||
|
if (isMatchedSlot) {
|
||||||
|
borderColor = withAlpha(rainbowRgb, 0xA0);
|
||||||
|
backgroundColor = withAlpha(rainbowRgb, 0x3C);
|
||||||
|
} else if (!isMatchedProvider) {
|
||||||
|
borderColor = withAlpha(0xFFFFFF, 0x40);
|
||||||
|
backgroundColor = withAlpha(0x000000, 0x18);
|
||||||
|
} else {
|
||||||
|
borderColor = withAlpha(0xFFFFFF, 0x30);
|
||||||
|
backgroundColor = withAlpha(0xFFFFFF, 0x14);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawSlotBox(guiGraphics, sx, sy, borderColor, backgroundColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在指定槽位坐标绘制彩虹流转的边框与浅底色(用于非 PatternSlot 的高亮场景)
|
||||||
|
*/
|
||||||
|
public static void drawSlotRainbowHighlight(GuiGraphics guiGraphics, int sx, int sy) {
|
||||||
|
int rainbowRgb = getRainbowRgb();
|
||||||
|
int borderColor = withAlpha(rainbowRgb, 0xA0);
|
||||||
|
int backgroundColor = withAlpha(rainbowRgb, 0x3C);
|
||||||
|
drawSlotBox(guiGraphics, sx, sy, borderColor, backgroundColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
"ae2.accessor.PatternAccessTermScreenSlotsRowAccessor",
|
"ae2.accessor.PatternAccessTermScreenSlotsRowAccessor",
|
||||||
"ae2.client.gui.AEBaseScreenMixin",
|
"ae2.client.gui.AEBaseScreenMixin",
|
||||||
"ae2.client.gui.PatternEncodingTermScreenMixin",
|
"ae2.client.gui.PatternEncodingTermScreenMixin",
|
||||||
|
"ae2.client.gui.PatternProviderCloseMixin",
|
||||||
"ae2.client.gui.PatternProviderScreenMixin",
|
"ae2.client.gui.PatternProviderScreenMixin",
|
||||||
"ae2.client.gui.SlotGridLayoutMixin",
|
"ae2.client.gui.SlotGridLayoutMixin",
|
||||||
"extendedae.accessor.GuiExPatternTerminalAccessor",
|
"extendedae.accessor.GuiExPatternTerminalAccessor",
|
||||||
|
|
@ -30,6 +31,7 @@
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ae2.AEProcessingPatternMixin",
|
"ae2.AEProcessingPatternMixin",
|
||||||
"ae2.CraftingCPUClusterMixin",
|
"ae2.CraftingCPUClusterMixin",
|
||||||
|
"ae2.IPatternDetailsMixin",
|
||||||
"ae2.accessor.MEStorageMenuAccessor",
|
"ae2.accessor.MEStorageMenuAccessor",
|
||||||
"ae2.accessor.PatternEncodingTermMenuAccessor",
|
"ae2.accessor.PatternEncodingTermMenuAccessor",
|
||||||
"ae2.accessor.PatternProviderLogicAccessor",
|
"ae2.accessor.PatternProviderLogicAccessor",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user