Add save and list features

This commit is contained in:
Surya 2021-05-20 22:43:56 +05:30
parent c528cd6790
commit c667dbb187
19 changed files with 324 additions and 146 deletions

View File

@ -1,7 +1,13 @@
# Save Coordinates Fabric MC 1.16.4+ # Save Coordinates Fabric MC 1.16.5+
## Usage ## Usage
`/sc "My House"` - Press `B` for menu.
- Select `save` to save the coordinate.
- Select `list` to view saved coordinates
`/sc Portal` ## Roadmap
- Server side support
- More metadata to a coordinate
- Better gui

View File

@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G
loader_version=0.11.3 loader_version=0.11.3
# Mod Properties # Mod Properties
mod_version = 1.0.0 mod_version = 0.0.1
maven_group = me.bionicbeanie.mods maven_group = me.bionicbeanie.mods
archives_base_name = save-coordinates archives_base_name = save-coordinates

View File

@ -2,28 +2,23 @@ package me.bionicbeanie.mods;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import com.mojang.brigadier.arguments.StringArgumentType; import me.bionicbeanie.mods.api.ICoordinateListHandler;
import com.mojang.brigadier.context.CommandContext; import me.bionicbeanie.mods.api.ICoordinateSaveHandler;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.api.IPositionCalculator;
import me.bionicbeanie.mods.core.ICoordinateSaveHandler; import me.bionicbeanie.mods.api.IScreen;
import me.bionicbeanie.mods.core.IFileStore; import me.bionicbeanie.mods.gui.CoordinatesGui;
import me.bionicbeanie.mods.core.IPositionCalculator;
import me.bionicbeanie.mods.gui.CoordinatesScreen; import me.bionicbeanie.mods.gui.CoordinatesScreen;
import me.bionicbeanie.mods.gui.PlayerPositionGuiDescription; import me.bionicbeanie.mods.impl.CoordinateListHandler;
import me.bionicbeanie.mods.impl.CoordinateSaveHandler; import me.bionicbeanie.mods.impl.CoordinateSaveHandler;
import me.bionicbeanie.mods.impl.FileStore; import me.bionicbeanie.mods.impl.FileStore;
import me.bionicbeanie.mods.impl.PositionCalculator; import me.bionicbeanie.mods.impl.PositionCalculator;
import me.bionicbeanie.mods.model.PlayerRawPosition; import me.bionicbeanie.mods.model.PlayerRawPosition;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v1.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource;
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;
import net.minecraft.client.options.KeyBinding; import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.InputUtil;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
public class SaveCoordinatesClient implements ClientModInitializer { public class SaveCoordinatesClient implements ClientModInitializer {
@ -32,32 +27,25 @@ public class SaveCoordinatesClient implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
ClientCommandManager.DISPATCHER.register(ClientCommandManager.literal("coords").then(ClientCommandManager
.argument("desc", StringArgumentType.string()).executes(SaveCoordinatesClient::printCoordinates)));
KeyBinding keyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding("key.savecoords.coords", KeyBinding keyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding("key.savecoords.coords",
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_H, "category.savecoords.generic")); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_H, "category.savecoords.generic"));
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
while (keyBinding.wasPressed()) { while (keyBinding.wasPressed()) {
PlayerRawPosition rawPosition = positionCalculator.locate(client.player); PlayerRawPosition rawPosition = positionCalculator.locate(client);
IFileStore fileStore = new FileStore(client.runDirectory.getAbsolutePath()); IFileStore fileStore = new FileStore(client.runDirectory.getAbsolutePath());
ICoordinateSaveHandler saveHandler = new CoordinateSaveHandler(fileStore); ICoordinateSaveHandler saveHandler = new CoordinateSaveHandler(fileStore);
client.openScreen(new CoordinatesScreen(new PlayerPositionGuiDescription(rawPosition, saveHandler))); ICoordinateListHandler listHandler = new CoordinateListHandler(fileStore);
IScreen screen = new IScreen() {
@Override
public void close() {
client.openScreen(null);
}
};
client.openScreen(
new CoordinatesScreen(new CoordinatesGui(rawPosition, saveHandler, screen, listHandler)));
} }
}); });
} }
private static int printCoordinates(CommandContext<FabricClientCommandSource> context)
throws CommandSyntaxException {
FabricClientCommandSource source = context.getSource();
PlayerRawPosition position = positionCalculator.locate(source.getPlayer());
Text text = new LiteralText("<Coordinates> " + position.getWorldDimension() + " at " + " [ " + position.getX()
+ " , " + position.getY() + " , " + position.getZ() + " ]");
source.getPlayer().sendMessage(text, false);
return 1;
}
} }

