From d9c32390a6b4ecfaf6117b9428a6cc661907dbde Mon Sep 17 00:00:00 2001 From: Surya Date: Sat, 30 Oct 2021 16:22:30 +0530 Subject: [PATCH] Allow locking beam location operation, update gui --- README.md | 5 ++ .../mods/savecoords/IKeyBinds.java | 1 + .../savecoords/SaveCoordinatesClient.java | 16 ++++- .../mods/savecoords/TranslationKeys.java | 4 ++ .../impl/CurrentPositionPingOperation.java | 36 +++++++++++ .../mods/savecoords/gui/impl/DIContainer.java | 8 ++- .../savecoords/gui/impl/DimensionButton.java | 56 ++---------------- .../gui/impl/PingPositionOperation.java | 2 +- .../mods/savecoords/impl/KeyBinds.java | 27 +++++---- .../savecoords/util/PartialCircularList.java | 49 +++++++++++++++ .../assets/savecoords/lang/en_us.json | 6 +- .../assets/savecoords/textures/gui/nether.png | Bin 6504 -> 5119 bytes 12 files changed, 141 insertions(+), 69 deletions(-) create mode 100644 src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/CurrentPositionPingOperation.java create mode 100644 src/main/java/me/bionicbeanie/mods/savecoords/util/PartialCircularList.java diff --git a/README.md b/README.md index 3faebca..277125f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,12 @@ Minecraft|[Fabric API](https://www.curseforge.com/minecraft/mc-mods/fabric-api/f - Press `H` to open menu - Press `B` to beam location +- Press `N` to lock beaming - Select `SAVE` to save the coordinate - Select `PING` to ping the coordinate to other players - Select `LIST` to view saved coordinates - Select `CONF` to update configs. Reachable through mod menu as well when available + +## Discord + +https://discord.gg/9xnv2gQbJt diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/IKeyBinds.java b/src/main/java/me/bionicbeanie/mods/savecoords/IKeyBinds.java index fefd782..6787de1 100644 --- a/src/main/java/me/bionicbeanie/mods/savecoords/IKeyBinds.java +++ b/src/main/java/me/bionicbeanie/mods/savecoords/IKeyBinds.java @@ -8,6 +8,7 @@ import net.minecraft.text.Text; public interface IKeyBinds { public static String DEFAULT = "default"; public static String PING = "ping"; + public static String PING_LOCK = "ping_lock"; public List getAllBinds(); public IKeyBinding getKeyBind(String name); diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/SaveCoordinatesClient.java b/src/main/java/me/bionicbeanie/mods/savecoords/SaveCoordinatesClient.java index 988c983..ab9e4a2 100644 --- a/src/main/java/me/bionicbeanie/mods/savecoords/SaveCoordinatesClient.java +++ b/src/main/java/me/bionicbeanie/mods/savecoords/SaveCoordinatesClient.java @@ -4,12 +4,16 @@ import me.bionicbeanie.mods.savecoords.IKeyBinds.IKeyBinding; import me.bionicbeanie.mods.savecoords.gui.impl.DIContainer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.TranslatableText; public class SaveCoordinatesClient implements ClientModInitializer { private static IKeyBinding defaultKeyBinding = getKeyBinding(IKeyBinds.DEFAULT); private static IKeyBinding pingKeyBinding = getKeyBinding(IKeyBinds.PING); - + private static IKeyBinding pingLockBinding = getKeyBinding(IKeyBinds.PING_LOCK); + + @SuppressWarnings("resource") @Override public void onInitializeClient() { @@ -18,6 +22,16 @@ public class SaveCoordinatesClient implements ClientModInitializer { DIContainer.getModGui().open(); } + while(pingLockBinding.wasPressed()) { + boolean enabled = DIContainer.togglePingBehavior(); + String translationKey = TranslationKeys.TOOLTIP_PING_DISABLED; + if(enabled) { + translationKey = TranslationKeys.TOOLTIP_PING_ENABLED; + } + + MinecraftClient.getInstance().player.sendMessage(new TranslatableText(translationKey), true); + } + while(pingKeyBinding.wasPressed()) { DIContainer.getPingPositionOperation().run(); } diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/TranslationKeys.java b/src/main/java/me/bionicbeanie/mods/savecoords/TranslationKeys.java index 9b7d690..2d1e3d3 100644 --- a/src/main/java/me/bionicbeanie/mods/savecoords/TranslationKeys.java +++ b/src/main/java/me/bionicbeanie/mods/savecoords/TranslationKeys.java @@ -3,6 +3,7 @@ package me.bionicbeanie.mods.savecoords; public interface TranslationKeys { public static String KEYBIND_DEFAULT = "key.savecoords.default"; public static String KEYBIND_PING = "key.savecoords.ping"; + public static String KEYBIND_PING_LOCK = "key.savecoords.ping_lock"; public static String CATEGORY_GENERIC = "category.savecoords.default"; public static String MENU_SAVE = "menu.savecoords.save"; public static String MENU_BACK = "menu.savecoords.back"; @@ -13,4 +14,7 @@ public interface TranslationKeys { public static String MENU_LOCATION = "menu.savecoords.location"; public static String MENU_NOTES = "menu.savecoords.notes"; public static String MENU_WORLD_NAME = "menu.savecoords.world_name"; + public static String TOOLTIP_PING_LOCK = "tooltip.savecoords.ping_lock"; + public static String TOOLTIP_PING_ENABLED = "tooltip.savecoords.ping_enabled"; + public static String TOOLTIP_PING_DISABLED = "tooltip.savecoords.ping_disabled"; } diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/CurrentPositionPingOperation.java b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/CurrentPositionPingOperation.java new file mode 100644 index 0000000..9c6706d --- /dev/null +++ b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/CurrentPositionPingOperation.java @@ -0,0 +1,36 @@ +package me.bionicbeanie.mods.savecoords.gui.impl; + +import java.util.function.Supplier; + +import me.bionicbeanie.mods.savecoords.IFileStore; +import me.bionicbeanie.mods.savecoords.TranslationKeys; +import me.bionicbeanie.mods.savecoords.model.PlayerRawPosition; +import net.minecraft.client.MinecraftClient; +import net.minecraft.text.TranslatableText; + +public class CurrentPositionPingOperation extends PingPositionOperation{ + + private boolean enabled = false; + + public CurrentPositionPingOperation(IFileStore fileStore, Supplier stateSupplier) { + super(fileStore, stateSupplier); + } + + public boolean toggleEnabled() { + this.enabled = !this.enabled; + + return this.enabled; + } + + @SuppressWarnings("resource") + @Override + protected void executeOperation(IFileStore fileStore, PlayerRawPosition position) throws Exception { + if (enabled) { + super.executeOperation(fileStore, position); + } else { + MinecraftClient.getInstance().player.sendMessage(new TranslatableText(TranslationKeys.TOOLTIP_PING_LOCK), + true); + } + } + +} diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DIContainer.java b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DIContainer.java index 8dc3110..3005249 100644 --- a/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DIContainer.java +++ b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DIContainer.java @@ -21,7 +21,7 @@ public class DIContainer { private static IModGui modGui; private static IKeyBinds keyBinds; private static ConfigScreenFactory modMenuScreenFactory; - private static PingPositionOperation pingPositionOperation; + private static CurrentPositionPingOperation pingPositionOperation; private static IDimensionAware dimensionAware; public static IModGui getModGui() { @@ -64,6 +64,10 @@ public class DIContainer { } }; } + + public static boolean togglePingBehavior() { + return pingPositionOperation.toggleEnabled(); + } private static void initialize() { if (!initialized) { @@ -77,7 +81,7 @@ public class DIContainer { dimensionAware = Factory.CreateDimensionAware(minecraftClient); modGui = new SaveCoordinatesGui(fileStore, playerLocator, dimensionAware, keyBinds, guiController); - pingPositionOperation = new PingPositionOperation(fileStore, () -> playerLocator.locate()); + pingPositionOperation = new CurrentPositionPingOperation(fileStore, () -> playerLocator.locate()); } } } diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DimensionButton.java b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DimensionButton.java index 771482f..9548847 100644 --- a/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DimensionButton.java +++ b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/DimensionButton.java @@ -5,14 +5,15 @@ import io.github.cottonmc.cotton.gui.widget.WSprite; import me.bionicbeanie.mods.savecoords.IDimensionAware; import me.bionicbeanie.mods.savecoords.IDimensionAware.IDimension; import me.bionicbeanie.mods.savecoords.model.PlayerRawPosition; +import me.bionicbeanie.mods.savecoords.util.PartialCircularList; import net.minecraft.text.LiteralText; public class DimensionButton extends WButton { - private CircularList allDimensions; + private PartialCircularList allDimensions; public DimensionButton(WSprite sprite, IDimensionAware dimensionAware, PlayerRawPosition existingPosition) { - allDimensions = new CircularList(); + allDimensions = new PartialCircularList(); for (IDimension dimension : dimensionAware.getDimensions()) { allDimensions.add(dimension); } @@ -39,53 +40,4 @@ public class DimensionButton extends WButton { public IDimension getDimension() { return allDimensions.current(); } -} - -// TODO : Probably move ad-hoc circular list elsewhere - -class Node { - T value; - Node next; - - Node(T t) { - this.value = t; - } -} - -class CircularList { - Node head = null; - Node tail = null; - Node current = null; - - void add(T t) { - if (head == null) { - head = new Node(t); - tail = head; - head.next = tail; - tail.next = head; - return; - } - - Node temp = new Node(t); - temp.next = head; - tail.next = temp; - tail = temp; - } - - T next() { - if (current == null) { - current = head; - } else { - current = current.next; - } - - return current.value; - } - - T current() { - if (current == null) { - return null; - } - return current.value; - } -} +} \ No newline at end of file diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/PingPositionOperation.java b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/PingPositionOperation.java index a351d27..64b595b 100644 --- a/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/PingPositionOperation.java +++ b/src/main/java/me/bionicbeanie/mods/savecoords/gui/impl/PingPositionOperation.java @@ -6,7 +6,7 @@ import me.bionicbeanie.mods.savecoords.IFileStore; import me.bionicbeanie.mods.savecoords.model.PlayerRawPosition; import net.minecraft.client.MinecraftClient; -class PingPositionOperation extends ViewOperationBase{ +class PingPositionOperation extends ViewOperationBase { public PingPositionOperation(IFileStore fileStore, Supplier stateSupplier) { super(fileStore, stateSupplier); diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/impl/KeyBinds.java b/src/main/java/me/bionicbeanie/mods/savecoords/impl/KeyBinds.java index 9fbe0f5..775bb4c 100644 --- a/src/main/java/me/bionicbeanie/mods/savecoords/impl/KeyBinds.java +++ b/src/main/java/me/bionicbeanie/mods/savecoords/impl/KeyBinds.java @@ -28,6 +28,9 @@ class KeyBinds implements IKeyBinds { KeyBindingEx PING = new KeyBindingEx(IKeyBinds.PING, TranslationKeys.KEYBIND_PING, InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_B, TranslationKeys.CATEGORY_GENERIC); + KeyBindingEx PING_LOCK = new KeyBindingEx(IKeyBinds.PING_LOCK, TranslationKeys.KEYBIND_PING_LOCK, + InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_N, TranslationKeys.CATEGORY_GENERIC); + private IFileStore fileStore; private Map keyBinds; private List unmodifiableList; @@ -38,9 +41,10 @@ class KeyBinds implements IKeyBinds { add(DEFAULT); add(PING); + add(PING_LOCK); initialize(); - + this.unmodifiableList = Collections.unmodifiableList(new ArrayList<>(keyBinds.values())); } @@ -84,17 +88,17 @@ class KeyBinds implements IKeyBinds { public Type getType() { return type; } - + @Override public Type getDefaultType() { return defaultType; } - + @Override public int getDefaultCode() { return defaultCode; } - + @Override public boolean wasPressed() { return super.wasPressed(); @@ -109,17 +113,17 @@ class KeyBinds implements IKeyBinds { public String getName() { return name; } - + @Override public Text getNameLocalizedText() { return new TranslatableText(getTranslationKey()); } - + @Override public Text getBoundKeyLocalizedText() { return super.getBoundKeyLocalizedText(); } - + void setBoundKey(Type type, int code) { super.setBoundKey(type.createFromCode(code)); @@ -131,7 +135,7 @@ class KeyBinds implements IKeyBinds { private void initialize() { try { ConfigData configData = fileStore.readConfigData(); - + Config[] configs = configData.getKeyConfigs(); if (configs == null) { @@ -150,15 +154,14 @@ class KeyBinds implements IKeyBinds { } catch (IOException e) { e.printStackTrace(); } - - + } private Type parseType(String type) { - if("KEYSYM".equalsIgnoreCase(type)) { + if ("KEYSYM".equalsIgnoreCase(type)) { return Type.KEYSYM; } - + return Type.MOUSE; } } diff --git a/src/main/java/me/bionicbeanie/mods/savecoords/util/PartialCircularList.java b/src/main/java/me/bionicbeanie/mods/savecoords/util/PartialCircularList.java new file mode 100644 index 0000000..0ebdea3 --- /dev/null +++ b/src/main/java/me/bionicbeanie/mods/savecoords/util/PartialCircularList.java @@ -0,0 +1,49 @@ +package me.bionicbeanie.mods.savecoords.util; + +public class PartialCircularList { + + public static class Node { + V value; + Node next; + + Node(V v) { + this.value = v; + } + } + + Node head = null; + Node tail = null; + Node current = null; + + public void add(T t) { + if (head == null) { + head = new Node(t); + tail = head; + head.next = tail; + tail.next = head; + return; + } + + Node temp = new Node(t); + temp.next = head; + tail.next = temp; + tail = temp; + } + + public T next() { + if (current == null) { + current = head; + } else { + current = current.next; + } + + return current.value; + } + + public T current() { + if (current == null) { + return null; + } + return current.value; + } +} diff --git a/src/main/resources/assets/savecoords/lang/en_us.json b/src/main/resources/assets/savecoords/lang/en_us.json index 9374545..5872ca9 100644 --- a/src/main/resources/assets/savecoords/lang/en_us.json +++ b/src/main/resources/assets/savecoords/lang/en_us.json @@ -1,6 +1,7 @@ { "key.savecoords.default": "Open GUI", "key.savecoords.ping": "Beam Location", + "key.savecoords.ping_lock": "Lock Beaming", "category.savecoords.default": "Generic", "menu.savecoords.save": "SAVE", "menu.savecoords.reset": "RESET", @@ -10,5 +11,8 @@ "menu.savecoords.conf": "CONF", "menu.savecoords.location": "location name", "menu.savecoords.notes": "additional notes", - "menu.savecoords.world_name": "world name" + "menu.savecoords.world_name": "world name", + "tooltip.savecoords.ping_lock": "You must first enable beaming current location", + "tooltip.savecoords.ping_enabled": "Beaming current location is now enabled", + "tooltip.savecoords.ping_disabled": "Beaming current location is now disabled" } \ No newline at end of file diff --git a/src/main/resources/assets/savecoords/textures/gui/nether.png b/src/main/resources/assets/savecoords/textures/gui/nether.png index d46f1aa6804c30217c8bbb8e75c49bb622c91d53..c3dca7deb298a8ea3e74f4452c844fe3eede47e7 100644 GIT binary patch delta 5092 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