diff --git a/CHANGELOG.md b/CHANGELOG.md index 446b67a..3ac07bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ and this project kind of adheres to [Semantic Versioning](https://semver.org/spe ### WIP [1.4.0] #### Changed -- The loading logic of the storage file +- the loading logic of the storage file. +- most static classes to non-static, should prevent leaks. +- Changed out java Timers for a tick-based timer. #### Added - **a config file!** 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 789ca88..df14cd6 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java @@ -6,7 +6,6 @@ import dev.mrsnowy.teleport_commands.commands.*; import dev.mrsnowy.teleport_commands.storage.DeathLocationStorage; import dev.mrsnowy.teleport_commands.storage.configManager; import dev.mrsnowy.teleport_commands.utils.teleporter; -import dev.mrsnowy.teleport_commands.utils.tools; import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -17,6 +16,7 @@ import java.nio.file.Path; import java.nio.file.Paths; public class TeleportCommands { + public static TeleportCommands INSTANCE; public String modLoader; public Path saveDir; public Path configDir; @@ -28,6 +28,7 @@ public class TeleportCommands { // Gets ran when the server starts, initializes the mod :3 public void initializeMod(MinecraftServer server) { + INSTANCE = this; Constants.LOGGER.info("Initializing Teleport Commands (V{})! Hello {}!", Constants.VERSION, modLoader); saveDir = Path.of(String.valueOf(server.getWorldPath(LevelResource.ROOT))); @@ -44,8 +45,8 @@ public class TeleportCommands { public void registerCommands(CommandDispatcher dispatcher) { new back(dispatcher, this); home.register(dispatcher); - tpa.register(dispatcher); - warp.register(dispatcher); + new tpa(dispatcher, this); + new warp(dispatcher, this); worldspawn.register(dispatcher); main.register(dispatcher); } diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java index 267c5f5..f4abee4 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java @@ -172,7 +172,7 @@ public class home { String worldString = player.serverLevel().dimension().location().toString(); // Gets the player's storage and creates it if it doesn't exist - Player playerStorage = StorageManager.STORAGE.addPlayer(player.getStringUUID()); + Player playerStorage = StorageManager.storage.addPlayer(player.getStringUUID()); // Create the NamedLocation NamedLocation warp = new NamedLocation(homeName, blockPos, worldString); diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java index f35ff4d..ed79c5d 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java @@ -4,6 +4,7 @@ import java.util.*; import com.mojang.brigadier.CommandDispatcher; import dev.mrsnowy.teleport_commands.Constants; +import dev.mrsnowy.teleport_commands.TeleportCommands; import dev.mrsnowy.teleport_commands.suggestions.tpaSuggestionProvider; import net.minecraft.ChatFormatting; @@ -19,10 +20,11 @@ import net.minecraft.world.phys.Vec3; import static dev.mrsnowy.teleport_commands.utils.tools.*; public class tpa { + TeleportCommands teleportCommands; - public static final ArrayList tpaList = new ArrayList<>(); + public final ArrayList tpaList = new ArrayList<>(); - public static class tpaArrayClass { + public class tpaArrayClass { public final String InitPlayer; public final String RecPlayer; final boolean here; @@ -35,7 +37,8 @@ public class tpa { } } - public static void register(CommandDispatcher commandDispatcher) { + public tpa(CommandDispatcher commandDispatcher, TeleportCommands teleportCommands) { + this.teleportCommands = teleportCommands; commandDispatcher.register(Commands.literal("tpa") .requires(source -> source.getPlayer() != null) @@ -112,8 +115,8 @@ public class tpa { } - private static void tpaCommandHandler(ServerPlayer FromPlayer, ServerPlayer ToPlayer, boolean here) throws NullPointerException { - long playerTpaList = tpa.tpaList.stream() + private void tpaCommandHandler(ServerPlayer FromPlayer, ServerPlayer ToPlayer, boolean here) throws NullPointerException { + long playerTpaList = tpaList.stream() .filter(tpa -> Objects.equals(FromPlayer.getStringUUID(), tpa.InitPlayer)) .filter(tpa -> Objects.equals(ToPlayer.getStringUUID(), tpa.RecPlayer)) .count(); @@ -183,7 +186,7 @@ public class tpa { } } - private static void tpaAccept(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { + private void tpaAccept(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { if (FromPlayer == ToPlayer) { FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.self", FromPlayer).withStyle(ChatFormatting.AQUA), true); return; @@ -206,10 +209,10 @@ public class tpa { BlockPos safeBlockPos = teleportData.get(); Vec3 teleportPos = new Vec3(safeBlockPos.getX() + 0.5, safeBlockPos.getY(), safeBlockPos.getZ() + 0.5); - Teleporter(toSentPlayer, destinationPlayer.serverLevel(), teleportPos); + teleportCommands.teleporter.teleportQueue(toSentPlayer, destinationPlayer.serverLevel(), teleportPos); } else { // if no safe location then just teleport to the player - Teleporter(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); + teleportCommands.teleporter.teleportQueue(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); } // if the player teleported then these messages get sent && the request gets removed @@ -223,7 +226,7 @@ public class tpa { } } - private static void tpaDeny(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { + private void tpaDeny(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { if (FromPlayer == ToPlayer) { FromPlayer.displayClientMessage(getTranslatedText("commands.teleport_commands.tpa.self", FromPlayer).withStyle(ChatFormatting.AQUA),true); diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/warp.java b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/warp.java index 9789be8..5416eb8 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/warp.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/warp.java @@ -3,6 +3,7 @@ package dev.mrsnowy.teleport_commands.commands; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import dev.mrsnowy.teleport_commands.Constants; +import dev.mrsnowy.teleport_commands.TeleportCommands; import dev.mrsnowy.teleport_commands.common.NamedLocation; import dev.mrsnowy.teleport_commands.suggestions.WarpSuggestionProvider; import dev.mrsnowy.teleport_commands.utils.tools; @@ -21,13 +22,14 @@ import net.minecraft.world.phys.Vec3; import java.util.List; import java.util.Optional; -import static dev.mrsnowy.teleport_commands.storage.StorageManager.*; -import static dev.mrsnowy.teleport_commands.utils.tools.Teleporter; import static dev.mrsnowy.teleport_commands.utils.tools.getTranslatedText; import static net.minecraft.commands.Commands.argument; public class warp { - public static void register(CommandDispatcher commandDispatcher) { + TeleportCommands teleportCommands; + + public warp(CommandDispatcher commandDispatcher, TeleportCommands teleportCommands) { + this.teleportCommands = teleportCommands; commandDispatcher.register(Commands.literal("setwarp") .requires(source -> @@ -131,7 +133,7 @@ public class warp { } - private static void SetWarp(ServerPlayer player, String warpName) throws Exception { + private void SetWarp(ServerPlayer player, String warpName) throws Exception { System.out.println(warpName); warpName = warpName.toLowerCase(); @@ -142,7 +144,7 @@ public class warp { NamedLocation warp = new NamedLocation(warpName, blockPos, worldString); // Adds the warp, returns true if the warp already exists - boolean warpExists = STORAGE.addWarp(warp); + boolean warpExists = teleportCommands.storageManager.storage.addWarp(warp); if (warpExists) { // Display error message that the warp already exists diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/CommandsMixin.java b/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/CommandsMixin.java index 27cac69..8df9e19 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/CommandsMixin.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/CommandsMixin.java @@ -20,6 +20,6 @@ public class CommandsMixin { Commands self = (Commands) (Object) this; CommandDispatcher dispatcher = self.getDispatcher(); - TeleportCommands.registerCommands(dispatcher); + TeleportCommands.INSTANCE.registerCommands(dispatcher); } } \ No newline at end of file diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/PlayerDeathMixin.java b/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/PlayerDeathMixin.java index 06c0200..477cede 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/PlayerDeathMixin.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/PlayerDeathMixin.java @@ -12,7 +12,16 @@ public class PlayerDeathMixin { @Inject(method = "die", at = @At("HEAD")) private void notifyDeath(CallbackInfo info) { + TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); + } + + @Inject(method = "onEnterCombat", at = @At("TAIL")) + private void combatEntered(CallbackInfo info) { +// TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); + } - TeleportCommands.onPlayerDeath((ServerPlayer) (Object) this); + @Inject(method = "onLeaveCombat", at = @At("TAIL")) + private void combatLeft(CallbackInfo info) { +// TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); } } \ No newline at end of file diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/ServerStartMixin.java b/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/ServerStartMixin.java index 8c5e0c4..ef713c7 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/ServerStartMixin.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/mixin/ServerStartMixin.java @@ -7,12 +7,21 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.function.BooleanSupplier; + @Mixin(MinecraftServer.class) public class ServerStartMixin { @Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;buildServerStatus()Lnet/minecraft/network/protocol/status/ServerStatus;", ordinal = 0)) private void runServer(CallbackInfo info) { - TeleportCommands.initializeMod((MinecraftServer) (Object) this); + new TeleportCommands().initializeMod((MinecraftServer) (Object) this); + } + + @Inject(method = "tickServer", at = @At(value = "TAIL")) + private void tickServer(BooleanSupplier hasTimeLeft, CallbackInfo info) { + TeleportCommands.INSTANCE.teleporter.checkPlayerData((MinecraftServer) (Object) this); + + // todo! do the same for TPA } } \ No newline at end of file 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 f0d6b62..070d84d 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 @@ -18,19 +18,19 @@ import java.util.Optional; import static java.util.Collections.unmodifiableList; public class StorageManager { - public Path STORAGE_FOLDER; - public Path STORAGE_FILE; - public StorageClass STORAGE; + public Path storageFolder; + public Path storageFile; + public StorageClass storage; - private final Gson GSON = new GsonBuilder().create(); + private final Gson gson = new GsonBuilder().create(); private final int defaultVersion = new StorageClass().getVersion(); private final TeleportCommands teleportCommands; /// Initializes the StorageManager class and loads the storage from the filesystem. public StorageManager(TeleportCommands teleportCommands) { this.teleportCommands = teleportCommands; - STORAGE_FOLDER = teleportCommands.saveDir.resolve("TeleportCommands/"); - STORAGE_FILE = STORAGE_FOLDER.resolve("storage.json"); + storageFolder = teleportCommands.saveDir.resolve("TeleportCommands/"); + storageFile = storageFolder.resolve("storage.json"); try { StorageLoader(); @@ -45,26 +45,26 @@ public class StorageManager { /// Loads the storage from the filesystem public void StorageLoader() throws Exception { - if (!STORAGE_FILE.toFile().exists() || STORAGE_FILE.toFile().length() == 0) { + if (!storageFile.toFile().exists() || storageFile.toFile().length() == 0) { Constants.LOGGER.warn("Storage file was not found or was empty! Initializing storage"); - Files.createDirectories(STORAGE_FOLDER); - STORAGE = new StorageClass(); + Files.createDirectories(storageFolder); + storage = new StorageClass(); StorageSaver(); Constants.LOGGER.info("Storage created successfully!"); } StorageMigrator(); - FileReader reader = new FileReader(STORAGE_FILE.toFile()); - STORAGE = GSON.fromJson(reader, StorageClass.class); - if (STORAGE == null) { + FileReader reader = new FileReader(storageFile.toFile()); + storage = gson.fromJson(reader, StorageClass.class); + if (storage == null) { Constants.LOGGER.warn("Storage file was empty! Initializing storage"); - STORAGE = new StorageClass(); + storage = new StorageClass(); StorageSaver(); } - STORAGE.cleanup(); + storage.cleanup(); StorageSaver(); // Save it so any missing values get added to the file. Constants.LOGGER.info("Storage loaded successfully!"); @@ -72,8 +72,8 @@ public class StorageManager { /// This function checks what version the storage file is and migrates it to the current version of the mod. public void StorageMigrator() throws Exception { - FileReader reader = new FileReader(STORAGE_FILE.toFile()); - JsonObject jsonObject = GSON.fromJson(reader, JsonObject.class); + FileReader reader = new FileReader(storageFile.toFile()); + JsonObject jsonObject = gson.fromJson(reader, JsonObject.class); int version = jsonObject.has("version") ? jsonObject.get("version").getAsInt() : 0; @@ -109,14 +109,14 @@ public class StorageManager { } // Save the storage :3 - byte[] json = GSON.toJson(jsonObject, JsonArray.class).getBytes(); - Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); + byte[] json = gson.toJson(jsonObject, JsonArray.class).getBytes(); + Files.write(storageFile, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); Constants.LOGGER.info("Storage file migrated to v{} successfully!", defaultVersion); } else if (version > defaultVersion) { String message = String.format("Teleport Commands: The storage file's version is newer than the supported version, found v%s, expected <= v%s.\n" + "If you intentionally backported then you can attempt to downgrade the storage file located at this location: \"%s\".\n", - version, defaultVersion, STORAGE_FILE.toAbsolutePath()); + version, defaultVersion, storageFile.toAbsolutePath()); throw new IllegalStateException(message); } @@ -125,9 +125,9 @@ public class StorageManager { /// Saves the storage to the filesystem public void StorageSaver() throws Exception { // todo! maybe throttle saves? - byte[] json = GSON.toJson( this.STORAGE ).getBytes(); + byte[] json = gson.toJson( this.storage).getBytes(); - Files.write(STORAGE_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); + Files.write(storageFile, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); } @@ -147,7 +147,7 @@ public class StorageManager { List homes = player.getHomes(); // Delete any homes with an invalid world_id (if enabled in config) - if (teleportCommands.config.CONFIG.home.isDeleteInvalid()) { + if (teleportCommands.config.config.home.isDeleteInvalid()) { homes.removeIf(home -> home.getWorld().isEmpty()); } @@ -158,7 +158,7 @@ public class StorageManager { } // Delete any warps with an invalid world_id (if enabled in config) - if (teleportCommands.config.CONFIG.warp.isDeleteInvalid()) { + if (teleportCommands.config.config.warp.isDeleteInvalid()) { Warps.removeIf(warp -> warp.getWorld().isEmpty()); } diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java index 4db9716..6da1a33 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java @@ -10,16 +10,16 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; public class configManager { - public Path CONFIG_FILE; - public ConfigClass CONFIG; + public Path configFile; + public ConfigClass config; - private final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); private final int defaultVersion = new ConfigClass().getVersion(); private final TeleportCommands teleportCommands; public configManager(TeleportCommands teleportCommands) { this.teleportCommands = teleportCommands; - CONFIG_FILE = teleportCommands.configDir.resolve("teleport_commands.json"); + configFile = teleportCommands.configDir.resolve("teleport_commands.json"); try { configLoader(); @@ -33,22 +33,22 @@ public class configManager { /// This function loads the config from disk public void configLoader() throws Exception { - if (!CONFIG_FILE.toFile().exists() || CONFIG_FILE.toFile().length() == 0) { + if (!configFile.toFile().exists() || configFile.toFile().length() == 0) { Files.createDirectories(teleportCommands.configDir); Constants.LOGGER.warn("Config file was not found or was empty! Initializing config"); - CONFIG = new ConfigClass(); + config = new ConfigClass(); configSaver(); Constants.LOGGER.info("Config created successfully!"); } configMigrator(); - FileReader reader = new FileReader(CONFIG_FILE.toFile()); - CONFIG = GSON.fromJson(reader, ConfigClass.class); - if (CONFIG == null) { + FileReader reader = new FileReader(configFile.toFile()); + config = gson.fromJson(reader, ConfigClass.class); + if (config == null) { Constants.LOGGER.warn("Config file was empty! Loading defaults..."); - CONFIG = new ConfigClass(); + config = new ConfigClass(); configSaver(); } @@ -58,8 +58,8 @@ public class configManager { /// This function checks what version the config file is and migrates it to the current version of the mod. public void configMigrator() throws Exception { - FileReader reader = new FileReader(CONFIG_FILE.toFile()); - JsonObject jsonObject = GSON.fromJson(reader, JsonObject.class); + FileReader reader = new FileReader(configFile.toFile()); + JsonObject jsonObject = gson.fromJson(reader, JsonObject.class); int version = jsonObject.has("version") ? jsonObject.get("version").getAsInt() : 0; @@ -74,7 +74,7 @@ public class configManager { } else if (version > defaultVersion) { String message = String.format("Teleport Commands: The config file's version is newer than the supported version, found v%s, expected <= v%s.\n" + "If you intentionally backported then you can attempt to downgrade the config file located at this location: \"%s\".\n", - version, defaultVersion, CONFIG_FILE.toAbsolutePath()); + version, defaultVersion, configFile.toAbsolutePath()); throw new IllegalStateException(message); } @@ -83,9 +83,9 @@ public class configManager { /// Saves the config to disk public void configSaver() throws Exception { // todo! maybe throttle saves? - byte[] json = GSON.toJson(CONFIG).getBytes(); + byte[] json = gson.toJson(config).getBytes(); - Files.write(CONFIG_FILE, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); + Files.write(configFile, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); } public static class ConfigClass { @@ -102,9 +102,15 @@ public class configManager { } public static final class Teleporting { - private int delay = 5; + /// Delay before teleporting + private int delay = 3; + /// Cooldown before they can teleport again + private int cooldown = 5; + /// Allow moving while teleporting private boolean whileMoving = true; + /// Allow fighting while teleporting private boolean whileFighting = false; + /// Cooldown after fighting before they can teleport again private int fightCooldown = 10; public int getDelay() { @@ -138,10 +144,19 @@ public class configManager { public void setFightCooldown(int fightCooldown) { this.fightCooldown = fightCooldown; } + + public int getCooldown() { + return cooldown; + } + + public void setCooldown(int cooldown) { + this.cooldown = cooldown; + } } public static final class Back { private boolean enabled = true; + /// Deletes the /back after teleporting, so you cant call /back twice. private boolean deleteAfterTeleport = false; public boolean isEnabled() { @@ -163,7 +178,9 @@ public class configManager { public static final class Home { private boolean enabled = true; + /// The maximum amount of homes a player can have private int playerMaximum = 20; + /// If a home with an invalid dimension should get automatically deleted private boolean deleteInvalid = false; public boolean isEnabled() { @@ -205,6 +222,7 @@ public class configManager { public static final class Warp { private boolean enabled = true; + /// If a warp with an invalid dimension should get automatically deleted private boolean deleteInvalid = false; public boolean isEnabled() { diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomeSuggestionProvider.java b/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomeSuggestionProvider.java index 06a3c50..205688b 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomeSuggestionProvider.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomeSuggestionProvider.java @@ -27,7 +27,7 @@ public class HomeSuggestionProvider implements SuggestionProvider getSuggestions(CommandContext context, SuggestionsBuilder builder) { try { ServerPlayer player = context.getSource().getPlayerOrException(); - Optional optionalPlayerStorage = teleportCommands.storageManager.STORAGE.getPlayer(player.getStringUUID()); + Optional optionalPlayerStorage = teleportCommands.storageManager.storage.getPlayer(player.getStringUUID()); if (optionalPlayerStorage.isPresent()) { Player playerStorage = optionalPlayerStorage.get(); diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/WarpSuggestionProvider.java b/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/WarpSuggestionProvider.java index 846f55b..be3beb9 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/WarpSuggestionProvider.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/WarpSuggestionProvider.java @@ -7,7 +7,6 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder; import dev.mrsnowy.teleport_commands.Constants; import dev.mrsnowy.teleport_commands.TeleportCommands; -import dev.mrsnowy.teleport_commands.storage.StorageManager; import dev.mrsnowy.teleport_commands.common.NamedLocation; import net.minecraft.commands.CommandSourceStack; @@ -26,7 +25,7 @@ public class WarpSuggestionProvider implements SuggestionProvider getSuggestions(CommandContext context, SuggestionsBuilder builder) { try { - List WarpStorage = teleportCommands.storageManager.STORAGE.getWarps(); + List WarpStorage = teleportCommands.storageManager.storage.getWarps(); for (NamedLocation currentWarp : WarpStorage) { builder.suggest(currentWarp.getName()); diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/utils/teleporter.java b/common/src/main/java/dev/mrsnowy/teleport_commands/utils/teleporter.java index 76aa468..107873a 100644 --- a/common/src/main/java/dev/mrsnowy/teleport_commands/utils/teleporter.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/utils/teleporter.java @@ -1,49 +1,148 @@ package dev.mrsnowy.teleport_commands.utils; import dev.mrsnowy.teleport_commands.TeleportCommands; +import net.minecraft.ChatFormatting; import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.world.phys.Vec3; +import javax.annotation.Nullable; import java.util.*; +import static dev.mrsnowy.teleport_commands.utils.tools.getTranslatedText; import static net.minecraft.sounds.SoundEvents.ENDERMAN_TELEPORT; public class teleporter { private final TeleportCommands teleportCommands; - private final Map playerData = new HashMap<>(); + private final Map playersData = new HashMap<>(); private static class PlayerData { - long lastTeleportTime = 0; - long lastHitTime = 0; - Vec3 lastPosition = Vec3.ZERO; + /// This value is set to when the teleport cooldown expires. + int teleportCooldownExpiry = 0; + boolean teleportCooldownExpired = true; + + /// This value is set to when the fight cooldown expires. + int fightCooldownExpiry = 0; + boolean fightCooldownExpired = true; + + /// A pending teleport, is null when nothing is pending. + @Nullable + pendingTeleport pendingTeleport = null; + +// Vec3 lastPosition = Vec3.ZERO; + } + + private static class pendingTeleport { + ServerLevel destinationWorld; + Vec3 destinationCoords; + int teleportDelayExpiry; + + pendingTeleport(ServerLevel destinationWorld, Vec3 destinationCoords, int teleportDelayExpiry) { + this.destinationWorld = destinationWorld; + this.destinationCoords = destinationCoords; + this.teleportDelayExpiry = teleportDelayExpiry; + } } public teleporter(TeleportCommands teleportCommands) { this.teleportCommands = teleportCommands; } + /// This gets ran every tick + public void checkPlayerData(MinecraftServer server) { + int currentTick = server.getTickCount(); + + playersData.entrySet().removeIf(entry -> { + PlayerData data = entry.getValue(); + + // Check if we are past the cooldown + if (!data.teleportCooldownExpired && (currentTick >= data.teleportCooldownExpiry)) { + data.teleportCooldownExpired = true; + + ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); + if (player != null) { + /// TODO! add actual generic message (just copied this one) + player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.exists", player).withStyle(ChatFormatting.WHITE), false); + } + } + + // Check if we are past the cooldown + if (!data.fightCooldownExpired && (currentTick >= data.fightCooldownExpiry)) { + data.fightCooldownExpired = true; + + ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); + if (player != null) { + /// TODO! add actual generic message (just copied this one) + player.displayClientMessage(getTranslatedText("commands.teleport_commands.warp.exists", player).withStyle(ChatFormatting.WHITE), false); + } + } + + /// 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) + if (data.pendingTeleport != null && (currentTick >= data.pendingTeleport.teleportDelayExpiry)) { + ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); + if (player != null) { + teleport(player, data.pendingTeleport.destinationWorld, data.pendingTeleport.destinationCoords); + } + + data.pendingTeleport = null; + } + + return (data.teleportCooldownExpired && data.fightCooldownExpired); + }); + } + /// Teleport the player :P - public void teleport(ServerPlayer player, ServerLevel world, Vec3 coords) { + public void teleportQueue( ServerPlayer player, ServerLevel world, Vec3 coords) { // Check if user is allowed to teleport by config settings - int delay = teleportCommands.config.CONFIG.teleporting.getDelay(); UUID playerUUID = player.getUUID(); - // save when they last teleported and check delay - if (playerData.containsKey(playerUUID)) { - PlayerData playerdata = playerData.get(playerUUID); + + if (!playersData.containsKey(playerUUID)) { + playersData.put(playerUUID, new PlayerData()); } + PlayerData data = playersData.get(playerUUID); + + // Check if we are already teleporting + if (data.pendingTeleport != null) { + /// TODO! add actual generic message (just copied this one) + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleporting.delay", player).withStyle(ChatFormatting.WHITE), false); + return; + } + + // Check if the teleport cooldowns are expired. + if (!data.teleportCooldownExpired || !data.fightCooldownExpired) { + /// TODO! add actual generic message (just copied this one) (and add seconds left :P) + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleporting.delay", player).withStyle(ChatFormatting.WHITE), false); + return; + } + + // teleport + int teleportingDelay = teleportCommands.config.config.teleporting.getDelay(); + + if (teleportingDelay >= 0) { + int currentTick = teleportCommands.server.getTickCount(); + data.pendingTeleport = new pendingTeleport(world, coords, currentTick + (teleportingDelay * 20)); + } else { + // bypass the delay + teleport(player, world, coords); + } + + // save pos and check if they have moved. // check if they got hit? whileFighting // save when they last got hit and if it exceeds fightCooldown + } + + private void teleport(ServerPlayer player, ServerLevel world, Vec3 coords) { // 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); @@ -61,20 +160,9 @@ public class teleporter { player.onUpdateAbilities(); } - // teleportation sound after teleport + // teleportation sound && effects after teleport world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.location()), SoundSource.PLAYERS, 0.4f, 1.0f); - - // delay visual effects so the player can see it when switching dimensions - Timer timer = new Timer(); - timer.schedule( - new TimerTask() { - @Override - 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 a good delay, ~ 2 ticks - ); + 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); } - } 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 ddc7170..6f6d1c3 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 @@ -14,6 +14,7 @@ import java.util.stream.StreamSupport; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -21,8 +22,6 @@ import static dev.mrsnowy.teleport_commands.Constants.MOD_ID; 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"); // checks a 7x7x7 location around the player in order to find a safe place to teleport them to. @@ -155,8 +154,8 @@ public class tools { // Gets the ids of all the worlds - public static List getWorldIds() { - return StreamSupport.stream(teleportCommands.server.getAllLevels().spliterator(), false) + public static List getWorldIds(MinecraftServer server) { + return StreamSupport.stream(server.getAllLevels().spliterator(), false) .map(level -> level.dimension().location().toString()) .toList(); }