View File

@ -0,0 +1,10 @@
package me.bionicbeanie.mods.api;
import java.util.List;
import me.bionicbeanie.mods.model.PlayerPosition;
public interface ICoordinateListHandler {
List<PlayerPosition> list();
}

View File

@ -1,4 +1,4 @@
package me.bionicbeanie.mods.core; package me.bionicbeanie.mods.api;
import me.bionicbeanie.mods.model.PlayerPosition; import me.bionicbeanie.mods.model.PlayerPosition;

View File

@ -1,4 +1,4 @@
package me.bionicbeanie.mods.core; package me.bionicbeanie.mods.api;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -10,4 +10,6 @@ public interface IFileStore {
public void save(List<PlayerPosition> positions) throws IOException; public void save(List<PlayerPosition> positions) throws IOException;
public void save(PlayerPosition position) throws IOException; public void save(PlayerPosition position) throws IOException;
public List<PlayerPosition> list() throws IOException;
} }

View File

@ -0,0 +1,9 @@
package me.bionicbeanie.mods.api;
import me.bionicbeanie.mods.model.PlayerRawPosition;
import net.minecraft.client.MinecraftClient;
public interface IPositionCalculator {
public PlayerRawPosition locate(MinecraftClient client);
}

View File

@ -0,0 +1,6 @@
package me.bionicbeanie.mods.api;
public interface IScreen {
void close();
}

View File

@ -1,9 +0,0 @@
package me.bionicbeanie.mods.core;
import me.bionicbeanie.mods.model.PlayerRawPosition;
import net.minecraft.client.network.ClientPlayerEntity;
public interface IPositionCalculator {
public PlayerRawPosition locate(ClientPlayerEntity player);
}

View File

@ -0,0 +1,37 @@
package me.bionicbeanie.mods.gui;
import io.github.cottonmc.cotton.gui.widget.WLabel;
import io.github.cottonmc.cotton.gui.widget.WPlainPanel;
import io.github.cottonmc.cotton.gui.widget.WSprite;
import me.bionicbeanie.mods.model.PlayerPosition;
import me.bionicbeanie.mods.util.DimensionSpriteUtil;
import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier;
public class CoordinateListItem extends WPlainPanel{
private WLabel coordinates;
private WLabel location;
private WSprite icon;
public CoordinateListItem() {
this.coordinates = new WLabel("Foo");
this.location = new WLabel("Foo");
this.icon = new WSprite(new Identifier("minecraft:textures/item/ender_eye.png"));
this.add(icon, 0, 0, 1*18, 1*18);
this.add(coordinates, 1*18, 0, 2*18, 1*18);
this.add(location, 0, 1*18, 3*18, 1*18);
this.icon.setSize(1*18, 1*18);
this.coordinates.setSize(2*18, 1*18);
this.location.setSize(3*18, 1*18);
this.setSize(3*18, 2*18);
}
public void setPosition(PlayerPosition position) {
this.icon.setImage(DimensionSpriteUtil.CreateWorldIconIdentifier(position.getWorldDimension()));
this.location.setText(new LiteralText(position.getLocationName()));
this.coordinates.setText(new LiteralText(position.getX() + "," + position.getY() + "," + position.getZ()));
}
}

