diff --git a/CHANGELOG.md b/CHANGELOG.md index 0984c00..1fe0ccb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### [W.I.P] -- Storage is loaded in memory instead of reading it again and again, Improves speed and IO usage -- Made it so the DeathLocation is only kept in memory (WIP) +- Storage is loaded in memory instead of reading it again and again, Improves speed and IO usage. (W.I.P) +- Adding comments to alot of code (W.I.P) +- Made it so the DeathLocation is only kept in memory - Improved the Storage classes and functions (I'm doing proper java, yipie) ### [v1.2.2] diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java b/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java index bf1efc5..d1eabce 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java @@ -4,6 +4,7 @@ import com.mojang.datafixers.util.Pair; import dev.mrsnowy.teleport_commands.storage.StorageManager; import dev.mrsnowy.teleport_commands.commands.*; +import dev.mrsnowy.teleport_commands.storage.backListStorage; import net.minecraft.commands.Commands; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -17,6 +18,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; + import net.minecraft.core.BlockPos; import static dev.mrsnowy.teleport_commands.storage.StorageManager.*; @@ -57,23 +59,12 @@ public static void initializeMod(MinecraftServer server) { // Runs when the playerDeath mixin calls it, updates the /back command position public static void onPlayerDeath(ServerPlayer player) { - try { - BlockPos pos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()); - - Pair storages = GetPlayerStorage(player.getStringUUID()); - - StorageManager.StorageClass.Player playerStorage = storages.getSecond(); - - playerStorage.deathLocation.x = pos.getX(); - playerStorage.deathLocation.y = pos.getY(); - playerStorage.deathLocation.z = pos.getZ(); - playerStorage.deathLocation.world = player.serverLevel().dimension().location().toString(); + BlockPos pos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()); + String world = player.serverLevel().dimension().location().toString(); + String uuid = player.getStringUUID(); - StorageSaver(); - - } catch (Exception e) { - LOGGER.error("Error while saving the player death location! => ", e); - } + backListStorage.backList backList = backListStorage.backList; + backList.setDeathLocation(uuid, pos, world); } // private static StorageManager.StorageClass loadStorage() throws Exception { @@ -83,7 +74,7 @@ public static void onPlayerDeath(ServerPlayer player) { // String jsonContent = Files.readString(STORAGE_FILE); // Gson gson = new GsonBuilder().create(); // -//} +// } // cleans and updates Storage to the newest "version". This is painful private static StorageClass storageValidator() { @@ -155,15 +146,6 @@ private static StorageClass storageValidator() { String DefaultHome = player.has("DefaultHome") ? player.get("DefaultHome").getAsString() : ""; - - // Clean death location after server restart - JsonObject deathLocation = new JsonObject(); - - deathLocation.addProperty("x", 0); - deathLocation.addProperty("y", 0); - deathLocation.addProperty("z", 0); - deathLocation.addProperty("world", ""); - JsonArray homes = new JsonArray(); if (player.has("Homes") && player.get("Homes").isJsonArray() ) { @@ -226,7 +208,6 @@ private static StorageClass storageValidator() { newPlayer.addProperty("UUID", UUID); newPlayer.addProperty("DefaultHome", DefaultHome); - newPlayer.add("deathLocationClass", deathLocation); newPlayer.add("Homes", homes); newPlayersArray.add(newPlayer); diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java index 20f0742..78f5b61 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java @@ -6,6 +6,7 @@ import java.util.*; +import dev.mrsnowy.teleport_commands.storage.backListStorage; import dev.mrsnowy.teleport_commands.utils.tools; import net.minecraft.ChatFormatting; import net.minecraft.commands.Commands; @@ -19,20 +20,6 @@ import static net.minecraft.commands.Commands.argument; public class back { - public static final ArrayList backList = new ArrayList<>(); - - public static class deathLocationClass { - final public String UUID; - final public BlockPos pos; - final public String world; - - public deathLocationClass(String uuid, BlockPos pos, String world) { - this.UUID = uuid; - this.pos = pos; - this.world = world; - backList.add(this); - } - } public static void register(Commands commandManager) { @@ -73,26 +60,29 @@ public static void register(Commands commandManager) { private static void ToDeathLocation(ServerPlayer player, boolean safetyDisabled) { - Optional OptionalDeathLocation = backList.stream() - .filter( deathLocation -> Objects.equals( deathLocation.UUID, player.getStringUUID() )) - .findFirst(); + backListStorage.backList backList = backListStorage.backList; - if (OptionalDeathLocation.isEmpty()) { - player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noLocation", player).withStyle(ChatFormatting.RED), true); + // get the deathLocation + Optional optionalDeathLocation = backList.getDeathLocation( player.getStringUUID() ); + if (optionalDeathLocation.isEmpty()) { + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noLocation", player) + .withStyle(ChatFormatting.RED), true); return; } - deathLocationClass deathLocation = OptionalDeathLocation.get(); + backListStorage.deathLocationClass deathLocation = optionalDeathLocation.get(); + // get the world Optional OptionalWorld = tools.getWorld( deathLocation.world ); if (OptionalWorld.isEmpty()) { - player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noLocation", player).withStyle(ChatFormatting.RED), true); + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noLocation", player) + .withStyle(ChatFormatting.RED), true); return; } ServerLevel world = OptionalWorld.get(); - // check if the death location isn't safe and that safety isn't enabled + // if safety is enabled, check if the death location is safe. if (!safetyDisabled) { Pair> teleportData = teleportSafetyChecker(deathLocation.pos, world, player); diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java index 1931a15..a887580 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java @@ -2,7 +2,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.mojang.datafixers.util.Pair; import dev.mrsnowy.teleport_commands.TeleportCommands; import net.minecraft.core.BlockPos; @@ -48,59 +47,61 @@ public static void StorageInit() { } } - public static StorageClass.Player PlayerAdd(String UUID) { - - // try to find an exising storage for this player - Optional playerStorage = STORAGE.Players.stream() - .filter(player -> Objects.equals(UUID, player.UUID)) - .findFirst(); - - if (playerStorage.isEmpty()) { - StorageClass.Player newPlayer = new StorageClass.Player(UUID); // TODO! verify that it creates the player proper - - List playerList = STORAGE.Players; - playerList.add(newPlayer); - -// StorageSaver(); // no need to save since no data is actually set yet! - TeleportCommands.LOGGER.info("Player '{}' added successfully in storage!", UUID); - return newPlayer; - } else { - TeleportCommands.LOGGER.info("Player '{}' already exists!", UUID); - return playerStorage.get(); - } - } +// public static StorageClass.Player PlayerAdd(String UUID) { +// +// // try to find an exising storage for this player +// Optional playerStorage = STORAGE.Players.stream() +// .filter(player -> Objects.equals(UUID, player.UUID)) +// .findFirst(); +// +// if (playerStorage.isEmpty()) { +// StorageClass.Player newPlayer = new StorageClass.Player(UUID); // TODO! verify that it creates the player proper +// +// List playerList = STORAGE.Players; +// playerList.add(newPlayer); +// +//// StorageSaver(); // no need to save since no data is actually set yet! +// TeleportCommands.LOGGER.info("Player '{}' added successfully in storage!", UUID); +// return newPlayer; +// } else { +// TeleportCommands.LOGGER.info("Player '{}' already exists!", UUID); +// return playerStorage.get(); +// } +// } public static void StorageSaver() throws Exception { Gson gson = new GsonBuilder().create(); byte[] json = gson.toJson( STORAGE ).getBytes(); - Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); - } + TeleportCommands.LOGGER.info(STORAGE.toString()); - public static Pair> getWarpStorage() { - return new Pair<>(STORAGE, STORAGE.Warps); + Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); } - public static Pair GetPlayerStorage(String UUID) { - - // try to find an exising storage for this player - Optional playerStorage = STORAGE.Players.stream() - .filter(player -> Objects.equals(UUID, player.UUID)) - .findFirst(); - - if (playerStorage.isEmpty()) { - StorageClass.Player player = PlayerAdd(UUID); // create a new player - - return new Pair<>(STORAGE, player); - } - - return new Pair<>(STORAGE, playerStorage.get()); - } +// public static Pair> getWarpStorage() { +// return new Pair<>(STORAGE, STORAGE.Warps); +// } + +// public static Pair GetPlayerStorage(String UUID) { +// +// // try to find an exising storage for this player +// Optional playerStorage = STORAGE.Players.stream() +// .filter(player -> Objects.equals(UUID, player.UUID)) +// .findFirst(); +// +// if (playerStorage.isEmpty()) { +// StorageClass.Player player = PlayerAdd(UUID); // create a new player +// +// return new Pair<>(STORAGE, player); +// } +// +// return new Pair<>(STORAGE, playerStorage.get()); +// } public static class StorageClass { - public static List Warps = new ArrayList<>(); - public static List Players = new ArrayList<>(); + public static warpList Warps = new warpList(); + public static playerList Players = new playerList(); public static class NamedLocation { public String name; @@ -118,22 +119,109 @@ public NamedLocation(String name, BlockPos pos, String world) { } } - public static class Location { - public int x = 0; - public int y = 0; - public int z = 0; - public String world = ""; + public static class warpList { + private final ArrayList warpList = new ArrayList<>(); + + // filters the warpList and finds the one with the name (if there is one) + public Optional getWarp(String name) { + return warpList.stream() + .filter( warp -> Objects.equals( warp.name, name )) + .findFirst(); + } + + // returns all warps + public ArrayList getWarps() { + return warpList; + } + + // creates a new warp, if there already is a warp it will update the existing one + public void setWarp(String name, BlockPos pos, String world) throws Exception { + Optional OptionalWarp = getWarp(name); + + if (OptionalWarp.isEmpty()) { + // create a new warp + NamedLocation warp = new NamedLocation(name, pos, world); + warpList.add(warp); + StorageSaver(); + } else { + // modify existing warp + NamedLocation warp = OptionalWarp.get(); + warp.name = name; + } + } } + public static class playerList { + private final ArrayList playerList = new ArrayList<>(); + + // filters the playerList and finds the one with the uuid (if there is one) + public Optional getPlayer(String uuid) { + return playerList.stream() + .filter( player -> Objects.equals( player.UUID, uuid )) + .findFirst(); + } + + // creates a new player, if there already is a player it will return the existing one + public Player addPlayer(String uuid, BlockPos pos, String world) { + Optional OptionalPlayer = getPlayer(uuid); + + if (OptionalPlayer.isEmpty()) { + // create new player + Player player = new Player(uuid); + playerList.add(player); + TeleportCommands.LOGGER.info("Player '{}' added successfully in storage!", uuid); + + return player; + } else { + // return existing player + TeleportCommands.LOGGER.info("Player '{}' already exists!", uuid); + return OptionalPlayer.get(); + } + } + } + + public static class Player { public final String UUID; public String DefaultHome = ""; - public Location deathLocation; // todo! deprecate - public List Homes = new ArrayList<>(); + public homeList Homes = new homeList(); public Player(String uuid) { this.UUID = uuid; } + + public static class homeList { + private final List Homes = new ArrayList<>(); + + // filters the Homes and finds the one with the name (if there is one) + public Optional getHome(String name) { + return Homes.stream() + .filter( home -> Objects.equals( home.name, name )) + .findFirst(); + } + + // returns all homes + public List getHomes() { + return Homes; + } + + // creates a new home, if there already is a home it will update the existing one + public void setHome(String name, BlockPos pos, String world) throws Exception { + Optional OptionalHome = getHome(name); + + if (OptionalHome.isEmpty()) { + NamedLocation home = new NamedLocation(name, pos, world); + + Homes.add(home); + StorageSaver(); + } else { + NamedLocation home = OptionalHome.get(); + + home.name = name; + StorageSaver(); + } + } + } } } } diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/storage/backListStorage.java b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/backListStorage.java new file mode 100644 index 0000000..d7543f0 --- /dev/null +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/backListStorage.java @@ -0,0 +1,51 @@ +package dev.mrsnowy.teleport_commands.storage; + +import net.minecraft.core.BlockPos; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; + +public class backListStorage { + public static final backList backList = new backList(); + + public static class backList { + private final ArrayList backList = new ArrayList<>(); + + // filters the deathLocationList and finds the one with the matching player uuid (if there is one) + public Optional getDeathLocation(String uuid) { + return backList.stream() + .filter( deathLocation -> Objects.equals( deathLocation.UUID, uuid )) + .findFirst(); + } + + // updates the deathLocation of a player, if there is no existing entry it will create a new deathLocation. + public void setDeathLocation(String uuid, BlockPos pos, String world) { + Optional OptionalDeathLocation = getDeathLocation(uuid); + + if (OptionalDeathLocation.isEmpty()) { + // create a new deathLocation + deathLocationClass deathLocation = new deathLocationClass(uuid, pos, world); + backList.add(deathLocation); + } else { + // modify existing deathLocation + deathLocationClass deathLocation = OptionalDeathLocation.get(); + + deathLocation.pos = pos; + deathLocation.world = world; + } + } + } + + public static class deathLocationClass { + public String UUID; + public BlockPos pos; + public String world; + + private deathLocationClass(String uuid, BlockPos pos, String world) { + this.UUID = uuid; + this.pos = pos; + this.world = world; + } + } +} \ No newline at end of file diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java b/common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java index 2b69a35..43e3804 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java @@ -4,7 +4,6 @@ import com.mojang.datafixers.util.Pair; import dev.mrsnowy.teleport_commands.TeleportCommands; - import java.io.*; import java.nio.charset.StandardCharsets; import java.util.*; @@ -30,12 +29,13 @@ public class tools { private static final Set unsafeCollisionFreeBlocks = Set.of("block.minecraft.lava", "block.minecraft.flowing_lava", "block.minecraft.end_portal", "block.minecraft.end_gateway","block.minecraft.fire", "block.minecraft.soul_fire", "block.minecraft.powder_snow", "block.minecraft.nether_portal"); public static void Teleporter(ServerPlayer player, ServerLevel world, Vec3 coords) { - // before teleportation effects + // teleportation effects & sounds before teleporting world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() + 1, player.getZ(), 20, 0.0D, 0.0D, 0.0D, 0.01); world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 1.0D, 0.0D, 0.03); world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.location()), SoundSource.PLAYERS, 0.4f, 1.0f); - var flying = player.getAbilities().flying; + // check if the player is currently flying + boolean flying = player.getAbilities().flying; // teleport! player.teleportTo(world, coords.x, coords.y, coords.z, Set.of(), player.getYRot(), player.getXRot(), false); @@ -46,11 +46,11 @@ public static void Teleporter(ServerPlayer player, ServerLevel world, Vec3 coord player.onUpdateAbilities(); } - + // teleportation sound after teleport world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.location()), SoundSource.PLAYERS, 0.4f, 1.0f); - Timer timer = new Timer(); // delay visual effects so the player can see it when switching dimensions + Timer timer = new Timer(); timer.schedule( new TimerTask() { @Override @@ -58,11 +58,11 @@ public void run() { world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() , player.getZ(), 20, 0.0D, 1.0D, 0.0D, 0.01); world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 0.0D, 0.0D, 0.03); } - }, 100 // hopefully good, ~ 2 ticks + }, 100 // hopefully a good delay, ~ 2 ticks ); } - + // checks a 7x7x7 location around the player in order to find a safe place to teleport them to. public static Pair> teleportSafetyChecker(BlockPos blockPos, ServerLevel world, ServerPlayer player) { int row = 1; int rows = 3; @@ -70,7 +70,7 @@ public static Pair> teleportSafetyChecker(BlockPos block BlockPos playerBlockPos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()); int playerX = blockPos.getX(); int playerY = blockPos.getY(); - int playerZ= blockPos.getZ(); + int playerZ = blockPos.getZ(); // find a safe location in an x row radius if (isBlockPosUnsafe(blockPos, world)) { @@ -126,7 +126,7 @@ public static Optional getWorld(String worldString) { } - // 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) + // 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!) public static MutableComponent getTranslatedText(String key, ServerPlayer player, MutableComponent... args) { String language = player.clientInformation().language().toLowerCase(); String regex = "%(\\d+)%"; @@ -197,21 +197,24 @@ public static MutableComponent getTranslatedText(String key, ServerPlayer player } } - + // checks if a bock position is unsafe, used by the teleportSafetyChecker. private static boolean isBlockPosUnsafe(BlockPos bottomPlayer, ServerLevel world) { + // get the block below the player BlockPos belowPlayer = new BlockPos(bottomPlayer.getX(), bottomPlayer.getY() -1, bottomPlayer.getZ()); // below the player String belowPlayerId = world.getBlockState(belowPlayer).getBlock().getDescriptionId(); // below the player + // get the bottom of the player String BottomPlayerId = world.getBlockState(bottomPlayer).getBlock().getDescriptionId(); // bottom of player + // get the top of the player BlockPos TopPlayer = new BlockPos(bottomPlayer.getX(), bottomPlayer.getY() + 1, bottomPlayer.getZ()); // top of player String TopPlayerId = world.getBlockState(TopPlayer).getBlock().getDescriptionId(); // top of player - // check if the death location isn't safe + // check if the block position isn't safe if ((belowPlayerId.equals("block.minecraft.water") || !world.getBlockState(belowPlayer).getCollisionShape(world, belowPlayer).isEmpty()) // check if the player is going to fall on teleport - && (world.getBlockState(bottomPlayer).getCollisionShape(world, bottomPlayer).isEmpty() && !unsafeCollisionFreeBlocks.contains(BottomPlayerId)) // check if it is a collision free block, that isn't dangerous + && (world.getBlockState(bottomPlayer).getCollisionShape(world, bottomPlayer).isEmpty() && !unsafeCollisionFreeBlocks.contains(BottomPlayerId)) // check if it is a collision free block that isn't dangerous && (!unsafeCollisionFreeBlocks.contains(TopPlayerId))) // check if it is a dangerous collision free block, if it is solid then the player crawls { return false; // it's safe