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 getting very close

MrSnowy 6745e07e 02166ebf

+260 -104
+3 -4
common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java
··· 7 7 import java.util.*; 8 8 9 9 import dev.mrsnowy.teleport_commands.TeleportCommands; 10 - import dev.mrsnowy.teleport_commands.storage.DeathLocationStorage; 11 10 import dev.mrsnowy.teleport_commands.common.DeathLocation; 12 11 import dev.mrsnowy.teleport_commands.utils.tools; 13 12 import net.minecraft.ChatFormatting; ··· 84 83 Constants.LOGGER.warn("({}) Error while going back! \nCouldn't find a world with the id: \"{}\" \nAvailable worlds: {}", 85 84 player.getName().getString(), 86 85 deathLocation.getWorldString(), 87 - tools.getWorldIds()); 86 + tools.getWorldIds(teleportCommands.server)); 88 87 89 88 player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.worldNotFound", player) 90 89 .withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); ··· 134 133 // teleport the player! 135 134 Vec3 teleportPos = new Vec3(teleportBlockPos.getX() + 0.5, teleportBlockPos.getY(), teleportBlockPos.getZ() + 0.5); 136 135 137 - player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.go", player), true); 138 - teleportCommands.tools.Teleporter(player, deathLocationWorld, teleportPos); 136 + // player.displayClientMessage(getTranslatedText("commands.teleport_commands.back.go", player), true); 137 + teleportCommands.teleporter.queue(player, deathLocationWorld, teleportPos, "commands.teleport_commands.back.go"); 139 138 } 140 139 } 141 140 }
+2 -2
common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java
··· 209 209 BlockPos safeBlockPos = teleportData.get(); 210 210 Vec3 teleportPos = new Vec3(safeBlockPos.getX() + 0.5, safeBlockPos.getY(), safeBlockPos.getZ() + 0.5); 211 211 212 - teleportCommands.teleporter.teleportQueue(toSentPlayer, destinationPlayer.serverLevel(), teleportPos); 212 + teleportCommands.teleporter.queue(toSentPlayer, destinationPlayer.serverLevel(), teleportPos); 213 213 } else { 214 214 // if no safe location then just teleport to the player 215 - teleportCommands.teleporter.teleportQueue(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); 215 + teleportCommands.teleporter.queue(toSentPlayer, destinationPlayer.serverLevel(), destinationPlayer.position()); 216 216 } 217 217 218 218 // if the player teleported then these messages get sent && the request gets removed
+32 -6
common/src/main/java/dev/mrsnowy/teleport_commands/mixin/PlayerDeathMixin.java
··· 1 1 package dev.mrsnowy.teleport_commands.mixin; 2 2 3 3 import dev.mrsnowy.teleport_commands.TeleportCommands; 4 + import net.minecraft.client.renderer.item.properties.numeric.Damage; 5 + import net.minecraft.commands.Commands; 6 + import net.minecraft.server.level.ServerLevel; 4 7 import net.minecraft.server.level.ServerPlayer; 8 + import net.minecraft.world.damagesource.DamageSource; 9 + import net.minecraft.world.entity.MoverType; 10 + import net.minecraft.world.phys.Vec3; 5 11 import org.spongepowered.asm.mixin.Mixin; 6 12 import org.spongepowered.asm.mixin.injection.At; 7 13 import org.spongepowered.asm.mixin.injection.Inject; 8 14 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 + import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 9 16 10 17 @Mixin(ServerPlayer.class) 11 18 public class PlayerDeathMixin { ··· 15 22 TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 16 23 } 17 24 18 - @Inject(method = "onEnterCombat", at = @At("TAIL")) 19 - private void combatEntered(CallbackInfo info) { 20 - // TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 25 + // @Inject(method = "onEnterCombat", at = @At("TAIL")) 26 + // private void combatEntered(CallbackInfo info) { 27 + //// TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 28 + // } 29 + // 30 + // @Inject(method = "onLeaveCombat", at = @At("TAIL")) 31 + // private void combatLeft(CallbackInfo info) { 32 + //// TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 33 + // } 34 + 35 + // This function is not on the ServerPlayer, but on the entity which the ServerPlayer is based on :P 36 + @Inject(method = "move", at = @At("TAIL")) 37 + private void onMove(MoverType type, Vec3 delta, CallbackInfo info) { 38 + if (type != MoverType.PLAYER && type != MoverType.SELF) return; 39 + if (delta.lengthSqr() == 0) return; 40 + 41 + ServerPlayer self = (ServerPlayer) (Object) this; 42 + TeleportCommands.INSTANCE.teleporter.reportPlayerMoved(self); 21 43 } 22 44 23 - @Inject(method = "onLeaveCombat", at = @At("TAIL")) 24 - private void combatLeft(CallbackInfo info) { 25 - // TeleportCommands.INSTANCE.onPlayerDeath((ServerPlayer) (Object) this); 45 + @Inject(method = "hurtServer", at = @At("TAIL")) 46 + private void onHurt(ServerLevel leve, DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) { 47 + // It returns true if the player got meaningfully damaged / they weren't immune 48 + if (info.getReturnValue()) { 49 + ServerPlayer self = (ServerPlayer) (Object) this; 50 + TeleportCommands.INSTANCE.teleporter.reportPlayerHurt(self); 51 + } 26 52 } 27 53 }
+1 -1
common/src/main/java/dev/mrsnowy/teleport_commands/mixin/ServerStartMixin.java
··· 20 20 21 21 @Inject(method = "tickServer", at = @At(value = "TAIL")) 22 22 private void tickServer(BooleanSupplier hasTimeLeft, CallbackInfo info) { 23 - TeleportCommands.INSTANCE.teleporter.checkPlayerData((MinecraftServer) (Object) this); 23 + TeleportCommands.INSTANCE.teleporter.tick((MinecraftServer) (Object) this); 24 24 25 25 // todo! do the same for TPA 26 26 }
+75 -37
common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java
··· 3 3 import com.google.gson.*; 4 4 import dev.mrsnowy.teleport_commands.Constants; 5 5 import dev.mrsnowy.teleport_commands.TeleportCommands; 6 + import dev.mrsnowy.teleport_commands.utils.tools; 6 7 7 8 import java.io.FileReader; 8 9 import java.nio.file.Files; ··· 88 89 Files.write(configFile, json, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); 89 90 } 90 91 91 - public static class ConfigClass { 92 + public class ConfigClass { 92 93 private final int version = 0; 93 94 public Teleporting teleporting = new Teleporting(); 94 95 public Back back = new Back(); ··· 101 102 return version; 102 103 } 103 104 104 - public static final class Teleporting { 105 - /// Delay before teleporting 106 - private int delay = 3; 107 - /// Cooldown before they can teleport again 108 - private int cooldown = 5; 105 + public final class Teleporting { 106 + /// Delay (in ticks) before teleporting 107 + private int delay = 60; 108 + /// Cooldown (in ticks) before a player can teleport again 109 + private int cooldown = 100; 109 110 /// Allow moving while teleporting 110 - private boolean whileMoving = true; 111 + private boolean allowMoving = true; 111 112 /// Allow fighting while teleporting 112 - private boolean whileFighting = false; 113 - /// Cooldown after fighting before they can teleport again 114 - private int fightCooldown = 10; 113 + private boolean allowFighting = false; 114 + /// Cooldown (in ticks) after fighting before a player can teleport again 115 + private int fightCooldown = 200; 115 116 116 117 public int getDelay() { 117 118 return delay; 118 119 } 119 120 120 - public void setDelay(int delay) { 121 + public void setDelay(int delay) throws Exception { 121 122 this.delay = delay; 123 + configSaver(); 122 124 } 123 125 124 - public boolean isWhileMoving() { 125 - return whileMoving; 126 + public boolean isAllowMoving() { 127 + return allowMoving; 126 128 } 127 129 128 - public void setWhileMoving(boolean whileMoving) { 129 - this.whileMoving = whileMoving; 130 + public void setAllowMoving(boolean allowMoving) throws Exception { 131 + this.allowMoving = allowMoving; 132 + configSaver(); 130 133 } 131 134 132 - public boolean isWhileFighting() { 133 - return whileFighting; 135 + public boolean isAllowFighting() { 136 + return allowFighting; 134 137 } 135 138 136 - public void setWhileFighting(boolean whileFighting) { 137 - this.whileFighting = whileFighting; 139 + public void setAllowFighting(boolean allowFighting) throws Exception { 140 + this.allowFighting = allowFighting; 141 + configSaver(); 138 142 } 139 143 140 144 public int getFightCooldown() { 141 145 return fightCooldown; 142 146 } 143 147 144 - public void setFightCooldown(int fightCooldown) { 148 + public void setFightCooldown(int fightCooldown) throws Exception { 145 149 this.fightCooldown = fightCooldown; 150 + configSaver(); 146 151 } 147 152 148 153 public int getCooldown() { 149 154 return cooldown; 150 155 } 151 156 152 - public void setCooldown(int cooldown) { 157 + public void setCooldown(int cooldown) throws Exception { 153 158 this.cooldown = cooldown; 159 + configSaver(); 154 160 } 155 161 } 156 162 157 - public static final class Back { 163 + public final class Back { 158 164 private boolean enabled = true; 165 + private String command = "back"; // TODO! do this for more commands 159 166 /// Deletes the /back after teleporting, so you cant call /back twice. 160 167 private boolean deleteAfterTeleport = false; 161 168 ··· 163 170 return enabled; 164 171 } 165 172 166 - public void setEnabled(boolean enabled) { 173 + public void setEnabled(boolean enabled) throws Exception { 167 174 this.enabled = enabled; 175 + configSaver(); 176 + } 177 + 178 + public String getCommand() { 179 + return command; 180 + } 181 + 182 + public void setCommand(String command) throws Exception { 183 + this.command = command; 184 + configSaver(); 185 + tools.reloadResources(teleportCommands.server); // Reload the commands 168 186 } 169 187 170 188 public boolean isDeleteAfterTeleport() { 171 189 return deleteAfterTeleport; 172 190 } 173 191 174 - public void setDeleteAfterTeleport(boolean deleteAfterTeleport) { 192 + public void setDeleteAfterTeleport(boolean deleteAfterTeleport) throws Exception { 175 193 this.deleteAfterTeleport = deleteAfterTeleport; 194 + configSaver(); 176 195 } 177 196 } 178 197 179 - public static final class Home { 198 + public final class Home { 180 199 private boolean enabled = true; 181 200 /// The maximum amount of homes a player can have 182 201 private int playerMaximum = 20; ··· 187 206 return enabled; 188 207 } 189 208 190 - public void setEnabled(boolean enabled) { 209 + public void setEnabled(boolean enabled) throws Exception { 191 210 this.enabled = enabled; 211 + configSaver(); 192 212 } 193 213 194 214 public int getPlayerMaximum() { 195 215 return playerMaximum; 196 216 } 197 217 198 - public void setPlayerMaximum(int playerMaximum) { 218 + public void setPlayerMaximum(int playerMaximum) throws Exception { 199 219 this.playerMaximum = playerMaximum; 220 + configSaver(); 200 221 } 201 222 202 223 public boolean isDeleteInvalid() { 203 224 return deleteInvalid; 204 225 } 205 226 206 - public void setDeleteInvalid(boolean deleteInvalid) { 227 + public void setDeleteInvalid(boolean deleteInvalid) throws Exception { 207 228 this.deleteInvalid = deleteInvalid; 229 + configSaver(); 208 230 } 209 231 } 210 232 211 - public static final class Tpa { 233 + public final class Tpa { 212 234 private boolean enabled = true; 213 235 214 236 public boolean isEnabled() { 215 237 return enabled; 216 238 } 217 239 218 - public void setEnabled(boolean enabled) { 240 + public void setEnabled(boolean enabled) throws Exception { 219 241 this.enabled = enabled; 242 + configSaver(); 220 243 } 221 244 } 222 245 223 - public static final class Warp { 246 + public final class Warp { 224 247 private boolean enabled = true; 248 + 225 249 /// If a warp with an invalid dimension should get automatically deleted 226 250 private boolean deleteInvalid = false; 227 251 ··· 229 253 return enabled; 230 254 } 231 255 232 - public void setEnabled(boolean enabled) { 256 + public void setEnabled(boolean enabled) throws Exception { 233 257 this.enabled = enabled; 258 + configSaver(); 234 259 } 235 260 236 261 public boolean isDeleteInvalid() { 237 262 return deleteInvalid; 238 263 } 239 264 240 - public void setDeleteInvalid(boolean deleteInvalid) { 265 + public void setDeleteInvalid(boolean deleteInvalid) throws Exception { 241 266 this.deleteInvalid = deleteInvalid; 267 + configSaver(); 242 268 } 243 269 } 244 270 245 - public static final class WorldSpawn { 271 + public final class WorldSpawn { 246 272 private boolean enabled = true; 273 + private String command = "worldspawn"; 247 274 private String world_id = "minecraft:overworld"; 248 275 249 276 public boolean isEnabled() { 250 277 return enabled; 251 278 } 252 279 253 - public void setEnabled(boolean enabled) { 280 + public void setEnabled(boolean enabled) throws Exception { 254 281 this.enabled = enabled; 282 + configSaver(); 255 283 } 256 284 257 285 public String getWorld_id() { 258 286 return world_id; 259 287 } 260 288 261 - public void setWorld_id(String world_id) { 289 + public void setWorld_id(String world_id) throws Exception { 262 290 this.world_id = world_id; 291 + configSaver(); 292 + } 293 + 294 + public String getCommand() { 295 + return command; 296 + } 297 + 298 + public void setCommand(String command) throws Exception { 299 + this.command = command; 300 + configSaver(); 301 + tools.reloadResources(teleportCommands.server); // Reload the commands 263 302 } 264 303 } 265 304 } 266 305 267 306 // --- Ideas! --- 268 - // Make config options for disabling certain commands 269 307 // Make config options for renaming certain commands 270 308 // Make config option for changing required permission level for certain commands 271 309 // Make config for setting max homes
+133 -54
common/src/main/java/dev/mrsnowy/teleport_commands/utils/teleporter.java
··· 2 2 3 3 import dev.mrsnowy.teleport_commands.TeleportCommands; 4 4 import net.minecraft.ChatFormatting; 5 + import net.minecraft.core.BlockPos; 5 6 import net.minecraft.core.particles.ParticleTypes; 7 + import net.minecraft.network.chat.Component; 6 8 import net.minecraft.server.MinecraftServer; 7 9 import net.minecraft.server.level.ServerLevel; 8 10 import net.minecraft.server.level.ServerPlayer; ··· 18 20 19 21 public class teleporter { 20 22 private final TeleportCommands teleportCommands; 21 - private final Map<UUID, PlayerData> playersData = new HashMap<>(); 23 + private final Map<UUID, PlayerData> players = new HashMap<>(); 22 24 23 25 private static class PlayerData { 24 - /// This value is set to when the teleport cooldown expires. 25 - int teleportCooldownExpiry = 0; 26 - boolean teleportCooldownExpired = true; 26 + /// This value is set to when the teleport cooldown expires (note this is the *cooldown* between teleports, not the delay before teleporting!). 27 + int teleportCooldownUntil = 0; 28 + boolean teleportOnCooldown = false; 27 29 28 30 /// This value is set to when the fight cooldown expires. 29 - int fightCooldownExpiry = 0; 30 - boolean fightCooldownExpired = true; 31 + int fightCooldownUntil = 0; 32 + boolean fightOnCooldown = false; 31 33 32 34 /// A pending teleport, is null when nothing is pending. 33 35 @Nullable 34 36 pendingTeleport pendingTeleport = null; 35 - 36 - // Vec3 lastPosition = Vec3.ZERO; 37 37 } 38 38 39 39 private static class pendingTeleport { 40 40 ServerLevel destinationWorld; 41 + BlockPos startingCoords; 41 42 Vec3 destinationCoords; 42 - int teleportDelayExpiry; 43 + int teleportDelayUntil; 44 + /// The tps that will be upheld until the teleport is finished (for displaying purposes) 45 + int tps; 46 + /// Message that gets sent when the teleportation happens 47 + String completionMessage; 43 48 44 - pendingTeleport(ServerLevel destinationWorld, Vec3 destinationCoords, int teleportDelayExpiry) { 49 + pendingTeleport(ServerLevel destinationWorld, Vec3 destinationCoords, BlockPos startingCoords, int teleportDelayUntil, int tps, String completionMessage) { 45 50 this.destinationWorld = destinationWorld; 46 51 this.destinationCoords = destinationCoords; 47 - this.teleportDelayExpiry = teleportDelayExpiry; 52 + this.startingCoords = startingCoords; 53 + this.teleportDelayUntil = teleportDelayUntil; 54 + this.tps = tps; 55 + this.completionMessage = completionMessage; 48 56 } 49 57 } 50 58 59 + // ---- 60 + 51 61 public teleporter(TeleportCommands teleportCommands) { 52 62 this.teleportCommands = teleportCommands; 53 63 } 54 64 55 - /// This gets ran every tick 56 - public void checkPlayerData(MinecraftServer server) { 65 + /// This function checks if any of the timers/cooldowns/delays have expired of each player in the "players" hashmap. 66 + /// This gets ran every tick. 67 + public void tick(MinecraftServer server) { 57 68 int currentTick = server.getTickCount(); 58 69 59 - playersData.entrySet().removeIf(entry -> { 70 + players.entrySet().removeIf(entry -> { 60 71 PlayerData data = entry.getValue(); 72 + boolean wasOnCooldown = data.teleportOnCooldown || data.fightOnCooldown; 61 73 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 - } 74 + if (data.teleportOnCooldown && (currentTick >= data.teleportCooldownUntil)) { 75 + data.teleportOnCooldown = false; 71 76 } 72 77 73 - // Check if we are past the cooldown 74 - if (!data.fightCooldownExpired && (currentTick >= data.fightCooldownExpiry)) { 75 - data.fightCooldownExpired = true; 78 + if (data.fightOnCooldown && (currentTick >= data.fightCooldownUntil)) { 79 + data.fightOnCooldown = false; 80 + } 76 81 82 + // Let the player know when the cooldowns are expired and that they are cool to teleport again 83 + if (wasOnCooldown && !data.teleportOnCooldown && !data.fightOnCooldown) { 77 84 ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); 78 85 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); 86 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleport.ready", player).withStyle(ChatFormatting.WHITE), true); 81 87 } 82 88 } 83 89 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)) { 90 + // Check if there is a pending teleport request (and if the delay is over) 91 + if (data.pendingTeleport != null) { 86 92 ServerPlayer player = server.getPlayerList().getPlayer(entry.getKey()); 87 - if (player != null) { 88 - teleport(player, data.pendingTeleport.destinationWorld, data.pendingTeleport.destinationCoords); 93 + 94 + /// delay is over 95 + if (currentTick >= data.pendingTeleport.teleportDelayUntil) { 96 + if (player != null) { 97 + teleport(player, data.pendingTeleport.destinationWorld, data.pendingTeleport.destinationCoords, data.pendingTeleport.completionMessage); 98 + } 99 + 100 + data.pendingTeleport = null; 101 + } else { 102 + // check if this is a whole number 103 + float secondsLeft = (float) (data.pendingTeleport.teleportDelayUntil - currentTick) / data.pendingTeleport.tps; 104 + if ((secondsLeft % 1) == 0 && player != null) { 105 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleport.progress", player).withStyle(ChatFormatting.WHITE), true); 106 + } 89 107 } 108 + } 90 109 91 - data.pendingTeleport = null; 92 - } 93 110 94 - return (data.teleportCooldownExpired && data.fightCooldownExpired); 111 + 112 + // remove the entry if there is no cooldowns and no teleports happening 113 + return (!data.teleportOnCooldown && !data.fightOnCooldown && data.pendingTeleport == null); 95 114 }); 96 115 } 97 116 98 - /// Teleport the player :P 99 - public void teleportQueue( ServerPlayer player, ServerLevel world, Vec3 coords) { 117 + /// Adds the player to the teleportation queue 118 + public void queue(ServerPlayer player, ServerLevel world, Vec3 coords) { 119 + queue(player, world, coords, "commands.teleport_commands.teleport.go"); 120 + } 121 + 122 + /// Adds the player to the teleportation queue 123 + public void queue(ServerPlayer player, ServerLevel world, Vec3 coords, String completionMessage) { 100 124 // Check if user is allowed to teleport by config settings 101 125 102 126 UUID playerUUID = player.getUUID(); 103 - 104 - if (!playersData.containsKey(playerUUID)) { 105 - playersData.put(playerUUID, new PlayerData()); 127 + if (!players.containsKey(playerUUID)) { 128 + players.put(playerUUID, new PlayerData()); 106 129 } 107 130 108 - PlayerData data = playersData.get(playerUUID); 131 + PlayerData data = players.get(playerUUID); 132 + int currentTick = teleportCommands.server.getTickCount(); 133 + int tps = (int) (1.0 / teleportCommands.server.tickRateManager().tickrate()); 109 134 110 135 // Check if we are already teleporting 111 136 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); 137 + int ticksLeft = data.pendingTeleport.teleportDelayUntil - currentTick; 138 + int secondsLeft = (int) Math.ceil( (double) ticksLeft / data.pendingTeleport.tps); 139 + 140 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleport.delay", player, 141 + Component.literal(String.valueOf(secondsLeft)), 142 + Component.literal(String.valueOf(ticksLeft)) 143 + ).withStyle(ChatFormatting.WHITE), false); 144 + 114 145 return; 115 146 } 116 147 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); 148 + // Check if we are still on cooldown 149 + if (data.teleportOnCooldown || data.fightOnCooldown) { 150 + int cooldownUntil = Math.max(data.teleportCooldownUntil, data.fightCooldownUntil); 151 + int ticksLeft = cooldownUntil - currentTick; 152 + int secondsLeft = (int) Math.ceil( (double) ticksLeft / tps); 153 + 154 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleport.cooldown", player, 155 + Component.literal(String.valueOf(secondsLeft)), 156 + Component.literal(String.valueOf(ticksLeft)) 157 + ).withStyle(ChatFormatting.WHITE), false); 158 + 121 159 return; 122 160 } 123 161 ··· 125 163 int teleportingDelay = teleportCommands.config.config.teleporting.getDelay(); 126 164 127 165 if (teleportingDelay >= 0) { 128 - int currentTick = teleportCommands.server.getTickCount(); 129 - data.pendingTeleport = new pendingTeleport(world, coords, currentTick + (teleportingDelay * 20)); 166 + BlockPos currentPos = player.blockPosition(); 167 + 168 + data.pendingTeleport = new pendingTeleport(world, coords, currentPos, currentTick + (teleportingDelay * 20), tps, completionMessage); 130 169 } else { 131 170 // bypass the delay 132 - teleport(player, world, coords); 171 + teleport(player, world, coords, completionMessage); 133 172 } 134 173 135 174 ··· 141 180 142 181 } 143 182 144 - 145 - private void teleport(ServerPlayer player, ServerLevel world, Vec3 coords) { 183 + /// Teleports the player :P 184 + private void teleport(ServerPlayer player, ServerLevel world, Vec3 coords, String completionMessage) { 146 185 // teleportation effects & sounds before teleporting 147 186 world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() + 1, player.getZ(), 20, 0.0D, 0.0D, 0.0D, 0.01); 148 187 world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 1.0D, 0.0D, 0.03); 149 188 world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.location()), SoundSource.PLAYERS, 0.4f, 1.0f); 150 189 151 - // check if the player is currently flying 152 190 boolean flying = player.getAbilities().flying; 153 191 154 - // teleport! 192 + player.displayClientMessage(getTranslatedText(completionMessage, player).withStyle(ChatFormatting.WHITE), true); 155 193 player.teleportTo(world, coords.x, coords.y, coords.z, Set.of(), player.getYRot(), player.getXRot(), false); 156 194 157 195 // Restore flying when teleporting trough dimensions ··· 164 202 world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.location()), SoundSource.PLAYERS, 0.4f, 1.0f); 165 203 world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() , player.getZ(), 20, 0.0D, 1.0D, 0.0D, 0.01); 166 204 world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 0.0D, 0.0D, 0.03); 205 + } 206 + 207 + 208 + public void reportPlayerMoved(ServerPlayer player) { 209 + if (teleportCommands.config.config.teleporting.isAllowMoving()) { 210 + return; // The config option isn't disabled 211 + } 212 + 213 + PlayerData data = players.get(player.getUUID()); 214 + 215 + if (data != null && data.pendingTeleport != null) { 216 + BlockPos pos = player.blockPosition(); 217 + boolean tooFar = data.pendingTeleport.startingCoords.closerThan(pos, 1.5); // Checks if they moved more than one block (1.5 for diagonals) 218 + 219 + if (tooFar) { 220 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleport.moving", player).withStyle(ChatFormatting.WHITE), true); 221 + data.pendingTeleport = null; 222 + } 223 + 224 + } 225 + } 226 + 227 + public void reportPlayerHurt(ServerPlayer player) { 228 + if (teleportCommands.config.config.teleporting.isAllowFighting()) { 229 + return; // The config option isn't disabled 230 + } 231 + 232 + PlayerData data = players.get(player.getUUID()); 233 + 234 + if (data != null) { 235 + int currentTick = teleportCommands.server.getTickCount(); 236 + 237 + data.fightCooldownUntil = currentTick + teleportCommands.config.config.teleporting.getFightCooldown(); 238 + data.fightOnCooldown = true; 239 + 240 + if (data.pendingTeleport != null) { 241 + player.displayClientMessage(getTranslatedText("commands.teleport_commands.teleport.fighting", player).withStyle(ChatFormatting.WHITE), true); 242 + data.pendingTeleport = null; 243 + } 244 + } 245 + 167 246 } 168 247 }
+6
common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java
··· 185 185 } 186 186 return false; // it's not safe! 187 187 } 188 + 189 + /// This function reloads "reloadable resources" which includes commands 190 + public static void reloadResources(MinecraftServer server) { 191 + Collection<String> collection = server.getPackRepository().getSelectedIds(); 192 + server.reloadResources(collection); 193 + } 188 194 }
+8
common/src/main/resources/assets/teleport_commands/lang/en_us.json
··· 52 52 "commands.teleport_commands.tpa.accepted": "Request accepted", 53 53 "commands.teleport_commands.tpa.denied": "Request denied", 54 54 55 + "commands.teleport_commands.teleport.go": "Teleporting", 56 + "commands.teleport_commands.teleport.progress": "Teleporting in %0% seconds (%1% ticks)", 57 + "commands.teleport_commands.teleport.delay": "You are already teleporting! (%0% seconds / %1% ticks left)", 58 + "commands.teleport_commands.teleport.ready": "Teleportation cooldowns have expired.", 59 + "commands.teleport_commands.teleport.onCooldown": "You are still on cooldown!\nPlease wait %0% seconds (%1% ticks) before teleporting.", 60 + "commands.teleport_commands.teleport.moving": "Teleportation has been canceled.\nPlease remain still while teleporting!", 61 + "commands.teleport_commands.teleport.fighting": "Teleportation has been canceled.\nPlease do not fight while teleporting!", 62 + 55 63 "commands.teleport_commands.common.teleport": "Teleporting", 56 64 "commands.teleport_commands.common.error": "An error occurred while teleporting!", 57 65 "commands.teleport_commands.common.noSafeLocation": "No safe location has been found!",