View File

@ -0,0 +1,144 @@
package me.bionicbeanie.mods.gui;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
import io.github.cottonmc.cotton.gui.widget.WButton;
import io.github.cottonmc.cotton.gui.widget.WGridPanel;
import io.github.cottonmc.cotton.gui.widget.WListPanel;
import io.github.cottonmc.cotton.gui.widget.WText;
import io.github.cottonmc.cotton.gui.widget.WTextField;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import me.bionicbeanie.mods.api.ICoordinateListHandler;
import me.bionicbeanie.mods.api.ICoordinateSaveHandler;
import me.bionicbeanie.mods.api.IScreen;
import me.bionicbeanie.mods.model.PlayerPosition;
import me.bionicbeanie.mods.model.PlayerRawPosition;
import me.bionicbeanie.mods.util.DimensionSpriteUtil;
import net.minecraft.text.LiteralText;
public class CoordinatesGui extends LightweightGuiDescription {
private WGridPanel root;
private ICoordinateSaveHandler coordinateSaveHandler;
private ICoordinateListHandler coordinateListHandler;
private PlayerRawPosition rawPosition;
private List<WWidget> children;
private IScreen screen;
public CoordinatesGui(PlayerRawPosition rawPosition, ICoordinateSaveHandler onSave, IScreen screen,
ICoordinateListHandler onList) {
this.root = createRootPanel();
this.rawPosition = rawPosition;
this.coordinateSaveHandler = onSave;
this.coordinateListHandler = onList;
this.screen = screen;
this.children = new ArrayList<>();
reset();
initializeDefaultView();
root.validate(this);
}
private void initializeDefaultView() {
WWidget xText = CreateWidgetForCoordinate(rawPosition.getX());
WWidget yText = CreateWidgetForCoordinate(rawPosition.getY());
WWidget zText = CreateWidgetForCoordinate(rawPosition.getZ());
add(xText, 0, 1, 2, 1);
add(yText, 0, 2, 2, 1);
add(zText, 0, 3, 2, 1);
WWidget icon = DimensionSpriteUtil.CreateWorldIcon(rawPosition.getWorldDimension());
add(icon, 4, 0, 1, 1);
WTextField name = CreateNameField();
add(name, 2, 2, 5, 1);
WWidget save = CreateSaveButton(coordinateSaveHandler, rawPosition, name);
add(save, 5, 5, 2, 1);
WWidget list = CreateListButton();
add(list, 0, 5, 2, 1);
}
private void initializeListView(List<PlayerPosition> playerPositions) {
BiConsumer<PlayerPosition, CoordinateListItem> configurator = (PlayerPosition position,
CoordinateListItem panel) -> {
panel.setPosition(position);
};
WListPanel<PlayerPosition, CoordinateListItem> listPanel = new WListPanel<>(playerPositions,
CoordinateListItem::new, configurator);
listPanel.setListItemHeight(2 * 18);
add(listPanel, 0, 0, 7, 7);
}
private void add(WWidget widget, int x, int y, int w, int h) {
root.add(widget, x, y, w, h);
children.add(widget);
}
private void reset() {
children.forEach(root::remove);
children.clear();
}
private WGridPanel createRootPanel() {
WGridPanel panel = new WGridPanel(18);
panel.setSize(7 * 18, 7 * 18);
setRootPanel(panel);
return panel;
}
private WWidget CreateWidgetForCoordinate(long l) {
return new WText(new LiteralText(String.valueOf(l)), 0x3939ac);
}
private WTextField CreateNameField() {
return new WTextField(new LiteralText("name"));
}
private WWidget CreateSaveButton(ICoordinateSaveHandler onSaveHandler, PlayerRawPosition rawPosition,
WTextField textField) {
WButton button = new WButton(new LiteralText("save"));
button.setOnClick(new Runnable() {
@Override
public void run() {
onSaveHandler.save(new PlayerPosition(rawPosition, textField.getText()));
reset();
screen.close();
}
});
return button;
}
private WWidget CreateListButton() {
CoordinatesGui gui = this;
WButton button = new WButton(new LiteralText("list"));
button.setOnClick(new Runnable() {
@Override
public void run() {
reset();
root.validate(gui);
List<PlayerPosition> playerPositions = coordinateListHandler.list();
initializeListView(playerPositions);
root.validate(gui);
}
});
return button;
}
}

