feat: Add Storage overlay search
This commit is contained in:
@@ -64,7 +64,7 @@ jarvis = "1.1.4"
|
|||||||
nealisp = "1.1.0"
|
nealisp = "1.1.0"
|
||||||
|
|
||||||
# Update from https://github.com/NotEnoughUpdates/MoulConfig/tags
|
# Update from https://github.com/NotEnoughUpdates/MoulConfig/tags
|
||||||
moulconfig = "3.1.0"
|
moulconfig = "3.2.0"
|
||||||
|
|
||||||
# Update from https://www.curseforge.com/minecraft/mc-mods/configured/files/all?page=1&pageSize=20
|
# Update from https://www.curseforge.com/minecraft/mc-mods/configured/files/all?page=1&pageSize=20
|
||||||
configured = "5441234"
|
configured = "5441234"
|
||||||
|
|||||||
@@ -32,12 +32,18 @@ public class HandledScreenRiser extends RiserUtils {
|
|||||||
String keyReleased = remapper.mapMethodName("intermediary", Intermediary.<Element>className(),
|
String keyReleased = remapper.mapMethodName("intermediary", Intermediary.<Element>className(),
|
||||||
Intermediary.methodName(Element::keyReleased),
|
Intermediary.methodName(Element::keyReleased),
|
||||||
keyReleasedDesc.getDescriptor());
|
keyReleasedDesc.getDescriptor());
|
||||||
|
// public boolean charTyped(char chr, int modifiers)
|
||||||
|
Type charTypedDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.CHAR_TYPE, Type.INT_TYPE);
|
||||||
|
String charTyped = remapper.mapMethodName("intermediary", Intermediary.<Element>className(),
|
||||||
|
Intermediary.methodName(Element::charTyped),
|
||||||
|
charTypedDesc.getDescriptor());
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTinkerers() {
|
public void addTinkerers() {
|
||||||
ClassTinkerers.addTransformation(HandledScreen, this::addMouseScroll, true);
|
ClassTinkerers.addTransformation(HandledScreen, this::addMouseScroll, true);
|
||||||
ClassTinkerers.addTransformation(HandledScreen, this::addKeyReleased, true);
|
ClassTinkerers.addTransformation(HandledScreen, this::addKeyReleased, true);
|
||||||
|
ClassTinkerers.addTransformation(HandledScreen, this::addCharTyped, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,56 +76,69 @@ public class HandledScreenRiser extends RiserUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addKeyReleased(ClassNode classNode) {
|
void addKeyReleased(ClassNode classNode) {
|
||||||
var keyReleasedNode = findMethod(classNode, keyReleased, keyReleasedDesc);
|
addSuperInjector(
|
||||||
|
classNode, keyReleased, keyReleasedDesc, "keyReleased_firmament",
|
||||||
|
insns -> {
|
||||||
|
// ALOAD 0, load this
|
||||||
|
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||||
|
// ILOAD 1-3, load args
|
||||||
|
insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
|
||||||
|
insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
|
||||||
|
insns.add(new VarInsnNode(Opcodes.ILOAD, 3));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCharTyped(ClassNode classNode) {
|
||||||
|
addSuperInjector(
|
||||||
|
classNode, charTyped, charTypedDesc, "charTyped_firmament",
|
||||||
|
insns -> {
|
||||||
|
// ALOAD 0, load this
|
||||||
|
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||||
|
// ILOAD 1-2, load args. chars = ints
|
||||||
|
insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
|
||||||
|
insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSuperInjector(
|
||||||
|
ClassNode classNode,
|
||||||
|
String name,
|
||||||
|
Type desc,
|
||||||
|
String firmamentName,
|
||||||
|
Consumer<InsnList> loadArgs
|
||||||
|
) {
|
||||||
|
var keyReleasedNode = findMethod(classNode, name, desc);
|
||||||
if (keyReleasedNode == null) {
|
if (keyReleasedNode == null) {
|
||||||
keyReleasedNode = new MethodNode(
|
keyReleasedNode = new MethodNode(
|
||||||
Modifier.PUBLIC,
|
Modifier.PUBLIC,
|
||||||
keyReleased,
|
name,
|
||||||
keyReleasedDesc.getDescriptor(),
|
desc.getDescriptor(),
|
||||||
null,
|
null,
|
||||||
new String[0]
|
new String[0]
|
||||||
);
|
);
|
||||||
var insns = keyReleasedNode.instructions;
|
var insns = keyReleasedNode.instructions;
|
||||||
// ALOAD 0, load this
|
loadArgs.accept(insns);
|
||||||
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
|
||||||
// ILOAD 1-3, load args
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ILOAD, 3));
|
|
||||||
// INVOKESPECIAL call super method
|
// INVOKESPECIAL call super method
|
||||||
insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, getTypeForClassName(Screen).getInternalName(),
|
insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, getTypeForClassName(Screen).getInternalName(),
|
||||||
keyReleased, keyReleasedDesc.getDescriptor()));
|
name, desc.getDescriptor()));
|
||||||
// IRETURN return int on stack (booleans are int at runtime)
|
// IRETURN return int on stack (booleans are int at runtime)
|
||||||
insns.add(new InsnNode(Opcodes.IRETURN));
|
insns.add(new InsnNode(Opcodes.IRETURN));
|
||||||
classNode.methods.add(keyReleasedNode);
|
classNode.methods.add(keyReleasedNode);
|
||||||
}
|
}
|
||||||
insertTrueHandler(keyReleasedNode, insns -> {
|
insertTrueHandler(keyReleasedNode, loadArgs, insns -> {
|
||||||
// ALOAD 0, load this
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
|
||||||
// ILOAD 1-3, load args
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ILOAD, 3));
|
|
||||||
}, insns -> {
|
|
||||||
// INVOKEVIRTUAL call custom handler
|
// INVOKEVIRTUAL call custom handler
|
||||||
insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
|
insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
|
||||||
getTypeForClassName(HandledScreen).getInternalName(),
|
getTypeForClassName(HandledScreen).getInternalName(),
|
||||||
"keyReleased_firmament",
|
firmamentName,
|
||||||
keyReleasedDesc.getDescriptor()));
|
desc.getDescriptor()));
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMouseScroll(ClassNode classNode) {
|
void addMouseScroll(ClassNode classNode) {
|
||||||
MethodNode mouseScrolledNode = findMethod(classNode, mouseScrolled, mouseScrolledDesc);
|
addSuperInjector(
|
||||||
if (mouseScrolledNode == null) {
|
classNode, mouseScrolled, mouseScrolledDesc, "mouseScrolled_firmament",
|
||||||
mouseScrolledNode = new MethodNode(
|
insns -> {
|
||||||
Modifier.PUBLIC,
|
|
||||||
mouseScrolled,
|
|
||||||
mouseScrolledDesc.getDescriptor(),
|
|
||||||
null,
|
|
||||||
new String[0]
|
|
||||||
);
|
|
||||||
var insns = mouseScrolledNode.instructions;
|
|
||||||
// ALOAD 0, load this
|
// ALOAD 0, load this
|
||||||
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||||
// DLOAD 1-4, load the 4 argument doubles. Note that since doubles are two entries wide we skip 2 each time.
|
// DLOAD 1-4, load the 4 argument doubles. Note that since doubles are two entries wide we skip 2 each time.
|
||||||
@@ -127,28 +146,6 @@ public class HandledScreenRiser extends RiserUtils {
|
|||||||
insns.add(new VarInsnNode(Opcodes.DLOAD, 3));
|
insns.add(new VarInsnNode(Opcodes.DLOAD, 3));
|
||||||
insns.add(new VarInsnNode(Opcodes.DLOAD, 5));
|
insns.add(new VarInsnNode(Opcodes.DLOAD, 5));
|
||||||
insns.add(new VarInsnNode(Opcodes.DLOAD, 7));
|
insns.add(new VarInsnNode(Opcodes.DLOAD, 7));
|
||||||
// INVOKESPECIAL call super method
|
|
||||||
insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, getTypeForClassName(Screen).getInternalName(), mouseScrolled, mouseScrolledDesc.getDescriptor()));
|
|
||||||
// IRETURN return int on stack (booleans are int at runtime)
|
|
||||||
insns.add(new InsnNode(Opcodes.IRETURN));
|
|
||||||
classNode.methods.add(mouseScrolledNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
insertTrueHandler(mouseScrolledNode, insns -> {
|
|
||||||
// ALOAD 0, load this
|
|
||||||
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
|
||||||
// DLOAD 1-4, load the 4 argument doubles. Note that since doubles are two entries wide we skip 2 each time.
|
|
||||||
insns.add(new VarInsnNode(Opcodes.DLOAD, 1));
|
|
||||||
insns.add(new VarInsnNode(Opcodes.DLOAD, 3));
|
|
||||||
insns.add(new VarInsnNode(Opcodes.DLOAD, 5));
|
|
||||||
insns.add(new VarInsnNode(Opcodes.DLOAD, 7));
|
|
||||||
}, insns -> {
|
|
||||||
// INVOKEVIRTUAL call custom handler
|
|
||||||
insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
|
|
||||||
getTypeForClassName(HandledScreen).getInternalName(),
|
|
||||||
"mouseScrolled_firmament",
|
|
||||||
mouseScrolledDesc.getDescriptor()));
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,10 +62,6 @@ public abstract class MixinHandledScreen<T extends ScreenHandler> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean keyReleased_firmament(int keyCode, int scanCode, int modifiers) {
|
|
||||||
return HandledScreenKeyReleasedEvent.Companion.publish(new HandledScreenKeyReleasedEvent((HandledScreen<?>) (Object) this, keyCode, scanCode, modifiers)).getCancelled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawForeground(Lnet/minecraft/client/gui/DrawContext;II)V", shift = At.Shift.AFTER))
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawForeground(Lnet/minecraft/client/gui/DrawContext;II)V", shift = At.Shift.AFTER))
|
||||||
public void onAfterRenderForeground(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
public void onAfterRenderForeground(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
|
||||||
context.getMatrices().push();
|
context.getMatrices().push();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
|||||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
import com.llamalad7.mixinextras.sugar.Local;
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
|
import moe.nea.firmament.events.HandledScreenKeyReleasedEvent;
|
||||||
import moe.nea.firmament.util.customgui.CoordRememberingSlot;
|
import moe.nea.firmament.util.customgui.CoordRememberingSlot;
|
||||||
import moe.nea.firmament.util.customgui.CustomGui;
|
import moe.nea.firmament.util.customgui.CustomGui;
|
||||||
import moe.nea.firmament.util.customgui.HasCustomGui;
|
import moe.nea.firmament.util.customgui.HasCustomGui;
|
||||||
@@ -73,6 +74,16 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
|
|||||||
return override != null && override.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
|
return override != null && override.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean keyReleased_firmament(int keyCode, int scanCode, int modifiers) {
|
||||||
|
if (HandledScreenKeyReleasedEvent.Companion.publish(new HandledScreenKeyReleasedEvent((HandledScreen<?>) (Object) this, keyCode, scanCode, modifiers)).getCancelled())
|
||||||
|
return true;
|
||||||
|
return override != null && override.keyReleased(keyCode, scanCode, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean charTyped_firmament(char chr, int modifiers) {
|
||||||
|
return override != null && override.charTyped(chr, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "init", at = @At("TAIL"))
|
@Inject(method = "init", at = @At("TAIL"))
|
||||||
private void onInit(CallbackInfo ci) {
|
private void onInit(CallbackInfo ci) {
|
||||||
if (override != null) {
|
if (override != null) {
|
||||||
@@ -179,6 +190,16 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void overrideKeyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
if (override != null) {
|
||||||
|
if (override.keyPressed(keyCode, scanCode, modifiers)) {
|
||||||
|
cir.setReturnValue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Inject(
|
@Inject(
|
||||||
method = "mouseReleased",
|
method = "mouseReleased",
|
||||||
at = @At("HEAD"), cancellable = true)
|
at = @At("HEAD"), cancellable = true)
|
||||||
|
|||||||
@@ -66,6 +66,18 @@ class StorageOverlayCustom(
|
|||||||
return overview.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
return overview.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
return overview.keyReleased(keyCode, scanCode, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
return overview.keyPressed(keyCode, scanCode, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun charTyped(chr: Char, modifiers: Int): Boolean {
|
||||||
|
return overview.charTyped(chr, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||||
return overview.mouseClicked(mouseX, mouseY, button, (handler as? StorageBackingHandle.Page)?.storagePageSlot)
|
return overview.mouseClicked(mouseX, mouseY, button, (handler as? StorageBackingHandle.Page)?.storagePageSlot)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
package moe.nea.firmament.features.inventory.storageoverlay
|
package moe.nea.firmament.features.inventory.storageoverlay
|
||||||
|
|
||||||
|
import io.github.notenoughupdates.moulconfig.common.IMinecraft
|
||||||
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
|
||||||
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
||||||
import io.github.notenoughupdates.moulconfig.gui.component.ColumnComponent
|
import io.github.notenoughupdates.moulconfig.gui.component.ColumnComponent
|
||||||
import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
|
import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
|
||||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.component.TextFieldComponent
|
||||||
|
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||||
|
import io.github.notenoughupdates.moulconfig.observer.Property
|
||||||
|
import java.util.TreeSet
|
||||||
import me.shedaniel.math.Point
|
import me.shedaniel.math.Point
|
||||||
import me.shedaniel.math.Rectangle
|
import me.shedaniel.math.Rectangle
|
||||||
import net.minecraft.client.gui.DrawContext
|
import net.minecraft.client.gui.DrawContext
|
||||||
import net.minecraft.client.gui.screen.Screen
|
import net.minecraft.client.gui.screen.Screen
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.screen.slot.Slot
|
import net.minecraft.screen.slot.Slot
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
@@ -20,10 +27,16 @@ import moe.nea.firmament.util.MC
|
|||||||
import moe.nea.firmament.util.MoulConfigUtils.adopt
|
import moe.nea.firmament.util.MoulConfigUtils.adopt
|
||||||
import moe.nea.firmament.util.MoulConfigUtils.clickMCComponentInPlace
|
import moe.nea.firmament.util.MoulConfigUtils.clickMCComponentInPlace
|
||||||
import moe.nea.firmament.util.MoulConfigUtils.drawMCComponentInPlace
|
import moe.nea.firmament.util.MoulConfigUtils.drawMCComponentInPlace
|
||||||
|
import moe.nea.firmament.util.MoulConfigUtils.typeMCComponentInPlace
|
||||||
|
import moe.nea.firmament.util.StringUtil.words
|
||||||
import moe.nea.firmament.util.assertTrueOr
|
import moe.nea.firmament.util.assertTrueOr
|
||||||
import moe.nea.firmament.util.customgui.customGui
|
import moe.nea.firmament.util.customgui.customGui
|
||||||
import moe.nea.firmament.util.mc.FakeSlot
|
import moe.nea.firmament.util.mc.FakeSlot
|
||||||
|
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
|
||||||
|
import moe.nea.firmament.util.mc.loreAccordingToNbt
|
||||||
import moe.nea.firmament.util.render.drawGuiTexture
|
import moe.nea.firmament.util.render.drawGuiTexture
|
||||||
|
import moe.nea.firmament.util.tr
|
||||||
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
|
||||||
class StorageOverlayScreen : Screen(Text.literal("")) {
|
class StorageOverlayScreen : Screen(Text.literal("")) {
|
||||||
|
|
||||||
@@ -83,10 +96,13 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
horizontalAmount: Double,
|
horizontalAmount: Double,
|
||||||
verticalAmount: Double
|
verticalAmount: Double
|
||||||
): Boolean {
|
): Boolean {
|
||||||
scroll = (scroll + StorageOverlay.adjustScrollSpeed(verticalAmount)).toFloat()
|
coerceScroll(StorageOverlay.adjustScrollSpeed(verticalAmount).toFloat())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
fun coerceScroll(offset: Float) {
|
||||||
|
scroll = (scroll + offset)
|
||||||
.coerceAtMost(getMaxScroll())
|
.coerceAtMost(getMaxScroll())
|
||||||
.coerceAtLeast(0F)
|
.coerceAtLeast(0F)
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMaxScroll() = lastRenderedInnerHeight.toFloat() - getScrollPanelInner().height
|
fun getMaxScroll() = lastRenderedInnerHeight.toFloat() - getScrollPanelInner().height
|
||||||
@@ -142,12 +158,26 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
|
|
||||||
val guiContext = GuiContext(EmptyComponent())
|
val guiContext = GuiContext(EmptyComponent())
|
||||||
private val knobStub = EmptyComponent()
|
private val knobStub = EmptyComponent()
|
||||||
val editButton = PanelComponent(ColumnComponent(FirmButtonComponent(TextComponent("Edit"), action = ::editPages)),
|
val editButton = FirmButtonComponent(TextComponent(tr("firmament.storage-overlay.edit-pages", "Edit Pages").string), action = ::editPages)
|
||||||
8, PanelComponent.DefaultBackgroundRenderer.TRANSPARENT)
|
val searchText = Property.of("") // TODO: sync with REI
|
||||||
|
val searchField = TextFieldComponent(searchText, 100, GetSetter.constant(true),
|
||||||
|
tr("firmament.storage-overlay.search.suggestion", "Search...").string,
|
||||||
|
IMinecraft.instance.defaultFontRenderer)
|
||||||
|
val controlComponent = PanelComponent(
|
||||||
|
ColumnComponent(
|
||||||
|
searchField,
|
||||||
|
editButton,
|
||||||
|
),
|
||||||
|
8, PanelComponent.DefaultBackgroundRenderer.TRANSPARENT
|
||||||
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
guiContext.adopt(editButton)
|
searchText.addObserver { _, _ ->
|
||||||
|
layoutedForEach(StorageOverlay.Data.data ?: StorageData(), { _, _, _ -> })
|
||||||
|
coerceScroll(0F)
|
||||||
|
}
|
||||||
guiContext.adopt(knobStub)
|
guiContext.adopt(knobStub)
|
||||||
|
guiContext.adopt(controlComponent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun drawControls(context: DrawContext, mouseX: Int, mouseY: Int) {
|
fun drawControls(context: DrawContext, mouseX: Int, mouseY: Int) {
|
||||||
@@ -157,7 +187,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
measurements.controlY,
|
measurements.controlY,
|
||||||
CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT)
|
CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT)
|
||||||
context.drawMCComponentInPlace(
|
context.drawMCComponentInPlace(
|
||||||
editButton,
|
controlComponent,
|
||||||
measurements.controlX, measurements.controlY,
|
measurements.controlX, measurements.controlY,
|
||||||
CONTROL_WIDTH, CONTROL_HEIGHT,
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
mouseX, mouseY)
|
mouseX, mouseY)
|
||||||
@@ -251,7 +281,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
knobGrabbed = false
|
knobGrabbed = false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (clickMCComponentInPlace(editButton,
|
if (clickMCComponentInPlace(controlComponent,
|
||||||
measurements.controlX, measurements.controlY,
|
measurements.controlX, measurements.controlY,
|
||||||
CONTROL_WIDTH, CONTROL_HEIGHT,
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
mouseX.toInt(), mouseY.toInt(),
|
mouseX.toInt(), mouseY.toInt(),
|
||||||
@@ -290,7 +320,7 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
knobGrabbed = true
|
knobGrabbed = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if (clickMCComponentInPlace(editButton,
|
if (clickMCComponentInPlace(controlComponent,
|
||||||
measurements.controlX, measurements.controlY,
|
measurements.controlX, measurements.controlY,
|
||||||
CONTROL_WIDTH, CONTROL_HEIGHT,
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
mouseX.toInt(), mouseY.toInt(),
|
mouseX.toInt(), mouseY.toInt(),
|
||||||
@@ -299,6 +329,78 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun charTyped(chr: Char, modifiers: Int): Boolean {
|
||||||
|
if (typeMCComponentInPlace(
|
||||||
|
controlComponent,
|
||||||
|
measurements.controlX, measurements.controlY,
|
||||||
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
|
KeyboardEvent.CharTyped(chr)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.charTyped(chr, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
if (typeMCComponentInPlace(
|
||||||
|
controlComponent,
|
||||||
|
measurements.controlX, measurements.controlY,
|
||||||
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
|
KeyboardEvent.KeyPressed(keyCode, false)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.keyReleased(keyCode, scanCode, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
if (typeMCComponentInPlace(
|
||||||
|
controlComponent,
|
||||||
|
measurements.controlX, measurements.controlY,
|
||||||
|
CONTROL_WIDTH, CONTROL_HEIGHT,
|
||||||
|
KeyboardEvent.KeyPressed(keyCode, true)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var searchCache: String? = null
|
||||||
|
var filteredPagesCache = setOf<StoragePageSlot>()
|
||||||
|
|
||||||
|
fun getFilteredPages(): Set<StoragePageSlot> {
|
||||||
|
val searchValue = searchText.get()
|
||||||
|
val data = StorageOverlay.Data.data ?: return filteredPagesCache // Do not update cache if data is missing
|
||||||
|
if (searchCache == searchValue) return filteredPagesCache
|
||||||
|
val result =
|
||||||
|
data.storageInventories
|
||||||
|
.entries.asSequence()
|
||||||
|
.filter { it.value.inventory?.stacks?.any { matchesSearch(it, searchValue) } ?: true }
|
||||||
|
.map { it.key }
|
||||||
|
.toSet()
|
||||||
|
searchCache = searchValue
|
||||||
|
filteredPagesCache = result
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun matchesSearch(itemStack: ItemStack, search: String): Boolean {
|
||||||
|
val searchWords = search.words().toCollection(TreeSet())
|
||||||
|
fun removePrefixes(value: String) {
|
||||||
|
searchWords.removeIf { value.contains(it, ignoreCase = true) }
|
||||||
|
}
|
||||||
|
itemStack.displayNameAccordingToNbt.unformattedString.words().forEach(::removePrefixes)
|
||||||
|
if (searchWords.isEmpty()) return true
|
||||||
|
itemStack.loreAccordingToNbt.forEach {
|
||||||
|
it.unformattedString.words().forEach(::removePrefixes)
|
||||||
|
}
|
||||||
|
return searchWords.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
private inline fun layoutedForEach(
|
private inline fun layoutedForEach(
|
||||||
data: StorageData,
|
data: StorageData,
|
||||||
func: (
|
func: (
|
||||||
@@ -309,7 +411,9 @@ class StorageOverlayScreen : Screen(Text.literal("")) {
|
|||||||
var yOffset = -scroll.toInt()
|
var yOffset = -scroll.toInt()
|
||||||
var xOffset = 0
|
var xOffset = 0
|
||||||
var maxHeight = 0
|
var maxHeight = 0
|
||||||
|
val filter = getFilteredPages()
|
||||||
for ((page, inventory) in data.storageInventories.entries) {
|
for ((page, inventory) in data.storageInventories.entries) {
|
||||||
|
if (page !in filter) continue
|
||||||
val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 4 + textRenderer.fontHeight }
|
val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 4 + textRenderer.fontHeight }
|
||||||
?: 18
|
?: 18
|
||||||
maxHeight = maxOf(maxHeight, currentHeight)
|
maxHeight = maxOf(maxHeight, currentHeight)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import io.github.notenoughupdates.moulconfig.gui.GuiComponent
|
|||||||
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
|
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
|
||||||
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
||||||
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
||||||
|
import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
|
||||||
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
||||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||||
import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
|
import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
|
||||||
@@ -247,6 +248,18 @@ object MoulConfigUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun typeMCComponentInPlace(
|
||||||
|
component: GuiComponent,
|
||||||
|
x: Int,
|
||||||
|
y: Int,
|
||||||
|
w: Int,
|
||||||
|
h: Int,
|
||||||
|
keyboardEvent: KeyboardEvent
|
||||||
|
): Boolean {
|
||||||
|
val immContext = createInPlaceFullContext(null, IMinecraft.instance.mouseX, IMinecraft.instance.mouseY)
|
||||||
|
return component.keyboardEvent(keyboardEvent, immContext.translated(x, y, w, h))
|
||||||
|
}
|
||||||
|
|
||||||
fun clickMCComponentInPlace(
|
fun clickMCComponentInPlace(
|
||||||
component: GuiComponent,
|
component: GuiComponent,
|
||||||
x: Int,
|
x: Int,
|
||||||
|
|||||||
@@ -10,4 +10,13 @@ object StringUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Iterable<String>.unwords() = joinToString(" ")
|
fun Iterable<String>.unwords() = joinToString(" ")
|
||||||
|
fun nextLexicographicStringOfSameLength(string: String): String {
|
||||||
|
val next = StringBuilder(string)
|
||||||
|
while (next.lastOrNull() == Character.MAX_VALUE) next.setLength(next.length - 1)
|
||||||
|
if (next.isEmpty()) return "" // There is no upper bound. Fall back to the empty string
|
||||||
|
val lastIdx = next.indices.last
|
||||||
|
next[lastIdx] = (next[lastIdx] + 1)
|
||||||
|
return next.toString()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,4 +76,16 @@ abstract class CustomGui {
|
|||||||
open fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
open fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun charTyped(chr: Char, modifiers: Int): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user