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.

bump, wip

MrSnowy 02166ebf 004481b5

+221 -91
+3 -1
CHANGELOG.md
··· 6 6 7 7 ### WIP [1.4.0] 8 8 #### Changed 9 - - The loading logic of the storage file 9 + - the loading logic of the storage file. 10 + - most static classes to non-static, should prevent leaks. 11 + - Changed out java Timers for a tick-based timer. 10 12 11 13 #### Added 12 14 - **a config file!**
+4 -3
common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java
··· 6 6 import dev.mrsnowy.teleport_commands.storage.DeathLocationStorage; 7 7 import dev.mrsnowy.teleport_commands.storage.configManager; 8 8 import dev.mrsnowy.teleport_commands.utils.teleporter; 9 - import dev.mrsnowy.teleport_commands.utils.tools; 10 9 import net.minecraft.commands.CommandSourceStack; 11 10 import net.minecraft.server.MinecraftServer; 12 11 import net.minecraft.server.level.ServerPlayer; ··· 17 16 import java.nio.file.Paths; 18 17 19 18 public class TeleportCommands { 19 + public static TeleportCommands INSTANCE; 20 20 public String modLoader; 21 21 public Path saveDir; 22 22 public Path configDir; ··· 28 28 29 29 // Gets ran when the server starts, initializes the mod :3 30 30 public void initializeMod(MinecraftServer server) { 31 + INSTANCE = this; 31 32 Constants.LOGGER.info("Initializing Teleport Commands (V{})! Hello {}!", Constants.VERSION, modLoader); 32 33 33 34 saveDir = Path.of(String.valueOf(server.getWorldPath(LevelResource.ROOT))); ··· 44 45 public void registerCommands(CommandDispatcher<CommandSourceStack> dispatcher) { 45 46 new back(dispatcher, this); 46 47 home.register(dispatcher); 47 - tpa.register(dispatcher); 48 - warp.register(dispatcher); 48 + new tpa(dispatcher, this); 49 + new warp(dispatcher, this); 49 50 worldspawn.register(dispatcher); 50 51 main.register(dispatcher); 51 52 }
+1 -1
common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java
··· 172 172 String worldString = player.serverLevel().dimension().location().toString(); 173 173 174 174 // Gets the player's storage and creates it if it doesn't exist 175 - Player playerStorage = StorageManager.STORAGE.addPlayer(player.getStringUUID()); 175 + Player playerStorage = StorageManager.storage.addPlayer(player.getStringUUID()); 176 176 177 177 // Create the NamedLocation 178 178 NamedLocation warp = new NamedLocation(homeName, blockPos, worldString);
+12 -9
common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java
··· 4 4 5 5 import com.mojang.brigadier.CommandDispatcher; 6 6 import dev.mrsnowy.teleport_commands.Constants; 7 + import dev.mrsnowy.teleport_commands.TeleportCommands; 7 8 import dev.mrsnowy.teleport_commands.suggestions.tpaSuggestionProvider; 8 9 9 10 import net.minecraft.ChatFormatting; ··· 19 20 import static dev.mrsnowy.teleport_commands.utils.tools.*; 20 21 21 22 public class tpa { 23 + TeleportCommands teleportCommands; 22 24 23 - public static final ArrayList<tpaArrayClass> tpaList = new ArrayList<>(); 25 + public final ArrayList<tpaArrayClass> tpaList = new ArrayList<>(); 24 26 25 - public static class tpaArrayClass { 27 + public class tpaArrayClass { 26 28 public final String InitPlayer; 27 29 public final String RecPlayer; 28 30 final boolean here; ··· 35 37 } 36 38 } 37 39 38 - public static void register(CommandDispatcher<CommandSourceStack> commandDispatcher) { 40 + public tpa(CommandDispatcher<CommandSourceStack> commandDispatcher, TeleportCommands teleportCommands) { 41 + this.teleportCommands = teleportCommands; 39 42 40 43 commandDispatcher.register(Commands.literal("tpa") 41 44 .requires(source -> source.getPlayer() != null) ··· 112 115 } 113 116 114 117 115 - private static void tpaCommandHandler(ServerPlayer FromPlayer, ServerPlayer ToPlayer, boolean here) throws NullPointerException { 116 - long playerTpaList = tpa.tpaList.stream() 118 + private void tpaCommandHandler(ServerPlayer FromPlayer, ServerPlayer ToPlayer, boolean here) throws NullPointerException { 119 + long playerTpaList = tpaList.stream() 117 120 .filter(tpa -> Objects.equals(FromPlayer.getStringUUID(), tpa.InitPlayer)) 118 121 .filter(tpa -> Objects.equals(ToPlayer.getStringUUID(), tpa.RecPlayer)) 119 122 .count(); ··· 183 186 } 184 187 } 185 188 186 - private static void tpaAccept(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { 189 + private void tpaAccept(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { 187 190 if (FromPlayer == ToPlayer) { 188 191 FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.self", FromPlayer).withStyle(ChatFormatting.AQUA), true); 189 192 return; ··· 206 209 BlockPos safeBlockPos = teleportData.get(); 207 210 Vec3 teleportPos = new Vec3(safeBlockPos.getX() + 0.5, safeBlockPos.getY(), safeBlockPos.getZ() + 0.5); 208 211 209 - Teleporter(toSentPlayer, destinationPlayer.serverLevel(), teleportPos); 212 + teleportCommands.teleporter.teleportQueue(toSentPlayer, destinationPlayer.serverLevel(), teleportPos); 210 213 } else { 211 214 // if no safe location then just teleport to the player 212 - Teleporter(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); 215 + teleportCommands.teleporter.teleportQueue(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); 213 216 } 214 217 215 218 // if the player teleported then these messages get sent && the request gets removed ··· 223 226 } 224 227 } 225 228 226 - private static void tpaDeny(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { 229 + private void tpaDeny(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { 227 230 if (FromPlayer == ToPlayer) { 228 231 FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.self", FromPlayer).withStyle(ChatFormatting.AQUA),true); 229 232
+7 -5
common/src/main/java/dev/mrsnowy/teleport_commands/commands/warp.java
··· 3 3 import com.mojang.brigadier.CommandDispatcher; 4 4 import com.mojang.brigadier.arguments.StringArgumentType; 5 5 import dev.mrsnowy.teleport_commands.Constants; 6 + import dev.mrsnowy.teleport_commands.TeleportCommands; 6 7 import dev.mrsnowy.teleport_commands.common.NamedLocation; 7 8 import dev.mrsnowy.teleport_commands.suggestions.WarpSuggestionProvider; 8 9 import dev.mrsnowy.teleport_commands.utils.tools; ··· 21 22 import java.util.List; 22 23 import java.util.Optional; 23 24 24 - import static dev.mrsnowy.teleport_commands.storage.StorageManager.*; 25 - import static dev.mrsnowy.teleport_commands.utils.tools.Teleporter; 26 25 import static dev.mrsnowy.teleport_commands.utils.tools.getTranslatedText; 27 26 import static net.minecraft.commands.Commands.argument; 28 27 29 28 public class warp { 30 - public static void register(CommandDispatcher<CommandSourceStack> commandDispatcher) { 29 + TeleportCommands teleportCommands; 30 + 31 + public warp(CommandDispatcher<CommandSourceStack> commandDispatcher, TeleportCommands teleportCommands) { 32 + this.teleportCommands = teleportCommands; 31 33 32 34 commandDispatcher.register(Commands.literal("setwarp") 33 35 .requires(source -> ··· 131 133 } 132 134 133 135 134 - private static void SetWarp(ServerPlayer player, String warpName) throws Exception { 136 + private void SetWarp(ServerPlayer player, String warpName) throws Exception { 135 137 System.out.println(warpName); 136 138 warpName = warpName.toLowerCase(); 137 139 ··· 142 144 NamedLocation warp = new NamedLocation(warpName, blockPos, worldString); 143 145 144 146 // Adds the warp, returns true if the warp already exists 145 - boolean warpExists = STORAGE.addWarp(warp); 147 + boolean warpExists = teleportCommands.storageManager.storage.addWarp(warp); 146 148 147 149 if (warpExists) { 148 150 // Display error message that the warp already exists
+1 -1
common/src/main/java/dev/mrsnowy/teleport_commands/mixin/CommandsMixin.java
··· 20 20 Commands self = (Commands) (Object) this; 21 21 CommandDispatcher<CommandSourceStack> dispatcher = self.getDispatcher(); 22 22 23 - TeleportCommands.registerCommands(dispatcher); 23 + TeleportCommands.INSTANCE.registerCommands(dispatcher); 24 24 } 25 25 }
+10 -1
common/src/main/java/dev/mrsnowy/teleport_commands/mixin/PlayerDeathMixin.java
··· 12 12 13 13 @Inject(method = "die", at = @At("HEAD")) 14 14 private void notifyDeath(CallbackInfo info) { 15 + TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 16 + } 15 17 16 - TeleportCommands.onPlayerDeath((ServerPlayer) (Object) this); 18 + @Inject(method = "onEnterCombat", at = @At("TAIL")) 19 + private void combatEntered(CallbackInfo info) { 20 + // TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 21 + } 22 + 23 + @Inject(method = "onLeaveCombat", at = @At("TAIL")) 24 + private void combatLeft(CallbackInfo info) { 25 + // TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 17 26 } 18 27 }
+10 -1
common/src/main/java/dev/mrsnowy/teleport_commands/mixin/ServerStartMixin.java
··· 7 7 import org.spongepowered.asm.mixin.injection.Inject; 8 8 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 9 10 + import java.util.function.BooleanSupplier; 11 + 10 12 @Mixin(MinecraftServer.class) 11 13 public class ServerStartMixin { 12 14 13 15 @Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;buildServerStatus()Lnet/minecraft/network/protocol/status/ServerStatus;", ordinal = 0)) 14 16 private void runServer(CallbackInfo info) { 15 17 16 - TeleportCommands.initializeMod((MinecraftServer) (Object) this); 18 + new TeleportCommands().initializeMod((MinecraftServer) (Object) this); 19 + } 20 + 21 + @Inject(method = "tickServer", at = @At(value = "TAIL")) 22 + private void tickServer(BooleanSupplier hasTimeLeft, CallbackInfo info) { 23 + TeleportCommands.INSTANCE.teleporter.checkPlayerData((MinecraftServer) (Object) this); 24 + 25 + // todo! do the same for TPA 17 26 } 18 27 }
+23 -23
common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java
··· 18 18 import static java.util.Collections.unmodifiableList; 19 19 20 20 public class StorageManager { 21 - public Path STORAGE_FOLDER; 22 - public Path STORAGE_FILE; 23 - public StorageClass STORAGE; 21 + public Path storageFolder; 22 + public Path storageFile; 23 + public StorageClass storage; 24 24 25 - private final Gson GSON = new GsonBuilder().create(); 25 + private final Gson gson = new GsonBuilder().create(); 26 26 private final int defaultVersion = new StorageClass().getVersion(); 27 27 private final TeleportCommands teleportCommands; 28 28 29 29 /// Initializes the StorageManager class and loads the storage from the filesystem. 30 30 public StorageManager(TeleportCommands teleportCommands) { 31 31 this.teleportCommands = teleportCommands; 32 - STORAGE_FOLDER = teleportCommands.saveDir.resolve("TeleportCommands/"); 33 - STORAGE_FILE = STORAGE_FOLDER.resolve("storage.json"); 32 + storageFolder = teleportCommands.saveDir.resolve("TeleportCommands/"); 33 + storageFile = storageFolder.resolve("storage.json"); 34 34 35 35 try { 36 36 StorageLoader(); ··· 45 45 /// Loads the storage from the filesystem 46 46 public void StorageLoader() throws Exception { 47 47 48 - if (!STORAGE_FILE.toFile().exists() || STORAGE_FILE.toFile().length() == 0) { 48 + if (!storageFile.toFile().exists() || storageFile.toFile().length() == 0) { 49 49 Constants.LOGGER.warn("Storage file was not found or was empty! Initializing storage"); 50 50 51 - Files.createDirectories(STORAGE_FOLDER); 52 - STORAGE = new StorageClass(); 51 + Files.createDirectories(storageFolder); 52 + storage = new StorageClass(); 53 53 StorageSaver(); 54 54 Constants.LOGGER.info("Storage created successfully!"); 55 55 } 56 56 57 57 StorageMigrator(); 58 58 59 - FileReader reader = new FileReader(STORAGE_FILE.toFile()); 60 - STORAGE = GSON.fromJson(reader, StorageClass.class); 61 - if (STORAGE == null) { 59 + FileReader reader = new FileReader(storageFile.toFile()); 60 + storage = gson.fromJson(reader, StorageClass.class); 61 + if (storage == null) { 62 62 Constants.LOGGER.warn("Storage file was empty! Initializing storage"); 63 - STORAGE = new StorageClass(); 63 + storage = new StorageClass(); 64 64 StorageSaver(); 65 65 } 66 66 67 - STORAGE.cleanup(); 67 + storage.cleanup(); 68 68 69 69 StorageSaver(); // Save it so any missing values get added to the file. 70 70 Constants.LOGGER.info("Storage loaded successfully!"); ··· 72 72 73 73 /// This function checks what version the storage file is and migrates it to the current version of the mod. 74 74 public void StorageMigrator() throws Exception { 75 - FileReader reader = new FileReader(STORAGE_FILE.toFile()); 76 - JsonObject jsonObject = GSON.fromJson(reader, JsonObject.class); 75 + FileReader reader = new FileReader(storageFile.toFile()); 76 + JsonObject jsonObject = gson.fromJson(reader, JsonObject.class); 77 77 78 78 int version = jsonObject.has("version") ? jsonObject.get("version").getAsInt() : 0; 79 79 ··· 109 109 } 110 110 111 111 // Save the storage :3 112 - byte[] json = GSON.toJson(jsonObject, JsonArray.class).getBytes(); 113 - Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); 112 + byte[] json = gson.toJson(jsonObject, JsonArray.class).getBytes(); 113 + Files.write(storageFile, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); 114 114 115 115 Constants.LOGGER.info("Storage file migrated to v{} successfully!", defaultVersion); 116 116 } else if (version > defaultVersion) { 117 117 String message = String.format("Teleport Commands: The storage file's version is newer than the supported version, found v%s, expected <= v%s.\n" + 118 118 "If you intentionally backported then you can attempt to downgrade the storage file located at this location: \"%s\".\n", 119 - version, defaultVersion, STORAGE_FILE.toAbsolutePath()); 119 + version, defaultVersion, storageFile.toAbsolutePath()); 120 120 121 121 throw new IllegalStateException(message); 122 122 } ··· 125 125 /// Saves the storage to the filesystem 126 126 public void StorageSaver() throws Exception { 127 127 // todo! maybe throttle saves? 128 - byte[] json = GSON.toJson( this.STORAGE ).getBytes(); 128 + byte[] json = gson.toJson( this.storage).getBytes(); 129 129 130 - Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); 130 + Files.write(storageFile, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); 131 131 } 132 132 133 133 ··· 147 147 List<NamedLocation> homes = player.getHomes(); 148 148 149 149 // Delete any homes with an invalid world_id (if enabled in config) 150 - if (teleportCommands.config.CONFIG.home.isDeleteInvalid()) { 150 + if (teleportCommands.config.config.home.isDeleteInvalid()) { 151 151 homes.removeIf(home -> home.getWorld().isEmpty()); 152 152 } 153 153 ··· 158 158 } 159 159 160 160 // Delete any warps with an invalid world_id (if enabled in config) 161 - if (teleportCommands.config.CONFIG.warp.isDeleteInvalid()) { 161 + if (teleportCommands.config.config.warp.isDeleteInvalid()) { 162 162 Warps.removeIf(warp -> warp.getWorld().isEmpty()); 163 163 } 164 164
+34 -16
common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java
··· 10 10 import java.nio.file.StandardOpenOption; 11 11 12 12 public class configManager { 13 - public Path CONFIG_FILE; 14 - public ConfigClass CONFIG; 13 + public Path configFile; 14 + public ConfigClass config; 15 15 16 - private final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); 16 + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); 17 17 private final int defaultVersion = new ConfigClass().getVersion(); 18 18 private final TeleportCommands teleportCommands; 19 19 20 20 public configManager(TeleportCommands teleportCommands) { 21 21 this.teleportCommands = teleportCommands; 22 - CONFIG_FILE = teleportCommands.configDir.resolve("teleport_commands.json"); 22 + configFile = teleportCommands.configDir.resolve("teleport_commands.json"); 23 23 24 24 try { 25 25 configLoader(); ··· 33 33 34 34 /// This function loads the config from disk 35 35 public void configLoader() throws Exception { 36 - if (!CONFIG_FILE.toFile().exists() || CONFIG_FILE.toFile().length() == 0) { 36 + if (!configFile.toFile().exists() || configFile.toFile().length() == 0) { 37 37 Files.createDirectories(teleportCommands.configDir); 38 38 39 39 Constants.LOGGER.warn("Config file was not found or was empty! Initializing config"); 40 - CONFIG = new ConfigClass(); 40 + config = new ConfigClass(); 41 41 configSaver(); 42 42 Constants.LOGGER.info("Config created successfully!"); 43 43 } 44 44 45 45 configMigrator(); 46 46 47 - FileReader reader = new FileReader(CONFIG_FILE.toFile()); 48 - CONFIG = GSON.fromJson(reader, ConfigClass.class); 49 - if (CONFIG == null) { 47 + FileReader reader = new FileReader(configFile.toFile()); 48 + config = gson.fromJson(reader, ConfigClass.class); 49 + if (config == null) { 50 50 Constants.LOGGER.warn("Config file was empty! Loading defaults..."); 51 - CONFIG = new ConfigClass(); 51 + config = new ConfigClass(); 52 52 configSaver(); 53 53 } 54 54 ··· 58 58 59 59 /// This function checks what version the config file is and migrates it to the current version of the mod. 60 60 public void configMigrator() throws Exception { 61 - FileReader reader = new FileReader(CONFIG_FILE.toFile()); 62 - JsonObject jsonObject = GSON.fromJson(reader, JsonObject.class); 61 + FileReader reader = new FileReader(configFile.toFile()); 62 + JsonObject jsonObject = gson.fromJson(reader, JsonObject.class); 63 63 64 64 int version = jsonObject.has("version") ? jsonObject.get("version").getAsInt() : 0; 65 65 ··· 74 74 } else if (version > defaultVersion) { 75 75 String message = String.format("Teleport Commands: The config file's version is newer than the supported version, found v%s, expected <= v%s.\n" + 76 76 "If you intentionally backported then you can attempt to downgrade the config file located at this location: \"%s\".\n", 77 - version, defaultVersion, CONFIG_FILE.toAbsolutePath()); 77 + version, defaultVersion, configFile.toAbsolutePath()); 78 78 79 79 throw new IllegalStateException(message); 80 80 } ··· 83 83 /// Saves the config to disk 84 84 public void configSaver() throws Exception { 85 85 // todo! maybe throttle saves? 86 - byte[] json = GSON.toJson(CONFIG).getBytes(); 86 + byte[] json = gson.toJson(config).getBytes(); 87 87 88 - Files.write(CONFIG_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); 88 + Files.write(configFile, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); 89 89 } 90 90 91 91 public static class ConfigClass { ··· 102 102 } 103 103 104 104 public static final class Teleporting { 105 - private int delay = 5; 105 + /// Delay before teleporting 106 + private int delay = 3; 107 + /// Cooldown before they can teleport again 108 + private int cooldown = 5; 109 + /// Allow moving while teleporting 106 110 private boolean whileMoving = true; 111 + /// Allow fighting while teleporting 107 112 private boolean whileFighting = false; 113 + /// Cooldown after fighting before they can teleport again 108 114 private int fightCooldown = 10; 109 115 110 116 public int getDelay() { ··· 138 144 public void setFightCooldown(int fightCooldown) { 139 145 this.fightCooldown = fightCooldown; 140 146 } 147 + 148 + public int getCooldown() { 149 + return cooldown; 150 + } 151 + 152 + public void setCooldown(int cooldown) { 153 + this.cooldown = cooldown; 154 + } 141 155 } 142 156 143 157 public static final class Back { 144 158 private boolean enabled = true; 159 + /// Deletes the /back after teleporting, so you cant call /back twice. 145 160 private boolean deleteAfterTeleport = false; 146 161 147 162 public boolean isEnabled() { ··· 163 178 164 179 public static final class Home { 165 180 private boolean enabled = true; 181 + /// The maximum amount of homes a player can have 166 182 private int playerMaximum = 20; 183 + /// If a home with an invalid dimension should get automatically deleted 167 184 private boolean deleteInvalid = false; 168 185 169 186 public boolean isEnabled() { ··· 205 222 206 223 public static final class Warp { 207 224 private boolean enabled = true; 225 + /// If a warp with an invalid dimension should get automatically deleted 208 226 private boolean deleteInvalid = false; 209 227 210 228 public boolean isEnabled() {
+1 -1
common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomeSuggestionProvider.java
··· 27 27 public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) { 28 28 try { 29 29 ServerPlayer player = context.getSource().getPlayerOrException(); 30 - Optional<Player> optionalPlayerStorage = teleportCommands.storageManager.STORAGE.getPlayer(player.getStringUUID()); 30 + Optional<Player> optionalPlayerStorage = teleportCommands.storageManager.storage.getPlayer(player.getStringUUID()); 31 31 32 32 if (optionalPlayerStorage.isPresent()) { 33 33 Player playerStorage = optionalPlayerStorage.get();
+1 -2
common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/WarpSuggestionProvider.java
··· 7 7 8 8 import dev.mrsnowy.teleport_commands.Constants; 9 9 import dev.mrsnowy.teleport_commands.TeleportCommands; 10 - import dev.mrsnowy.teleport_commands.storage.StorageManager; 11 10 import dev.mrsnowy.teleport_commands.common.NamedLocation; 12 11 13 12 import net.minecraft.commands.CommandSourceStack; ··· 26 25 @Override 27 26 public CompletableFuture<Suggestions> getSuggestions(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) { 28 27 try { 29 - List<NamedLocation> WarpStorage = teleportCommands.storageManager.STORAGE.getWarps(); 28 + List<NamedLocation> WarpStorage = teleportCommands.storageManager.storage.getWarps(); 30 29 31 30 for (NamedLocation currentWarp : WarpStorage) { 32 31 builder.suggest(currentWarp.getName());
+111 -23
common/src/main/java/dev/mrsnowy/teleport_commands/utils/teleporter.java
··· 1 1 package dev.mrsnowy.teleport_commands.utils; 2 2 3 3 import dev.mrsnowy.teleport_commands.TeleportCommands; 4 + import net.minecraft.ChatFormatting; 4 5 import net.minecraft.core.particles.ParticleTypes; 6 + import net.minecraft.server.MinecraftServer; 5 7 import net.minecraft.server.level.ServerLevel; 6 8 import net.minecraft.server.level.ServerPlayer; 7 9 import net.minecraft.sounds.SoundEvent; 8 10 import net.minecraft.sounds.SoundSource; 9 11 import net.minecraft.world.phys.Vec3; 10 12 13 + import javax.annotation.Nullable; 11 14 import java.util.*; 12 15 16 + import static dev.mrsnowy.teleport_commands.utils.tools.getTranslatedText; 13 17 import static net.minecraft.sounds.SoundEvents.ENDERMAN_TELEPORT; 14 18 15 19 public class teleporter { 16 20 private final TeleportCommands teleportCommands; 17 - private final Map<UUID, PlayerData> playerData = new HashMap<>(); 21 + private final Map<UUID, PlayerData> playersData = new HashMap<>(); 18 22 19 23 private static class PlayerData { 20 - long lastTeleportTime = 0; 21 - long lastHitTime = 0; 22 - Vec3 lastPosition = Vec3.ZERO; 24 + /// This value is set to when the teleport cooldown expires. 25 + int teleportCooldownExpiry = 0; 26 + boolean teleportCooldownExpired = true; 27 + 28 + /// This value is set to when the fight cooldown expires. 29 + int fightCooldownExpiry = 0; 30 + boolean fightCooldownExpired = true; 31 + 32 + /// A pending teleport, is null when nothing is pending. 33 + @Nullable 34 + pendingTeleport pendingTeleport = null; 35 + 36 + // Vec3 lastPosition = Vec3.ZERO; 37 + } 38 + 39 + private static class pendingTeleport { 40 + ServerLevel destinationWorld; 41 + Vec3 destinationCoords; 42 + int teleportDelayExpiry; 43 + 44 + pendingTeleport(ServerLevel destinationWorld, Vec3 destinationCoords, int teleportDelayExpiry) { 45 + this.destinationWorld = destinationWorld; 46 + this.destinationCoords = destinationCoords; 47 + this.teleportDelayExpiry = teleportDelayExpiry; 48 + } 23 49 } 24 50 25 51 public teleporter(TeleportCommands teleportCommands) { 26 52 this.teleportCommands = teleportCommands; 27 53 } 28 54 55 + /// This gets ran every tick 56 + public void checkPlayerData(MinecraftServer server) { 57 + int currentTick = server.getTickCount(); 58 + 59 + playersData.entrySet().removeIf(entry -> { 60 + PlayerData data = entry.getValue(); 61 + 62 + // Check if we are past the cooldown 63 + if (!data.teleportCooldownExpired && (currentTick >= data.teleportCooldownExpiry)) { 64 + data.teleportCooldownExpired = true; 65 + 66 + ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); 67 + if (player != null) { 68 + /// TODO! add actual generic message (just copied this one) 69 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.exists", player).withStyle(ChatFormatting.WHITE), false); 70 + } 71 + } 72 + 73 + // Check if we are past the cooldown 74 + if (!data.fightCooldownExpired && (currentTick >= data.fightCooldownExpiry)) { 75 + data.fightCooldownExpired = true; 76 + 77 + ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); 78 + if (player != null) { 79 + /// TODO! add actual generic message (just copied this one) 80 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.exists", player).withStyle(ChatFormatting.WHITE), false); 81 + } 82 + } 83 + 84 + /// Check if there is a pending teleport request and if we are ready to teleport (we ignore the fightDelay since that is only relevant for starting a request) 85 + if (data.pendingTeleport != null && (currentTick >= data.pendingTeleport.teleportDelayExpiry)) { 86 + ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); 87 + if (player != null) { 88 + teleport(player, data.pendingTeleport.destinationWorld, data.pendingTeleport.destinationCoords); 89 + } 90 + 91 + data.pendingTeleport = null; 92 + } 93 + 94 + return (data.teleportCooldownExpired && data.fightCooldownExpired); 95 + }); 96 + } 97 + 29 98 /// Teleport the player :P 30 - public void teleport(ServerPlayer player, ServerLevel world, Vec3 coords) { 99 + public void teleportQueue( ServerPlayer player, ServerLevel world, Vec3 coords) { 31 100 // Check if user is allowed to teleport by config settings 32 101 33 - int delay = teleportCommands.config.CONFIG.teleporting.getDelay(); 34 102 UUID playerUUID = player.getUUID(); 35 - // save when they last teleported and check delay 36 - if (playerData.containsKey(playerUUID)) { 37 - PlayerData playerdata = playerData.get(playerUUID); 103 + 104 + if (!playersData.containsKey(playerUUID)) { 105 + playersData.put(playerUUID, new PlayerData()); 106 + } 107 + 108 + PlayerData data = playersData.get(playerUUID); 109 + 110 + // Check if we are already teleporting 111 + if (data.pendingTeleport != null) { 112 + /// TODO! add actual generic message (just copied this one) 113 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleporting.delay", player).withStyle(ChatFormatting.WHITE), false); 114 + return; 115 + } 116 + 117 + // Check if the teleport cooldowns are expired. 118 + if (!data.teleportCooldownExpired || !data.fightCooldownExpired) { 119 + /// TODO! add actual generic message (just copied this one) (and add seconds left :P) 120 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleporting.delay", player).withStyle(ChatFormatting.WHITE), false); 121 + return; 122 + } 123 + 124 + // teleport 125 + int teleportingDelay = teleportCommands.config.config.teleporting.getDelay(); 126 + 127 + if (teleportingDelay >= 0) { 128 + int currentTick = teleportCommands.server.getTickCount(); 129 + data.pendingTeleport = new pendingTeleport(world, coords, currentTick + (teleportingDelay * 20)); 130 + } else { 131 + // bypass the delay 132 + teleport(player, world, coords); 38 133 } 134 + 39 135 40 136 // save pos and check if they have moved. 41 137 ··· 43 139 44 140 // save when they last got hit and if it exceeds fightCooldown 45 141 142 + } 46 143 144 + 145 + private void teleport(ServerPlayer player, ServerLevel world, Vec3 coords) { 47 146 // teleportation effects & sounds before teleporting 48 147 world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() + 1, player.getZ(), 20, 0.0D, 0.0D, 0.0D, 0.01); 49 148 world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 1.0D, 0.0D, 0.03); ··· 61 160 player.onUpdateAbilities(); 62 161 } 63 162 64 - // teleportation sound after teleport 163 + // teleportation sound && effects after teleport 65 164 world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.location()), SoundSource.PLAYERS, 0.4f, 1.0f); 66 - 67 - // delay visual effects so the player can see it when switching dimensions 68 - Timer timer = new Timer(); 69 - timer.schedule( 70 - new TimerTask() { 71 - @Override 72 - public void run() { 73 - world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() , player.getZ(), 20, 0.0D, 1.0D, 0.0D, 0.01); 74 - world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 0.0D, 0.0D, 0.03); 75 - } 76 - }, 100 // hopefully a good delay, ~ 2 ticks 77 - ); 165 + world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() , player.getZ(), 20, 0.0D, 1.0D, 0.0D, 0.01); 166 + world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 0.0D, 0.0D, 0.03); 78 167 } 79 - 80 168 }
+3 -4
common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java
··· 14 14 import net.minecraft.core.BlockPos; 15 15 import net.minecraft.network.chat.Component; 16 16 import net.minecraft.network.chat.MutableComponent; 17 + import net.minecraft.server.MinecraftServer; 17 18 import net.minecraft.server.level.ServerLevel; 18 19 import net.minecraft.server.level.ServerPlayer; 19 20 ··· 21 22 22 23 23 24 public class tools { 24 - 25 - 26 25 private static final Set<String> 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"); 27 26 28 27 // checks a 7x7x7 location around the player in order to find a safe place to teleport them to. ··· 155 154 156 155 157 156 // Gets the ids of all the worlds 158 - public static List<String> getWorldIds() { 159 - return StreamSupport.stream(teleportCommands.server.getAllLevels().spliterator(), false) 157 + public static List<String> getWorldIds(MinecraftServer server) { 158 + return StreamSupport.stream(server.getAllLevels().spliterator(), false) 160 159 .map(level -> level.dimension().location().toString()) 161 160 .toList(); 162 161 }