View File

@ -1,76 +0,0 @@
package me.bionicbeanie.mods.gui;
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
import io.github.cottonmc.cotton.gui.widget.WButton;
import io.github.cottonmc.cotton.gui.widget.WGridPanel;
import io.github.cottonmc.cotton.gui.widget.WSprite;
import io.github.cottonmc.cotton.gui.widget.WText;
import io.github.cottonmc.cotton.gui.widget.WTextField;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import me.bionicbeanie.mods.core.ICoordinateSaveHandler;
import me.bionicbeanie.mods.model.PlayerPosition;
import me.bionicbeanie.mods.model.PlayerRawPosition;
import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier;
public class PlayerPositionGuiDescription extends LightweightGuiDescription {
public PlayerPositionGuiDescription(PlayerRawPosition rawPosition, ICoordinateSaveHandler onSave) {
WGridPanel root = new WGridPanel(18);
setRootPanel(root);
// 18 * 18 is the size of 1 item slot. Inset is 7 px
// Dims should be 18 * 3 + 14 by 18 + 14
root.setSize(70, 34);
WWidget xText = CreateWidgetForCoordinate(rawPosition.getX());
WWidget yText = CreateWidgetForCoordinate(rawPosition.getY());
WWidget zText = CreateWidgetForCoordinate(rawPosition.getZ());
root.add(xText, 0, 1, 5, 2);
root.add(yText, 0, 2, 5, 2);
root.add(zText, 0, 3, 5, 2);
WWidget icon = CreateWorldIcon(rawPosition.getWorldDimension());
root.add(icon, 3, 0, 1, 1);
WTextField name = CreateNameField();
root.add(name, 2, 2, 5, 5);
WWidget save = CreateSaveButton(onSave, rawPosition, name);
root.add(save, 3, 4, 2, 2);
root.validate(this);
}
private WWidget CreateWidgetForCoordinate(long l) {
return new WText(new LiteralText(String.valueOf(l)), 0x3939ac);
}
private WWidget CreateWorldIcon(String dimension) {
String dimensionItem = "netherite_ingot";
if(dimension.contains("overworld")) {
dimensionItem = "diamond";
} else if(dimension.contains("end")) {
dimensionItem = "ender_eye";
}
return new WSprite(new Identifier("minecraft:textures/item/" + dimensionItem + ".png"));
}
private WTextField CreateNameField() {
return new WTextField(new LiteralText("name"));
}
private WWidget CreateSaveButton(ICoordinateSaveHandler onSaveHandler, PlayerRawPosition rawPosition, WTextField textField) {
WButton button = new WButton(new LiteralText("save"));
button.setOnClick(new Runnable() {
@Override
public void run() {
onSaveHandler.save(new PlayerPosition(rawPosition, textField.getText()));
}
});
return button;
}
}

View File

@ -0,0 +1,29 @@
package me.bionicbeanie.mods.impl;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import me.bionicbeanie.mods.api.ICoordinateListHandler;
import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.model.PlayerPosition;
public class CoordinateListHandler implements ICoordinateListHandler{
private IFileStore fileStore;
public CoordinateListHandler(IFileStore fileStore) {
this.fileStore = fileStore;
}
@Override
public List<PlayerPosition> list() {
try {
return fileStore.list();
} catch (IOException e) {
return Collections.emptyList();
}
}
}

View File

