From 9ea94530c6ff12c625eeea4ef2a54eaf37b4dc22 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:16:16 -0300 Subject: [PATCH 01/17] Create maven.yml yay --- .github/workflows/maven.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..6e0f78a --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,30 @@ +name: Java Build + +on: + push: + branches: [ "master", "main" ] + pull_request: + branches: [ "master", "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + + - name: Build with Maven + run: mvn -B package --file pom.xml + + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: StoneDamager-Build + path: target/*.jar From bdc145c1e4bf351d66ca0b5bf42ec9ea9cbcc8d7 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:17:54 -0300 Subject: [PATCH 02/17] Update DamageHandler.java --- .../stonedamager/utils/DamageHandler.java | 167 +++++++----------- 1 file changed, 64 insertions(+), 103 deletions(-) diff --git a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java index 9d0f0c3..808724a 100644 --- a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java +++ b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java @@ -1,19 +1,17 @@ package host.plas.stonedamager.utils; -import host.plas.bou.scheduling.TaskManager; -import host.plas.bou.utils.ClassHelper; -import host.plas.bou.utils.EntityUtils; -import host.plas.stonedamager.StoneDamager; import host.plas.stonedamager.data.DamagableSelection; import host.plas.stonedamager.events.ScheduledDamageEvent; import lombok.Getter; import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; -import java.util.Optional; +import java.util.Collection; import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.ConcurrentSkipListSet; public class DamageHandler { @Getter @Setter @@ -24,115 +22,78 @@ public static void setTickable(DamagableSelection damagableSelection) { } public static void unsetTickable(String identifier) { - tickMap.forEach((damagableSelection, aLong) -> { - if (damagableSelection.getIdentifier().equals(identifier)) { - tickMap.remove(damagableSelection); - } - }); - } - - public static void addAllTickables(ConcurrentSkipListSet tickMap) { - tickMap.forEach(DamageHandler::setTickable); - } - - public static void clearTickables() { - tickMap.clear(); - } - - public static Optional getTickable(String identifier) { - return tickMap.keySet().stream().filter(damagableSelection -> damagableSelection.getIdentifier().equals(identifier)).findFirst(); + tickMap.keySet().removeIf(selection -> selection.getIdentifier().equals(identifier)); } - public static long getTicksLeft(String identifier) { - return getTickable(identifier).map(damagableSelection -> tickMap.get(damagableSelection)).orElse(1L); + public static void addAllTickables(Collection selections) { + selections.forEach(DamageHandler::setTickable); } - public static void tickTicksLeft(String identifier) { - getTickable(identifier).ifPresent(damagableSelection -> { - long ticks = tickMap.get(damagableSelection); - ticks -= 1; - tickMap.put(damagableSelection, ticks); - }); - } - - public static void resetTicksLeft(String identifier) { - getTickable(identifier).ifPresent(damagableSelection -> { - tickMap.put(damagableSelection, damagableSelection.getTicksPerDamage()); - }); - } - - public static void fire(LivingEntity entity, DamagableSelection damagableSelection, boolean isInSync) { - ScheduledDamageEvent event = new ScheduledDamageEvent(entity, damagableSelection).fire(); - if (event.isCancelled()) return; - - try { - if (isInSync) { - fireInSync(event); - } else { - if (ClassHelper.isFolia()) { - TaskManager.getScheduler().runTask(entity, () -> { - fireInSync(event); - }); - } else { - TaskManager.getScheduler().runTask(() -> { - fireInSync(event); - }); - } + /** + * Helper: Find the closest player to a location to attribute the damage to. + */ + private static Player getClosestPlayer(Location loc) { + if (loc.getWorld() == null) return null; + Player closest = null; + double closestDist = Double.MAX_VALUE; + + // Scan for players within 15 blocks + for (Player p : loc.getWorld().getPlayers()) { + double dist = p.getLocation().distanceSquared(loc); + if (dist < 225 && dist < closestDist) { // 15^2 = 225 + closestDist = dist; + closest = p; } - } catch (Throwable e) { - StoneDamager.getInstance().logWarningWithInfo("Error while firing damage event.", e); - } - } - - public static void fireInSync(ScheduledDamageEvent event) { - try { - double damage = event.getDamagableSelection().getDamageAmount(); - - event.getEntity().damage(damage); - } catch (Throwable e) { - StoneDamager.getInstance().logWarningWithInfo("Error while firing damage event in sync.", e); } + return closest; } public static void tick() { - try { - getTickMap().forEach((damagableSelection, ticks) -> { - if (! damagableSelection.isEnabled()) return; - - if (ticks > 0) { - tickTicksLeft(damagableSelection.getIdentifier()); - } else { - EntityUtils.collectEntitiesThenDo((entity) -> { - try { - if (ClassHelper.isFolia()) { - TaskManager.getScheduler().runTask(entity, getDamageTask(damagableSelection, entity)); - } else { - TaskManager.getScheduler().runTask(getDamageTask(damagableSelection, entity)); - } - } catch (Throwable e) { - StoneDamager.getInstance().logWarningWithInfo("Error while ticking entities.", e); + if (tickMap.isEmpty()) return; + + tickMap.forEach((selection, ticksLeft) -> { + if (ticksLeft <= 0) { + // Reset the timer for this block + tickMap.put(selection, selection.getTicksPerDamage()); + + // Instead of guessing selection.getAffectedEntities(), we manually find them. + // We assume selection.getLocation() exists. + Location loc = selection.getLocation(); + + if (loc != null && loc.getWorld() != null) { + // Look for victims within 1 block of the stone cutter + Collection nearby = loc.getWorld().getNearbyEntities(loc, 1.0, 1.0, 1.0); + + // Find the "owner" of this damage (closest player) + Player damager = getClosestPlayer(loc); + + for (Entity entity : nearby) { + if (!(entity instanceof LivingEntity)) continue; + LivingEntity victim = (LivingEntity) entity; + if (victim.isDead()) continue; + + double damage = selection.getDamageAmount(); + + // Fire event + ScheduledDamageEvent event = new ScheduledDamageEvent(victim, damage, selection); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) continue; + + // Deal the damage + if (damager != null) { + // Attributes damage to the player (drops XP) + victim.damage(event.getDamage(), damager); + } else { + // Fallback to generic damage + victim.damage(event.getDamage()); } - }); - - resetTicksLeft(damagableSelection.getIdentifier()); + } } - }); - } catch (Throwable e) { - StoneDamager.getInstance().logWarningWithInfo("Error while ticking entities.", e); - } - } - - public static Runnable getDamageTask(DamagableSelection damagableSelection, Entity entity) { - return () -> { - if (! damagableSelection.isEnabled()) return; - - if (! (entity instanceof LivingEntity)) return; - LivingEntity livingEntity = (LivingEntity) entity; - - if (damagableSelection.check(livingEntity)) { - fire(livingEntity, damagableSelection, true); + } else { + tickMap.put(selection, ticksLeft - 1); } - }; + }); } } From 7d28bc44a9d8cc26aa4b6dcaf23562b6cb656e78 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:22:44 -0300 Subject: [PATCH 03/17] Update maven.yml --- .github/workflows/maven.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 6e0f78a..9a8ee06 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -18,13 +18,25 @@ jobs: with: java-version: '17' distribution: 'temurin' - cache: maven + # Removed 'cache: maven' to prevent crashing if pom.xml is nested - name: Build with Maven - run: mvn -B package --file pom.xml + run: | + # Find the pom.xml file anywhere in the repository + POM_PATH=$(find . -name "pom.xml" -type f | head -n 1) + + if [ -z "$POM_PATH" ]; then + echo "::error::Could not find pom.xml. Make sure you uploaded the source code correctly." + exit 1 + fi + + echo "Found pom.xml at: $POM_PATH" + mvn -B package --file "$POM_PATH" - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: StoneDamager-Build - path: target/*.jar + path: | + **/target/*.jar + !**/original-*.jar From 08396b70d20ad10a9e8cf782e8a625ad8e50e758 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:25:12 -0300 Subject: [PATCH 04/17] Update maven.yml --- .github/workflows/maven.yml | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9a8ee06..1e306ba 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,4 +1,4 @@ -name: Java Build +name: Java CI with Gradle on: push: @@ -18,25 +18,16 @@ jobs: with: java-version: '17' distribution: 'temurin' - # Removed 'cache: maven' to prevent crashing if pom.xml is nested + cache: gradle - - name: Build with Maven - run: | - # Find the pom.xml file anywhere in the repository - POM_PATH=$(find . -name "pom.xml" -type f | head -n 1) - - if [ -z "$POM_PATH" ]; then - echo "::error::Could not find pom.xml. Make sure you uploaded the source code correctly." - exit 1 - fi - - echo "Found pom.xml at: $POM_PATH" - mvn -B package --file "$POM_PATH" + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: StoneDamager-Build - path: | - **/target/*.jar - !**/original-*.jar + path: build/libs/*.jar From 9479913cf001cd3bfa92984e65df32b12599f56a Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:29:13 -0300 Subject: [PATCH 05/17] Update DamageHandler.java --- .../stonedamager/utils/DamageHandler.java | 167 +++++++++++------- 1 file changed, 103 insertions(+), 64 deletions(-) diff --git a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java index 808724a..9d0f0c3 100644 --- a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java +++ b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java @@ -1,17 +1,19 @@ package host.plas.stonedamager.utils; +import host.plas.bou.scheduling.TaskManager; +import host.plas.bou.utils.ClassHelper; +import host.plas.bou.utils.EntityUtils; +import host.plas.stonedamager.StoneDamager; import host.plas.stonedamager.data.DamagableSelection; import host.plas.stonedamager.events.ScheduledDamageEvent; import lombok.Getter; import lombok.Setter; -import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import java.util.Collection; +import java.util.Optional; import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.ConcurrentSkipListSet; public class DamageHandler { @Getter @Setter @@ -22,78 +24,115 @@ public static void setTickable(DamagableSelection damagableSelection) { } public static void unsetTickable(String identifier) { - tickMap.keySet().removeIf(selection -> selection.getIdentifier().equals(identifier)); + tickMap.forEach((damagableSelection, aLong) -> { + if (damagableSelection.getIdentifier().equals(identifier)) { + tickMap.remove(damagableSelection); + } + }); + } + + public static void addAllTickables(ConcurrentSkipListSet tickMap) { + tickMap.forEach(DamageHandler::setTickable); + } + + public static void clearTickables() { + tickMap.clear(); + } + + public static Optional getTickable(String identifier) { + return tickMap.keySet().stream().filter(damagableSelection -> damagableSelection.getIdentifier().equals(identifier)).findFirst(); } - public static void addAllTickables(Collection selections) { - selections.forEach(DamageHandler::setTickable); + public static long getTicksLeft(String identifier) { + return getTickable(identifier).map(damagableSelection -> tickMap.get(damagableSelection)).orElse(1L); } - /** - * Helper: Find the closest player to a location to attribute the damage to. - */ - private static Player getClosestPlayer(Location loc) { - if (loc.getWorld() == null) return null; - Player closest = null; - double closestDist = Double.MAX_VALUE; - - // Scan for players within 15 blocks - for (Player p : loc.getWorld().getPlayers()) { - double dist = p.getLocation().distanceSquared(loc); - if (dist < 225 && dist < closestDist) { // 15^2 = 225 - closestDist = dist; - closest = p; + public static void tickTicksLeft(String identifier) { + getTickable(identifier).ifPresent(damagableSelection -> { + long ticks = tickMap.get(damagableSelection); + ticks -= 1; + tickMap.put(damagableSelection, ticks); + }); + } + + public static void resetTicksLeft(String identifier) { + getTickable(identifier).ifPresent(damagableSelection -> { + tickMap.put(damagableSelection, damagableSelection.getTicksPerDamage()); + }); + } + + public static void fire(LivingEntity entity, DamagableSelection damagableSelection, boolean isInSync) { + ScheduledDamageEvent event = new ScheduledDamageEvent(entity, damagableSelection).fire(); + if (event.isCancelled()) return; + + try { + if (isInSync) { + fireInSync(event); + } else { + if (ClassHelper.isFolia()) { + TaskManager.getScheduler().runTask(entity, () -> { + fireInSync(event); + }); + } else { + TaskManager.getScheduler().runTask(() -> { + fireInSync(event); + }); + } } + } catch (Throwable e) { + StoneDamager.getInstance().logWarningWithInfo("Error while firing damage event.", e); + } + } + + public static void fireInSync(ScheduledDamageEvent event) { + try { + double damage = event.getDamagableSelection().getDamageAmount(); + + event.getEntity().damage(damage); + } catch (Throwable e) { + StoneDamager.getInstance().logWarningWithInfo("Error while firing damage event in sync.", e); } - return closest; } public static void tick() { - if (tickMap.isEmpty()) return; - - tickMap.forEach((selection, ticksLeft) -> { - if (ticksLeft <= 0) { - // Reset the timer for this block - tickMap.put(selection, selection.getTicksPerDamage()); - - // Instead of guessing selection.getAffectedEntities(), we manually find them. - // We assume selection.getLocation() exists. - Location loc = selection.getLocation(); - - if (loc != null && loc.getWorld() != null) { - // Look for victims within 1 block of the stone cutter - Collection nearby = loc.getWorld().getNearbyEntities(loc, 1.0, 1.0, 1.0); - - // Find the "owner" of this damage (closest player) - Player damager = getClosestPlayer(loc); - - for (Entity entity : nearby) { - if (!(entity instanceof LivingEntity)) continue; - LivingEntity victim = (LivingEntity) entity; - if (victim.isDead()) continue; - - double damage = selection.getDamageAmount(); - - // Fire event - ScheduledDamageEvent event = new ScheduledDamageEvent(victim, damage, selection); - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) continue; - - // Deal the damage - if (damager != null) { - // Attributes damage to the player (drops XP) - victim.damage(event.getDamage(), damager); - } else { - // Fallback to generic damage - victim.damage(event.getDamage()); + try { + getTickMap().forEach((damagableSelection, ticks) -> { + if (! damagableSelection.isEnabled()) return; + + if (ticks > 0) { + tickTicksLeft(damagableSelection.getIdentifier()); + } else { + EntityUtils.collectEntitiesThenDo((entity) -> { + try { + if (ClassHelper.isFolia()) { + TaskManager.getScheduler().runTask(entity, getDamageTask(damagableSelection, entity)); + } else { + TaskManager.getScheduler().runTask(getDamageTask(damagableSelection, entity)); + } + } catch (Throwable e) { + StoneDamager.getInstance().logWarningWithInfo("Error while ticking entities.", e); } - } + }); + + resetTicksLeft(damagableSelection.getIdentifier()); } + }); - } else { - tickMap.put(selection, ticksLeft - 1); + } catch (Throwable e) { + StoneDamager.getInstance().logWarningWithInfo("Error while ticking entities.", e); + } + } + + public static Runnable getDamageTask(DamagableSelection damagableSelection, Entity entity) { + return () -> { + if (! damagableSelection.isEnabled()) return; + + if (! (entity instanceof LivingEntity)) return; + LivingEntity livingEntity = (LivingEntity) entity; + + if (damagableSelection.check(livingEntity)) { + fire(livingEntity, damagableSelection, true); } - }); + }; } } From 837292ab52d8302622252460cdfea18087654c3d Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:38:10 -0300 Subject: [PATCH 06/17] Update dependencies.gradle --- dependencies.gradle | 65 +++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index cf0046b..9cff826 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,33 +1,58 @@ ext { + // Implementation dependencies (shaded inside your plugin) IMPL = [ ] + + // Dependencies to be shaded using the Shadow plugin SHADOW = [ ] + + // Annotation processors (compile-time only) ANNO = [ - 'com.github.streamline-essentials:BukkitOfUtils:master-SNAPSHOT', - 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', - 'net.kyori:adventure-api:4.16.0', - 'net.kyori:adventure-text-serializer-gson:4.16.0', - 'net.kyori:adventure-text-serializer-legacy:4.16.0', - 'net.kyori:adventure-text-serializer-plain:4.16.0', - 'net.kyori:adventure-text-minimessage:4.16.0', - 'net.kyori:adventure-text-serializer-ansi:4.16.0', - 'net.kyori:ansi:1.0.3', + // Streamline Core APIs + "com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT", + "com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT", + + // BukkitOfUtils – REQUIRED for tv.quaint.events, tv.quaint.objects, tv.quaint.storage + "com.github.Quaint-Studios:BukkitOfUtils:1.1.15", + + // Folia & Adventure + "dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT", + "net.kyori:adventure-api:4.16.0", + "net.kyori:adventure-text-serializer-gson:4.16.0", + "net.kyori:adventure-text-serializer-legacy:4.16.0", + "net.kyori:adventure-text-serializer-plain:4.16.0", + "net.kyori:adventure-text-minimessage:4.16.0", + "net.kyori:adventure-text-serializer-ansi:4.16.0", + "net.kyori:ansi:1.0.3", ] + + // Compile-only dependencies (not included in final jar) COMP_ONLY = [ - 'com.github.streamline-essentials:BukkitOfUtils:master-SNAPSHOT', - 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', - 'net.kyori:adventure-api:4.16.0', - 'net.kyori:adventure-text-serializer-gson:4.16.0', - 'net.kyori:adventure-text-serializer-legacy:4.16.0', - 'net.kyori:adventure-text-serializer-plain:4.16.0', - 'net.kyori:adventure-text-minimessage:4.16.0', - 'net.kyori:adventure-text-serializer-ansi:4.16.0', - 'net.kyori:ansi:1.0.3', + // Streamline Core APIs + "com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT", + "com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT", + + // BukkitOfUtils – provides tv.quaint.* classes + "com.github.Quaint-Studios:BukkitOfUtils:1.1.15", + + // Folia & Adventure APIs + "dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT", + "net.kyori:adventure-api:4.16.0", + "net.kyori:adventure-text-serializer-gson:4.16.0", + "net.kyori:adventure-text-serializer-legacy:4.16.0", + "net.kyori:adventure-text-serializer-plain:4.16.0", + "net.kyori:adventure-text-minimessage:4.16.0", + "net.kyori:adventure-text-serializer-ansi:4.16.0", + "net.kyori:ansi:1.0.3", ] + + // Local files (empty unless you add custom jars) FILES = [ ] + + // Other plugin APIs you depend on OTHER_PLUGINS = [ - 'me.clip:placeholderapi:2.11.5', + "me.clip:placeholderapi:2.11.5", ] -} \ No newline at end of file +} From 5ccfe76c2b3689269202f63d1206a40409b7f227 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:41:59 -0300 Subject: [PATCH 07/17] Update dependencies.gradle --- dependencies.gradle | 71 +++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 9cff826..80c42b0 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,58 +1,41 @@ ext { - // Implementation dependencies (shaded inside your plugin) IMPL = [ ] - - // Dependencies to be shaded using the Shadow plugin SHADOW = [ ] - - // Annotation processors (compile-time only) ANNO = [ - // Streamline Core APIs - "com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT", - "com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT", - - // BukkitOfUtils – REQUIRED for tv.quaint.events, tv.quaint.objects, tv.quaint.storage - "com.github.Quaint-Studios:BukkitOfUtils:1.1.15", - - // Folia & Adventure - "dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT", - "net.kyori:adventure-api:4.16.0", - "net.kyori:adventure-text-serializer-gson:4.16.0", - "net.kyori:adventure-text-serializer-legacy:4.16.0", - "net.kyori:adventure-text-serializer-plain:4.16.0", - "net.kyori:adventure-text-minimessage:4.16.0", - "net.kyori:adventure-text-serializer-ansi:4.16.0", - "net.kyori:ansi:1.0.3", + // Updated to CamelCase per JitPack requirements and added Core modules + 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', + 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', + 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', + + 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', + 'net.kyori:adventure-api:4.16.0', + 'net.kyori:adventure-text-serializer-gson:4.16.0', + 'net.kyori:adventure-text-serializer-legacy:4.16.0', + 'net.kyori:adventure-text-serializer-plain:4.16.0', + 'net.kyori:adventure-text-minimessage:4.16.0', + 'net.kyori:adventure-text-serializer-ansi:4.16.0', + 'net.kyori:ansi:1.0.3', ] - - // Compile-only dependencies (not included in final jar) COMP_ONLY = [ - // Streamline Core APIs - "com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT", - "com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT", - - // BukkitOfUtils – provides tv.quaint.* classes - "com.github.Quaint-Studios:BukkitOfUtils:1.1.15", - - // Folia & Adventure APIs - "dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT", - "net.kyori:adventure-api:4.16.0", - "net.kyori:adventure-text-serializer-gson:4.16.0", - "net.kyori:adventure-text-serializer-legacy:4.16.0", - "net.kyori:adventure-text-serializer-plain:4.16.0", - "net.kyori:adventure-text-minimessage:4.16.0", - "net.kyori:adventure-text-serializer-ansi:4.16.0", - "net.kyori:ansi:1.0.3", + // Updated to CamelCase per JitPack requirements and added Core modules + 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', + 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', + 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', + + 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', + 'net.kyori:adventure-api:4.16.0', + 'net.kyori:adventure-text-serializer-gson:4.16.0', + 'net.kyori:adventure-text-serializer-legacy:4.16.0', + 'net.kyori:adventure-text-serializer-plain:4.16.0', + 'net.kyori:adventure-text-minimessage:4.16.0', + 'net.kyori:adventure-text-serializer-ansi:4.16.0', + 'net.kyori:ansi:1.0.3', ] - - // Local files (empty unless you add custom jars) FILES = [ ] - - // Other plugin APIs you depend on OTHER_PLUGINS = [ - "me.clip:placeholderapi:2.11.5", + 'me.clip:placeholderapi:2.11.5', ] } From a0d681663ef699d121c3cb8bf2517e3a4308bfd9 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:42:31 -0300 Subject: [PATCH 08/17] Update build.gradle --- build.gradle | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 578a94b..ba9ecf1 100644 --- a/build.gradle +++ b/build.gradle @@ -23,9 +23,6 @@ repositories { mavenLocal() maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' - - // As of Gradle 5.1, you can limit this to only those - // dependencies you expect from it content { includeGroup 'org.bukkit' includeGroup 'org.spigotmc' @@ -37,7 +34,17 @@ repositories { name = "sonatype" url = "https://oss.sonatype.org/content/groups/public/" } - maven { url "https://jitpack.io" } + + // Updated JitPack repo to handle Private Repositories (401 Error Fix) + maven { + url "https://jitpack.io" + credentials { + // Default to empty string if authToken is not set to prevent crash on public builds + username = project.hasProperty('authToken') ? project.authToken : "" + password = "" + } + } + maven { name = "placeholderapi" url = "https://repo.extendedclip.com/content/repositories/placeholderapi/" @@ -95,4 +102,4 @@ artifacts { wrapper { gradleVersion = '8.9' distributionType = Wrapper.DistributionType.ALL -} \ No newline at end of file +} From b2f273d64fc84a1892edf97e563bfd92a842ea14 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:46:20 -0300 Subject: [PATCH 09/17] Update build.gradle --- build.gradle | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index ba9ecf1..698ab0e 100644 --- a/build.gradle +++ b/build.gradle @@ -35,13 +35,14 @@ repositories { url = "https://oss.sonatype.org/content/groups/public/" } - // Updated JitPack repo to handle Private Repositories (401 Error Fix) + // Updated JitPack repo logic to be conditional + // This prevents 401 errors on public repos if the authToken is empty maven { url "https://jitpack.io" - credentials { - // Default to empty string if authToken is not set to prevent crash on public builds - username = project.hasProperty('authToken') ? project.authToken : "" - password = "" + if (project.hasProperty('authToken') && project.authToken.toString().trim()) { + credentials { + username = project.authToken + } } } From 4ed61ee0d14895042ececf2190c359042748c6e3 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:46:32 -0300 Subject: [PATCH 10/17] Update dependencies.gradle --- dependencies.gradle | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 80c42b0..1227024 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -4,11 +4,8 @@ ext { SHADOW = [ ] ANNO = [ - // Updated to CamelCase per JitPack requirements and added Core modules + // Lombok is handled by the plugin, but keeping standard dependencies here if needed 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', - 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', - 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', - 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', 'net.kyori:adventure-api:4.16.0', 'net.kyori:adventure-text-serializer-gson:4.16.0', @@ -19,11 +16,13 @@ ext { 'net.kyori:ansi:1.0.3', ] COMP_ONLY = [ - // Updated to CamelCase per JitPack requirements and added Core modules + // Updated BukkitOfUtils to the new Group ID 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', + + // New StreamlineCore Dependencies requested by Dev 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', - + 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', 'net.kyori:adventure-api:4.16.0', 'net.kyori:adventure-text-serializer-gson:4.16.0', From 09b976c0661d08cff741871e7048006205d2702f Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:47:17 -0300 Subject: [PATCH 11/17] Update dependencies.gradle --- dependencies.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 1227024..701cc4e 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -35,6 +35,5 @@ ext { FILES = [ ] OTHER_PLUGINS = [ - 'me.clip:placeholderapi:2.11.5', ] } From 7c2b58a33efcc33685451e6638df3e02e7f2eca5 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:52:44 -0300 Subject: [PATCH 12/17] Update dependencies.gradle --- dependencies.gradle | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 701cc4e..c740b58 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -16,13 +16,9 @@ ext { 'net.kyori:ansi:1.0.3', ] COMP_ONLY = [ - // Updated BukkitOfUtils to the new Group ID + // Updated BukkitOfUtils to the new Group ID matching BrewFaster 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', - // New StreamlineCore Dependencies requested by Dev - 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', - 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', - 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', 'net.kyori:adventure-api:4.16.0', 'net.kyori:adventure-text-serializer-gson:4.16.0', From d7726cfab09828e98f5abc1cec85c67bf1b35cf7 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 06:54:22 -0300 Subject: [PATCH 13/17] Update DamageHandler.java --- .../stonedamager/utils/DamageHandler.java | 60 +++++++++++++------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java index 9d0f0c3..f1d03e5 100644 --- a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java +++ b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java @@ -10,6 +10,7 @@ import lombok.Setter; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import java.util.Optional; import java.util.concurrent.ConcurrentSkipListMap; @@ -40,24 +41,24 @@ public static void clearTickables() { } public static Optional getTickable(String identifier) { - return tickMap.keySet().stream().filter(damagableSelection -> damagableSelection.getIdentifier().equals(identifier)).findFirst(); + return tickMap.keySet().stream().filter(d -> d.getIdentifier().equals(identifier)).findFirst(); } public static long getTicksLeft(String identifier) { - return getTickable(identifier).map(damagableSelection -> tickMap.get(damagableSelection)).orElse(1L); + return getTickable(identifier).map(d -> tickMap.get(d)).orElse(1L); } public static void tickTicksLeft(String identifier) { - getTickable(identifier).ifPresent(damagableSelection -> { - long ticks = tickMap.get(damagableSelection); + getTickable(identifier).ifPresent(d -> { + long ticks = tickMap.get(d); ticks -= 1; - tickMap.put(damagableSelection, ticks); + tickMap.put(d, ticks); }); } public static void resetTicksLeft(String identifier) { - getTickable(identifier).ifPresent(damagableSelection -> { - tickMap.put(damagableSelection, damagableSelection.getTicksPerDamage()); + getTickable(identifier).ifPresent(d -> { + tickMap.put(d, d.getTicksPerDamage()); }); } @@ -70,13 +71,9 @@ public static void fire(LivingEntity entity, DamagableSelection damagableSelecti fireInSync(event); } else { if (ClassHelper.isFolia()) { - TaskManager.getScheduler().runTask(entity, () -> { - fireInSync(event); - }); + TaskManager.getScheduler().runTask(entity, () -> fireInSync(event)); } else { - TaskManager.getScheduler().runTask(() -> { - fireInSync(event); - }); + TaskManager.getScheduler().runTask(() -> fireInSync(event)); } } } catch (Throwable e) { @@ -84,11 +81,40 @@ public static void fire(LivingEntity entity, DamagableSelection damagableSelecti } } + // New helper: find nearest player within range + private static Player getNearestPlayer(LivingEntity entity, double range) { + Player nearest = null; + double nearestDist = Double.MAX_VALUE; + + for (Player p : entity.getWorld().getPlayers()) { + if (!p.isOnline() || p.isDead()) continue; + + double dist = p.getLocation().distance(entity.getLocation()); + if (dist <= range && dist < nearestDist) { + nearestDist = dist; + nearest = p; + } + } + + return nearest; + } + public static void fireInSync(ScheduledDamageEvent event) { try { + LivingEntity target = event.getEntity(); double damage = event.getDamagableSelection().getDamageAmount(); - event.getEntity().damage(damage); + // Find closest player within 30 blocks + Player attacker = getNearestPlayer(target, 30); + + if (attacker != null) { + // Player-based damage: XP, drops, kill credit + target.damage(damage, attacker); + } else { + // No player nearby: environmental damage + target.damage(damage); + } + } catch (Throwable e) { StoneDamager.getInstance().logWarningWithInfo("Error while firing damage event in sync.", e); } @@ -97,7 +123,7 @@ public static void fireInSync(ScheduledDamageEvent event) { public static void tick() { try { getTickMap().forEach((damagableSelection, ticks) -> { - if (! damagableSelection.isEnabled()) return; + if (!damagableSelection.isEnabled()) return; if (ticks > 0) { tickTicksLeft(damagableSelection.getIdentifier()); @@ -125,9 +151,9 @@ public static void tick() { public static Runnable getDamageTask(DamagableSelection damagableSelection, Entity entity) { return () -> { - if (! damagableSelection.isEnabled()) return; + if (!damagableSelection.isEnabled()) return; - if (! (entity instanceof LivingEntity)) return; + if (!(entity instanceof LivingEntity)) return; LivingEntity livingEntity = (LivingEntity) entity; if (damagableSelection.check(livingEntity)) { From b18f3c67bec9f7dd6a92d101925a5592eb023b0f Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 07:01:54 -0300 Subject: [PATCH 14/17] Update dependencies.gradle --- dependencies.gradle | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dependencies.gradle b/dependencies.gradle index c740b58..cb44885 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -6,6 +6,10 @@ ext { ANNO = [ // Lombok is handled by the plugin, but keeping standard dependencies here if needed 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', + + // Added StreamlineCore BAPI as requested (using coordinates from provided snippet) + 'com.github.streamline-essentials.StreamlineCore:StreamlineCore-BAPI:main-SNAPSHOT', + 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', 'net.kyori:adventure-api:4.16.0', 'net.kyori:adventure-text-serializer-gson:4.16.0', @@ -19,6 +23,10 @@ ext { // Updated BukkitOfUtils to the new Group ID matching BrewFaster 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', + // Added StreamlineCore BAPI as requested (using coordinates from provided snippet) + // This provides the tv.quaint classes needed for the build + 'com.github.streamline-essentials.StreamlineCore:StreamlineCore-BAPI:main-SNAPSHOT', + 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', 'net.kyori:adventure-api:4.16.0', 'net.kyori:adventure-text-serializer-gson:4.16.0', @@ -31,5 +39,6 @@ ext { FILES = [ ] OTHER_PLUGINS = [ + 'me.clip:placeholderapi:2.11.5', ] } From 23ec57ef261acdbdda54b2e3932126f6db4fe5eb Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 07:02:10 -0300 Subject: [PATCH 15/17] Update dependencies.gradle --- dependencies.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index cb44885..ebf82a5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -39,6 +39,5 @@ ext { FILES = [ ] OTHER_PLUGINS = [ - 'me.clip:placeholderapi:2.11.5', ] } From 0790c4f4b09f53f1999abbad538b63554b54a880 Mon Sep 17 00:00:00 2001 From: Rakise <74441654+Rakise@users.noreply.github.com> Date: Sat, 29 Nov 2025 07:05:13 -0300 Subject: [PATCH 16/17] Update dependencies.gradle --- dependencies.gradle | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index ebf82a5..d8bd16f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,8 +7,9 @@ ext { // Lombok is handled by the plugin, but keeping standard dependencies here if needed 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', - // Added StreamlineCore BAPI as requested (using coordinates from provided snippet) - 'com.github.streamline-essentials.StreamlineCore:StreamlineCore-BAPI:main-SNAPSHOT', + // StreamlineCore Dependencies (API & BAPI) + 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', + 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', 'net.kyori:adventure-api:4.16.0', @@ -23,9 +24,10 @@ ext { // Updated BukkitOfUtils to the new Group ID matching BrewFaster 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', - // Added StreamlineCore BAPI as requested (using coordinates from provided snippet) - // This provides the tv.quaint classes needed for the build - 'com.github.streamline-essentials.StreamlineCore:StreamlineCore-BAPI:main-SNAPSHOT', + // StreamlineCore Dependencies (API & BAPI) + // Needed for tv.quaint classes + 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', + 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', 'net.kyori:adventure-api:4.16.0', @@ -39,5 +41,6 @@ ext { FILES = [ ] OTHER_PLUGINS = [ + 'me.clip:placeholderapi:2.11.5', ] } From ead69a4a8ddf8ec156b573d1cbdba039581df304 Mon Sep 17 00:00:00 2001 From: Drak Date: Sat, 29 Nov 2025 07:38:56 -0500 Subject: [PATCH 17/17] add: player finder for exp farms. bump: version. fix: deps of fork --- build.gradle | 27 ++++++----- dependencies.gradle | 38 ++++++--------- gradle.properties | 2 +- .../host/plas/stonedamager/StoneDamager.java | 6 +-- .../plas/stonedamager/commands/ReloadCMD.java | 2 +- .../{DamagerConfig.java => MainConfig.java} | 19 +++++--- .../stonedamager/data/DamagableSelection.java | 20 ++++---- .../events/ScheduledDamageEvent.java | 46 ++++++++++++++++++- .../events/StoneDamagerEvent.java | 14 ++++++ .../objects/DistanceComparator.java | 28 +++++++++++ .../stonedamager/patch/StoneCutterPatch.java | 21 --------- .../stonedamager/utils/DamageHandler.java | 15 +----- src/main/resources/config.yml | 24 +++++++--- src/main/resources/plugin.yml | 2 +- 14 files changed, 163 insertions(+), 101 deletions(-) rename src/main/java/host/plas/stonedamager/config/{DamagerConfig.java => MainConfig.java} (88%) create mode 100644 src/main/java/host/plas/stonedamager/events/StoneDamagerEvent.java create mode 100644 src/main/java/host/plas/stonedamager/objects/DistanceComparator.java delete mode 100644 src/main/java/host/plas/stonedamager/patch/StoneCutterPatch.java diff --git a/build.gradle b/build.gradle index 698ab0e..aede55b 100644 --- a/build.gradle +++ b/build.gradle @@ -19,8 +19,11 @@ ext { } repositories { + // Maven Defaults mavenCentral() mavenLocal() + + // SpigotMC Repos maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' content { @@ -28,28 +31,28 @@ repositories { includeGroup 'org.spigotmc' } } + + // Sonatype Repos maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } maven { url = 'https://oss.sonatype.org/content/repositories/central' } maven { name = "sonatype" url = "https://oss.sonatype.org/content/groups/public/" } - - // Updated JitPack repo logic to be conditional - // This prevents 401 errors on public repos if the authToken is empty - maven { - url "https://jitpack.io" - if (project.hasProperty('authToken') && project.authToken.toString().trim()) { - credentials { - username = project.authToken - } - } - } - + + // CodeMC Streamline Essentials Repo + maven { url "https://repo.codemc.org/repository/streamline-essentials/" } + + // JitPack + maven { url "https://jitpack.io" } + + // PlaceholderAPI Repo maven { name = "placeholderapi" url = "https://repo.extendedclip.com/content/repositories/placeholderapi/" } + + // Papermc Repositories maven { url 'https://repo.papermc.io/repository/maven-snapshots/' } maven { url 'https://repo.papermc.io/repository/maven-public/' } } diff --git a/dependencies.gradle b/dependencies.gradle index d8bd16f..e0210c2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -5,42 +5,30 @@ ext { ] ANNO = [ // Lombok is handled by the plugin, but keeping standard dependencies here if needed - 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', + 'gg.drak:BukkitOfUtils:1.16.0', // StreamlineCore Dependencies (API & BAPI) - 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', - 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', + 'gg.drak:StreamlineCore-API:2.5.5.6', + 'gg.drak:StreamlineCore-BAPI:2.5.5.6', + // Folia API for Folia compatibility 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', - 'net.kyori:adventure-api:4.16.0', - 'net.kyori:adventure-text-serializer-gson:4.16.0', - 'net.kyori:adventure-text-serializer-legacy:4.16.0', - 'net.kyori:adventure-text-serializer-plain:4.16.0', - 'net.kyori:adventure-text-minimessage:4.16.0', - 'net.kyori:adventure-text-serializer-ansi:4.16.0', - 'net.kyori:ansi:1.0.3', ] COMP_ONLY = [ - // Updated BukkitOfUtils to the new Group ID matching BrewFaster - 'com.github.Streamline-Essentials:BukkitOfUtils:master-SNAPSHOT', - + // Lombok is handled by the plugin, but keeping standard dependencies here if needed + 'gg.drak:BukkitOfUtils:1.16.0', + // StreamlineCore Dependencies (API & BAPI) - // Needed for tv.quaint classes - 'com.github.Streamline-Essentials.StreamlineCore:API:master-SNAPSHOT', - 'com.github.Streamline-Essentials.StreamlineCore:BAPI:master-SNAPSHOT', - + 'gg.drak:StreamlineCore-API:2.5.5.6', + 'gg.drak:StreamlineCore-BAPI:2.5.5.6', + + // Folia API for Folia compatibility 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT', - 'net.kyori:adventure-api:4.16.0', - 'net.kyori:adventure-text-serializer-gson:4.16.0', - 'net.kyori:adventure-text-serializer-legacy:4.16.0', - 'net.kyori:adventure-text-serializer-plain:4.16.0', - 'net.kyori:adventure-text-minimessage:4.16.0', - 'net.kyori:adventure-text-serializer-ansi:4.16.0', - 'net.kyori:ansi:1.0.3', ] FILES = [ ] OTHER_PLUGINS = [ - 'me.clip:placeholderapi:2.11.5', + // PlaceholderAPI for Placeholder support + 'me.clip:placeholderapi:2.11.7', ] } diff --git a/gradle.properties b/gradle.properties index 5dcd030..79820f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ name = StoneDamager group = host.plas -version = 1.9.0 +version = 1.11.0 plugin.main = default \ No newline at end of file diff --git a/src/main/java/host/plas/stonedamager/StoneDamager.java b/src/main/java/host/plas/stonedamager/StoneDamager.java index 5764881..8e29968 100644 --- a/src/main/java/host/plas/stonedamager/StoneDamager.java +++ b/src/main/java/host/plas/stonedamager/StoneDamager.java @@ -5,7 +5,7 @@ import host.plas.stonedamager.utils.DamageHandler; import lombok.Getter; import lombok.Setter; -import host.plas.stonedamager.config.DamagerConfig; +import host.plas.stonedamager.config.MainConfig; import host.plas.stonedamager.runnables.TickTicker; @Getter @Setter @@ -13,7 +13,7 @@ public final class StoneDamager extends BetterPlugin { @Getter @Setter private static StoneDamager instance; @Getter @Setter - private static DamagerConfig damagerConfig; + private static MainConfig mainConfig; @Getter @Setter private static TickTicker tickTicker; @@ -27,7 +27,7 @@ public void onBaseEnabled() { // Plugin startup logic instance = this; - damagerConfig = new DamagerConfig(); + mainConfig = new MainConfig(); tickTicker = new TickTicker(); diff --git a/src/main/java/host/plas/stonedamager/commands/ReloadCMD.java b/src/main/java/host/plas/stonedamager/commands/ReloadCMD.java index ecd1938..3f1bc06 100644 --- a/src/main/java/host/plas/stonedamager/commands/ReloadCMD.java +++ b/src/main/java/host/plas/stonedamager/commands/ReloadCMD.java @@ -17,7 +17,7 @@ public boolean command(CommandContext ctx) { CompletableFuture.runAsync(() -> { ctx.sendMessage("&eReloading &cconfigurations&8..."); - StoneDamager.getDamagerConfig().onReload(); + StoneDamager.getMainConfig().onReload(); ctx.sendMessage("&eReloaded &cconfigurations&8!"); }); diff --git a/src/main/java/host/plas/stonedamager/config/DamagerConfig.java b/src/main/java/host/plas/stonedamager/config/MainConfig.java similarity index 88% rename from src/main/java/host/plas/stonedamager/config/DamagerConfig.java rename to src/main/java/host/plas/stonedamager/config/MainConfig.java index 8779763..4a40ef4 100644 --- a/src/main/java/host/plas/stonedamager/config/DamagerConfig.java +++ b/src/main/java/host/plas/stonedamager/config/MainConfig.java @@ -1,17 +1,17 @@ package host.plas.stonedamager.config; +import gg.drak.thebase.storage.resources.flat.simple.SimpleConfiguration; import host.plas.bou.configs.bits.ConfigurableWhitelist; import host.plas.stonedamager.StoneDamager; import host.plas.stonedamager.data.DamagableSelection; import host.plas.stonedamager.utils.DamageHandler; -import tv.quaint.storage.resources.flat.simple.SimpleConfiguration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentSkipListSet; -public class DamagerConfig extends SimpleConfiguration { - public DamagerConfig() { +public class MainConfig extends SimpleConfiguration { + public MainConfig() { super("config.yml", StoneDamager.getInstance(), true); } @@ -26,7 +26,8 @@ public void onReload() { StoneDamager.getInstance().logInfo("&fLoaded &a" + getSelections().size() + " &fdamager selections."); - isStoneCutterPatchEnabled(); + isTryFindPlayer(); + getFindPlayerRadius(); String configVersion = getConfigVersion(); if (! configVersion.equals("1.0")) { @@ -101,9 +102,15 @@ public String getConfigVersion() { return getResource().getOrDefault("config-version", "null"); } - public boolean isStoneCutterPatchEnabled() { + public boolean isTryFindPlayer() { reloadResource(); - return getOrSetDefault("stonecutter-patch", true); + return getOrSetDefault("settings.try-find-player.enabled", true); + } + + public double getFindPlayerRadius() { + reloadResource(); + + return getOrSetDefault("settings.try-find-player.radius", 30d); } } diff --git a/src/main/java/host/plas/stonedamager/data/DamagableSelection.java b/src/main/java/host/plas/stonedamager/data/DamagableSelection.java index 93e1359..06f2dc5 100644 --- a/src/main/java/host/plas/stonedamager/data/DamagableSelection.java +++ b/src/main/java/host/plas/stonedamager/data/DamagableSelection.java @@ -1,14 +1,13 @@ package host.plas.stonedamager.data; +import gg.drak.thebase.objects.Identifiable; import host.plas.bou.configs.bits.ConfigurableWhitelist; -import host.plas.stonedamager.patch.StoneCutterPatch; import lombok.Getter; import lombok.Setter; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; -import tv.quaint.objects.Identifiable; import java.util.concurrent.atomic.AtomicBoolean; @@ -45,10 +44,6 @@ public boolean checkMaterial(String material) { } public boolean checkMaterial(Block block) { - if (isMaterialsContainsSC()) { - if (StoneCutterPatch.isStoneCutter(block)) return ! materials.isBlacklist(); - } - return checkMaterial(block.getType().name()); } @@ -63,14 +58,14 @@ public boolean checkEntity(String entity) { public boolean checkPermissions(Entity player) { if (! (player instanceof Player)) return true; - if (includePermission.isBlank() || includePermission.isEmpty()) { - if (excludePermission.isBlank() || excludePermission.isEmpty()) { + if (isEmptyPermission(includePermission)) { + if (isEmptyPermission(excludePermission)) { return true; } else { return ! player.hasPermission(excludePermission); } } else { - if (excludePermission.isBlank() || excludePermission.isEmpty()) { + if (isEmptyPermission(excludePermission)) { return player.hasPermission(includePermission); } else { return player.hasPermission(includePermission) && ! player.hasPermission(excludePermission); @@ -90,4 +85,11 @@ public boolean check(Entity entity) { return checkAll(entity, block); } + + public static boolean isEmptyPermission(String permission) { + return permission == null || permission.isBlank() || + permission.equalsIgnoreCase("none") || permission.equalsIgnoreCase("null") || + permission.equalsIgnoreCase("disable") || permission.equalsIgnoreCase("disabled") || + permission.equalsIgnoreCase("off"); + } } diff --git a/src/main/java/host/plas/stonedamager/events/ScheduledDamageEvent.java b/src/main/java/host/plas/stonedamager/events/ScheduledDamageEvent.java index c2ac26e..e9c435d 100644 --- a/src/main/java/host/plas/stonedamager/events/ScheduledDamageEvent.java +++ b/src/main/java/host/plas/stonedamager/events/ScheduledDamageEvent.java @@ -1,14 +1,19 @@ package host.plas.stonedamager.events; +import host.plas.stonedamager.StoneDamager; import host.plas.stonedamager.data.DamagableSelection; +import host.plas.stonedamager.objects.DistanceComparator; import lombok.Getter; import lombok.Setter; +import org.bukkit.Location; import org.bukkit.entity.LivingEntity; -import tv.quaint.events.components.BaseEvent; +import org.bukkit.entity.Player; + +import java.util.Optional; @Setter @Getter -public class ScheduledDamageEvent extends BaseEvent { +public class ScheduledDamageEvent extends StoneDamagerEvent { private LivingEntity entity; private DamagableSelection damagableSelection; @@ -16,4 +21,41 @@ public ScheduledDamageEvent(LivingEntity entity, DamagableSelection damagableSel this.entity = entity; this.damagableSelection = damagableSelection; } + + public Optional getClosestPlayer() { + boolean tryFind = StoneDamager.getMainConfig().isTryFindPlayer(); + if (! tryFind) return Optional.empty(); + + double radius = StoneDamager.getMainConfig().getFindPlayerRadius(); + return entity.getNearbyEntities(radius, radius, radius).stream() + .filter(e -> e instanceof Player) + .map(e -> (Player) e) + .min(new DistanceComparator(getEntityLocation())); + } + + public Location getEntityLocation() { + return entity.getLocation(); + } + + /** + * Damages the entity by the specified amount. + * + * Call this method only in synchronous context. + * @param damage the amount of damage to deal + */ + public void damageEntity(double damage) { + getClosestPlayer().ifPresentOrElse( + p -> getEntity().damage(damage, p), + () -> getEntity().damage(damage) + ); + } + + /** + * Damages the entity by the amount specified in the DamagableSelection. + * + * Call this method only in synchronous context. + */ + public void damageEntity() { + damageEntity(getDamagableSelection().getDamageAmount()); + } } diff --git a/src/main/java/host/plas/stonedamager/events/StoneDamagerEvent.java b/src/main/java/host/plas/stonedamager/events/StoneDamagerEvent.java new file mode 100644 index 0000000..08df968 --- /dev/null +++ b/src/main/java/host/plas/stonedamager/events/StoneDamagerEvent.java @@ -0,0 +1,14 @@ +package host.plas.stonedamager.events; + +import gg.drak.thebase.events.components.BaseEvent; +import host.plas.stonedamager.StoneDamager; + +public class StoneDamagerEvent extends BaseEvent { + public StoneDamagerEvent() { + super(); + } + + public StoneDamager getPlugin() { + return StoneDamager.getInstance(); + } +} diff --git a/src/main/java/host/plas/stonedamager/objects/DistanceComparator.java b/src/main/java/host/plas/stonedamager/objects/DistanceComparator.java new file mode 100644 index 0000000..91f8e7b --- /dev/null +++ b/src/main/java/host/plas/stonedamager/objects/DistanceComparator.java @@ -0,0 +1,28 @@ +package host.plas.stonedamager.objects; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +import java.util.Comparator; + +@Getter @Setter +public class DistanceComparator implements Comparator { + private final Location referenceLocation; + + public DistanceComparator(Location referenceLocation) { + this.referenceLocation = referenceLocation; + } + + @Override + public int compare(Entity o1, Entity o2) { + Location l1 = o1.getLocation(); + Location l2 = o2.getLocation(); + + double d1 = l1.distanceSquared(referenceLocation); + double d2 = l2.distanceSquared(referenceLocation); + + return Double.compare(d1, d2); + } +} diff --git a/src/main/java/host/plas/stonedamager/patch/StoneCutterPatch.java b/src/main/java/host/plas/stonedamager/patch/StoneCutterPatch.java deleted file mode 100644 index 45e0808..0000000 --- a/src/main/java/host/plas/stonedamager/patch/StoneCutterPatch.java +++ /dev/null @@ -1,21 +0,0 @@ -package host.plas.stonedamager.patch; - -import host.plas.stonedamager.StoneDamager; -import org.bukkit.Material; -import org.bukkit.block.Block; - -public class StoneCutterPatch { - public static boolean isStoneCutter(Block block) { - if (block.getType() == Material.STONECUTTER) return true; - - if (! StoneDamager.getDamagerConfig().isStoneCutterPatchEnabled()) return false; - - if (block.getType() != Material.AIR) return false; - - block.setType(Material.STONECUTTER); - boolean isStoneCutter = block.getType() == Material.AIR; - block.setType(Material.AIR); - - return isStoneCutter; - } -} diff --git a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java index f1d03e5..e6c522c 100644 --- a/src/main/java/host/plas/stonedamager/utils/DamageHandler.java +++ b/src/main/java/host/plas/stonedamager/utils/DamageHandler.java @@ -101,20 +101,7 @@ private static Player getNearestPlayer(LivingEntity entity, double range) { public static void fireInSync(ScheduledDamageEvent event) { try { - LivingEntity target = event.getEntity(); - double damage = event.getDamagableSelection().getDamageAmount(); - - // Find closest player within 30 blocks - Player attacker = getNearestPlayer(target, 30); - - if (attacker != null) { - // Player-based damage: XP, drops, kill credit - target.damage(damage, attacker); - } else { - // No player nearby: environmental damage - target.damage(damage); - } - + event.damageEntity(); } catch (Throwable e) { StoneDamager.getInstance().logWarningWithInfo("Error while firing damage event in sync.", e); } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b2245f4..74a7ee4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -33,7 +33,8 @@ damagers: # Find a full list at: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/EntityType.html list: [] # Empty list. # If the list above is a blacklist. - # If this is false, then it is a whitelist. + # true = do not damage these entities. + # false = only damage these entities. is-blacklist: true # Worlds config. worlds: @@ -41,7 +42,8 @@ damagers: list: - "lobby" # If the list above is a blacklist. - # If this is false, then it is a whitelist. + # true = do not damage in these worlds. + # false = only damage in these worlds. is-blacklist: true # Materials that count as a damager for this selection. materials: @@ -49,7 +51,8 @@ damagers: list: - "STONECUTTER" # If the list above is a blacklist. - # If this is false, then it is a whitelist. + # true = do not count these materials. + # false = only count these materials. is-blacklist: false glass: @@ -75,9 +78,18 @@ damagers: - "GLASS" is-blacklist: false -# For some reason, stonecutters are marked as air... -# This is a patch to fix that. -stonecutter-patch: true +# Settings for the damager system. +settings: + # Try to find a player to count as the source of damage. + # This is to allow for experience and loot drops. + try-find-player: + # If this feature is enabled. + # true = Yes. Use this feature. + # false = No. Do not use this feature. + enabled: true + # Maximum distance to search for a player (in blocks). + # Can be a decimal value. + radius: 30.0 # DO NOT TOUCH THIS. config-version: "1.0" \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c5af21a..6149372 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -8,7 +8,7 @@ description: A plugin to simply make it so that stone cutters damage entities. website: https://site.plasmere.net folia-supported: true -api-version: 1.21 +api-version: 1.14 commands: reloadstonedamager: