diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 80e2a94..7953419 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -158,6 +158,8 @@ jobs:
teams-api(optional)
ezcountdown(optional)
ezeconomy(optional)
+ pvpmanager(optional)
+ simple-combatlog(optional)
# ──────────────────────────────────────────────────────────────────────
# 8. DISCORD NOTIFICATION
diff --git a/CHANGELOG.md b/CHANGELOG.md
index be5ecc2..ddd6dad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,29 @@ Release tags use the `v` prefix (e.g. `v3.0.2`).
---
+## [3.3.0] - 2026-05-16
+
+### Added
+
+- **PvP tag integration**: EzRTP now detects when a player enters combat and cancels their
+ pending teleport or active countdown. Three plugins are supported out of the box:
+ - **[CombatLogX](https://www.spigotmc.org/resources/combatlogx.31689/)** — auto-detected at startup; soft dependency.
+ - **[PvPManager](https://modrinth.com/plugin/pvpmanager)** — auto-detected at startup; soft dependency.
+ - **[Simple Combat Log](https://modrinth.com/plugin/simple-combatlog)** (NikeyV1/CombatLog) — auto-detected at startup; soft dependency.
+ - All three are added to `softdepend` in `plugin.yml` so they load before EzRTP when
+ present. No configuration change is required on servers that do not use any of them.
+ - New `pvp-tag-integration` section in `rtp.yml`:
+ - `cancel-countdown-on-pvp-tag` (default `true`): cancel an active countdown the moment
+ the player is tagged.
+ - `cancel-queued-on-pvp-tag` (default `true`): skip a queued teleport if the player is
+ already in combat when their slot is dispatched.
+ - New message keys `countdown-pvp-cancel` and `queue-pvp-tag-cancel` in `messages/*.yml`
+ for the cancellation notifications.
+ - Modrinth release metadata now declares `pvpmanager` and `simple-combatlog` as optional
+ dependencies.
+
+---
+
## [3.2.3] - 2026-05-16
### Fixed
diff --git a/docs/config/rtp.md b/docs/config/rtp.md
index 4d55a34..c5e187f 100644
--- a/docs/config/rtp.md
+++ b/docs/config/rtp.md
@@ -230,6 +230,30 @@ Supported values: `worldguard`, `griefprevention`, `teamsapi`.
---
+## PvP tag integration
+
+Cancels a pending teleport or active countdown when the player enters combat.
+Requires one of the supported PvP tag plugins to be installed (all are soft-dependencies):
+[CombatLogX](https://www.spigotmc.org/resources/combatlogx.31689/),
+[PvPManager](https://modrinth.com/plugin/pvpmanager), or
+[Simple Combat Log](https://modrinth.com/plugin/simple-combatlog).
+
+| Key | Default | Description |
+| :--- | :--- | :--- |
+| `pvp-tag-integration.cancel-countdown-on-pvp-tag` | `true` | Cancel an active countdown the moment the player receives a PvP tag. |
+| `pvp-tag-integration.cancel-queued-on-pvp-tag` | `true` | Skip a queued teleport if the player is already in combat when their slot is dispatched. |
+
+```yml
+pvp-tag-integration:
+ cancel-countdown-on-pvp-tag: true
+ cancel-queued-on-pvp-tag: true
+```
+
+If no supported PvP tag plugin is installed the section is silently ignored.
+See the [PvP Tag integration guide](../integrations/pvp-tag) for setup details.
+
+---
+
## Particles (arrival effect)
An optional particle burst played at the destination when the player arrives.
diff --git a/docs/integrations/index.md b/docs/integrations/index.md
index 8482760..2611753 100644
--- a/docs/integrations/index.md
+++ b/docs/integrations/index.md
@@ -8,3 +8,12 @@ has_children: true
EzRTP integrates with several popular plugins. Browse the pages below to
set up each one.
+
+| Page | Plugins covered |
+| :--- | :--- |
+| [Vault / Economy](vault-economy) | Vault, EzEconomy |
+| [PlaceholderAPI](placeholderapi) | PlaceholderAPI |
+| [Chunky](chunky) | Chunky (world pre-generation) |
+| [Protection](protection-worldguard-griefprevention) | WorldGuard, GriefPrevention, TeamsAPI |
+| [PvP Tag](pvp-tag) | CombatLogX, PvPManager, Simple Combat Log |
+| [Network / Proxy](network-proxy) | BungeeCord / Velocity proxy destinations |
diff --git a/docs/integrations/pvp-tag.md b/docs/integrations/pvp-tag.md
new file mode 100644
index 0000000..bd5b03b
--- /dev/null
+++ b/docs/integrations/pvp-tag.md
@@ -0,0 +1,72 @@
+---
+title: PvP Tag (CombatLogX / PvPManager / Simple Combat Log)
+nav_order: 5
+parent: Integrations
+---
+
+# PvP Tag Integration
+
+Use this integration when you want EzRTP to cancel a pending teleport or active
+countdown the moment a player enters combat.
+
+## Supported plugins
+
+All three plugins are optional soft-dependencies. EzRTP auto-detects whichever
+ones are present and registers them at startup. You can have more than one
+installed simultaneously.
+
+| Plugin | Where to get it |
+| :--- | :--- |
+| [CombatLogX](https://www.spigotmc.org/resources/combatlogx.31689/) | SpigotMC (597 K+ downloads) |
+| [PvPManager](https://modrinth.com/plugin/pvpmanager) | Modrinth · [SpigotMC (free)](https://www.spigotmc.org/resources/pvpmanager-lite.845/) |
+| [Simple Combat Log](https://modrinth.com/plugin/simple-combatlog) | Modrinth · [GitHub](https://github.com/NikeyV1/CombatLog) |
+
+No configuration change is required on servers that do not use any of them.
+
+## What this integration does
+
+- **Countdown cancellation** — if a player receives a PvP tag while a countdown is
+ ticking, the teleport is cancelled and a configurable message is sent.
+- **Queue cancellation** — if a queued teleport slot is dispatched while the player
+ is already tagged, the teleport is skipped and the player must re-queue.
+
+## Where to configure it
+
+File: `plugins/EzRTP/rtp.yml`
+
+```yml
+pvp-tag-integration:
+ cancel-countdown-on-pvp-tag: true
+ cancel-queued-on-pvp-tag: true
+```
+
+### Key settings
+
+- `cancel-countdown-on-pvp-tag`
+ - `true`: cancel the active countdown as soon as the player is tagged.
+ - `false`: ignore combat tags during countdown (teleport proceeds regardless).
+- `cancel-queued-on-pvp-tag`
+ - `true`: skip the queued teleport if the player is in combat at dispatch time.
+ - `false`: dispatch the queued teleport even while in combat.
+
+## Messages
+
+Add or override these keys in `plugins/EzRTP/messages/en.yml`:
+
+| Key | Default text |
+| :--- | :--- |
+| `countdown-pvp-cancel` | `Teleport cancelled — you entered combat!` |
+| `queue-pvp-tag-cancel` | `Teleport skipped — you are in combat!` |
+
+## Startup log
+
+When a supported plugin is detected, EzRTP logs a confirmation on enable:
+
+```text
+[EzRTP] PvP tag integration: CombatLogX detected.
+[EzRTP] PvP tag integration: PvPManager detected.
+[EzRTP] PvP tag integration: Simple Combat Log detected.
+```
+
+If none of the supported plugins are installed, no message is printed and the
+feature is effectively disabled.
diff --git a/ezrtp-api/pom.xml b/ezrtp-api/pom.xml
index e6d10ac..9939a2a 100644
--- a/ezrtp-api/pom.xml
+++ b/ezrtp-api/pom.xml
@@ -5,13 +5,13 @@
com.skyblockexp
ezrtp-parent
- 3.2.3
+ 3.3.0
../pom.xml
com.skyblockexp
ezrtp-api
- 3.2.3
+ 3.3.0
jar
EzRTP API
Lightweight public API for EzRTP intended for third-party plugins.
diff --git a/ezrtp-bukkit/pom.xml b/ezrtp-bukkit/pom.xml
index d69c0cf..f81da51 100644
--- a/ezrtp-bukkit/pom.xml
+++ b/ezrtp-bukkit/pom.xml
@@ -5,13 +5,13 @@
com.skyblockexp
ezrtp-parent
- 3.2.3
+ 3.3.0
../pom.xml
com.skyblockexp
ezrtp-bukkit
- 3.2.3
+ 3.3.0
jar
EzRTP (Bukkit)
EzRTP Bukkit-compatible plugin module.
@@ -111,7 +111,7 @@
com.skyblockexp
ezrtp-common
- 3.2.3
+ 3.3.0
diff --git a/ezrtp-common/pom.xml b/ezrtp-common/pom.xml
index c94f377..5a23887 100644
--- a/ezrtp-common/pom.xml
+++ b/ezrtp-common/pom.xml
@@ -5,13 +5,13 @@
com.skyblockexp
ezrtp-parent
- 3.2.3
+ 3.3.0
../pom.xml
com.skyblockexp
ezrtp-common
- 3.2.3
+ 3.3.0
jar
EzRTP Common
Shared utilities for EzRTP (platform-independent)
@@ -89,6 +89,34 @@
7.0.2
+
+
+ com.github.sirblobman.api
+ core
+ 2.9-SNAPSHOT
+ provided
+
+
+ com.github.sirblobman.combatlogx
+ api
+ 11.6-SNAPSHOT
+ provided
+
+
+
+ me.chancesd.pvpmanager
+ pvpmanager
+ 4.0.8
+ provided
+
+
+
+ com.github.NikeyV1
+ CombatLog
+ master-SNAPSHOT
+ provided
+
+
org.junit.jupiter
junit-jupiter
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/bootstrap/EzRtpPluginBootstrap.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/bootstrap/EzRtpPluginBootstrap.java
index 0573433..d797e9a 100644
--- a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/bootstrap/EzRtpPluginBootstrap.java
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/bootstrap/EzRtpPluginBootstrap.java
@@ -39,6 +39,7 @@
import org.bukkit.plugin.Plugin;
import com.skyblockexp.ezrtp.teleport.ChunkyProvider;
import com.skyblockexp.ezrtp.teleport.ChunkyRuntimeProvider;
+import com.skyblockexp.ezrtp.pvptag.PvpTagService;
// Chunky API is optional; use runtime loader via ChunkyRuntimeProvider
import java.io.File;
@@ -86,6 +87,7 @@ public final class EzRtpPluginBootstrap {
private UsageResetScheduler usageResetScheduler;
private final HeatmapSimulationStore heatmapSimulationStore = new HeatmapSimulationStore();
private com.skyblockexp.ezrtp.teleport.ChunkyWarmupCoordinator chunkyWarmupCoordinator;
+ private PvpTagService pvpTagService;
public EzRtpPluginBootstrap(EzRtpPlugin plugin) {
this.plugin = plugin;
@@ -238,6 +240,24 @@ public void reloadPluginConfiguration() {
plugin.getLogger().info("Chunky integration disabled in configuration.");
chunkyAPI = null;
}
+
+ // Initialize PvP tag providers once; registered only when the corresponding plugin is present.
+ if (pvpTagService == null) {
+ pvpTagService = new PvpTagService();
+ if (plugin.getServer().getPluginManager().isPluginEnabled("CombatLogX")) {
+ pvpTagService.registerProvider(new com.skyblockexp.ezrtp.pvptag.CombatLogXPvpTagProvider());
+ plugin.getLogger().info("PvP tag integration: CombatLogX detected.");
+ }
+ if (plugin.getServer().getPluginManager().isPluginEnabled("PvPManager")) {
+ pvpTagService.registerProvider(new com.skyblockexp.ezrtp.pvptag.PvpManagerPvpTagProvider());
+ plugin.getLogger().info("PvP tag integration: PvPManager detected.");
+ }
+ if (plugin.getServer().getPluginManager().isPluginEnabled("CombatLog")) {
+ pvpTagService.registerProvider(new com.skyblockexp.ezrtp.pvptag.SimpleCombatLogPvpTagProvider());
+ plugin.getLogger().info("PvP tag integration: Simple Combat Log detected.");
+ }
+ }
+
messageProvider = configurationService.getMessageProvider();
// Initialize text rendering settings (force legacy conversion for older clients)
boolean forceLegacy = configurationService.getEffectiveBaseConfiguration().getBoolean("messages.force-legacy-colors", false);
@@ -272,7 +292,7 @@ public void reloadPluginConfiguration() {
teleportService = new RandomTeleportService(plugin, defaultSettings,
configuration.getQueueSettings(), economyService,
(player, settings) -> configuration.resolveTeleportCost(player, settings),
- protectionRegistry, messageProvider, ChunkLoadStrategyRegistry.get(), PlatformRuntimeRegistry.get(), chunkyAPI, chunkyWarmupCoordinator);
+ protectionRegistry, messageProvider, ChunkLoadStrategyRegistry.get(), PlatformRuntimeRegistry.get(), chunkyAPI, chunkyWarmupCoordinator, pvpTagService);
try { EzRtpAPI.registerProvider(plugin, teleportService); } catch (Throwable ignored) {}
} else {
teleportService.reload(defaultSettings, configuration.getQueueSettings());
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/RandomTeleportSettings.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/RandomTeleportSettings.java
index f5aa88e..1c8a2b7 100644
--- a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/RandomTeleportSettings.java
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/RandomTeleportSettings.java
@@ -4,6 +4,7 @@
import com.skyblockexp.ezrtp.config.biome.BiomePreCacheSettings;
import com.skyblockexp.ezrtp.config.biome.BiomeSearchSettings;
import com.skyblockexp.ezrtp.config.biome.ChunkyIntegrationSettings;
+import com.skyblockexp.ezrtp.config.pvptag.PvpTagIntegrationSettings;
import com.skyblockexp.ezrtp.config.biome.RareBiomeOptimizationSettings;
import com.skyblockexp.ezrtp.config.effects.CountdownBossBarSettings;
import com.skyblockexp.ezrtp.config.effects.CountdownParticleSettings;
@@ -61,6 +62,7 @@ public final class RandomTeleportSettings {
private final boolean cancelOnMove;
private final double cancelDistance;
private final double warnDistance;
+ private final PvpTagIntegrationSettings pvpTagIntegrationSettings;
public RandomTeleportSettings(ConfigurationSection configSection,
String worldName, int centerX, int centerZ, int minimumRadius, int maximumRadius,
@@ -92,7 +94,8 @@ public RandomTeleportSettings(ConfigurationSection configSection,
minY, maxY, biomeInclude, biomeExclude, protectionSettings, preCacheSettings,
rareBiomeOptimizationSettings, chunkLoadingSettings, enableFallbackToCache,
biomeSearchSettings, biomeFilteringEnabled, biomeSystemEnabled, safetySettings,
- searchPattern, chunkyIntegrationSettings, false, true, 2.0, 1.0);
+ searchPattern, chunkyIntegrationSettings, false, true, 2.0, 1.0,
+ PvpTagIntegrationSettings.defaults());
}
public RandomTeleportSettings(ConfigurationSection configSection,
@@ -126,7 +129,8 @@ public RandomTeleportSettings(ConfigurationSection configSection,
minY, maxY, biomeInclude, biomeExclude, protectionSettings, preCacheSettings,
rareBiomeOptimizationSettings, chunkLoadingSettings, enableFallbackToCache,
biomeSearchSettings, biomeFilteringEnabled, biomeSystemEnabled, safetySettings,
- searchPattern, chunkyIntegrationSettings, suppressPlayerMessages, true, 2.0, 1.0);
+ searchPattern, chunkyIntegrationSettings, suppressPlayerMessages, true, 2.0, 1.0,
+ PvpTagIntegrationSettings.defaults());
}
public RandomTeleportSettings(ConfigurationSection configSection,
@@ -155,7 +159,8 @@ public RandomTeleportSettings(ConfigurationSection configSection,
boolean suppressPlayerMessages,
boolean cancelOnMove,
double cancelDistance,
- double warnDistance) {
+ double warnDistance,
+ PvpTagIntegrationSettings pvpTagIntegrationSettings) {
this.configSection = configSection;
this.worldName = worldName;
this.centerX = centerX;
@@ -193,6 +198,8 @@ public RandomTeleportSettings(ConfigurationSection configSection,
this.cancelOnMove = cancelOnMove;
this.cancelDistance = Math.max(0.0, cancelDistance);
this.warnDistance = Math.max(0.0, warnDistance);
+ this.pvpTagIntegrationSettings =
+ pvpTagIntegrationSettings != null ? pvpTagIntegrationSettings : PvpTagIntegrationSettings.defaults();
}
public Integer getMinY() { return minY; }
public Integer getMaxY() { return maxY; }
@@ -234,6 +241,8 @@ public RandomTeleportSettings(ConfigurationSection configSection,
public ChunkyIntegrationSettings getChunkyIntegrationSettings() { return chunkyIntegrationSettings; }
+ public PvpTagIntegrationSettings getPvpTagIntegrationSettings() { return pvpTagIntegrationSettings; }
+
/** Returns {@code true} only when {@code heatmap.enabled: true} is explicitly set in the world's rtp.yml section. */
public boolean isHeatmapEnabled() {
return configSection != null && configSection.getBoolean("heatmap.enabled", false);
@@ -263,7 +272,7 @@ public RandomTeleportSettings withWorldName(String newWorldName) {
chunkLoadingSettings, enableFallbackToCache, biomeSearchSettings,
biomeFilteringEnabled, biomeSystemEnabled, safetySettings,
searchPattern, chunkyIntegrationSettings, suppressPlayerMessages,
- cancelOnMove, cancelDistance, warnDistance);
+ cancelOnMove, cancelDistance, warnDistance, pvpTagIntegrationSettings);
}
public RandomTeleportSettings withSuppressPlayerMessages(boolean suppress) {
@@ -278,7 +287,7 @@ public RandomTeleportSettings withSuppressPlayerMessages(boolean suppress) {
chunkLoadingSettings, enableFallbackToCache, biomeSearchSettings,
biomeFilteringEnabled, biomeSystemEnabled, safetySettings,
searchPattern, chunkyIntegrationSettings, suppress,
- cancelOnMove, cancelDistance, warnDistance);
+ cancelOnMove, cancelDistance, warnDistance, pvpTagIntegrationSettings);
}
public static RandomTeleportSettings fromConfiguration(ConfigurationSection section, java.util.logging.Logger logger) {
@@ -306,7 +315,8 @@ public static RandomTeleportSettings fromConfiguration(ConfigurationSection sect
false,
true,
2.0,
- 1.0);
+ 1.0,
+ PvpTagIntegrationSettings.defaults());
}
String worldName = section.getString("world", "world");
@@ -425,6 +435,9 @@ public static RandomTeleportSettings fromConfiguration(ConfigurationSection sect
? countdownSection.getDouble("warn-distance", 1.0)
: 1.0;
+ PvpTagIntegrationSettings pvpTagIntegrationSettings = PvpTagIntegrationSettings.fromConfiguration(
+ section.getConfigurationSection("pvp-tag-integration"), PvpTagIntegrationSettings.defaults());
+
return new RandomTeleportSettings(section, worldName, centerX, centerZ, minRadius, maxRadius, maxAttempts, useWorldBorder, unsafeBlocks,
messages, particleSettings, onJoinTeleportSettings, countdownBossBarSettings, countdownParticleSettings,
teleportCost, countdownSeconds, countdownChatMessagesEnabled, debugRejectionLogging, minY, maxY,
@@ -443,7 +456,8 @@ public static RandomTeleportSettings fromConfiguration(ConfigurationSection sect
false,
cancelOnMove,
cancelDistance,
- warnDistance);
+ warnDistance,
+ pvpTagIntegrationSettings);
}
public static RandomTeleportSettings fromConfiguration(ConfigurationSection section, java.util.logging.Logger logger, RandomTeleportSettings fallback) {
@@ -597,6 +611,10 @@ public static RandomTeleportSettings fromConfiguration(ConfigurationSection sect
? countdownSection.getDouble("warn-distance", 1.0)
: (fallback != null ? fallback.getWarnDistance() : 1.0);
+ PvpTagIntegrationSettings pvpTagIntegrationSettings = PvpTagIntegrationSettings.fromConfiguration(
+ section.getConfigurationSection("pvp-tag-integration"),
+ fallback != null ? fallback.getPvpTagIntegrationSettings() : PvpTagIntegrationSettings.defaults());
+
return new RandomTeleportSettings(section, worldName, centerX, centerZ, minRadius, maxRadius, maxAttempts,
useWorldBorder, unsafeBlocks, messages, particleSettings, onJoinTeleportSettings, countdownBossBarSettings,
countdownParticleSettings, teleportCost, countdownSeconds, countdownChatMessagesEnabled, debugRejectionLogging, minY, maxY,
@@ -615,7 +633,8 @@ public static RandomTeleportSettings fromConfiguration(ConfigurationSection sect
fallback != null && fallback.isSuppressPlayerMessages(),
cancelOnMove,
cancelDistance,
- warnDistance);
+ warnDistance,
+ pvpTagIntegrationSettings);
}
public int getCountdownSeconds() {
return countdownSeconds;
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/pvptag/PvpTagIntegrationSettings.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/pvptag/PvpTagIntegrationSettings.java
new file mode 100644
index 0000000..56d714f
--- /dev/null
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/config/pvptag/PvpTagIntegrationSettings.java
@@ -0,0 +1,40 @@
+package com.skyblockexp.ezrtp.config.pvptag;
+
+import org.bukkit.configuration.ConfigurationSection;
+
+/** Configuration for PvP-tag integration (PvPManager / CombatLogX). */
+public final class PvpTagIntegrationSettings {
+
+ private final boolean cancelCountdownOnPvpTag;
+ private final boolean cancelQueuedOnPvpTag;
+
+ public PvpTagIntegrationSettings(boolean cancelCountdownOnPvpTag, boolean cancelQueuedOnPvpTag) {
+ this.cancelCountdownOnPvpTag = cancelCountdownOnPvpTag;
+ this.cancelQueuedOnPvpTag = cancelQueuedOnPvpTag;
+ }
+
+ public boolean isCancelCountdownOnPvpTag() {
+ return cancelCountdownOnPvpTag;
+ }
+
+ public boolean isCancelQueuedOnPvpTag() {
+ return cancelQueuedOnPvpTag;
+ }
+
+ public static PvpTagIntegrationSettings defaults() {
+ return new PvpTagIntegrationSettings(true, true);
+ }
+
+ public static PvpTagIntegrationSettings fromConfiguration(
+ ConfigurationSection section, PvpTagIntegrationSettings fallback) {
+ PvpTagIntegrationSettings def = fallback != null ? fallback : defaults();
+ if (section == null) {
+ return def;
+ }
+ boolean cancelCountdown =
+ section.getBoolean("cancel-countdown-on-pvp-tag", def.isCancelCountdownOnPvpTag());
+ boolean cancelQueued =
+ section.getBoolean("cancel-queued-on-pvp-tag", def.isCancelQueuedOnPvpTag());
+ return new PvpTagIntegrationSettings(cancelCountdown, cancelQueued);
+ }
+}
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageKey.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageKey.java
index 9d0e2b9..d306afd 100644
--- a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageKey.java
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageKey.java
@@ -20,12 +20,14 @@ public enum MessageKey {
// Queue messages
QUEUE_QUEUED("queue-queued"),
QUEUE_FULL("queue-full"),
+ QUEUE_PVP_TAG_CANCEL("queue-pvp-tag-cancel"),
// Countdown messages
COUNTDOWN_START("countdown-start"),
COUNTDOWN_TICK("countdown-tick"),
COUNTDOWN_MOVE_WARN("countdown-move-warn"),
COUNTDOWN_MOVE_CANCEL("countdown-move-cancel"),
+ COUNTDOWN_PVP_CANCEL("countdown-pvp-cancel"),
// Cooldown and usage limit messages
COOLDOWN("cooldown"),
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageProvider.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageProvider.java
index b496086..b04d32b 100644
--- a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageProvider.java
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/message/MessageProvider.java
@@ -290,6 +290,8 @@ private static String getDefaultMessage(MessageKey key) {
case STATS_BIOME_ACTIVITY_HEADER -> "Biomes by Activity (Page /, Total: biomes):";
case STATS_NAVIGATION -> "Navigation:";
case STATS_LEGEND -> "Legend:";
+ case COUNTDOWN_PVP_CANCEL -> "Teleport cancelled because you entered combat.";
+ case QUEUE_PVP_TAG_CANCEL -> "Your queued teleport was cancelled because you entered combat.";
};
}
}
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/CombatLogXPvpTagProvider.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/CombatLogXPvpTagProvider.java
new file mode 100644
index 0000000..3c03960
--- /dev/null
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/CombatLogXPvpTagProvider.java
@@ -0,0 +1,40 @@
+package com.skyblockexp.ezrtp.pvptag;
+
+import com.github.sirblobman.combatlogx.api.ICombatLogX;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+/**
+ * {@link PvpTagProvider} backed by CombatLogX.
+ * Only instantiate when the CombatLogX plugin is confirmed to be loaded.
+ */
+public final class CombatLogXPvpTagProvider implements PvpTagProvider {
+
+ private final ICombatLogX api;
+
+ public CombatLogXPvpTagProvider() {
+ this.api = (ICombatLogX) Bukkit.getPluginManager().getPlugin("CombatLogX");
+ }
+
+ @Override
+ public String getName() {
+ return "CombatLogX";
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return api != null && Bukkit.getPluginManager().isPluginEnabled("CombatLogX");
+ }
+
+ @Override
+ public boolean isInCombat(Player player) {
+ if (api == null || player == null) {
+ return false;
+ }
+ try {
+ return api.getCombatManager().isInCombat(player);
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+}
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpManagerPvpTagProvider.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpManagerPvpTagProvider.java
new file mode 100644
index 0000000..d8e7f21
--- /dev/null
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpManagerPvpTagProvider.java
@@ -0,0 +1,35 @@
+package com.skyblockexp.ezrtp.pvptag;
+
+import me.chancesd.pvpmanager.player.CombatPlayer;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+/**
+ * {@link PvpTagProvider} backed by PvPManager.
+ * Only instantiate when the PvPManager plugin is confirmed to be loaded.
+ */
+public final class PvpManagerPvpTagProvider implements PvpTagProvider {
+
+ @Override
+ public String getName() {
+ return "PvPManager";
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return Bukkit.getPluginManager().isPluginEnabled("PvPManager");
+ }
+
+ @Override
+ public boolean isInCombat(Player player) {
+ if (player == null) {
+ return false;
+ }
+ try {
+ CombatPlayer combatPlayer = CombatPlayer.get(player);
+ return combatPlayer != null && combatPlayer.isInCombat();
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+}
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpTagProvider.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpTagProvider.java
new file mode 100644
index 0000000..0b7ed09
--- /dev/null
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpTagProvider.java
@@ -0,0 +1,16 @@
+package com.skyblockexp.ezrtp.pvptag;
+
+import org.bukkit.entity.Player;
+
+/** Adapter interface for PvP-tag providers (e.g. CombatLogX, PvPManager). */
+public interface PvpTagProvider {
+
+ /** Display name used for logging. */
+ String getName();
+
+ /** Returns {@code true} when the underlying plugin is loaded and enabled. */
+ boolean isAvailable();
+
+ /** Returns {@code true} when {@code player} is currently in combat according to this provider. */
+ boolean isInCombat(Player player);
+}
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpTagService.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpTagService.java
new file mode 100644
index 0000000..65d0e9e
--- /dev/null
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/PvpTagService.java
@@ -0,0 +1,36 @@
+package com.skyblockexp.ezrtp.pvptag;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.bukkit.entity.Player;
+
+/** Aggregates zero or more {@link PvpTagProvider}s and exposes a unified {@code isInCombat} check. */
+public final class PvpTagService {
+
+ private final List providers = new ArrayList<>();
+
+ public void registerProvider(PvpTagProvider provider) {
+ providers.add(provider);
+ }
+
+ /** Returns {@code true} when at least one provider is registered. */
+ public boolean isEnabled() {
+ return !providers.isEmpty();
+ }
+
+ /**
+ * Returns {@code true} when any available provider reports {@code player} as being in combat.
+ * Returns {@code false} when {@code player} is {@code null} or no providers are registered.
+ */
+ public boolean isInCombat(Player player) {
+ if (player == null) {
+ return false;
+ }
+ for (PvpTagProvider provider : providers) {
+ if (provider.isAvailable() && provider.isInCombat(player)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/SimpleCombatLogPvpTagProvider.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/SimpleCombatLogPvpTagProvider.java
new file mode 100644
index 0000000..f0fce2b
--- /dev/null
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/pvptag/SimpleCombatLogPvpTagProvider.java
@@ -0,0 +1,40 @@
+package com.skyblockexp.ezrtp.pvptag;
+
+import de.nikey.combatLog.CombatLog;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
+/**
+ * {@link PvpTagProvider} backed by Simple Combat Log (NikeyV1/CombatLog).
+ * Only instantiate when the plugin is confirmed to be loaded.
+ * Modrinth: https://modrinth.com/plugin/simple-combatlog
+ */
+public final class SimpleCombatLogPvpTagProvider implements PvpTagProvider {
+
+ @Override
+ public String getName() {
+ return "Simple Combat Log";
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return Bukkit.getPluginManager().isPluginEnabled("CombatLog");
+ }
+
+ @Override
+ public boolean isInCombat(Player player) {
+ if (player == null) {
+ return false;
+ }
+ try {
+ Plugin plugin = Bukkit.getPluginManager().getPlugin("CombatLog");
+ if (!(plugin instanceof CombatLog combatLog)) {
+ return false;
+ }
+ return combatLog.getCombatManager().isInCombat(player);
+ } catch (Throwable t) {
+ return false;
+ }
+ }
+}
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/CountdownManager.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/CountdownManager.java
index c7637a7..47954c4 100644
--- a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/CountdownManager.java
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/CountdownManager.java
@@ -5,6 +5,7 @@
import com.skyblockexp.ezrtp.config.RandomTeleportSettings;
import com.skyblockexp.ezrtp.message.MessageKey;
import com.skyblockexp.ezrtp.message.MessageProvider;
+import com.skyblockexp.ezrtp.pvptag.PvpTagService;
import com.skyblockexp.ezrtp.util.MessageUtil;
import org.bukkit.Bukkit;
@@ -28,15 +29,25 @@ public final class CountdownManager {
private final org.bukkit.plugin.java.JavaPlugin plugin;
private final PlatformScheduler scheduler;
private final MessageProvider messageProvider;
+ private final PvpTagService pvpTagService;
private final Map countdownBossBars = new HashMap<>();
public CountdownManager(
org.bukkit.plugin.java.JavaPlugin plugin,
PlatformScheduler scheduler,
MessageProvider messageProvider) {
+ this(plugin, scheduler, messageProvider, null);
+ }
+
+ public CountdownManager(
+ org.bukkit.plugin.java.JavaPlugin plugin,
+ PlatformScheduler scheduler,
+ MessageProvider messageProvider,
+ PvpTagService pvpTagService) {
this.plugin = plugin;
this.scheduler = scheduler;
this.messageProvider = messageProvider;
+ this.pvpTagService = pvpTagService;
}
/**
@@ -100,6 +111,19 @@ private void runCountdown(Player player, RandomTeleportSettings teleportSettings
}
}
+ // PvP tag cancellation check
+ if (pvpTagService != null
+ && teleportSettings.getPvpTagIntegrationSettings().isCancelCountdownOnPvpTag()
+ && pvpTagService.isInCombat(player)) {
+ clearCountdownBossBar(player.getUniqueId());
+ if (!teleportSettings.isSuppressPlayerMessages()) {
+ MessageUtil.send(
+ player, messageProvider.format(MessageKey.COUNTDOWN_PVP_CANCEL, player));
+ }
+ if (callback != null) callback.accept(false);
+ return;
+ }
+
// Show countdown tick message
if (teleportSettings.isCountdownChatMessagesEnabled() && !teleportSettings.isSuppressPlayerMessages()) {
com.skyblockexp.ezrtp.util.MessageUtil.send(player, messageProvider.format(MessageKey.COUNTDOWN_TICK,
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/RandomTeleportService.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/RandomTeleportService.java
index 3ad7f06..7095ccb 100644
--- a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/RandomTeleportService.java
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/RandomTeleportService.java
@@ -28,6 +28,7 @@
import com.skyblockexp.ezrtp.teleport.biome.WeightedRareBiomeStrategy;
import com.skyblockexp.ezrtp.teleport.queue.ChunkLoadQueue;
import com.skyblockexp.ezrtp.teleport.queue.TeleportQueueManager;
+import com.skyblockexp.ezrtp.pvptag.PvpTagService;
import com.skyblockexp.ezrtp.util.DebugFileLogger;
import org.bukkit.Bukkit;
@@ -65,6 +66,7 @@ public final class RandomTeleportService implements com.skyblockexp.ezrtp.api.Te
private final ChunkyProvider chunkyAPI;
private final com.skyblockexp.ezrtp.teleport.ChunkyWarmupCoordinator chunkyWarmupCoordinator;
private final HotspotStorage hotspotStorage;
+ private final PvpTagService pvpTagService;
private RandomTeleportSettings settings;
private TeleportQueueSettings queueSettings;
@@ -80,10 +82,12 @@ public RandomTeleportService(org.bukkit.plugin.java.JavaPlugin plugin,
ChunkLoadStrategy chunkLoadStrategy,
PlatformRuntime platformRuntime,
ChunkyProvider chunkyAPI,
- com.skyblockexp.ezrtp.teleport.ChunkyWarmupCoordinator chunkyWarmupCoordinator) {
+ com.skyblockexp.ezrtp.teleport.ChunkyWarmupCoordinator chunkyWarmupCoordinator,
+ PvpTagService pvpTagService) {
this.plugin = plugin;
this.chunkyAPI = chunkyAPI;
this.chunkyWarmupCoordinator = chunkyWarmupCoordinator;
+ this.pvpTagService = pvpTagService;
this.debugFileLogger = new DebugFileLogger(plugin);
this.settings = settings;
this.queueSettings = queueSettings != null ? queueSettings : TeleportQueueSettings.disabled();
@@ -102,8 +106,9 @@ public RandomTeleportService(org.bukkit.plugin.java.JavaPlugin plugin,
this.biomeFilterExecutor = Executors.newSingleThreadExecutor(
r -> new Thread(r, "ezrtp-biome-filter"));
this.locationFinder = new LocationFinder(plugin, statistics, biomeCache, rareBiomeRegistry, chunkLoadQueue, locationValidator, searchStrategy, platformRuntime, chunkyAPI, chunkyWarmupCoordinator, biomeFilterExecutor);
- this.countdownManager = new CountdownManager(plugin, platformRuntime.scheduler(), messageProvider);
+ this.countdownManager = new CountdownManager(plugin, platformRuntime.scheduler(), messageProvider, pvpTagService);
this.queueManager = new TeleportQueueManager(plugin, platformRuntime.scheduler(), this.queueSettings, messageProvider);
+ this.queueManager.setPvpTagService(pvpTagService);
this.costCalculator = new TeleportCostCalculator(economyService, costResolver);
this.teleportExecutor = new TeleportExecutor(plugin, platformRuntime.scheduler(), messageProvider, statistics,
costCalculator, countdownManager, locationFinder, queueManager, () -> this.settings);
diff --git a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/queue/TeleportQueueManager.java b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/queue/TeleportQueueManager.java
index 23ad57d..64f2bbf 100644
--- a/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/queue/TeleportQueueManager.java
+++ b/ezrtp-common/src/main/java/com/skyblockexp/ezrtp/teleport/queue/TeleportQueueManager.java
@@ -5,6 +5,7 @@
import com.skyblockexp.ezrtp.message.MessageKey;
import com.skyblockexp.ezrtp.message.MessageProvider;
import com.skyblockexp.ezrtp.platform.PlatformScheduler;
+import com.skyblockexp.ezrtp.pvptag.PvpTagService;
import com.skyblockexp.ezrtp.teleport.TeleportReason;
import org.bukkit.entity.Player;
@@ -34,6 +35,7 @@ public interface QueueExecutionHandler {
private boolean queueProcessing;
private UUID activeTeleportPlayer;
private QueueExecutionHandler executionHandler;
+ private PvpTagService pvpTagService;
public TeleportQueueManager(
org.bukkit.plugin.java.JavaPlugin plugin,
@@ -50,6 +52,10 @@ public void setExecutionHandler(QueueExecutionHandler executionHandler) {
this.executionHandler = executionHandler;
}
+ public void setPvpTagService(PvpTagService pvpTagService) {
+ this.pvpTagService = pvpTagService;
+ }
+
/**
* Enqueues a teleport request if queuing is enabled and player cannot bypass.
* Returns true if enqueued, false if should proceed immediately.
@@ -118,6 +124,16 @@ private void dispatchNextTeleport() {
if (player == null || !player.isOnline()) {
continue;
}
+ if (pvpTagService != null
+ && next.settings().getPvpTagIntegrationSettings().isCancelQueuedOnPvpTag()
+ && pvpTagService.isInCombat(player)) {
+ if (!next.settings().isSuppressPlayerMessages()) {
+ MessageUtil.send(
+ player,
+ messageProvider.format(MessageKey.QUEUE_PVP_TAG_CANCEL, player));
+ }
+ continue;
+ }
activeTeleportPlayer = next.playerId();
executionHandler.execute(player, next.settings(), next.reason(), this::completeQueuedTeleport);
return;
diff --git a/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/api/EzRtpServiceEndToEndTest.java b/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/api/EzRtpServiceEndToEndTest.java
index 5bf39ce..97a4abf 100644
--- a/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/api/EzRtpServiceEndToEndTest.java
+++ b/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/api/EzRtpServiceEndToEndTest.java
@@ -67,7 +67,8 @@ void constructService_and_callSafeMethods() throws Exception {
chunkLoadStrategy,
platformRuntime,
chunkyProvider,
- new ChunkyWarmupCoordinator()
+ new ChunkyWarmupCoordinator(),
+ null
);
assertNotNull(service.getStatistics());
diff --git a/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/packaging/MessagesPackagingTest.java b/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/packaging/MessagesPackagingTest.java
index 30b7ce6..991441f 100644
--- a/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/packaging/MessagesPackagingTest.java
+++ b/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/packaging/MessagesPackagingTest.java
@@ -2,6 +2,8 @@
import org.junit.jupiter.api.Test;
+import java.net.URL;
+
import static org.junit.jupiter.api.Assertions.*;
/**
@@ -16,7 +18,15 @@ public void packagedResourcesUseLocalizedMessages() {
// Expect the localized default to be present
assertNotNull(loader.getResource("messages/en.yml"), "messages/en.yml should be on the classpath");
- // Expect the legacy top-level messages.yml to be absent
- assertNull(loader.getResource("messages.yml"), "legacy top-level messages.yml should not be packaged");
+ // Expect the legacy top-level messages.yml to be absent from EzRTP's own compiled output.
+ // Third-party dependency JARs on the test classpath may contain their own messages.yml,
+ // so we only fail if the resource originates from a compiled classes directory.
+ URL legacyResource = loader.getResource("messages.yml");
+ if (legacyResource != null) {
+ String url = legacyResource.toString();
+ assertFalse(
+ url.contains("/classes/") || url.contains("\\classes\\"),
+ "legacy top-level messages.yml should not be packaged in EzRTP's own output; found at: " + url);
+ }
}
}
diff --git a/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/pvptag/PvpTagServiceTest.java b/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/pvptag/PvpTagServiceTest.java
new file mode 100644
index 0000000..1f0448e
--- /dev/null
+++ b/ezrtp-common/src/test/java/com/skyblockexp/ezrtp/pvptag/PvpTagServiceTest.java
@@ -0,0 +1,89 @@
+package com.skyblockexp.ezrtp.pvptag;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.bukkit.entity.Player;
+import org.junit.jupiter.api.Test;
+
+class PvpTagServiceTest {
+
+ @Test
+ void isEnabled_noProviders_returnsFalse() {
+ PvpTagService service = new PvpTagService();
+ assertFalse(service.isEnabled());
+ }
+
+ @Test
+ void isEnabled_withProvider_returnsTrue() {
+ PvpTagService service = new PvpTagService();
+ service.registerProvider(stubProvider("Test", true, false));
+ assertTrue(service.isEnabled());
+ }
+
+ @Test
+ void isInCombat_noProviders_returnsFalse() {
+ PvpTagService service = new PvpTagService();
+ Player player = mock(Player.class);
+ assertFalse(service.isInCombat(player));
+ }
+
+ @Test
+ void isInCombat_nullPlayer_returnsFalse() {
+ PvpTagService service = new PvpTagService();
+ service.registerProvider(stubProvider("Test", true, true));
+ assertFalse(service.isInCombat(null));
+ }
+
+ @Test
+ void isInCombat_notInCombat_returnsFalse() {
+ PvpTagService service = new PvpTagService();
+ Player player = mock(Player.class);
+ service.registerProvider(stubProvider("Test", true, false));
+ assertFalse(service.isInCombat(player));
+ }
+
+ @Test
+ void isInCombat_inCombat_returnsTrue() {
+ PvpTagService service = new PvpTagService();
+ Player player = mock(Player.class);
+ service.registerProvider(stubProvider("Test", true, true));
+ assertTrue(service.isInCombat(player));
+ }
+
+ @Test
+ void isInCombat_unavailableProvider_skipped() {
+ PvpTagService service = new PvpTagService();
+ Player player = mock(Player.class);
+ service.registerProvider(stubProvider("Unavailable", false, true));
+ assertFalse(service.isInCombat(player));
+ }
+
+ @Test
+ void isInCombat_firstProviderFalse_secondProviderTrue_returnsTrue() {
+ PvpTagService service = new PvpTagService();
+ Player player = mock(Player.class);
+ service.registerProvider(stubProvider("First", true, false));
+ service.registerProvider(stubProvider("Second", true, true));
+ assertTrue(service.isInCombat(player));
+ }
+
+ @Test
+ void isInCombat_multipleProviders_allFalse_returnsFalse() {
+ PvpTagService service = new PvpTagService();
+ Player player = mock(Player.class);
+ service.registerProvider(stubProvider("First", true, false));
+ service.registerProvider(stubProvider("Second", true, false));
+ assertFalse(service.isInCombat(player));
+ }
+
+ private static PvpTagProvider stubProvider(String name, boolean available, boolean inCombat) {
+ PvpTagProvider provider = mock(PvpTagProvider.class);
+ when(provider.getName()).thenReturn(name);
+ when(provider.isAvailable()).thenReturn(available);
+ when(provider.isInCombat(org.mockito.ArgumentMatchers.any())).thenReturn(inCombat);
+ return provider;
+ }
+}
diff --git a/ezrtp-paper/pom.xml b/ezrtp-paper/pom.xml
index 3f06324..e929096 100644
--- a/ezrtp-paper/pom.xml
+++ b/ezrtp-paper/pom.xml
@@ -5,13 +5,13 @@
com.skyblockexp
ezrtp-parent
- 3.2.3
+ 3.3.0
../pom.xml
com.skyblockexp
ezrtp-paper
- 3.2.3
+ 3.3.0
jar
EzRTP (Paper)
Paper-optimized module for EzRTP
@@ -32,7 +32,7 @@
com.skyblockexp
ezrtp-common
- 3.2.3
+ 3.3.0
provided
diff --git a/ezrtp-purpur/pom.xml b/ezrtp-purpur/pom.xml
index c493da8..6821aca 100644
--- a/ezrtp-purpur/pom.xml
+++ b/ezrtp-purpur/pom.xml
@@ -5,7 +5,7 @@
com.skyblockexp
ezrtp-parent
- 3.2.3
+ 3.3.0
../pom.xml
@@ -18,12 +18,12 @@
com.skyblockexp
ezrtp-paper
- 3.2.3
+ 3.3.0
com.skyblockexp
ezrtp-common
- 3.2.3
+ 3.3.0
provided
diff --git a/ezrtp-spigot/pom.xml b/ezrtp-spigot/pom.xml
index cf9cec8..48c017b 100644
--- a/ezrtp-spigot/pom.xml
+++ b/ezrtp-spigot/pom.xml
@@ -5,13 +5,13 @@
com.skyblockexp
ezrtp-parent
- 3.2.3
+ 3.3.0
../pom.xml
com.skyblockexp
ezrtp-spigot
- 3.2.3
+ 3.3.0
jar
EzRTP (Spigot)
Spigot-optimized module for EzRTP
@@ -26,7 +26,7 @@
com.skyblockexp
ezrtp-common
- 3.2.3
+ 3.3.0
diff --git a/pom.xml b/pom.xml
index 2b90215..1ac3a15 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.skyblockexp
ezrtp-parent
- 3.2.3
+ 3.3.0
pom
EzRTP Parent
Aggregator POM for EzRTP multi-module build
@@ -97,6 +97,10 @@
jitpack
https://jitpack.io
+
+ sirblobman-public
+ https://nexus.sirblobman.xyz/public/
+
diff --git a/src/main/resources/messages/en.yml b/src/main/resources/messages/en.yml
index 7370567..a54f9fb 100644
--- a/src/main/resources/messages/en.yml
+++ b/src/main/resources/messages/en.yml
@@ -169,3 +169,7 @@ stats-cache-info: "Cache Information:"
stats-biome-activity-header: "Biomes by Activity (Page /, Total: biomes):"
stats-navigation: "Navigation:"
stats-legend: "Legend:"
+
+# PvP tag integration
+countdown-pvp-cancel: "Teleport cancelled because you entered combat."
+queue-pvp-tag-cancel: "Your queued teleport was cancelled because you entered combat."
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 7263eb7..e9475da 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -12,6 +12,9 @@ softdepend:
- PlaceholderAPI
- Chunky
- TeamsAPI
+ - CombatLogX
+ - PvPManager
+ - CombatLog
commands:
rtp:
description: Teleport to a random safe location in the configured world.
diff --git a/src/main/resources/rtp.yml b/src/main/resources/rtp.yml
index eef40de..329c0ff 100644
--- a/src/main/resources/rtp.yml
+++ b/src/main/resources/rtp.yml
@@ -115,6 +115,13 @@ chunky-integration:
max-coordinator-entries: 2000
low-memory-retention-minutes: 10
+# PvP tag integration — cancels teleport when player enters combat
+pvp-tag-integration:
+ # Cancel active countdown when player is tagged by PvPManager or CombatLogX.
+ cancel-countdown-on-pvp-tag: true
+ # Skip a queued teleport when the player is already in combat at dispatch time.
+ cancel-queued-on-pvp-tag: true
+
heatmap:
enabled: false