Add 'edit' functionality, improve ui, fix modularity, sort positions based on last modified, store more metadata

This commit is contained in:
Surya 2021-05-28 23:48:09 +05:30
parent 0ee7dfbde5
commit ff679311cd
21 changed files with 470 additions and 134 deletions

View File

@ -13,6 +13,7 @@ import me.bionicbeanie.mods.gui.view.DefaultViewHandler;
import me.bionicbeanie.mods.gui.view.ListViewHandler; import me.bionicbeanie.mods.gui.view.ListViewHandler;
import me.bionicbeanie.mods.impl.FileStore; import me.bionicbeanie.mods.impl.FileStore;
import me.bionicbeanie.mods.impl.PlayerLocator; import me.bionicbeanie.mods.impl.PlayerLocator;
import me.bionicbeanie.mods.model.PlayerPosition;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
@ -50,11 +51,11 @@ public class SaveCoordinatesClient implements ClientModInitializer {
private IGui CreateModGui(MinecraftClient client) { private IGui CreateModGui(MinecraftClient client) {
IGui gui = new SaveCoordinatesGui(); IGui gui = new SaveCoordinatesGui();
IFileStore fileStore = new FileStore(client.runDirectory.getAbsolutePath()); IFileStore fileStore = new FileStore(client.runDirectory.getAbsolutePath());
IViewHandler saveHandler = new DefaultViewHandler(fileStore, locator, client, gui); IViewHandler<PlayerPosition> defaultHandler = new DefaultViewHandler(fileStore, locator, client, gui);
IViewHandler listHandler = new ListViewHandler(fileStore, gui, client); IViewHandler<Void> listHandler = new ListViewHandler(fileStore, gui, client);
IScreenController screenController = new ScreenController(client); IScreenController screenController = new ScreenController(client);
gui.init(saveHandler, listHandler, screenController); gui.init(defaultHandler, listHandler, screenController);
return gui; return gui;
} }

View File

@ -7,8 +7,12 @@ import me.bionicbeanie.mods.model.PlayerPosition;
public interface IFileStore { public interface IFileStore {
public void save(PlayerPosition position) throws IOException; public String getDefaultWorld() throws IOException;
public void setDefaultWorld(String defaultWorldName) throws IOException;
public void save(PlayerPosition position) throws IOException;
public void delete(String id) throws IOException; public void delete(String id) throws IOException;
public List<PlayerPosition> list() throws IOException; public List<PlayerPosition> list() throws IOException;

View File

@ -1,13 +1,18 @@
package me.bionicbeanie.mods.api; package me.bionicbeanie.mods.api;
import me.bionicbeanie.mods.model.PlayerPosition;
public interface IGui { public interface IGui {
public void init(IViewHandler saveHandler, IViewHandler listHandler, IScreenController screenController); public void init(IViewHandler<PlayerPosition> saveHandler, IViewHandler<Void> listHandler,
IScreenController screenController);
public void showDefaultView(); public void showDefaultView();
public void setDefaultViewState(PlayerPosition position);
public void showListView(); public void showListView();
public void close(); public void close();
} }

View File

@ -1,7 +1,9 @@
package me.bionicbeanie.mods.api; package me.bionicbeanie.mods.api;
public interface IViewHandler { public interface IViewHandler<T> {
void setState(T state);
void clearState();
void placeWidgets(IRootGridPanel rootPanel); void placeWidgets(IRootGridPanel rootPanel);
} }

View File

@ -0,0 +1,5 @@
package me.bionicbeanie.mods.api;
public interface IViewOperation extends Runnable {
}

View File

@ -3,20 +3,22 @@ package me.bionicbeanie.mods.gui;
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription; import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
import me.bionicbeanie.mods.api.IGui; import me.bionicbeanie.mods.api.IGui;
import me.bionicbeanie.mods.api.IViewHandler; import me.bionicbeanie.mods.api.IViewHandler;
import me.bionicbeanie.mods.model.PlayerPosition;
import me.bionicbeanie.mods.api.IRootGridPanel; import me.bionicbeanie.mods.api.IRootGridPanel;
import me.bionicbeanie.mods.api.IScreenController; import me.bionicbeanie.mods.api.IScreenController;
public class SaveCoordinatesGui extends LightweightGuiDescription implements IGui { public class SaveCoordinatesGui extends LightweightGuiDescription implements IGui {
private IRootGridPanel rootGridPanel; private IRootGridPanel rootGridPanel;
private IViewHandler saveHandler; private IViewHandler<PlayerPosition> defaultHandler;
private IViewHandler listHandler; private IViewHandler<Void> listHandler;
private IScreenController screenController; private IScreenController screenController;
@Override @Override
public void init(IViewHandler saveHandler, IViewHandler listHandler, IScreenController screenController) { public void init(IViewHandler<PlayerPosition> saveHandler, IViewHandler<Void> listHandler,
IScreenController screenController) {
this.rootGridPanel = createRootPanel(); this.rootGridPanel = createRootPanel();
this.saveHandler = saveHandler; this.defaultHandler = saveHandler;
this.listHandler = listHandler; this.listHandler = listHandler;
this.screenController = screenController; this.screenController = screenController;
@ -25,7 +27,12 @@ public class SaveCoordinatesGui extends LightweightGuiDescription implements IGu
@Override @Override
public void showDefaultView() { public void showDefaultView() {
showView(saveHandler); showView(defaultHandler);
}
@Override
public void setDefaultViewState(PlayerPosition position) {
defaultHandler.setState(position);
} }
@Override @Override
@ -44,15 +51,16 @@ public class SaveCoordinatesGui extends LightweightGuiDescription implements IGu
private IRootGridPanel createRootPanel() { private IRootGridPanel createRootPanel() {
RootGridPanel panel = new RootGridPanel(18); RootGridPanel panel = new RootGridPanel(18);
panel.setSize(10 * 18, 10 * 18); panel.setSize(15 * 18, 10 * 18);
setRootPanel(panel); setRootPanel(panel);
return panel; return panel;
} }
private void showView(IViewHandler handler) { private void showView(IViewHandler<?> handler) {
rootGridPanel.reset(); rootGridPanel.reset();
handler.placeWidgets(rootGridPanel); handler.placeWidgets(rootGridPanel);
rootGridPanel.validate(this); rootGridPanel.validate(this);
} }
} }

View File

@ -1,8 +1,5 @@
package me.bionicbeanie.mods.gui.view; package me.bionicbeanie.mods.gui.view;
import java.io.IOException;
import java.util.UUID;
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.WLabel;
import io.github.cottonmc.cotton.gui.widget.WText; import io.github.cottonmc.cotton.gui.widget.WText;
@ -18,7 +15,7 @@ import me.bionicbeanie.mods.util.DimensionSpriteUtil;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
public class DefaultViewHandler extends ViewHandlerBase { public class DefaultViewHandler extends ViewHandlerBase<PlayerPosition> {
private IPlayerLocator locator; private IPlayerLocator locator;
@ -28,37 +25,64 @@ public class DefaultViewHandler extends ViewHandlerBase {
} }
@Override @Override
public void placeWidgets(IRootGridPanel root) { public void placeWidgets(IRootGridPanel root, PlayerPosition existingPosition) {
PlayerRawPosition rawPosition = locator.locate(client); PlayerRawPosition rawPosition = existingPosition == null ? locator.locate(client) : existingPosition;
WWidget xLabel = CreateLabelForCoorindate("X");
WWidget yLabel = CreateLabelForCoorindate("Y");
WWidget zLabel = CreateLabelForCoorindate("Z");
WWidget xLabel= CreateLabelForCoorindate("X");
WWidget yLabel= CreateLabelForCoorindate("Y");
WWidget zLabel= CreateLabelForCoorindate("Z");
WWidget xText = CreateWidgetForCoordinate(rawPosition.getX()); WWidget xText = CreateWidgetForCoordinate(rawPosition.getX());
WWidget yText = CreateWidgetForCoordinate(rawPosition.getY()); WWidget yText = CreateWidgetForCoordinate(rawPosition.getY());
WWidget zText = CreateWidgetForCoordinate(rawPosition.getZ()); WWidget zText = CreateWidgetForCoordinate(rawPosition.getZ());
root.add(xLabel, 1, 1, 2, 1); root.add(xLabel, 2, 1, 2, 1);
root.add(yLabel, 1, 2, 2, 1); root.add(yLabel, 2, 2, 2, 1);
root.add(zLabel, 1, 3, 2, 1); root.add(zLabel, 2, 3, 2, 1);
root.add(xText, 2, 1, 2, 1); root.add(xText, 3, 1, 2, 1);
root.add(yText, 2, 2, 2, 1); root.add(yText, 3, 2, 2, 1);
root.add(zText, 2, 3, 2, 1); root.add(zText, 3, 3, 2, 1);
WWidget icon = DimensionSpriteUtil.CreateWorldIcon(rawPosition.getWorldDimension()); WWidget icon = DimensionSpriteUtil.CreateWorldIcon(rawPosition.getWorldDimension());
root.add(icon, 6, 1, 2, 2); root.add(icon, 8, 1, 2, 2);
WTextField name = CreateNameField(); String defaultWorld = getDefaultWorld(existingPosition);
root.add(name, 0, 6, 8, 1); WTextField world = CreateWorldField(defaultWorld);
root.add(world, 0, 4, 4, 1);
WWidget save = CreateSaveButton(rawPosition, name); WTextField location = CreateLocationField(existingPosition);
root.add(save, 9, 6, 2, 1); root.add(location, 5, 4, 7, 1);
WTextField notes = CreateNotesField(existingPosition);
root.add(notes, 0, 6, 12, 1);
WWidget save = CreateSaveButton(rawPosition, location, notes, world, existingPosition);
root.add(save, 13, 6, 2, 1);
WWidget list = CreateListButton(); WWidget list = CreateListButton();
root.add(list, 9, 8, 2, 1); root.add(list, 13, 9, 2, 1);
WWidget ping = CreatePingButton(rawPosition);
root.add(ping, 13, 1, 2, 1);
WWidget close = CreateCloseButton();
root.add(close, 0, 9, 2, 1);
}
private String getDefaultWorld(PlayerPosition existingPosition) {
if (existingPosition != null && existingPosition.getPositionMetadata().getWorldName() != null) {
return existingPosition.getPositionMetadata().getWorldName();
}
try {
return fileStore.getDefaultWorld();
} catch (Exception e) {
e.printStackTrace();
}
return "";
} }
private WWidget CreateLabelForCoorindate(String label) { private WWidget CreateLabelForCoorindate(String label) {
@ -69,31 +93,57 @@ public class DefaultViewHandler extends ViewHandlerBase {
return new WText(new LiteralText(String.valueOf(l)), 0x3939ac); return new WText(new LiteralText(String.valueOf(l)), 0x3939ac);
} }
private WTextField CreateNameField() { private WTextField CreateLocationField(PlayerPosition existingPosition) {
return new WTextField(new LiteralText("location name")); WTextField location = new WTextField(new LiteralText("location name"));
if (existingPosition != null) {
location.setText(existingPosition.getLocationName());
}
location.setMaxLength(20);
return location;
} }
private WWidget CreateSaveButton(PlayerRawPosition rawPosition, WTextField textField) { private WTextField CreateNotesField(PlayerPosition existingPosition) {
WButton button = new WButton(new LiteralText("save")); WTextField notes = new WTextField(new LiteralText("additional notes"));
button.setOnClick(new Runnable() {
@Override
public void run() {
try {
String id = UUID.randomUUID().toString();
fileStore.save(new PlayerPosition(id, rawPosition, textField.getText(), null));
} catch (IOException e) {
e.printStackTrace();
}
gui.close(); if (existingPosition != null && existingPosition.getPositionMetadata() != null) {
} notes.setText(existingPosition.getPositionMetadata().getNotes());
}); }
return notes;
}
private WTextField CreateWorldField(String defaultWorld) {
WTextField world = new WTextField(new LiteralText("world name"));
world.setMaxLength(7);
world.setText(defaultWorld);
return world;
}
private WWidget CreateSaveButton(PlayerRawPosition rawPosition, WTextField location, WTextField notes,
WTextField world, PlayerPosition existingPosition) {
WButton button = new WButton(new LiteralText("SAVE"));
button.setOnClick(new SaveOperation(fileStore, gui, rawPosition, world, location, notes, existingPosition));
return button; return button;
} }
private WWidget CreateListButton() { private WWidget CreateListButton() {
WButton button = new WButton(new LiteralText("list")); WButton button = new WButton(new LiteralText("LIST"));
button.setOnClick(gui::showListView); button.setOnClick(gui::showListView);
return button; return button;
} }
private WWidget CreatePingButton(PlayerRawPosition rawPosition) {
WButton button = new WButton(new LiteralText("PING"));
button.setOnClick(new PingOperation(fileStore, gui, rawPosition));
return button;
}
private WWidget CreateCloseButton() {
WButton button = new WButton(new LiteralText("CLOSE"));
button.setOnClick(gui::close);
return button;
}
} }

View File

@ -0,0 +1,18 @@
package me.bionicbeanie.mods.gui.view;
import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IGui;
import me.bionicbeanie.mods.model.PlayerPosition;
public class DeleteOperation extends ViewPositionOperationBase {
public DeleteOperation(IFileStore fileStore, IGui gui, PlayerPosition position) {
super(fileStore, gui, position);
}
@Override
protected void executeOperation(IFileStore fileStore, IGui gui, PlayerPosition position) throws Exception {
fileStore.delete(position.getId());
gui.showListView();
}
}

View File

@ -1,6 +1,7 @@
package me.bionicbeanie.mods.gui.view; package me.bionicbeanie.mods.gui.view;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -18,34 +19,53 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
public class ListViewHandler extends ViewHandlerBase { public class ListViewHandler extends ViewHandlerBase<Void> {
public ListViewHandler(IFileStore fileStore, IGui gui, MinecraftClient client) { public ListViewHandler(IFileStore fileStore, IGui gui, MinecraftClient client) {
super(fileStore, gui, client); super(fileStore, gui, client);
} }
@Override @Override
public void placeWidgets(IRootGridPanel root) { public void placeWidgets(IRootGridPanel root, Void nullState) {
BiConsumer<PlayerPosition, CoordinatesListItemPanel> configurator = (PlayerPosition position, List<PlayerPosition> positions = getPositions(fileStore);
CoordinatesListItemPanel panel) -> { WListPanel<PlayerPosition, CoordinatesListItemPanel> listPanel = createListPane(positions);
WButton backButton = createBackButton();
root.add(listPanel, 0, 0, 15, 9);
root.add(backButton, 0, 9, 2, 1);
}
private WButton createBackButton() {
WButton backButton = new WButton(new LiteralText("BACK"));
backButton.setOnClick(gui::showDefaultView);
return backButton;
}
private WListPanel<PlayerPosition, CoordinatesListItemPanel> createListPane(List<PlayerPosition> positions) {
BiConsumer<PlayerPosition, CoordinatesListItemPanel> configurator = (position, panel) -> {
panel.setPosition(position, fileStore, gui); panel.setPosition(position, fileStore, gui);
}; };
List<PlayerPosition> positions; WListPanel<PlayerPosition, CoordinatesListItemPanel> panel = new WListPanel<>(positions,
try {
positions = fileStore.list();
} catch (IOException e) {
e.printStackTrace();
return;
}
WListPanel<PlayerPosition, CoordinatesListItemPanel> listPanel = new WListPanel<>(positions,
CoordinatesListItemPanel::new, configurator); CoordinatesListItemPanel::new, configurator);
listPanel.setListItemHeight(2 * 18); panel.setListItemHeight(2 * 18);
root.add(listPanel, 0, 0, 11, 11); return panel;
}
private List<PlayerPosition> getPositions(IFileStore fileStore) {
try {
List<PlayerPosition> positions = fileStore.list();
Collections.sort(positions, (p1, p2) -> p2.getPositionMetadata().getLastModified()
.compareTo(p1.getPositionMetadata().getLastModified()));
return positions;
} catch (IOException e) {
e.printStackTrace();
return Collections.emptyList();
}
} }
public static class CoordinatesListItemPanel extends WPlainPanel { public static class CoordinatesListItemPanel extends WPlainPanel {
@ -54,44 +74,49 @@ public class ListViewHandler extends ViewHandlerBase {
private WLabel location; private WLabel location;
private WSprite icon; private WSprite icon;
private WButton deleteButton; private WButton deleteButton;
private WButton pingButton;
private WButton detailButton;
private WLabel world;
public CoordinatesListItemPanel() { public CoordinatesListItemPanel() {
this.coordinates = new WLabel("Foo"); this.coordinates = new WLabel("Foo");
this.location = new WLabel("Foo"); this.location = new WLabel("Foo");
this.world = new WLabel("Foo");
this.icon = new WSprite(new Identifier("minecraft:textures/item/ender_eye.png")); this.icon = new WSprite(new Identifier("minecraft:textures/item/ender_eye.png"));
this.deleteButton = new WButton(new LiteralText("x")); this.deleteButton = new WButton(new LiteralText("x"));
this.pingButton = new WButton(new LiteralText("!"));
this.detailButton = new WButton(new LiteralText("+"));
this.add(icon, 0, 0, 1 * 9, 1 * 9); this.add(icon, 0, 0, 1 * 9, 1 * 9);
this.add(location, 1 * 18, 0, 4 * 18, 1 * 18); this.add(world, 1 * 18, 0, 3 * 18, 1 * 18);
this.add(location, 4 * 18, 0, 4 * 18, 1 * 18);
this.add(coordinates, 1 * 18, 1 * 18, 9 * 18, 1 * 18); this.add(coordinates, 1 * 18, 1 * 18, 9 * 18, 1 * 18);
this.add(deleteButton, 9 * 18, 0, 1 * 18, 1 * 18); this.add(deleteButton, 13 * 18, 0, 1 * 18, 1 * 18);
this.add(pingButton, 12 * 18, 0, 1 * 18, 1 * 18);
this.add(detailButton, 11 * 18, 0, 1 * 18, 1 * 18);
this.icon.setSize(1 * 15, 1 * 15); this.icon.setSize(1 * 15, 1 * 15);
this.world.setSize(3 * 18, 1 * 18);
this.location.setSize(9 * 18, 1 * 18); this.location.setSize(9 * 18, 1 * 18);
this.coordinates.setSize(2 * 18, 9 * 18); this.coordinates.setSize(2 * 18, 9 * 18);
this.deleteButton.setSize(1 * 18, 1 * 18); this.deleteButton.setSize(1 * 18, 1 * 18);
this.setSize(9 * 18, 2 * 18); this.pingButton.setSize(1 * 18, 1 * 18);
this.detailButton.setSize(1 * 18, 1 * 18);
this.setSize(15 * 18, 2 * 18);
} }
public void setPosition(PlayerPosition position, IFileStore fileStore, IGui gui) { public void setPosition(PlayerPosition position, IFileStore fileStore, IGui gui) {
this.icon.setImage(DimensionSpriteUtil.CreateWorldIconIdentifier(position.getWorldDimension())); this.icon.setImage(DimensionSpriteUtil.CreateWorldIconIdentifier(position.getWorldDimension()));
this.location.setText(new LiteralText(position.getLocationName())); this.location.setText(new LiteralText(position.getLocationName()));
this.location.setColor(0x3939ac); this.location.setColor(0x3939ac);
this.world.setText(new LiteralText("[" + position.getPositionMetadata().getWorldName() + "]"));
this.world.setColor(0xb80000);
this.coordinates this.coordinates
.setText(new LiteralText(position.getX() + ", " + position.getY() + ", " + position.getZ())); .setText(new LiteralText(position.getX() + ", " + position.getY() + ", " + position.getZ()));
this.deleteButton.setOnClick(new Runnable() { this.deleteButton.setOnClick(new DeleteOperation(fileStore, gui, position));
this.pingButton.setOnClick(new PingOperation(fileStore, gui, position));
@Override this.detailButton.setOnClick(new ShowDetailOperation(fileStore, gui, position));
public void run() {
try {
fileStore.delete(position.getId());
gui.showListView();
} catch (IOException e) {
e.printStackTrace();
}
}
});
} }
} }
} }

View File

@ -0,0 +1,23 @@
package me.bionicbeanie.mods.gui.view;
import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IGui;
import me.bionicbeanie.mods.model.PlayerRawPosition;
import net.minecraft.client.MinecraftClient;
public class PingOperation extends ViewOperationBase{
private PlayerRawPosition position;
public PingOperation(IFileStore fileStore, IGui gui, PlayerRawPosition position) {
super(fileStore, gui);
this.position = position;
}
@SuppressWarnings("resource")
@Override
protected void executeOperation(IFileStore fileStore, IGui gui) throws Exception {
MinecraftClient.getInstance().player.sendChatMessage(position.toString());
}
}

View File

@ -0,0 +1,54 @@
package me.bionicbeanie.mods.gui.view;
import java.util.UUID;
import io.github.cottonmc.cotton.gui.widget.WTextField;
import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IGui;
import me.bionicbeanie.mods.model.PlayerPosition;
import me.bionicbeanie.mods.model.PlayerRawPosition;
import me.bionicbeanie.mods.model.PositionMetadata;
public class SaveOperation extends ViewOperationBase {
private PlayerRawPosition rawPosition;
private WTextField location, notes;
private WTextField world;
private PlayerPosition existingPosition;
public SaveOperation(IFileStore fileStore, IGui gui, PlayerRawPosition rawPosition, WTextField world,
WTextField location, WTextField notes, PlayerPosition existingPosition) {
super(fileStore, gui);
this.rawPosition = rawPosition;
this.existingPosition = existingPosition;
this.world = world;
this.location = location;
this.notes = notes;
}
@Override
protected void executeOperation(IFileStore fileStore, IGui gui) throws Exception {
String id = existingPosition == null ? UUID.randomUUID().toString() : existingPosition.getId();
PositionMetadata metadata = CreateMetadata(existingPosition);
PlayerPosition position = new PlayerPosition(id, rawPosition, this.location.getText(), metadata);
fileStore.save(position);
fileStore.setDefaultWorld(position.getPositionMetadata().getWorldName());
gui.showListView();
gui.setDefaultViewState(null);
}
private PositionMetadata CreateMetadata(PlayerPosition existingPosition) {
if(existingPosition == null) {
return new PositionMetadata(this.world.getText(), this.notes.getText());
}
existingPosition.getPositionMetadata().setWorldName(this.world.getText());
existingPosition.getPositionMetadata().setNotes(this.notes.getText());
existingPosition.getPositionMetadata().updateLastModified();
return existingPosition.getPositionMetadata();
}
}

View File

@ -0,0 +1,19 @@
package me.bionicbeanie.mods.gui.view;
import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IGui;
import me.bionicbeanie.mods.model.PlayerPosition;
public class ShowDetailOperation extends ViewPositionOperationBase {
public ShowDetailOperation(IFileStore fileStore, IGui gui, PlayerPosition position) {
super(fileStore, gui, position);
}
@Override
protected void executeOperation(IFileStore fileStore, IGui gui, PlayerPosition position) throws Exception {
gui.setDefaultViewState(position);
gui.showDefaultView();
}
}

View File

@ -3,15 +3,17 @@ package me.bionicbeanie.mods.gui.view;
import io.github.cottonmc.cotton.gui.widget.WWidget; import io.github.cottonmc.cotton.gui.widget.WWidget;
import me.bionicbeanie.mods.api.IFileStore; import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IGui; import me.bionicbeanie.mods.api.IGui;
import me.bionicbeanie.mods.api.IRootGridPanel;
import me.bionicbeanie.mods.api.IViewHandler; import me.bionicbeanie.mods.api.IViewHandler;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
public abstract class ViewHandlerBase implements IViewHandler { public abstract class ViewHandlerBase<T> implements IViewHandler<T> {
protected IFileStore fileStore; protected IFileStore fileStore;
protected IGui gui; protected IGui gui;
protected MinecraftClient client; protected MinecraftClient client;
protected WWidget panel; protected WWidget panel;
private T state;
protected ViewHandlerBase(IFileStore fileStore, IGui gui, MinecraftClient client) { protected ViewHandlerBase(IFileStore fileStore, IGui gui, MinecraftClient client) {
this.fileStore = fileStore; this.fileStore = fileStore;
@ -19,4 +21,21 @@ public abstract class ViewHandlerBase implements IViewHandler {
this.client = client; this.client = client;
} }
protected abstract void placeWidgets(IRootGridPanel rootPanel, T state);
@Override
public void clearState() {
state = null;
}
@Override
public void setState(T state) {
this.state = state;
}
@Override
public void placeWidgets(IRootGridPanel rootPanel) {
placeWidgets(rootPanel, state);
}
} }

View File

@ -0,0 +1,26 @@
package me.bionicbeanie.mods.gui.view;
import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IGui;
public abstract class ViewOperationBase implements Runnable {
private IFileStore fileStore;
private IGui gui;
public ViewOperationBase(IFileStore fileStore, IGui gui) {
this.fileStore = fileStore;
this.gui = gui;
}
@Override
public void run() {
try {
executeOperation(fileStore, gui);
} catch (Exception e) {
e.printStackTrace();
}
}
protected abstract void executeOperation(IFileStore fileStore, IGui gui) throws Exception;
}

View File

@ -0,0 +1,22 @@
package me.bionicbeanie.mods.gui.view;
import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IGui;
import me.bionicbeanie.mods.model.PlayerPosition;
public abstract class ViewPositionOperationBase extends ViewOperationBase{
private PlayerPosition position;
public ViewPositionOperationBase(IFileStore fileStore, IGui gui, PlayerPosition position) {
super(fileStore, gui);
this.position = position;
}
@Override
protected void executeOperation(IFileStore fileStore, IGui gui) throws Exception {
executeOperation(fileStore, gui, position);
}
protected abstract void executeOperation(IFileStore fileStore, IGui gui, PlayerPosition position) throws Exception;
}

View File

@ -15,6 +15,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import me.bionicbeanie.mods.api.IFileStore; import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.model.ModData;
import me.bionicbeanie.mods.model.PlayerPosition; import me.bionicbeanie.mods.model.PlayerPosition;
public class FileStore implements IFileStore { public class FileStore implements IFileStore {
@ -26,12 +27,9 @@ public class FileStore implements IFileStore {
private Gson gson; private Gson gson;
public FileStore(String baseDir) { public FileStore(String baseDir) {
this.gson = new GsonBuilder() this.gson = new GsonBuilder().setPrettyPrinting().setLenient().create();
.setPrettyPrinting()
.setLenient()
.create();
this.saveFilePath = Paths.get(baseDir, DEFAULT_DIR, DEFAULT_FILE); this.saveFilePath = Paths.get(baseDir, DEFAULT_DIR, DEFAULT_FILE);
try { try {
Files.createDirectories(Paths.get(baseDir, DEFAULT_DIR)); Files.createDirectories(Paths.get(baseDir, DEFAULT_DIR));
Files.createFile(this.saveFilePath); Files.createFile(this.saveFilePath);
@ -43,15 +41,28 @@ public class FileStore implements IFileStore {
} }
@Override @Override
public List<PlayerPosition> list() throws IOException { public String getDefaultWorld() throws IOException {
List<String> lines = Files.readAllLines(saveFilePath); ModData data = load();
PlayerPosition[] positions = gson.fromJson(String.join("", lines), PlayerPosition[].class);
return data.defaultWorldName;
}
@Override
public void setDefaultWorld(String defaultWorldName) throws IOException {
ModData data = load();
data.defaultWorldName = defaultWorldName;
dump(data);
}
@Override
public List<PlayerPosition> list() throws IOException {
ModData data = load();
List<PlayerPosition> playerPositionList = new LinkedList<>(); List<PlayerPosition> playerPositionList = new LinkedList<>();
if (positions != null) { if (data.positions != null) {
for (int i = 0; i < positions.length; ++i) { for (int i = 0; i < data.positions.length; ++i) {
playerPositionList.add(positions[i]); playerPositionList.add(data.positions[i]);
} }
} }
@ -60,25 +71,45 @@ public class FileStore implements IFileStore {
@Override @Override
public void save(PlayerPosition position) throws IOException { public void save(PlayerPosition position) throws IOException {
List<PlayerPosition> playerPositions = list(); List<PlayerPosition> playerPositions = list();
playerPositions.removeIf(p -> StringUtils.equalsIgnoreCase(position.getId(), p.getId()));
playerPositions.add(position); playerPositions.add(position);
saveAll(playerPositions); savePositions(playerPositions);
} }
@Override @Override
public void delete(String id) throws IOException { public void delete(String id) throws IOException {
List<PlayerPosition> playerPositions = list(); List<PlayerPosition> playerPositions = list();
playerPositions.removeIf(p -> StringUtils.equalsIgnoreCase(id, p.getId())); playerPositions.removeIf(p -> StringUtils.equalsIgnoreCase(id, p.getId()));
savePositions(playerPositions);
saveAll(playerPositions);
} }
private void saveAll(List<PlayerPosition> playerPositions) throws IOException { private void dump(ModData data) throws IOException {
String serialized = gson.toJson(playerPositions.toArray()); String serialized = gson.toJson(data);
Files.write(saveFilePath, serialized.getBytes(), StandardOpenOption.TRUNCATE_EXISTING); Files.write(saveFilePath, serialized.getBytes(), StandardOpenOption.TRUNCATE_EXISTING);
} }
private void savePositions(List<PlayerPosition> playerPositions) throws IOException {
ModData data = load();
data.positions = playerPositions.toArray(new PlayerPosition[playerPositions.size()]);
dump(data);
}
private ModData load() throws IOException {
List<String> lines = Files.readAllLines(saveFilePath);
try {
return gson.fromJson(String.join("", lines), ModData.class);
} catch (Exception e) {
// Fallback for old versions
ModData data = new ModData();
data.defaultWorldName = "";
data.positions = gson.fromJson(String.join("", lines), PlayerPosition[].class);
dump(data);
return data;
}
}
} }

View File

@ -0,0 +1,8 @@
package me.bionicbeanie.mods.model;
public class ModData {
public String defaultWorldName;
public PlayerPosition[] positions;
}

View File

@ -1,35 +1,18 @@
package me.bionicbeanie.mods.model; package me.bionicbeanie.mods.model;
public class PlayerPosition { public class PlayerPosition extends PlayerRawPosition {
private PlayerRawPosition rawPosition;
private String id, locationName; private String id, locationName;
private PositionMetadata positionMetadata; private PositionMetadata positionMetadata;
public PlayerPosition(String id, PlayerRawPosition rawPosition, String locationName, public PlayerPosition(String id, PlayerRawPosition rawPosition, String locationName,
PositionMetadata positionMetadata) { PositionMetadata positionMetadata) {
super(rawPosition.getX(), rawPosition.getY(), rawPosition.getZ(), rawPosition.getWorldDimension());
this.id = id; this.id = id;
this.rawPosition = rawPosition;
this.positionMetadata = positionMetadata; this.positionMetadata = positionMetadata;
this.locationName = locationName; this.locationName = locationName;
} }
public long getX() {
return rawPosition.getX();
}
public long getY() {
return rawPosition.getY();
}
public long getZ() {
return rawPosition.getZ();
}
public String getWorldDimension() {
return rawPosition.getWorldDimension();
}
public String getLocationName() { public String getLocationName() {
return locationName; return locationName;
} }
@ -41,4 +24,10 @@ public class PlayerPosition {
public String getId() { public String getId() {
return id; return id;
} }
@Override
public String toString() {
return this.locationName + " in [ " + this.getWorldDimension() + " ] at [ " + this.getX() + ", " + this.getY()
+ ", " + this.getZ() + " ]";
}
} }

View File

@ -27,4 +27,9 @@ public class PlayerRawPosition {
return worldDimension; return worldDimension;
} }
@Override
public String toString() {
return "I'm in [ " + worldDimension + " ] at [ " + x + ", " + y + ", " + z + " ]";
}
} }

View File

@ -1,25 +1,44 @@
package me.bionicbeanie.mods.model; package me.bionicbeanie.mods.model;
import java.util.Date; import java.time.LocalDateTime;
public class PositionMetadata { public class PositionMetadata {
private String worldName, notes; private String worldName, notes;
private Date created, lastModified; private LocalDateTime created, lastModified;
public PositionMetadata(String worldName, String notes) {
this.worldName = worldName;
this.notes = notes;
this.created = LocalDateTime.now();
this.lastModified = this.created;
}
public String getWorldName() { public String getWorldName() {
return worldName; return worldName;
} }
public void setWorldName(String worldName) {
this.worldName = worldName;
}
public String getNotes() { public String getNotes() {
return notes; return notes;
} }
public Date getCreated() { public void setNotes(String notes) {
this.notes = notes;
}
public LocalDateTime getCreated() {
return created; return created;
} }
public Date getLastModified() { public LocalDateTime getLastModified() {
return lastModified; return lastModified;
} }
public void updateLastModified() {
this.lastModified = LocalDateTime.now();
}
} }

View File

@ -13,7 +13,10 @@ public class DimensionSpriteUtil {
public static Identifier CreateWorldIconIdentifier(String dimension) { public static Identifier CreateWorldIconIdentifier(String dimension) {
String dimensionItem = "netherite_ingot"; String dimensionItem = "netherite_ingot";
if (dimension.contains("overworld")) { if(dimension == null) {
dimensionItem = "barrier";
}
else if (dimension.contains("overworld")) {
dimensionItem = "totem_of_undying"; dimensionItem = "totem_of_undying";
} else if (dimension.contains("end")) { } else if (dimension.contains("end")) {
dimensionItem = "ender_eye"; dimensionItem = "ender_eye";