@ -2,8 +2,8 @@ package me.bionicbeanie.mods.impl;
import java.io.IOException; import java.io.IOException;
import me.bionicbeanie.mods.core.ICoordinateSaveHandler; import me.bionicbeanie.mods.api.ICoordinateSaveHandler;
import me.bionicbeanie.mods.core.IFileStore; import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.model.PlayerPosition; import me.bionicbeanie.mods.model.PlayerPosition;
public class CoordinateSaveHandler implements ICoordinateSaveHandler{ public class CoordinateSaveHandler implements ICoordinateSaveHandler{

View File

@ -11,7 +11,7 @@ import java.util.List;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import me.bionicbeanie.mods.core.IFileStore; import me.bionicbeanie.mods.api.IFileStore;
import me.bionicbeanie.mods.model.PlayerPosition; import me.bionicbeanie.mods.model.PlayerPosition;
public class FileStore implements IFileStore { public class FileStore implements IFileStore {
@ -43,21 +43,28 @@ public class FileStore implements IFileStore {
} }
@Override @Override
public void save(PlayerPosition position) throws IOException { public List<PlayerPosition> list() throws IOException {
List<String> lines = Files.readAllLines(saveFilePath); List<String> lines = Files.readAllLines(saveFilePath);
PlayerPosition[] players = gson.fromJson(String.join("", lines), PlayerPosition[].class); PlayerPosition[] positions = gson.fromJson(String.join("", lines), PlayerPosition[].class);
List<PlayerPosition> playersList = new LinkedList<>(); List<PlayerPosition> playerPositionList = new LinkedList<>();
if(players != null) { if(positions != null) {
for(int i = 0; i < players.length; ++i) { for(int i = 0; i < positions.length; ++i) {
playersList.add(players[i]); playerPositionList.add(positions[i]);
} }
} }
playersList.add(position); return playerPositionList;
}
String serialized = gson.toJson(playersList.toArray()); @Override
public void save(PlayerPosition position) throws IOException {
List<PlayerPosition> playerPositions = list();
playerPositions.add(position);
String serialized = gson.toJson(playerPositions.toArray());
Files.writeString(saveFilePath, serialized, StandardOpenOption.WRITE); Files.writeString(saveFilePath, serialized, StandardOpenOption.WRITE);
} }

View File

@ -1,18 +1,18 @@
package me.bionicbeanie.mods.impl; package me.bionicbeanie.mods.impl;
import me.bionicbeanie.mods.core.IPositionCalculator; import me.bionicbeanie.mods.api.IPositionCalculator;
import me.bionicbeanie.mods.model.PlayerRawPosition; import me.bionicbeanie.mods.model.PlayerRawPosition;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
public class PositionCalculator implements IPositionCalculator{ public class PositionCalculator implements IPositionCalculator {
public PlayerRawPosition locate(ClientPlayerEntity player) { public PlayerRawPosition locate(MinecraftClient client) {
Vec3d pos = player.getPos(); Vec3d pos = client.player.getPos();
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 = player.world.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

@ -26,4 +26,5 @@ public class PlayerRawPosition {
public String getWorldDimension() { public String getWorldDimension() {
return worldDimension; return worldDimension;
} }
} }

View File

@ -0,0 +1,24 @@
package me.bionicbeanie.mods.util;
import io.github.cottonmc.cotton.gui.widget.WSprite;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import net.minecraft.util.Identifier;
public class DimensionSpriteUtil {
public static WWidget CreateWorldIcon(String dimension) {
return new WSprite(CreateWorldIconIdentifier(dimension));
}
public static Identifier CreateWorldIconIdentifier(String dimension) {
String dimensionItem = "netherite_ingot";
if (dimension.contains("overworld")) {
dimensionItem = "diamond";
} else if (dimension.contains("end")) {
dimensionItem = "ender_eye";
}
return new Identifier("minecraft:textures/item/" + dimensionItem + ".png");
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

After

Width:  |  Height:  |  Size: 10 KiB