···55The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7788+### [W.I.P]
99+- Storage is loaded in memory instead of reading it again and again, Improves speed and IO usage
1010+- Made it so the DeathLocation is only kept in memory (WIP)
1111+- Improved the Storage classes and functions (I'm doing proper java, yipie)
1212+813### [v1.2.2]
914- Handled a case where the client (geyser) will return the language as uppercase instead of lowercase.
1015- Fixed null-pointer exceptions being logged when a language file couldn't be found.
···44import com.google.gson.GsonBuilder;
55import com.mojang.datafixers.util.Pair;
66import dev.mrsnowy.teleport_commands.TeleportCommands;
77+import net.minecraft.core.BlockPos;
7889import java.io.File;
910import java.nio.file.Files;
···1718public class StorageManager {
1819 public static Path STORAGE_FOLDER;
1920 public static Path STORAGE_FILE;
2121+ public static StorageClass STORAGE;
20222123 public static void StorageInit() {
2224 STORAGE_FOLDER = TeleportCommands.SAVE_DIR.resolve("TeleportCommands/");
2325 STORAGE_FILE = STORAGE_FOLDER.resolve("storage.json");
24262527 try {
2828+ // check if the folder exists and create it
2629 if (!Files.exists(STORAGE_FOLDER)) {
2730 Files.createDirectories(STORAGE_FOLDER);
2831 }
29323333+ // check if the file exists and create it
3034 if (!Files.exists(STORAGE_FILE)) {
3135 Files.createFile(STORAGE_FILE);
3236 }
33373434- // create the storage
3838+ // create the basic storage if it is empty
3539 if (new File(String.valueOf(STORAGE_FILE)).length() == 0) {
3636- StorageClass root = new StorageClass();
3737- root.Players = new ArrayList<>();
3838- root.Warps = new ArrayList<>();
3939- StorageSaver(root);
4040+ STORAGE = new StorageClass();
4141+ StorageSaver(); // todo! verify that it creates em correctly
4042 }
41434244 } catch (Exception e) {
4343- TeleportCommands.LOGGER.error("Error while creating the storage file! Exiting! {}", e.getMessage());
4545+ TeleportCommands.LOGGER.error("Error while creating the storage file! Exiting! => ", e);
4446 // crashing is probably better here, otherwise the whole mod will be broken
4547 System.exit(1);
4648 }
4749 }
48504949- public static void StorageAdd(String UUID) throws Exception {
5050- StorageClass storage = StorageRetriever();
5151+ public static StorageClass.Player PlayerAdd(String UUID) {
51525252- Optional<StorageClass.Player> playerStorage = storage.Players.stream()
5353+ // try to find an exising storage for this player
5454+ Optional<StorageClass.Player> playerStorage = STORAGE.Players.stream()
5355 .filter(player -> Objects.equals(UUID, player.UUID))
5456 .findFirst();
55575658 if (playerStorage.isEmpty()) {
5757- StorageClass.Player newPlayer = new StorageClass.Player();
5858-5959- newPlayer.UUID = UUID;
6060- newPlayer.DefaultHome = "";
6161- newPlayer.deathLocation = new StorageClass.Location();
6262- newPlayer.deathLocation.x = new StorageClass.Location().x;
6363- newPlayer.deathLocation.y = new StorageClass.Location().y;
6464- newPlayer.deathLocation.z = new StorageClass.Location().z;
6565- newPlayer.deathLocation.world = "";
6666-6767- newPlayer.Homes = new ArrayList<>();
5959+ StorageClass.Player newPlayer = new StorageClass.Player(UUID); // TODO! verify that it creates the player proper
68606969- List<StorageClass.Player> playerList = storage.Players;
6161+ List<StorageClass.Player> playerList = STORAGE.Players;
7062 playerList.add(newPlayer);
71637272- StorageSaver(storage);
6464+// StorageSaver(); // no need to save since no data is actually set yet!
7365 TeleportCommands.LOGGER.info("Player '{}' added successfully in storage!", UUID);
6666+ return newPlayer;
7467 } else {
7568 TeleportCommands.LOGGER.info("Player '{}' already exists!", UUID);
6969+ return playerStorage.get();
7670 }
7771 }
78727979- public static void StorageSaver(StorageClass storage) throws Exception {
7373+ public static void StorageSaver() throws Exception {
8074 Gson gson = new GsonBuilder().create();
8181- byte[] json = gson.toJson(storage).getBytes();
7575+ byte[] json = gson.toJson( STORAGE ).getBytes();
7676+8277 Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
8378 }
84798585- private static StorageClass StorageRetriever() throws Exception {
8686- // double check that the storage file is intact
8787- if (new File(String.valueOf(STORAGE_FILE)).length() == 0) {
8888- StorageInit();
8989- }
9090- String jsonContent = Files.readString(STORAGE_FILE);
9191- Gson gson = new GsonBuilder().create();
9292- return gson.fromJson(jsonContent, StorageClass.class);
8080+ public static Pair<StorageClass, List<StorageClass.NamedLocation>> getWarpStorage() {
8181+ return new Pair<>(STORAGE, STORAGE.Warps);
9382 }
94839595- public static Pair<StorageClass, List<StorageClass.NamedLocation>> getWarpStorage() throws Exception {
9696- StorageClass storage = StorageRetriever();
9797- return new Pair<>(storage, storage.Warps);
9898- }
8484+ public static Pair<StorageClass, StorageClass.Player> GetPlayerStorage(String UUID) {
9985100100-101101- public static Pair<StorageClass, StorageClass.Player> GetPlayerStorage(String UUID) throws Exception {
102102- StorageClass storage = StorageRetriever();
103103-104104- Optional<StorageClass.Player> playerStorage = storage.Players.stream()
8686+ // try to find an exising storage for this player
8787+ Optional<StorageClass.Player> playerStorage = STORAGE.Players.stream()
10588 .filter(player -> Objects.equals(UUID, player.UUID))
10689 .findFirst();
1079010891 if (playerStorage.isEmpty()) {
109109- StorageAdd(UUID);
9292+ StorageClass.Player player = PlayerAdd(UUID); // create a new player
11093111111- storage = StorageRetriever();
112112-113113- playerStorage = storage.Players.stream()
114114- .filter(player -> Objects.equals(UUID, player.UUID))
115115- .findFirst();
116116-117117- if (playerStorage.isEmpty()) {
118118- throw new Exception("No Player found?!");
119119- }
9494+ return new Pair<>(STORAGE, player);
12095 }
12196122122- return new Pair<>(storage, playerStorage.get());
9797+ return new Pair<>(STORAGE, playerStorage.get());
12398 }
12499125100126101 public static class StorageClass {
127127- public List<NamedLocation> Warps;
128128- public List<Player> Players;
102102+ public static List<NamedLocation> Warps = new ArrayList<>();
103103+ public static List<Player> Players = new ArrayList<>();
129104130105 public static class NamedLocation {
131106 public String name;
132132- public int x;
133133- public int y;
134134- public int z;
135135- public String world;
107107+ public final int x;
108108+ public final int y;
109109+ public final int z;
110110+ public final String world;
111111+112112+ public NamedLocation(String name, BlockPos pos, String world) {
113113+ this.name = name;
114114+ this.x = pos.getX();
115115+ this.y = pos.getY();
116116+ this.z = pos.getZ();
117117+ this.world = world;
118118+ }
136119 }
137120138121 public static class Location {
139139- public int x;
140140- public int y;
141141- public int z;
142142- public String world;
122122+ public int x = 0;
123123+ public int y = 0;
124124+ public int z = 0;
125125+ public String world = "";
143126 }
144127145128 public static class Player {
146146- public String UUID;
147147- public String DefaultHome;
148148- public Location deathLocation;
149149- public List<NamedLocation> Homes;
129129+ public final String UUID;
130130+ public String DefaultHome = "";
131131+ public Location deathLocation; // todo! deprecate
132132+ public List<NamedLocation> Homes = new ArrayList<>();
133133+134134+ public Player(String uuid) {
135135+ this.UUID = uuid;
136136+ }
150137 }
151138 }
152139}
···33import com.google.gson.*;
44import com.mojang.datafixers.util.Pair;
55import dev.mrsnowy.teleport_commands.TeleportCommands;
66-import dev.mrsnowy.teleport_commands.storage.StorageManager;
66+7788import java.io.*;
99import java.nio.charset.StandardCharsets;
1010import java.util.*;
1111import java.util.regex.Matcher;
1212import java.util.regex.Pattern;
1313+import java.util.stream.StreamSupport;
13141415import net.minecraft.core.BlockPos;
1516import net.minecraft.core.particles.ParticleTypes;
···2223import net.minecraft.world.phys.Vec3;
23242425import static dev.mrsnowy.teleport_commands.TeleportCommands.MOD_ID;
2525-import static dev.mrsnowy.teleport_commands.storage.StorageManager.GetPlayerStorage;
2626-import static dev.mrsnowy.teleport_commands.storage.StorageManager.StorageSaver;
2726import static net.minecraft.sounds.SoundEvents.ENDERMAN_TELEPORT;
28272928public class tools {
···6463 }
656466656767- public static void DeathLocationUpdater(BlockPos pos, ServerLevel world, String UUID) throws Exception {
6868- Pair<StorageManager.StorageClass, StorageManager.StorageClass.Player> storages = GetPlayerStorage(UUID);
6969-7070- StorageManager.StorageClass storage = storages.getFirst();
7171- StorageManager.StorageClass.Player playerStorage = storages.getSecond();
7272-7373- playerStorage.deathLocation.x = pos.getX();
7474- playerStorage.deathLocation.y = pos.getY();
7575- playerStorage.deathLocation.z = pos.getZ();
7676- playerStorage.deathLocation.world = world.dimension().location().toString();
7777-7878- StorageSaver(storage);
7979- }
8080-8181-8282- public static Pair<Integer, Optional<Vec3>> teleportSafetyChecker(int playerX, int playerY, int playerZ, ServerLevel world, ServerPlayer player) {
6666+ public static Pair<Integer, Optional<Vec3>> teleportSafetyChecker(BlockPos blockPos, ServerLevel world, ServerPlayer player) {
8367 int row = 1;
8468 int rows = 3;
85698670 BlockPos playerBlockPos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ());
8787- BlockPos blockPos = new BlockPos(playerX, playerY, playerZ);
7171+ int playerX = blockPos.getX();
7272+ int playerY = blockPos.getY();
7373+ int playerZ= blockPos.getZ();
88748975 // find a safe location in an x row radius
9076 if (isBlockPosUnsafe(blockPos, world)) {
···129115 }
130116 }
131117118118+119119+ // function to quickly filter the worlds and compare them to a string
120120+ public static Optional<ServerLevel> getWorld(String worldString) {
121121+122122+ return StreamSupport.stream( TeleportCommands.SERVER.getAllLevels().spliterator(), false ) // woa, this looks silly
123123+ .filter(level -> Objects.equals( level.dimension().location().toString(), worldString ))
124124+ .findFirst();
125125+126126+ }
132127133128134129 // Gets the translated text for each player based on their language, this is fully server side and actually works (UNLIKE MOJANG'S TRANSLATED KEY'S WHICH ARE CLIENT SIDE) (I'm not mad, I swear)
···204199205200206201 private static boolean isBlockPosUnsafe(BlockPos bottomPlayer, ServerLevel world) {
207207- // bottomPlayer is presumed to be the bottom of the player character
208202209203 BlockPos belowPlayer = new BlockPos(bottomPlayer.getX(), bottomPlayer.getY() -1, bottomPlayer.getZ()); // below the player
210204 String belowPlayerId = world.getBlockState(belowPlayer).getBlock().getDescriptionId(); // below the player
···216210217211218212 // check if the death location isn't safe
219219- if (
220220- (belowPlayerId.equals("block.minecraft.water") || !world.getBlockState(belowPlayer).getCollisionShape(world, belowPlayer).isEmpty()) // check if the player is going to fall on teleport
221221- && (world.getBlockState(bottomPlayer).getCollisionShape(world, bottomPlayer).isEmpty() && !unsafeCollisionFreeBlocks.contains(BottomPlayerId)) // check if it is a collision free block, that isn't dangerous
222222- && (!unsafeCollisionFreeBlocks.contains(TopPlayerId)) // check if it is a dangerous collision free block, if it is solid then the player crawls
223223- ) {
213213+ if ((belowPlayerId.equals("block.minecraft.water") || !world.getBlockState(belowPlayer).getCollisionShape(world, belowPlayer).isEmpty()) // check if the player is going to fall on teleport
214214+ && (world.getBlockState(bottomPlayer).getCollisionShape(world, bottomPlayer).isEmpty() && !unsafeCollisionFreeBlocks.contains(BottomPlayerId)) // check if it is a collision free block, that isn't dangerous
215215+ && (!unsafeCollisionFreeBlocks.contains(TopPlayerId))) // check if it is a dangerous collision free block, if it is solid then the player crawls
216216+ {
224217 return false; // it's safe
225218 }
226219 return true; // it's not safe!