diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index de70921e..08c6c74d 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -10,7 +10,7 @@ object Versions { const val ETERNALCODE_COMMONS = "1.3.1" const val MULTIFICATION = "1.2.2" - const val PACKETS_EVENTS = "2.9.5" + const val PACKETS_EVENTS = "2.11.1" const val ADVENTURE_PLATFORM_BUKKIT = "4.4.1" const val ADVENTURE_API = "4.25.0" diff --git a/eternalcombat-api/src/main/java/com/eternalcode/combat/fight/trident/FightTridentService.java b/eternalcombat-api/src/main/java/com/eternalcode/combat/fight/trident/FightTridentService.java new file mode 100644 index 00000000..9ff19dd3 --- /dev/null +++ b/eternalcombat-api/src/main/java/com/eternalcode/combat/fight/trident/FightTridentService.java @@ -0,0 +1,16 @@ +package com.eternalcode.combat.fight.trident; + +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; + +public interface FightTridentService { + + Instant getDelay(UUID uuid); + + Duration getRemainingDelay(UUID uuid); + + boolean hasDelay(UUID uuid); + + void markDelay(UUID uuid); +} diff --git a/eternalcombat-plugin/build.gradle.kts b/eternalcombat-plugin/build.gradle.kts index 77d94a62..98f8539d 100644 --- a/eternalcombat-plugin/build.gradle.kts +++ b/eternalcombat-plugin/build.gradle.kts @@ -88,9 +88,9 @@ bukkit { tasks { runServer { - minecraftVersion("1.21.8") + minecraftVersion("1.21.10") downloadPlugins.url("https://cdn.modrinth.com/data/1u6JkXh5/versions/Jk1z2u7n/worldedit-bukkit-7.3.16.jar") - downloadPlugins.url("https://github.com/retrooper/packetevents/releases/download/v2.9.5/packetevents-spigot-2.9.5.jar") + downloadPlugins.modrinth("packetevents", "${Versions.PACKETS_EVENTS}+spigot") downloadPlugins.url("https://cdn.modrinth.com/data/DKY9btbd/versions/PO4MKx7e/worldguard-bukkit-7.0.14-dist.jar") } } 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 c2de7b8d..8286caf7 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/CombatPlugin.java @@ -16,6 +16,9 @@ import com.eternalcode.combat.fight.knockback.KnockbackService; import com.eternalcode.combat.fight.tagout.FightTagOutService; import com.eternalcode.combat.fight.pearl.FightPearlService; +import com.eternalcode.combat.fight.trident.FightTridentController; +import com.eternalcode.combat.fight.trident.FightTridentService; +import com.eternalcode.combat.fight.trident.FightTridentServiceImpl; import com.eternalcode.combat.handler.InvalidUsageHandlerImpl; import com.eternalcode.combat.handler.MissingPermissionHandlerImpl; import com.eternalcode.combat.config.ConfigService; @@ -78,6 +81,7 @@ public final class CombatPlugin extends JavaPlugin implements EternalCombatApi { private FightManager fightManager; private FightPearlService fightPearlService; + private FightTridentService fightTridentService; private FightTagOutService fightTagOutService; private FightEffectService fightEffectService; @@ -106,6 +110,7 @@ public void onEnable() { this.fightManager = new FightManagerImpl(eventManager); this.fightPearlService = new FightPearlServiceImpl(pluginConfig.pearl); + this.fightTridentService = new FightTridentServiceImpl(pluginConfig.trident); this.fightTagOutService = new FightTagOutServiceImpl(); this.fightEffectService = new FightEffectServiceImpl(); @@ -173,7 +178,8 @@ public void onEnable() { new FightTagController(this.fightManager, pluginConfig), new FightUnTagController(this.fightManager, pluginConfig, logoutService), new FightActionBlockerController(this.fightManager, noticeService, pluginConfig, server), - new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService), + new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService, pluginConfig), + new FightTridentController(pluginConfig.trident, noticeService, this.fightManager, this.fightTridentService, pluginConfig), new UpdaterNotificationController(updaterService, pluginConfig, this.audienceProvider, miniMessage), new KnockbackRegionController(noticeService, this.regionProvider, this.fightManager, knockbackService, server), new FightEffectController(pluginConfig.effect, this.fightEffectService, this.fightManager, this.getServer()), diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java index ac46f959..3aeb8cad 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java @@ -5,6 +5,7 @@ import com.eternalcode.combat.fight.effect.FightEffectSettings; import com.eternalcode.combat.fight.knockback.KnockbackSettings; import com.eternalcode.combat.fight.pearl.FightPearlSettings; +import com.eternalcode.combat.fight.trident.FightTridentSettings; import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; import java.time.Duration; @@ -35,6 +36,13 @@ public class PluginConfig extends OkaeriConfig { }) public FightPearlSettings pearl = new FightPearlSettings(); + @Comment({ + " ", + "# Settings related to Trident", + "# Configure cooldowns, restrictions, and other behaviors for Trident during combat." + }) + public FightTridentSettings trident = new FightTridentSettings(); + @Comment({ " ", "# Custom effects applied during combat.", diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlController.java index bfd35700..1fc3b4ca 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlController.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlController.java @@ -1,6 +1,8 @@ package com.eternalcode.combat.fight.pearl; +import com.eternalcode.combat.config.implementation.PluginConfig; import com.eternalcode.combat.fight.FightManager; +import com.eternalcode.combat.fight.event.CauseOfTag; import com.eternalcode.combat.notification.NoticeService; import com.eternalcode.combat.util.DurationUtil; import java.time.Duration; @@ -14,7 +16,6 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; -import org.bukkit.inventory.ItemStack; public class FightPearlController implements Listener { @@ -22,17 +23,20 @@ public class FightPearlController implements Listener { private final NoticeService noticeService; private final FightManager fightManager; private final FightPearlService fightPearlService; + private final PluginConfig config; public FightPearlController( FightPearlSettings settings, NoticeService noticeService, FightManager fightManager, - FightPearlService fightPearlService + FightPearlService fightPearlService, + PluginConfig config ) { this.settings = settings; this.noticeService = noticeService; this.fightManager = fightManager; this.fightPearlService = fightPearlService; + this.config = config; } @EventHandler(priority = EventPriority.HIGHEST) @@ -63,6 +67,11 @@ public void onPearlThrow(ProjectileLaunchEvent event) { if (this.settings.pearlCooldownEnabled) { handlePearlCooldown(event, player, playerId); } + + if (this.settings.pearlResetsTimer) { + Duration combatTime = this.config.settings.combatTimerDuration; + this.fightManager.tag(playerId, combatTime, CauseOfTag.NON_PLAYER); + } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlSettings.java index 4cb29803..67e9f6d4 100644 --- a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlSettings.java +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/pearl/FightPearlSettings.java @@ -21,6 +21,9 @@ public class FightPearlSettings extends OkaeriConfig { @Comment("# Set true, If you want add cooldown to pearls") public boolean pearlCooldownEnabled = false; + @Comment("# Set true, If you want to reset timer when player throws ender pearl") + public boolean pearlResetsTimer = true; + @Comment({ "# Block throwing pearls with delay?", "# If you set this to for example 3s, player will have to wait 3 seconds before throwing another pearl" diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentController.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentController.java new file mode 100644 index 00000000..42037a4e --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentController.java @@ -0,0 +1,107 @@ +package com.eternalcode.combat.fight.trident; + +import com.eternalcode.combat.config.implementation.PluginConfig; +import com.eternalcode.combat.fight.FightManager; +import com.eternalcode.combat.fight.event.CauseOfTag; +import com.eternalcode.combat.notification.NoticeService; +import com.eternalcode.combat.util.DurationUtil; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerRiptideEvent; +import org.bukkit.inventory.ItemStack; + +import java.time.Duration; +import java.util.UUID; + +public class FightTridentController implements Listener { + + private final FightTridentSettings settings; + private final NoticeService noticeService; + private final FightManager fightManager; + private final FightTridentService fightTridentService; + private final PluginConfig config; + + public FightTridentController( + FightTridentSettings settings, + NoticeService noticeService, + FightManager fightManager, + FightTridentService fightTridentService, + PluginConfig config + ) { + this.settings = settings; + this.noticeService = noticeService; + this.fightManager = fightManager; + this.fightTridentService = fightTridentService; + this.config = config; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onTridentInteract(PlayerInteractEvent event) { + ItemStack item = event.getItem(); + + if (item == null || item.getType() != Material.TRIDENT) { + return; + } + + Player player = event.getPlayer(); + UUID playerId = player.getUniqueId(); + + if (!this.fightManager.isInCombat(playerId)) { + return; + } + + if (this.settings.tridentThrowDisabledDuringCombat) { + event.setCancelled(true); + this.noticeService.create() + .player(playerId) + .notice(this.settings.tridentThrowBlockedDuringCombat) + .send(); + return; + } + + if (this.settings.tridentCooldownEnabled) { + this.handleTridentCooldown(event, player, playerId); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onTridentRiptide(PlayerRiptideEvent event) { + Player player = event.getPlayer(); + UUID playerId = player.getUniqueId(); + + if (!this.fightManager.isInCombat(playerId)) { + return; + } + + if (this.settings.tridentResetsTimer) { + Duration combatTime = this.config.settings.combatTimerDuration; + this.fightManager.tag(playerId, combatTime, CauseOfTag.NON_PLAYER); + } + } + + private void handleTridentCooldown(PlayerInteractEvent event, Player player, UUID playerId) { + if (this.settings.tridentThrowDelay.isZero()) { + return; + } + + if (this.fightTridentService.hasDelay(playerId)) { + event.setCancelled(true); + Duration remainingDelay = this.fightTridentService.getRemainingDelay(playerId); + + this.noticeService.create() + .player(playerId) + .notice(this.settings.tridentThrowBlockedDelayDuringCombat) + .placeholder("{TIME}", DurationUtil.format(remainingDelay)) + .send(); + return; + } + + this.fightTridentService.markDelay(playerId); + int cooldownTicks = (int) (this.settings.tridentThrowDelay.toMillis() / 50); + player.setCooldown(Material.TRIDENT, cooldownTicks); + } +} diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentServiceImpl.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentServiceImpl.java new file mode 100644 index 00000000..0f1ef247 --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentServiceImpl.java @@ -0,0 +1,51 @@ +package com.eternalcode.combat.fight.trident; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; + +public class FightTridentServiceImpl implements FightTridentService { + private final FightTridentSettings tridentSettings; + private final Cache<@NotNull UUID, Instant> tridentStartTimes; + + public FightTridentServiceImpl(FightTridentSettings tridentSettings) { + this.tridentSettings = tridentSettings; + this.tridentStartTimes = Caffeine.newBuilder() + .expireAfterWrite(tridentSettings.tridentThrowDelay) + .build(); + } + + @Override + public void markDelay(UUID uuid) { + this.tridentStartTimes.put(uuid, Instant.now()); + } + + @Override + public boolean hasDelay(UUID uuid) { + return this.tridentStartTimes.getIfPresent(uuid) != null; + } + + @Override + public Duration getRemainingDelay(UUID uuid) { + Instant startTime = this.tridentStartTimes.getIfPresent(uuid); + if (startTime == null) { + return Duration.ZERO; + } + + Duration elapsed = Duration.between(startTime, Instant.now()); + Duration remaining = this.tridentSettings.tridentThrowDelay.minus(elapsed); + + return remaining.isNegative() ? Duration.ZERO : remaining; + } + + @Override + public Instant getDelay(UUID uuid) { + Instant startTime = this.tridentStartTimes.getIfPresent(uuid); + return startTime != null ? startTime.plus(this.tridentSettings.tridentThrowDelay) : Instant.MIN; + } +} + diff --git a/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentSettings.java b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentSettings.java new file mode 100644 index 00000000..a76ce925 --- /dev/null +++ b/eternalcombat-plugin/src/main/java/com/eternalcode/combat/fight/trident/FightTridentSettings.java @@ -0,0 +1,39 @@ +package com.eternalcode.combat.fight.trident; + +import com.eternalcode.multification.bukkit.notice.BukkitNotice; +import com.eternalcode.multification.notice.Notice; +import eu.okaeri.configs.OkaeriConfig; +import eu.okaeri.configs.annotation.Comment; + +import java.time.Duration; + +public class FightTridentSettings extends OkaeriConfig { + + @Comment({ + "# Set to true to disable throwing tridents during combat.", + "# This will work globally, but can be overridden by region settings" + }) + public boolean tridentThrowDisabledDuringCombat = false; + + @Comment("# Set to true so throwing trident will result in cooldown - delay between throws") + public boolean tridentCooldownEnabled = false; + + @Comment("# Set to true, so the users will get combat log when they throw tridents") + public boolean tridentResetsTimer = false; + + @Comment({ + "# Should throwing trident be on cooldown?", + "# Setting this option to 3s will make players wait 3 seconds between trident throws" + }) + public Duration tridentThrowDelay = Duration.ofSeconds(3); + + @Comment("# Message sent to the player when throwing trident is disabled") + public Notice tridentThrowBlockedDuringCombat = BukkitNotice.builder() + .chat("Throwing trident is prohibited during combat!") + .build(); + + @Comment("# Message marking delay between trident throws") + public Notice tridentThrowBlockedDelayDuringCombat = BukkitNotice.builder() + .chat("You must wait {TIME} before next throw!") + .build(); +}