diff --git a/eternalcombat-api/src/main/java/com/eternalcode/combat/region/Region.java b/eternalcombat-api/src/main/java/com/eternalcode/combat/region/Region.java index 95eb0e6b..6d2907c2 100644 --- a/eternalcombat-api/src/main/java/com/eternalcode/combat/region/Region.java +++ b/eternalcombat-api/src/main/java/com/eternalcode/combat/region/Region.java @@ -1,6 +1,7 @@ package com.eternalcode.combat.region; import org.bukkit.Location; +import org.bukkit.World; public interface Region { @@ -11,6 +12,18 @@ public interface Region { Location getMax(); default boolean contains(Location location) { + if (location == null) { + return false; + } + + Location min = this.getMin(); + World regionWorld = min.getWorld(); + World locationWorld = location.getWorld(); + + if (regionWorld == null || locationWorld == null || !regionWorld.equals(locationWorld)) { + return false; + } + return this.contains(location.getX(), location.getY(), location.getZ()); } diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java index 7872ac47..2a08b9c2 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java @@ -139,7 +139,7 @@ public void onEnable() { this.regionProvider = bridgeService.getRegionProvider(); BorderService borderService = new BorderServiceImpl(scheduler, server, regionProvider, eventManager, () -> pluginConfig.border); - KnockbackService knockbackService = new KnockbackService(pluginConfig, scheduler, regionProvider); + KnockbackService knockbackService = new KnockbackService(pluginConfig, this.fightManager, scheduler, regionProvider, server); this.liteCommands = LiteBukkitFactory.builder(FALLBACK_PREFIX, this, server) .message(LiteBukkitMessages.PLAYER_NOT_FOUND, pluginConfig.messagesSettings.playerNotFound) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/knockback/KnockbackService.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/knockback/KnockbackService.java index 99c91d64..cb5c3af2 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/knockback/KnockbackService.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/knockback/KnockbackService.java @@ -1,6 +1,7 @@ package com.eternalcode.combat.fight.knockback; import com.eternalcode.combat.config.implementation.PluginConfig; +import com.eternalcode.combat.fight.FightManager; import com.eternalcode.combat.region.Point; import com.eternalcode.combat.region.Region; import com.eternalcode.combat.region.RegionProvider; @@ -12,6 +13,7 @@ import java.util.Optional; import java.util.UUID; import org.bukkit.Location; +import org.bukkit.Server; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.util.Vector; @@ -19,19 +21,37 @@ public final class KnockbackService { private final PluginConfig config; + private final FightManager fightManager; private final MinecraftScheduler scheduler; private final RegionProvider regionProvider; + private final Server server; private final Map insideRegion = new HashMap<>(); - public KnockbackService(PluginConfig config, MinecraftScheduler scheduler, RegionProvider regionProvider) { + public KnockbackService( + PluginConfig config, + FightManager fightManager, + MinecraftScheduler scheduler, + RegionProvider regionProvider, + Server server + ) { this.config = config; + this.fightManager = fightManager; this.scheduler = scheduler; this.regionProvider = regionProvider; + this.server = server; } public void knockbackLater(Region region, Player player, Duration duration) { - this.scheduler.runLater(() -> this.knockback(region, player), duration); + UUID uniqueId = player.getUniqueId(); + this.scheduler.runLater(() -> { + Player onlinePlayer = this.server.getPlayer(uniqueId); + if (onlinePlayer == null || !this.fightManager.isInCombat(uniqueId) || onlinePlayer.isDead()) { + return; + } + + this.knockback(region, onlinePlayer); + }, duration); } public void forceKnockbackLater(Player player, Region region) { @@ -43,8 +63,15 @@ public void forceKnockbackLater(Player player, Region region) { scheduler.runLater( player.getLocation(), () -> { - insideRegion.remove(player.getUniqueId()); - Location playerLocation = player.getLocation(); + UUID uniqueId = player.getUniqueId(); + insideRegion.remove(uniqueId); + + Player onlinePlayer = this.server.getPlayer(uniqueId); + if (onlinePlayer == null || !this.fightManager.isInCombat(uniqueId) || onlinePlayer.isDead()) { + return; + } + + Location playerLocation = onlinePlayer.getLocation(); if (!region.contains(playerLocation) && !regionProvider.isInRegion(playerLocation)) { return; } @@ -52,7 +79,7 @@ public void forceKnockbackLater(Player player, Region region) { Location location = generate(playerLocation, Point2D.from(region.getMin()), Point2D.from(region.getMax())); - PaperLib.teleportAsync(player, location, TeleportCause.PLUGIN); + PaperLib.teleportAsync(onlinePlayer, location, TeleportCause.PLUGIN); }, this.config.knockback.forceDelay); } diff --git a/eternalcombat-plugin/test/com/eternalcode/combat/region/RegionContainsWorldCheckTest.java b/eternalcombat-plugin/test/com/eternalcode/combat/region/RegionContainsWorldCheckTest.java new file mode 100644 index 00000000..7d83c293 --- /dev/null +++ b/eternalcombat-plugin/test/com/eternalcode/combat/region/RegionContainsWorldCheckTest.java @@ -0,0 +1,38 @@ +package com.eternalcode.combat.region; + +import org.bukkit.Location; +import org.bukkit.World; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.mock; + +class RegionContainsWorldCheckTest { + + @Test + void shouldNotContainLocationFromDifferentWorld() { + World regionWorld = mock(World.class); + World otherWorld = mock(World.class); + + Region region = new Region() { + @Override + public Point getCenter() { + return new Point(regionWorld, 5.0, 5.0); + } + + @Override + public Location getMin() { + return new Location(regionWorld, 0.0, 0.0, 0.0); + } + + @Override + public Location getMax() { + return new Location(regionWorld, 10.0, 10.0, 10.0); + } + }; + + Location locationInOtherWorld = new Location(otherWorld, 5.0, 5.0, 5.0); + + assertFalse(region.contains(locationInOtherWorld)); + } +}