Allow position and dimension editing

This commit is contained in:
Surya 2021-09-03 23:50:43 +05:30
parent 441dfb5ffb
commit 39ca71bc63
13 changed files with 265 additions and 69 deletions

View File

@ -0,0 +1,21 @@
package me.bionicbeanie.mods.savecoords;
import java.util.List;
import net.minecraft.util.Identifier;
public interface IDimensionAware {
List<IDimension> getDimensions();
IDimension getCurrentDimension();
IDimension getDimension(String dimensionKey);
public interface IDimension {
public String getName();
public Identifier getSpriteIdentifier();
}
}

View File

@ -2,6 +2,7 @@ package me.bionicbeanie.mods.savecoords.gui.impl;
import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import me.bionicbeanie.mods.savecoords.IDimensionAware;
import me.bionicbeanie.mods.savecoords.IFileStore; import me.bionicbeanie.mods.savecoords.IFileStore;
import me.bionicbeanie.mods.savecoords.IKeyBinds; import me.bionicbeanie.mods.savecoords.IKeyBinds;
import me.bionicbeanie.mods.savecoords.IModGui; import me.bionicbeanie.mods.savecoords.IModGui;
@ -21,6 +22,7 @@ public class DIContainer {
private static IKeyBinds keyBinds; private static IKeyBinds keyBinds;
private static ConfigScreenFactory<Screen> modMenuScreenFactory; private static ConfigScreenFactory<Screen> modMenuScreenFactory;
private static PingPositionOperation pingPositionOperation; private static PingPositionOperation pingPositionOperation;
private static IDimensionAware dimensionAware;
public static IModGui getModGui() { public static IModGui getModGui() {
initialize(); initialize();
@ -72,7 +74,8 @@ public class DIContainer {
guiController = new GuiController(minecraftClient); guiController = new GuiController(minecraftClient);
playerLocator = Factory.CreatePlayerLocator(minecraftClient); playerLocator = Factory.CreatePlayerLocator(minecraftClient);
keyBinds = Factory.CreateKeyBinds(fileStore); keyBinds = Factory.CreateKeyBinds(fileStore);
modGui = new SaveCoordinatesGui(fileStore, playerLocator, keyBinds, guiController); dimensionAware = Factory.CreateDimensionAware(minecraftClient);
modGui = new SaveCoordinatesGui(fileStore, playerLocator, dimensionAware, keyBinds, guiController);
pingPositionOperation = new PingPositionOperation(fileStore, () -> playerLocator.locate()); pingPositionOperation = new PingPositionOperation(fileStore, () -> playerLocator.locate());
} }

View File

@ -4,10 +4,10 @@ import java.util.UUID;
import java.util.function.Supplier; import java.util.function.Supplier;
import io.github.cottonmc.cotton.gui.widget.WButton; import io.github.cottonmc.cotton.gui.widget.WButton;
import io.github.cottonmc.cotton.gui.widget.WLabel;
import io.github.cottonmc.cotton.gui.widget.WSprite; import io.github.cottonmc.cotton.gui.widget.WSprite;
import io.github.cottonmc.cotton.gui.widget.WTextField; import io.github.cottonmc.cotton.gui.widget.WTextField;
import io.github.cottonmc.cotton.gui.widget.WWidget; import io.github.cottonmc.cotton.gui.widget.WWidget;
import me.bionicbeanie.mods.savecoords.IDimensionAware;
import me.bionicbeanie.mods.savecoords.IFileStore; import me.bionicbeanie.mods.savecoords.IFileStore;
import me.bionicbeanie.mods.savecoords.IPlayerLocator; import me.bionicbeanie.mods.savecoords.IPlayerLocator;
import me.bionicbeanie.mods.savecoords.TranslationKeys; import me.bionicbeanie.mods.savecoords.TranslationKeys;
@ -15,7 +15,6 @@ import me.bionicbeanie.mods.savecoords.gui.IRootPanel;
import me.bionicbeanie.mods.savecoords.model.PlayerPosition; import me.bionicbeanie.mods.savecoords.model.PlayerPosition;
import me.bionicbeanie.mods.savecoords.model.PlayerRawPosition; import me.bionicbeanie.mods.savecoords.model.PlayerRawPosition;
import me.bionicbeanie.mods.savecoords.model.PositionMetadata; import me.bionicbeanie.mods.savecoords.model.PositionMetadata;
import me.bionicbeanie.mods.savecoords.util.DimensionKeys;
import me.bionicbeanie.mods.savecoords.util.ResourceUtils; import me.bionicbeanie.mods.savecoords.util.ResourceUtils;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
@ -29,10 +28,12 @@ class DefaultViewHandler extends ViewHandlerBase<PlayerPosition> {
private WButton pingButton; private WButton pingButton;
private WButton closeButton; private WButton closeButton;
private WButton configButton; private WButton configButton;
private IDimensionAware dimensionAware;
public DefaultViewHandler(IFileStore fileStore, IPlayerLocator locator) { public DefaultViewHandler(IFileStore fileStore, IPlayerLocator locator, IDimensionAware dimensionAware) {
this.fileStore = fileStore; this.fileStore = fileStore;
this.locator = locator; this.locator = locator;
this.dimensionAware = dimensionAware;
this.listButton = CreateButton(TranslationKeys.MENU_LIST); this.listButton = CreateButton(TranslationKeys.MENU_LIST);
this.saveButton = CreateButton(TranslationKeys.MENU_SAVE); this.saveButton = CreateButton(TranslationKeys.MENU_SAVE);
@ -53,7 +54,7 @@ class DefaultViewHandler extends ViewHandlerBase<PlayerPosition> {
WTextField xText = CreateWidgetForCoordinate(rawPosition.getX()); WTextField xText = CreateWidgetForCoordinate(rawPosition.getX());
WTextField yText = CreateWidgetForCoordinate(rawPosition.getY()); WTextField yText = CreateWidgetForCoordinate(rawPosition.getY());
WTextField zText = CreateWidgetForCoordinate(rawPosition.getZ()); WTextField zText = CreateWidgetForCoordinate(rawPosition.getZ());
root.add(xLabel, 0, 1, 1, 1); root.add(xLabel, 0, 1, 1, 1);
root.add(yLabel, 0, 2, 1, 1); root.add(yLabel, 0, 2, 1, 1);
root.add(zLabel, 0, 3, 1, 1); root.add(zLabel, 0, 3, 1, 1);
@ -61,22 +62,22 @@ class DefaultViewHandler extends ViewHandlerBase<PlayerPosition> {
root.add(xText, 1, 1, 6, 1); root.add(xText, 1, 1, 6, 1);
root.add(yText, 1, 2, 6, 1); root.add(yText, 1, 2, 6, 1);
root.add(zText, 1, 3, 6, 1); root.add(zText, 1, 3, 6, 1);
WSprite worldIcon = ResourceUtils.createWorldIcon(getDimension(rawPosition)); DimensionSprite dimensionSprite = new DimensionSprite();
root.add(worldIcon, 9, 1, 2, 2); root.add(dimensionSprite, 9, 0, 2, 2);
WWidget worldButton = CreateWorldButton(worldIcon); DimensionButton dimensionButton = CreateDimensionButton(dimensionSprite, existingPosition);
root.add(worldButton, 8, 3, 4, 1); root.add(dimensionButton, 8, 3, 4, 1);
String defaultWorldName = getDefaultWorldName(existingPosition); String defaultWorldName = getDefaultWorldName(existingPosition);
WTextField world = CreateWorldField(defaultWorldName); WTextField worldNameField = CreateWorldField(defaultWorldName);
root.add(world, 0, 5, 4, 1); root.add(worldNameField, 0, 5, 4, 1);
WTextField location = CreateLocationField(existingPosition); WTextField locationField = CreateLocationField(existingPosition);
root.add(location, 5, 5, 7, 1); root.add(locationField, 5, 5, 7, 1);
WTextField notes = CreateNotesField(existingPosition); WTextField notesField = CreateNotesField(existingPosition);
root.add(notes, 0, 7, 12, 1); root.add(notesField, 0, 7, 12, 1);
root.add(saveButton, 13, 7, 2, 1); root.add(saveButton, 13, 7, 2, 1);
root.add(listButton, 13, 9, 2, 1); root.add(listButton, 13, 9, 2, 1);
@ -84,35 +85,19 @@ class DefaultViewHandler extends ViewHandlerBase<PlayerPosition> {
root.add(closeButton, 0, 9, 2, 1); root.add(closeButton, 0, 9, 2, 1);
root.add(configButton, 10, 9, 2, 1); root.add(configButton, 10, 9, 2, 1);
return createPlayerPositionSupplier(existingPosition, xText, yText, zText, world, location, notes); return createPlayerPositionSupplier(
existingPosition,
xText,
yText,
zText,
dimensionButton,
worldNameField,
locationField,
notesField);
} }
private WWidget CreateWorldButton(WSprite worldIcon) { private DimensionButton CreateDimensionButton(WSprite worldIcon, PlayerRawPosition existingPosition) {
WButton button = new WButton(new LiteralText(DimensionKeys.OVERWORLD)); return new DimensionButton(worldIcon, dimensionAware, existingPosition);
button.setOnClick(() -> button.setLabel(new LiteralText(DimensionKeys.NETHER)));
return button;
}
private String getDimension(PlayerRawPosition rawPosition) {
String dimensionIdentifier = rawPosition.getWorldDimension();
if(isDimension(DimensionKeys.OVERWORLD, dimensionIdentifier)) {
return DimensionKeys.OVERWORLD;
}
if(isDimension(DimensionKeys.NETHER, dimensionIdentifier)) {
return DimensionKeys.NETHER;
}
if(isDimension(DimensionKeys.END, dimensionIdentifier)) {
return DimensionKeys.END;
}
return DimensionKeys.UNKNOWN;
}
private boolean isDimension(String dimension, String dimensionIdentifier) {
return dimensionIdentifier != null && dimensionIdentifier.contains(dimension);
} }
public void onSaveButtonClick(Runnable runnable) { public void onSaveButtonClick(Runnable runnable) {
@ -135,17 +120,17 @@ class DefaultViewHandler extends ViewHandlerBase<PlayerPosition> {
this.configButton.setOnClick(runnable); this.configButton.setOnClick(runnable);
} }
private Supplier<PlayerPosition> createPlayerPositionSupplier(PlayerPosition existingPosition, private Supplier<PlayerPosition> createPlayerPositionSupplier(PlayerPosition existingPosition, WTextField xText,
WTextField xText, WTextField yText, WTextField zText, WTextField world, WTextField yText, WTextField zText, DimensionButton dimensionButton, WTextField world, WTextField location,
WTextField location, WTextField notes) { WTextField notes) {
return () -> { return () -> {
String id = CreateId(existingPosition); String id = CreateId(existingPosition);
long x = parseLong(xText); long x = parseLong(xText);
long y = parseLong(yText); long y = parseLong(yText);
long z = parseLong(zText); long z = parseLong(zText);
PlayerRawPosition rawPosition = new PlayerRawPosition(x, y, z, "overworld"); PlayerRawPosition rawPosition = new PlayerRawPosition(x, y, z, dimensionButton.getDimension().getName());
PositionMetadata metadata = CreateMetadata(existingPosition, world, notes); PositionMetadata metadata = CreateMetadata(existingPosition, world, notes);
return new PlayerPosition(id, rawPosition, location.getText(), metadata); return new PlayerPosition(id, rawPosition, location.getText(), metadata);
@ -188,7 +173,6 @@ class DefaultViewHandler extends ViewHandlerBase<PlayerPosition> {
} }
private WWidget CreateLabelForCoordinate(String label) { private WWidget CreateLabelForCoordinate(String label) {
//return new WLabel(label, 0xb80000);
WButton labelButton = new WButton(new LiteralText(label)); WButton labelButton = new WButton(new LiteralText(label));
labelButton.setEnabled(false); labelButton.setEnabled(false);
return labelButton; return labelButton;

View File

@ -0,0 +1,91 @@
package me.bionicbeanie.mods.savecoords.gui.impl;
import io.github.cottonmc.cotton.gui.widget.WButton;
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 net.minecraft.text.LiteralText;
public class DimensionButton extends WButton {
private CircularList<IDimension> allDimensions;
public DimensionButton(WSprite sprite, IDimensionAware dimensionAware, PlayerRawPosition existingPosition) {
allDimensions = new CircularList<IDimension>();
for (IDimension dimension : dimensionAware.getDimensions()) {
allDimensions.add(dimension);
}
IDimension existingDimension = dimensionAware.getCurrentDimension();
if(existingPosition != null) {
existingDimension = dimensionAware.getDimension(existingPosition.getWorldDimension());
}
while(allDimensions.next() != existingDimension);
IDimension currentDimension = allDimensions.current();
sprite.setImage(currentDimension.getSpriteIdentifier());
setLabel(new LiteralText(currentDimension.getName()));
setOnClick(() -> {
allDimensions.next();
IDimension current = getDimension();
sprite.setImage(current.getSpriteIdentifier());
setLabel(new LiteralText(current.getName()));
});
}
public IDimension getDimension() {
return allDimensions.current();
}
}
// TODO : Probably move ad-hoc circular list elsewhere
class Node<T> {
T value;
Node<T> next;
Node(T t) {
this.value = t;
}
}
class CircularList<T> {
Node<T> head = null;
Node<T> tail = null;
Node<T> current = null;
void add(T t) {
if (head == null) {
head = new Node<T>(t);
tail = head;
head.next = tail;
tail.next = head;
return;
}
Node<T> temp = new Node<T>(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;
}
}

View File

@ -0,0 +1,17 @@
package me.bionicbeanie.mods.savecoords.gui.impl;
import io.github.cottonmc.cotton.gui.widget.WSprite;
import me.bionicbeanie.mods.savecoords.util.ResourceUtils;
import net.minecraft.util.Identifier;
public class DimensionSprite extends WSprite {
public DimensionSprite() {
super(ResourceUtils.getIdentifier("unknown"));
}
public void setDimension(String dimensionKey) {
Identifier identifier = ResourceUtils.getIdentifier(dimensionKey);
this.setImage(identifier);
}
}

View File

@ -43,7 +43,7 @@ class ListViewHandler extends ViewHandlerBase<Void> {
public Supplier<Void> setupView(IRootPanel root, Void nullState) { public Supplier<Void> setupView(IRootPanel root, Void nullState) {
List<PlayerPosition> positions = getPositions(fileStore); List<PlayerPosition> positions = getPositions(fileStore);
WListPanel<PlayerPosition, CoordinatesListItemPanel> listPanel = createListPane(positions); WListPanel<PlayerPosition, CoordinatesListItemPanel> listPanel = createListPanel(positions);
root.add(listPanel, 0, 0, 15, 9); root.add(listPanel, 0, 0, 15, 9);
root.add(backButton, 0, 9, 2, 1); root.add(backButton, 0, 9, 2, 1);
@ -59,7 +59,7 @@ class ListViewHandler extends ViewHandlerBase<Void> {
return new WButton(new TranslatableText(TranslationKeys.MENU_BACK)); return new WButton(new TranslatableText(TranslationKeys.MENU_BACK));
} }
private WListPanel<PlayerPosition, CoordinatesListItemPanel> createListPane(List<PlayerPosition> positions) { private WListPanel<PlayerPosition, CoordinatesListItemPanel> createListPanel(List<PlayerPosition> positions) {
BiConsumer<PlayerPosition, CoordinatesListItemPanel> configurator = (pos, p) -> p.setPosition(pos, fileStore); BiConsumer<PlayerPosition, CoordinatesListItemPanel> configurator = (pos, p) -> p.setPosition(pos, fileStore);
WListPanel<PlayerPosition, CoordinatesListItemPanel> panel = createListPanel(positions, configurator); WListPanel<PlayerPosition, CoordinatesListItemPanel> panel = createListPanel(positions, configurator);

View File

@ -2,6 +2,7 @@ package me.bionicbeanie.mods.savecoords.gui.impl;
import java.util.List; import java.util.List;
import me.bionicbeanie.mods.savecoords.IDimensionAware;
import me.bionicbeanie.mods.savecoords.IFileStore; import me.bionicbeanie.mods.savecoords.IFileStore;
import me.bionicbeanie.mods.savecoords.IKeyBinds; import me.bionicbeanie.mods.savecoords.IKeyBinds;
import me.bionicbeanie.mods.savecoords.IKeyBinds.IKeyBinding; import me.bionicbeanie.mods.savecoords.IKeyBinds.IKeyBinding;
@ -21,13 +22,16 @@ public class SaveCoordinatesGui implements IModGui {
private IViewHandler<Void> listHandler; private IViewHandler<Void> listHandler;
private IViewHandler<List<IKeyBinding>> configHandler; private IViewHandler<List<IKeyBinding>> configHandler;
private IPlayerLocator locator; private IPlayerLocator locator;
private IDimensionAware dimensionAware;
private IKeyBinds keyBinds; private IKeyBinds keyBinds;
SaveCoordinatesGui(IFileStore fileStore, IPlayerLocator locator, IKeyBinds binds, IGuiController screenController) { SaveCoordinatesGui(IFileStore fileStore, IPlayerLocator locator, IDimensionAware dimensionAware, IKeyBinds binds,
IGuiController screenController) {
this.screenController = screenController; this.screenController = screenController;
this.fileStore = fileStore; this.fileStore = fileStore;
this.keyBinds = binds; this.keyBinds = binds;
this.locator = locator; this.locator = locator;
this.dimensionAware = dimensionAware;
this.defaultHandler = CreateDefaultViewHandler(); this.defaultHandler = CreateDefaultViewHandler();
this.listHandler = CreateListViewHandler(); this.listHandler = CreateListViewHandler();
@ -40,7 +44,7 @@ public class SaveCoordinatesGui implements IModGui {
} }
private IViewHandler<PlayerPosition> CreateDefaultViewHandler() { private IViewHandler<PlayerPosition> CreateDefaultViewHandler() {
DefaultViewHandler handler = new DefaultViewHandler(fileStore, locator); DefaultViewHandler handler = new DefaultViewHandler(fileStore, locator, dimensionAware);
handler.onSaveButtonClick(this::savePosition); handler.onSaveButtonClick(this::savePosition);
handler.onListButtonClick(this::showListView); handler.onListButtonClick(this::showListView);

View File

@ -0,0 +1,83 @@
package me.bionicbeanie.mods.savecoords.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.bionicbeanie.mods.savecoords.IDimensionAware;
import me.bionicbeanie.mods.savecoords.util.ResourceUtils;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.Identifier;
public class DimensionAware implements IDimensionAware {
private List<Dimension> allDimensions;
private List<IDimension> allDimensionsReadOnly;
private IDimension UNKNOWN = new Dimension("Unknown", ResourceUtils.getIdentifier("unknown"));
private MinecraftClient minecraftClient;
public DimensionAware(MinecraftClient minecraftClient) {
this.minecraftClient = minecraftClient;
allDimensions = new ArrayList<>();
initialize(allDimensions);
allDimensionsReadOnly = Collections.unmodifiableList(allDimensions);
}
// TODO: Provide a hook for other mods to add in their dimension info
private void initialize(List<Dimension> dimensions) {
dimensions.add(new Dimension("Overworld", ResourceUtils.getIdentifier("overworld")));
dimensions.add(new Dimension("Nether", ResourceUtils.getIdentifier("nether")));
dimensions.add(new Dimension("End", ResourceUtils.getIdentifier("end")));
}
@Override
public List<IDimension> getDimensions() {
return allDimensionsReadOnly;
}
@Override
public IDimension getCurrentDimension() {
String dimensionKey = minecraftClient.player.getEntityWorld().getRegistryKey().getValue().toString();
return getDimension(dimensionKey);
}
@Override
public IDimension getDimension(String dimensionKey) {
for (Dimension dimension : allDimensions) {
if (dimension.isDimension(dimensionKey)) {
return dimension;
}
}
return UNKNOWN;
}
static class Dimension implements IDimension {
private String name;
private Identifier spriteIdentifier;
Dimension(String name, Identifier spriteIdentifier) {
this.name = name;
this.spriteIdentifier = spriteIdentifier;
}
@Override
public String getName() {
return name;
}
@Override
public Identifier getSpriteIdentifier() {
return spriteIdentifier;
}
boolean isDimension(String registryKey) {
return (registryKey != null && registryKey.toLowerCase().contains(this.name.toLowerCase()));
}
}
}

View File

@ -1,5 +1,6 @@
package me.bionicbeanie.mods.savecoords.impl; package me.bionicbeanie.mods.savecoords.impl;
import me.bionicbeanie.mods.savecoords.IDimensionAware;
import me.bionicbeanie.mods.savecoords.IFileStore; import me.bionicbeanie.mods.savecoords.IFileStore;
import me.bionicbeanie.mods.savecoords.IKeyBinds; import me.bionicbeanie.mods.savecoords.IKeyBinds;
import me.bionicbeanie.mods.savecoords.IPlayerLocator; import me.bionicbeanie.mods.savecoords.IPlayerLocator;
@ -18,4 +19,8 @@ public class Factory {
public static IKeyBinds CreateKeyBinds(IFileStore fileStore) { public static IKeyBinds CreateKeyBinds(IFileStore fileStore) {
return new KeyBinds(fileStore); return new KeyBinds(fileStore);
} }
public static IDimensionAware CreateDimensionAware(MinecraftClient client) {
return new DimensionAware(client);
}
} }

View File

@ -18,6 +18,7 @@ class PlayerLocator implements IPlayerLocator {
long x = Math.round(pos.x); long x = Math.round(pos.x);
long y = Math.round(pos.y); long y = Math.round(pos.y);
long z = Math.round(pos.z); long z = Math.round(pos.z);
String worldDimension = client.player.getEntityWorld().getRegistryKey().getValue().toString(); String worldDimension = client.player.getEntityWorld().getRegistryKey().getValue().toString();
return new PlayerRawPosition(x, y, z, worldDimension); return new PlayerRawPosition(x, y, z, worldDimension);

View File

@ -1,9 +0,0 @@
package me.bionicbeanie.mods.savecoords.util;
public class DimensionKeys {
public static String OVERWORLD = "overworld";
public static String NETHER = "nether";
public static String END = "end";
public static String UNKNOWN = "unknown";
}

View File

@ -21,7 +21,8 @@ public class IdentifiersCache {
} }
public Identifier get(String resourceName) { public Identifier get(String resourceName) {
return cache.getOrDefault(resourceName, cache.get(DEFAULT)); String key = resourceName.toLowerCase();
return cache.getOrDefault(key, cache.get(DEFAULT));
} }
private static void add(String resourceName, Map<String, Identifier> cache) { private static void add(String resourceName, Map<String, Identifier> cache) {

View File

@ -1,6 +1,5 @@
package me.bionicbeanie.mods.savecoords.util; package me.bionicbeanie.mods.savecoords.util;
import io.github.cottonmc.cotton.gui.widget.WSprite;
import io.github.cottonmc.cotton.gui.widget.icon.Icon; import io.github.cottonmc.cotton.gui.widget.icon.Icon;
import io.github.cottonmc.cotton.gui.widget.icon.TextureIcon; import io.github.cottonmc.cotton.gui.widget.icon.TextureIcon;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -9,10 +8,6 @@ public class ResourceUtils {
private static IdentifiersCache cache = new IdentifiersCache(); private static IdentifiersCache cache = new IdentifiersCache();
public static WSprite createWorldIcon(String dimension) {
return new WSprite(getIdentifier(dimension));
}
public static Identifier getIdentifier(String resourceName) { public static Identifier getIdentifier(String resourceName) {
return cache.get(resourceName); return cache.get(resourceName);
} }