A Minecraft server-side mod that adds various teleportation related commands
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

very wip, not yet tested

+229 -222
+5
CHANGELOG.md
··· 5 5 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), 6 6 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 7 8 + ### [W.I.P] 9 + - Storage is loaded in memory instead of reading it again and again, Improves speed and IO usage 10 + - Made it so the DeathLocation is only kept in memory (WIP) 11 + - Improved the Storage classes and functions (I'm doing proper java, yipie) 12 + 8 13 ### [v1.2.2] 9 14 - Handled a case where the client (geyser) will return the language as uppercase instead of lowercase. 10 15 - Fixed null-pointer exceptions being logged when a language file couldn't be found.
+41 -17
common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java
··· 1 1 package dev.mrsnowy.teleport_commands; 2 2 3 3 import com.google.gson.*; 4 + import com.mojang.datafixers.util.Pair; 4 5 import dev.mrsnowy.teleport_commands.storage.StorageManager; 5 6 import dev.mrsnowy.teleport_commands.commands.*; 6 7 import net.minecraft.commands.Commands; 7 - import net.minecraft.core.BlockPos; 8 8 import net.minecraft.server.MinecraftServer; 9 9 import net.minecraft.server.level.ServerPlayer; 10 10 import net.minecraft.world.level.storage.LevelResource; ··· 17 17 import java.nio.file.Path; 18 18 import java.nio.file.Paths; 19 19 import java.nio.file.StandardOpenOption; 20 + import net.minecraft.core.BlockPos; 20 21 21 - import static dev.mrsnowy.teleport_commands.utils.tools.DeathLocationUpdater; 22 + import static dev.mrsnowy.teleport_commands.storage.StorageManager.*; 22 23 23 24 public class TeleportCommands { 24 25 public static final String MOD_ID = "teleport_commands"; ··· 42 43 43 44 SERVER = server; 44 45 45 - cleanStorage(); 46 + StorageManager.STORAGE = storageValidator(); 46 47 47 48 // initialize commands, also allows me to easily disable any when there is a config 48 49 Commands commandManager = server.getCommands(); ··· 53 54 worldspawn.register(commandManager); 54 55 } 55 56 57 + 58 + // Runs when the playerDeath mixin calls it, updates the /back command position 56 59 public static void onPlayerDeath(ServerPlayer player) { 57 60 try { 58 - // update /back command position 59 - DeathLocationUpdater(new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()), player.serverLevel(), player.getStringUUID()); 61 + BlockPos pos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()); 62 + 63 + Pair<StorageManager.StorageClass, StorageManager.StorageClass.Player> storages = GetPlayerStorage(player.getStringUUID()); 64 + 65 + StorageManager.StorageClass.Player playerStorage = storages.getSecond(); 66 + 67 + playerStorage.deathLocation.x = pos.getX(); 68 + playerStorage.deathLocation.y = pos.getY(); 69 + playerStorage.deathLocation.z = pos.getZ(); 70 + playerStorage.deathLocation.world = player.serverLevel().dimension().location().toString(); 71 + 72 + StorageSaver(); 60 73 61 74 } catch (Exception e) { 62 - LOGGER.error(e.toString()); 75 + LOGGER.error("Error while saving the player death location! => ", e); 63 76 } 64 77 } 65 78 66 - // cleans and updates Storage to the newest "version" 67 - private static void cleanStorage() { 79 + // private static StorageManager.StorageClass loadStorage() throws Exception { 80 + // // double check that the storage file is intact 81 + // StorageInit(); 82 + // 83 + // String jsonContent = Files.readString(STORAGE_FILE); 84 + // Gson gson = new GsonBuilder().create(); 85 + // 86 + //} 87 + 88 + // cleans and updates Storage to the newest "version". This is painful 89 + private static StorageClass storageValidator() { 68 90 LOGGER.info("Cleaning and updating Storage!"); 91 + 69 92 try { 70 - StorageManager.StorageInit(); 93 + StorageInit(); 94 + 71 95 long startFileSize = Files.size(StorageManager.STORAGE_FILE); 72 96 73 97 FileReader reader = new FileReader(StorageManager.STORAGE_FILE.toString()); 74 98 JsonElement jsonElement = JsonParser.parseReader(reader); 75 99 76 100 if (jsonElement.isJsonObject()) { 101 + 77 102 JsonObject mainJsonObject = jsonElement.getAsJsonObject(); 78 103 JsonArray newWarpsArray = new JsonArray(); 79 104 JsonArray newPlayersArray = new JsonArray(); ··· 87 112 // Warp 88 113 if (warpElement.isJsonObject()) { 89 114 JsonObject warp = warpElement.getAsJsonObject(); 90 - 91 115 92 116 String warpName = warp.has("name") ? warp.get("name").getAsString() : ""; 93 117 Integer warpX = warp.has("x") ? warp.get("x").getAsInt() : null; ··· 109 133 } 110 134 } 111 135 } 112 - 113 - 114 136 } 115 137 116 138 ··· 204 226 205 227 newPlayer.addProperty("UUID", UUID); 206 228 newPlayer.addProperty("DefaultHome", DefaultHome); 207 - newPlayer.add("deathLocation", deathLocation); 229 + newPlayer.add("deathLocationClass", deathLocation); 208 230 newPlayer.add("Homes", homes); 209 231 210 232 newPlayersArray.add(newPlayer); ··· 225 247 byte[] json = gson.toJson(mainJsonObject).getBytes(); 226 248 Files.write(StorageManager.STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); 227 249 228 - long endFileSize = Files.size(StorageManager.STORAGE_FILE); 229 - 230 - LOGGER.info("Success! Cleaned: {}B", Math.round((startFileSize - endFileSize))); 250 + LOGGER.info("Success! Cleaned: {}B", Math.round(( startFileSize - Files.size(StorageManager.STORAGE_FILE) ))); 251 + return gson.fromJson(mainJsonObject, StorageManager.StorageClass.class); 231 252 } 253 + 232 254 } catch (IOException e) { 233 255 LOGGER.error("Error while cleaning the database!", e); 234 256 } 235 - } 257 + 258 + return null; 259 + } 236 260 }
+59 -49
common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java
··· 3 3 import com.mojang.brigadier.arguments.BoolArgumentType; 4 4 import com.mojang.datafixers.util.Pair; 5 5 import dev.mrsnowy.teleport_commands.TeleportCommands; 6 - import dev.mrsnowy.teleport_commands.storage.StorageManager; 7 6 8 7 import java.util.*; 9 8 9 + import dev.mrsnowy.teleport_commands.utils.tools; 10 10 import net.minecraft.ChatFormatting; 11 11 import net.minecraft.commands.Commands; 12 12 import net.minecraft.core.BlockPos; ··· 15 15 import net.minecraft.server.level.ServerPlayer; 16 16 import net.minecraft.world.phys.Vec3; 17 17 18 - import static dev.mrsnowy.teleport_commands.storage.StorageManager.GetPlayerStorage; 19 18 import static dev.mrsnowy.teleport_commands.utils.tools.*; 20 19 import static net.minecraft.commands.Commands.argument; 21 20 22 21 public class back { 22 + public static final ArrayList<deathLocationClass> backList = new ArrayList<>(); 23 + 24 + public static class deathLocationClass { 25 + final public String UUID; 26 + final public BlockPos pos; 27 + final public String world; 28 + 29 + public deathLocationClass(String uuid, BlockPos pos, String world) { 30 + this.UUID = uuid; 31 + this.pos = pos; 32 + this.world = world; 33 + backList.add(this); 34 + } 35 + } 23 36 24 37 public static void register(Commands commandManager) { 25 38 ··· 58 71 } 59 72 60 73 61 - private static void ToDeathLocation(ServerPlayer player, boolean safetyDisabled) throws Exception { 62 - StorageManager.StorageClass.Player playerStorage = GetPlayerStorage(player.getStringUUID()).getSecond(); 63 - 64 - // todo : fix... what do i need to fix LMAO 65 - 66 - if (playerStorage.deathLocation == null) { 67 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.noLocation", player).withStyle(ChatFormatting.RED), true); 68 - } else { 69 - final BlockPos pos = new BlockPos(playerStorage.deathLocation.x, playerStorage.deathLocation.y, playerStorage.deathLocation.z); 74 + private static void ToDeathLocation(ServerPlayer player, boolean safetyDisabled) { 70 75 71 - boolean found = false; 72 - for (ServerLevel currentWorld : TeleportCommands.SERVER.getAllLevels()) { 76 + Optional<deathLocationClass> OptionalDeathLocation = backList.stream() 77 + .filter( deathLocation -> Objects.equals( deathLocation.UUID, player.getStringUUID() )) 78 + .findFirst(); 73 79 74 - if (Objects.equals(currentWorld.dimension().location().toString(), playerStorage.deathLocation.world)) { 80 + if (OptionalDeathLocation.isEmpty()) { 81 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noLocation", player).withStyle(ChatFormatting.RED), true); 82 + return; 83 + } 75 84 76 - // check if the death location isn't safe and that safety isn't enabled 77 - if (!safetyDisabled) { 85 + deathLocationClass deathLocation = OptionalDeathLocation.get(); 78 86 79 - Pair<Integer, Optional<Vec3>> teleportData = teleportSafetyChecker(pos.getX(), pos.getY(), pos.getZ(), currentWorld, player); 87 + Optional<ServerLevel> OptionalWorld = tools.getWorld( deathLocation.world ); 88 + if (OptionalWorld.isEmpty()) { 89 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noLocation", player).withStyle(ChatFormatting.RED), true); 90 + return; 91 + } 80 92 81 - switch (teleportData.getFirst()) { 82 - case 0: // safe location found! 83 - if (teleportData.getSecond().isPresent()) { 84 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.go", player), true); 85 - Teleporter(player, currentWorld, teleportData.getSecond().get()); 86 - } else { 87 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.error", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); 88 - } 93 + ServerLevel world = OptionalWorld.get(); 89 94 90 - break; 91 - case 1: // same 92 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.same", player).withStyle(ChatFormatting.AQUA), true); 93 - break; 94 - case 2: // no safe location 95 + // check if the death location isn't safe and that safety isn't enabled 96 + if (!safetyDisabled) { 95 97 96 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noSafeLocation", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), false); 97 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.safetyIsForLosers", player).withStyle(ChatFormatting.AQUA), false); 98 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.forceTeleport", player).withStyle(ChatFormatting.AQUA, ChatFormatting.BOLD) 99 - .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/back true"))),false); 100 - break; 101 - } 98 + Pair<Integer, Optional<Vec3>> teleportData = teleportSafetyChecker(deathLocation.pos, world, player); 102 99 100 + switch (teleportData.getFirst()) { 101 + case 0: // safe location found! 102 + if (teleportData.getSecond().isPresent()) { 103 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.go", player), true); 104 + Teleporter(player, world, teleportData.getSecond().get()); 103 105 } else { 104 - BlockPos playerBlockPos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()); 105 - if (!playerBlockPos.equals(pos) || player.level() != currentWorld) { 106 - 107 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.go", player), true); 108 - Teleporter(player, currentWorld, new Vec3(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5)); 109 - 110 - } else { 111 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.same", player).withStyle(ChatFormatting.AQUA), true); 112 - } 106 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.error", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); 113 107 } 114 108 109 + break; 110 + case 1: // same 111 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.same", player).withStyle(ChatFormatting.AQUA), true); 112 + break; 113 + case 2: // no safe location 115 114 116 - found = true; 115 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noSafeLocation", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), false); 116 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.safetyIsForLosers", player).withStyle(ChatFormatting.AQUA), false); 117 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.forceTeleport", player).withStyle(ChatFormatting.AQUA, ChatFormatting.BOLD) 118 + .withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/back true"))),false); 117 119 break; 118 - } 119 120 } 120 121 121 - if (!found) { 122 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.noLocation", player).withStyle(ChatFormatting.RED), true); 122 + } else { 123 + BlockPos playerBlockPos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()); 124 + 125 + if (!playerBlockPos.equals(deathLocation.pos) || player.level() != world) { 126 + 127 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.go", player), true); 128 + Teleporter(player, world, new Vec3(deathLocation.pos.getX() + 0.5, deathLocation.pos.getY(), deathLocation.pos.getZ() + 0.5)); 129 + 130 + } else { 131 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.same", player).withStyle(ChatFormatting.AQUA), true); 123 132 } 124 133 } 134 + 125 135 } 126 136 }
+5 -11
common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java
··· 172 172 173 173 if (homeNotFound) { 174 174 // Create a new NamedLocation 175 - StorageManager.StorageClass.NamedLocation homeLocation = new StorageManager.StorageClass.NamedLocation(); 176 - 177 - homeLocation.name = homeName; 178 - homeLocation.x = blockPos.getX(); 179 - homeLocation.y = blockPos.getY(); 180 - homeLocation.z = blockPos.getZ(); 181 - homeLocation.world = world.dimension().location().toString(); 175 + StorageManager.StorageClass.NamedLocation homeLocation = new StorageManager.StorageClass.NamedLocation(homeName, blockPos, world.dimension().location().toString()); 182 176 183 177 playerStorage.Homes.add(homeLocation); 184 178 ··· 186 180 playerStorage.DefaultHome = homeName; 187 181 } 188 182 189 - StorageSaver(storage); 183 + StorageSaver(); 190 184 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.set", player), true); 191 185 } else { 192 186 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.exists", player).withStyle(ChatFormatting.RED), true); ··· 251 245 if (Objects.equals(currentHome.name, homeName)) { 252 246 // delete the home 253 247 playerStorage.Homes.remove(currentHome); 254 - StorageSaver(storage); 248 + StorageSaver(); 255 249 256 250 deletedHome = true; 257 251 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.delete", player), true); ··· 294 288 } 295 289 296 290 currentHome.name = newHomeName; 297 - StorageSaver(storage); 291 + StorageSaver(); 298 292 299 293 WarpRenamed = true; 300 294 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.rename", player), true); ··· 332 326 if (!Objects.equals(playerStorage.DefaultHome, homeName)) { 333 327 334 328 playerStorage.DefaultHome = homeName; 335 - StorageSaver(storage); 329 + StorageSaver(); 336 330 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.default", player), true); 337 331 338 332 } else {
+42 -39
common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java
··· 21 21 public static final ArrayList<tpaArrayClass> tpaList = new ArrayList<>(); 22 22 23 23 public static class tpaArrayClass { 24 - public String InitPlayer; 25 - public String RecPlayer; 26 - boolean here; 24 + public final String InitPlayer; 25 + public final String RecPlayer; 26 + final boolean here; 27 + 28 + public tpaArrayClass(String initPlayer, String recPlayer, boolean here) { 29 + InitPlayer = initPlayer; 30 + RecPlayer = recPlayer; 31 + this.here = here; 32 + tpaList.add(this); 33 + } 27 34 } 28 35 29 36 public static void register(Commands commandManager) { ··· 122 129 String hereText = here ? "Here" : ""; 123 130 124 131 // Store da request 125 - tpaArrayClass tpaRequest = new tpaArrayClass(); 126 - tpaRequest.InitPlayer = FromPlayer.getStringUUID(); 127 - tpaRequest.RecPlayer = ToPlayer.getStringUUID(); 128 - tpaRequest.here = here; 129 - tpaList.add(tpaRequest); 132 + tpaArrayClass tpaRequest = new tpaArrayClass( FromPlayer.getStringUUID(), ToPlayer.getStringUUID(), here ); 130 133 131 134 String ReceivedFromPlayer = Objects.requireNonNull(FromPlayer.getName().getString(), "FromPlayer name cannot be null"); 132 135 String SentToPlayer = Objects.requireNonNull(ToPlayer.getName().getString(), "ToPlayer name cannot be null"); ··· 163 166 private static void tpaAccept(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { 164 167 if (FromPlayer == ToPlayer) { 165 168 FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.self", FromPlayer).withStyle(ChatFormatting.AQUA),true); 169 + return; 170 + } 166 171 167 - } else { 168 - Optional<tpaArrayClass> tpaStorage = tpaList.stream() 169 - .filter(tpa -> Objects.equals(ToPlayer.getStringUUID(), tpa.InitPlayer)) 170 - .filter(tpa -> Objects.equals(FromPlayer.getStringUUID(), tpa.RecPlayer)) 171 - .findFirst(); 172 + Optional<tpaArrayClass> tpaStorage = tpaList.stream() 173 + .filter(tpa -> Objects.equals(ToPlayer.getStringUUID(), tpa.InitPlayer)) 174 + .filter(tpa -> Objects.equals(FromPlayer.getStringUUID(), tpa.RecPlayer)) 175 + .findFirst(); 172 176 173 - // Check if there is a request 174 - if (tpaStorage.isPresent()) { 177 + // Check if there is a request 178 + if (tpaStorage.isPresent()) { 175 179 176 - ServerPlayer destinationPlayer = tpaStorage.get().here ? ToPlayer : FromPlayer; 177 - ServerPlayer toSentPlayer = tpaStorage.get().here ? FromPlayer : ToPlayer; 180 + ServerPlayer destinationPlayer = tpaStorage.get().here ? ToPlayer : FromPlayer; 181 + ServerPlayer toSentPlayer = tpaStorage.get().here ? FromPlayer : ToPlayer; 178 182 179 - Pair<Integer, Optional<Vec3>> teleportData = teleportSafetyChecker(destinationPlayer.getBlockX(), destinationPlayer.getBlockY(), destinationPlayer.getBlockZ(), destinationPlayer.serverLevel(), toSentPlayer); 183 + Pair<Integer, Optional<Vec3>> teleportData = teleportSafetyChecker(destinationPlayer.blockPosition(), destinationPlayer.serverLevel(), toSentPlayer); // todo! make sure .blockPosition is correct 180 184 181 - switch (teleportData.getFirst()) { 182 - case 1: // same (let it fall through) 183 - case 0: // safe! 184 - if (teleportData.getSecond().isPresent() ) { 185 + switch (teleportData.getFirst()) { 186 + case 1: // same (let it fall through) 187 + case 0: // safe! 188 + if (teleportData.getSecond().isPresent() ) { 185 189 186 - Teleporter(toSentPlayer, destinationPlayer.serverLevel(), teleportData.getSecond().get()); 187 - break; 188 - } else { 189 - toSentPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.common.error", toSentPlayer).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); 190 - return; // exit 191 - } 192 - case 2: // if no safe location then just teleport to the player 193 - Teleporter(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); 190 + Teleporter(toSentPlayer, destinationPlayer.serverLevel(), teleportData.getSecond().get()); 194 191 break; 195 - } 192 + } else { 193 + toSentPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.common.error", toSentPlayer).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); 194 + return; // exit 195 + } 196 + case 2: // if no safe location then just teleport to the player 197 + Teleporter(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); 198 + break; 199 + } 196 200 197 - // if the player teleported then these messages get sent && the request gets removed 198 - FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.accepted", FromPlayer).withStyle(ChatFormatting.WHITE),true); 199 - ToPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.accepted", ToPlayer).withStyle(ChatFormatting.GREEN),true); 200 - tpaList.remove(tpaStorage.get()); 201 + // if the player teleported then these messages get sent && the request gets removed 202 + FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.accepted", FromPlayer).withStyle(ChatFormatting.WHITE),true); 203 + ToPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.accepted", ToPlayer).withStyle(ChatFormatting.GREEN),true); 204 + tpaList.remove(tpaStorage.get()); 201 205 202 - // No request found 203 - } else { 204 - FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.notFound", FromPlayer).withStyle(ChatFormatting.RED),true); 205 - } 206 + // No request found 207 + } else { 208 + FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.notFound", FromPlayer).withStyle(ChatFormatting.RED),true); 206 209 } 207 210 } 208 211
+4 -12
common/src/main/java/dev/mrsnowy/teleport_commands/commands/warp.java
··· 4 4 import com.mojang.datafixers.util.Pair; 5 5 import dev.mrsnowy.teleport_commands.TeleportCommands; 6 6 import dev.mrsnowy.teleport_commands.storage.StorageManager; 7 - import dev.mrsnowy.teleport_commands.suggestions.HomeSuggestionProvider; 8 7 import dev.mrsnowy.teleport_commands.suggestions.WarpSuggestionProvider; 9 8 import net.minecraft.ChatFormatting; 10 9 import net.minecraft.commands.Commands; ··· 149 148 150 149 if (warpNotFound) { 151 150 // Create a new NamedLocation 152 - StorageClass.NamedLocation warpData = new StorageClass.NamedLocation(); 153 - 154 - warpData.name = warpName; 155 - warpData.x = blockPos.getX(); 156 - warpData.y = blockPos.getY(); 157 - warpData.z = blockPos.getZ(); 158 - warpData.world = world.dimension().location().toString(); 159 - 151 + StorageClass.NamedLocation warpData = new StorageClass.NamedLocation(warpName, blockPos, world.dimension().location().toString()); 160 152 storage.Warps.add(warpData); 161 153 162 - StorageSaver(storage); 154 + StorageSaver(); 163 155 player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.set", player), true); 164 156 } else { 165 157 player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.exists", player).withStyle(ChatFormatting.RED), true); ··· 215 207 if (Objects.equals(currentWarp.name, warpName)){ 216 208 // delete the warp 217 209 WarpStorage.remove(currentWarp); 218 - StorageSaver(storage); 210 + StorageSaver(); 219 211 220 212 deletedWarp = true; 221 213 player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.delete", player), true); ··· 255 247 if (Objects.equals(currentWarp.name, warpName)){ 256 248 257 249 currentWarp.name = newWarpName; 258 - StorageSaver(storage); 250 + StorageSaver(); 259 251 WarpRenamed = true; 260 252 player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.rename", player), true); 261 253
+1 -2
common/src/main/java/dev/mrsnowy/teleport_commands/commands/worldspawn.java
··· 11 11 import net.minecraft.server.level.ServerPlayer; 12 12 import net.minecraft.world.phys.Vec3; 13 13 14 - import java.util.Iterator; 15 14 import java.util.Objects; 16 15 import java.util.Optional; 17 16 ··· 63 62 BlockPos worldSpawn = Objects.requireNonNull(world,"Overworld cannot be null").getSharedSpawnPos(); 64 63 65 64 if (!safetyDisabled) { 66 - Pair<Integer, Optional<Vec3>> teleportData = teleportSafetyChecker(worldSpawn.getX(), worldSpawn.getY(), worldSpawn.getZ(), world, player); 65 + Pair<Integer, Optional<Vec3>> teleportData = teleportSafetyChecker(worldSpawn, world, player); 67 66 68 67 switch (teleportData.getFirst()) { 69 68 case 0: // safe location found!
+53 -66
common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java
··· 4 4 import com.google.gson.GsonBuilder; 5 5 import com.mojang.datafixers.util.Pair; 6 6 import dev.mrsnowy.teleport_commands.TeleportCommands; 7 + import net.minecraft.core.BlockPos; 7 8 8 9 import java.io.File; 9 10 import java.nio.file.Files; ··· 17 18 public class StorageManager { 18 19 public static Path STORAGE_FOLDER; 19 20 public static Path STORAGE_FILE; 21 + public static StorageClass STORAGE; 20 22 21 23 public static void StorageInit() { 22 24 STORAGE_FOLDER = TeleportCommands.SAVE_DIR.resolve("TeleportCommands/"); 23 25 STORAGE_FILE = STORAGE_FOLDER.resolve("storage.json"); 24 26 25 27 try { 28 + // check if the folder exists and create it 26 29 if (!Files.exists(STORAGE_FOLDER)) { 27 30 Files.createDirectories(STORAGE_FOLDER); 28 31 } 29 32 33 + // check if the file exists and create it 30 34 if (!Files.exists(STORAGE_FILE)) { 31 35 Files.createFile(STORAGE_FILE); 32 36 } 33 37 34 - // create the storage 38 + // create the basic storage if it is empty 35 39 if (new File(String.valueOf(STORAGE_FILE)).length() == 0) { 36 - StorageClass root = new StorageClass(); 37 - root.Players = new ArrayList<>(); 38 - root.Warps = new ArrayList<>(); 39 - StorageSaver(root); 40 + STORAGE = new StorageClass(); 41 + StorageSaver(); // todo! verify that it creates em correctly 40 42 } 41 43 42 44 } catch (Exception e) { 43 - TeleportCommands.LOGGER.error("Error while creating the storage file! Exiting! {}", e.getMessage()); 45 + TeleportCommands.LOGGER.error("Error while creating the storage file! Exiting! => ", e); 44 46 // crashing is probably better here, otherwise the whole mod will be broken 45 47 System.exit(1); 46 48 } 47 49 } 48 50 49 - public static void StorageAdd(String UUID) throws Exception { 50 - StorageClass storage = StorageRetriever(); 51 + public static StorageClass.Player PlayerAdd(String UUID) { 51 52 52 - Optional<StorageClass.Player> playerStorage = storage.Players.stream() 53 + // try to find an exising storage for this player 54 + Optional<StorageClass.Player> playerStorage = STORAGE.Players.stream() 53 55 .filter(player -> Objects.equals(UUID, player.UUID)) 54 56 .findFirst(); 55 57 56 58 if (playerStorage.isEmpty()) { 57 - StorageClass.Player newPlayer = new StorageClass.Player(); 58 - 59 - newPlayer.UUID = UUID; 60 - newPlayer.DefaultHome = ""; 61 - newPlayer.deathLocation = new StorageClass.Location(); 62 - newPlayer.deathLocation.x = new StorageClass.Location().x; 63 - newPlayer.deathLocation.y = new StorageClass.Location().y; 64 - newPlayer.deathLocation.z = new StorageClass.Location().z; 65 - newPlayer.deathLocation.world = ""; 66 - 67 - newPlayer.Homes = new ArrayList<>(); 59 + StorageClass.Player newPlayer = new StorageClass.Player(UUID); // TODO! verify that it creates the player proper 68 60 69 - List<StorageClass.Player> playerList = storage.Players; 61 + List<StorageClass.Player> playerList = STORAGE.Players; 70 62 playerList.add(newPlayer); 71 63 72 - StorageSaver(storage); 64 + // StorageSaver(); // no need to save since no data is actually set yet! 73 65 TeleportCommands.LOGGER.info("Player '{}' added successfully in storage!", UUID); 66 + return newPlayer; 74 67 } else { 75 68 TeleportCommands.LOGGER.info("Player '{}' already exists!", UUID); 69 + return playerStorage.get(); 76 70 } 77 71 } 78 72 79 - public static void StorageSaver(StorageClass storage) throws Exception { 73 + public static void StorageSaver() throws Exception { 80 74 Gson gson = new GsonBuilder().create(); 81 - byte[] json = gson.toJson(storage).getBytes(); 75 + byte[] json = gson.toJson( STORAGE ).getBytes(); 76 + 82 77 Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); 83 78 } 84 79 85 - private static StorageClass StorageRetriever() throws Exception { 86 - // double check that the storage file is intact 87 - if (new File(String.valueOf(STORAGE_FILE)).length() == 0) { 88 - StorageInit(); 89 - } 90 - String jsonContent = Files.readString(STORAGE_FILE); 91 - Gson gson = new GsonBuilder().create(); 92 - return gson.fromJson(jsonContent, StorageClass.class); 80 + public static Pair<StorageClass, List<StorageClass.NamedLocation>> getWarpStorage() { 81 + return new Pair<>(STORAGE, STORAGE.Warps); 93 82 } 94 83 95 - public static Pair<StorageClass, List<StorageClass.NamedLocation>> getWarpStorage() throws Exception { 96 - StorageClass storage = StorageRetriever(); 97 - return new Pair<>(storage, storage.Warps); 98 - } 84 + public static Pair<StorageClass, StorageClass.Player> GetPlayerStorage(String UUID) { 99 85 100 - 101 - public static Pair<StorageClass, StorageClass.Player> GetPlayerStorage(String UUID) throws Exception { 102 - StorageClass storage = StorageRetriever(); 103 - 104 - Optional<StorageClass.Player> playerStorage = storage.Players.stream() 86 + // try to find an exising storage for this player 87 + Optional<StorageClass.Player> playerStorage = STORAGE.Players.stream() 105 88 .filter(player -> Objects.equals(UUID, player.UUID)) 106 89 .findFirst(); 107 90 108 91 if (playerStorage.isEmpty()) { 109 - StorageAdd(UUID); 92 + StorageClass.Player player = PlayerAdd(UUID); // create a new player 110 93 111 - storage = StorageRetriever(); 112 - 113 - playerStorage = storage.Players.stream() 114 - .filter(player -> Objects.equals(UUID, player.UUID)) 115 - .findFirst(); 116 - 117 - if (playerStorage.isEmpty()) { 118 - throw new Exception("No Player found?!"); 119 - } 94 + return new Pair<>(STORAGE, player); 120 95 } 121 96 122 - return new Pair<>(storage, playerStorage.get()); 97 + return new Pair<>(STORAGE, playerStorage.get()); 123 98 } 124 99 125 100 126 101 public static class StorageClass { 127 - public List<NamedLocation> Warps; 128 - public List<Player> Players; 102 + public static List<NamedLocation> Warps = new ArrayList<>(); 103 + public static List<Player> Players = new ArrayList<>(); 129 104 130 105 public static class NamedLocation { 131 106 public String name; 132 - public int x; 133 - public int y; 134 - public int z; 135 - public String world; 107 + public final int x; 108 + public final int y; 109 + public final int z; 110 + public final String world; 111 + 112 + public NamedLocation(String name, BlockPos pos, String world) { 113 + this.name = name; 114 + this.x = pos.getX(); 115 + this.y = pos.getY(); 116 + this.z = pos.getZ(); 117 + this.world = world; 118 + } 136 119 } 137 120 138 121 public static class Location { 139 - public int x; 140 - public int y; 141 - public int z; 142 - public String world; 122 + public int x = 0; 123 + public int y = 0; 124 + public int z = 0; 125 + public String world = ""; 143 126 } 144 127 145 128 public static class Player { 146 - public String UUID; 147 - public String DefaultHome; 148 - public Location deathLocation; 149 - public List<NamedLocation> Homes; 129 + public final String UUID; 130 + public String DefaultHome = ""; 131 + public Location deathLocation; // todo! deprecate 132 + public List<NamedLocation> Homes = new ArrayList<>(); 133 + 134 + public Player(String uuid) { 135 + this.UUID = uuid; 136 + } 150 137 } 151 138 } 152 139 }
+19 -26
common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java
··· 3 3 import com.google.gson.*; 4 4 import com.mojang.datafixers.util.Pair; 5 5 import dev.mrsnowy.teleport_commands.TeleportCommands; 6 - import dev.mrsnowy.teleport_commands.storage.StorageManager; 6 + 7 7 8 8 import java.io.*; 9 9 import java.nio.charset.StandardCharsets; 10 10 import java.util.*; 11 11 import java.util.regex.Matcher; 12 12 import java.util.regex.Pattern; 13 + import java.util.stream.StreamSupport; 13 14 14 15 import net.minecraft.core.BlockPos; 15 16 import net.minecraft.core.particles.ParticleTypes; ··· 22 23 import net.minecraft.world.phys.Vec3; 23 24 24 25 import static dev.mrsnowy.teleport_commands.TeleportCommands.MOD_ID; 25 - import static dev.mrsnowy.teleport_commands.storage.StorageManager.GetPlayerStorage; 26 - import static dev.mrsnowy.teleport_commands.storage.StorageManager.StorageSaver; 27 26 import static net.minecraft.sounds.SoundEvents.ENDERMAN_TELEPORT; 28 27 29 28 public class tools { ··· 64 63 } 65 64 66 65 67 - public static void DeathLocationUpdater(BlockPos pos, ServerLevel world, String UUID) throws Exception { 68 - Pair<StorageManager.StorageClass, StorageManager.StorageClass.Player> storages = GetPlayerStorage(UUID); 69 - 70 - StorageManager.StorageClass storage = storages.getFirst(); 71 - StorageManager.StorageClass.Player playerStorage = storages.getSecond(); 72 - 73 - playerStorage.deathLocation.x = pos.getX(); 74 - playerStorage.deathLocation.y = pos.getY(); 75 - playerStorage.deathLocation.z = pos.getZ(); 76 - playerStorage.deathLocation.world = world.dimension().location().toString(); 77 - 78 - StorageSaver(storage); 79 - } 80 - 81 - 82 - public static Pair<Integer, Optional<Vec3>> teleportSafetyChecker(int playerX, int playerY, int playerZ, ServerLevel world, ServerPlayer player) { 66 + public static Pair<Integer, Optional<Vec3>> teleportSafetyChecker(BlockPos blockPos, ServerLevel world, ServerPlayer player) { 83 67 int row = 1; 84 68 int rows = 3; 85 69 86 70 BlockPos playerBlockPos = new BlockPos(player.getBlockX(), player.getBlockY(), player.getBlockZ()); 87 - BlockPos blockPos = new BlockPos(playerX, playerY, playerZ); 71 + int playerX = blockPos.getX(); 72 + int playerY = blockPos.getY(); 73 + int playerZ= blockPos.getZ(); 88 74 89 75 // find a safe location in an x row radius 90 76 if (isBlockPosUnsafe(blockPos, world)) { ··· 129 115 } 130 116 } 131 117 118 + 119 + // function to quickly filter the worlds and compare them to a string 120 + public static Optional<ServerLevel> getWorld(String worldString) { 121 + 122 + return StreamSupport.stream( TeleportCommands.SERVER.getAllLevels().spliterator(), false ) // woa, this looks silly 123 + .filter(level -> Objects.equals( level.dimension().location().toString(), worldString )) 124 + .findFirst(); 125 + 126 + } 132 127 133 128 134 129 // 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) ··· 204 199 205 200 206 201 private static boolean isBlockPosUnsafe(BlockPos bottomPlayer, ServerLevel world) { 207 - // bottomPlayer is presumed to be the bottom of the player character 208 202 209 203 BlockPos belowPlayer = new BlockPos(bottomPlayer.getX(), bottomPlayer.getY() -1, bottomPlayer.getZ()); // below the player 210 204 String belowPlayerId = world.getBlockState(belowPlayer).getBlock().getDescriptionId(); // below the player ··· 216 210 217 211 218 212 // check if the death location isn't safe 219 - if ( 220 - (belowPlayerId.equals("block.minecraft.water") || !world.getBlockState(belowPlayer).getCollisionShape(world, belowPlayer).isEmpty()) // check if the player is going to fall on teleport 221 - && (world.getBlockState(bottomPlayer).getCollisionShape(world, bottomPlayer).isEmpty() && !unsafeCollisionFreeBlocks.contains(BottomPlayerId)) // check if it is a collision free block, that isn't dangerous 222 - && (!unsafeCollisionFreeBlocks.contains(TopPlayerId)) // check if it is a dangerous collision free block, if it is solid then the player crawls 223 - ) { 213 + if ((belowPlayerId.equals("block.minecraft.water") || !world.getBlockState(belowPlayer).getCollisionShape(world, belowPlayer).isEmpty()) // check if the player is going to fall on teleport 214 + && (world.getBlockState(bottomPlayer).getCollisionShape(world, bottomPlayer).isEmpty() && !unsafeCollisionFreeBlocks.contains(BottomPlayerId)) // check if it is a collision free block, that isn't dangerous 215 + && (!unsafeCollisionFreeBlocks.contains(TopPlayerId))) // check if it is a dangerous collision free block, if it is solid then the player crawls 216 + { 224 217 return false; // it's safe 225 218 } 226 219 return true; // it's not safe!