Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ object Versions {

const val PLACEHOLDER_API = "2.12.3"
const val LANDS_API = "7.25.4"
const val GRIEF_PREVENTION = "16.18.7"
const val WORLDEDIT = "3ISh7ADm" //cannot use numeric version bc of duplicated version on modrinth
const val PACKETEVENTS = "2.11.1"
const val WORLDGUARD = "7.0.15-beta-01"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ tasks {
downloadPlugins.modrinth("PacketEvents", "2.12.2+spigot")
downloadPlugins.modrinth("WorldGuard", "7.0.17")
downloadPlugins.modrinth("LuckPerms", "v5.5.53-bukkit")
downloadPlugins.modrinth("GriefPrevention", Versions.GRIEF_PREVENTION)
}
}
10 changes: 10 additions & 0 deletions eternalcombat-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ dependencies {
// Lands
compileOnly("com.github.angeschossen:LandsAPI:${Versions.LANDS_API}")

// GriefPrevention
compileOnly("com.github.GriefPrevention:GriefPrevention:${Versions.GRIEF_PREVENTION}") {
isTransitive = false
}

// Multification
implementation("com.eternalcode:multification-paper:${Versions.MULTIFICATION}")
implementation("com.eternalcode:multification-okaeri:${Versions.MULTIFICATION}")
Expand Down Expand Up @@ -96,6 +101,11 @@ paper {
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}

register("GriefPrevention") {
required = false
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}

register("PlaceholderAPI") {
required = false
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.eternalcode.combat.region.CompositeRegionProvider;
import com.eternalcode.combat.region.bukkit.DefaultRegionProvider;
import com.eternalcode.combat.region.RegionProvider;
import com.eternalcode.combat.region.griefprevention.GriefPreventionRegionProvider;
import com.eternalcode.combat.region.worldguard.WorldGuardRegionProvider;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -55,6 +56,12 @@ public void init(Server server) {
() -> this.logger.warning("WorldGuard not found; skipping WorldGuardRegionProvider.")
);

this.initialize(
"GriefPrevention",
() -> providers.add(new GriefPreventionRegionProvider(this.config)),
() -> this.logger.warning("GriefPrevention not found; skipping GriefPreventionRegionProvider.")
);

if (providers.isEmpty()) {
providers.add(new DefaultRegionProvider(this.config.regions.restrictedRegionRadius));
this.logger.warning("No region plugin found; using DefaultRegionProvider.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public class RegionSettings extends OkaeriConfig {
public List<String> blockedRegions = Collections.singletonList("your_region");

@Comment({
"# Prevent players from entering regions where PVP is disabled by WorldGuard.",
"# Prevent players from entering regions where PVP is disabled by the region plugin",
"# (WorldGuard PVP flag, GriefPrevention no-combat-in-claims settings).",
"# Set to 'true' to enforce this restriction, or 'false' to allow PVP in all regions."
})
public boolean preventPvpInRegions = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.eternalcode.combat.region.griefprevention;

import com.eternalcode.combat.region.Point;
import com.eternalcode.combat.region.Region;
import me.ryanhamshire.GriefPrevention.Claim;
import org.bukkit.Location;
import org.bukkit.World;

record GriefPreventionRegion(World world, Claim claim) implements Region {

@Override
public Point getCenter() {
Location min = this.claim.getLesserBoundaryCorner();
Location max = this.claim.getGreaterBoundaryCorner();

double x = (min.getX() + max.getX()) / 2.0;
double z = (min.getZ() + max.getZ()) / 2.0;

return new Point(this.world, x, z);
}

@Override
public Location getMin() {
Location min = this.claim.getLesserBoundaryCorner();
return new Location(this.world, min.getBlockX(), this.world.getMinHeight(), min.getBlockZ());
}

@Override
public Location getMax() {
Location max = this.claim.getGreaterBoundaryCorner();
return new Location(this.world, max.getBlockX(), this.world.getMaxHeight() - 1, max.getBlockZ());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the claim's greater boundary in containment

GriefPrevention's greater boundary corner is inclusive, but Region.contains compares every coordinate with < getMax(). Consequently, a combat-tagged player standing on a claim's maximum X or Z row is reported by GriefPrevention as inside the claim while GriefPreventionRegion.contains reports them outside; moves within that row are then handled as attempts to enter and cancelled rather than receiving the normal inside-region knockback. Represent the upper bounds as exclusive or override containment so the greater boundary blocks remain included.

Useful? React with 👍 / 👎.

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.eternalcode.combat.region.griefprevention;

import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.region.Region;
import com.eternalcode.combat.region.RegionProvider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Optional;
import java.util.TreeSet;
import me.ryanhamshire.GriefPrevention.Claim;
import me.ryanhamshire.GriefPrevention.GriefPrevention;
import org.bukkit.Location;
import org.bukkit.World;

public class GriefPreventionRegionProvider implements RegionProvider {

private final TreeSet<String> claims = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
private final PluginConfig pluginConfig;

public GriefPreventionRegionProvider(PluginConfig pluginConfig) {
this.claims.addAll(pluginConfig.regions.blockedRegions);
this.pluginConfig = pluginConfig;
}

@Override
public Optional<Region> getRegion(Location location) {
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(location, true, null);

if (claim == null || !this.isCombatClaim(claim)) {
return Optional.empty();
}

return Optional.of(new GriefPreventionRegion(location.getWorld(), claim));
}

@Override
public Collection<Region> getRegions(World world) {
List<Region> regions = new ArrayList<>();

for (Claim claim : this.snapshotClaims()) {
if (!world.equals(claim.getLesserBoundaryCorner().getWorld())) {
continue;
}

if (this.isCombatClaim(claim)) {
regions.add(new GriefPreventionRegion(world, claim));
}
}

return regions;
}

private boolean isCombatClaim(Claim claim) {
if (this.claims.contains(String.valueOf(claim.getID()))) {
return true;
}

if (!this.pluginConfig.regions.preventPvpInRegions) {
return false;
}

World world = claim.getLesserBoundaryCorner().getWorld();
GriefPrevention griefPrevention = GriefPrevention.instance;

if (world == null || !griefPrevention.pvpRulesApply(world)) {
return false;
}

if (!claim.isAdminClaim()) {
return griefPrevention.config_pvp_noCombatInPlayerLandClaims;
}

if (claim.parent == null) {
return griefPrevention.config_pvp_noCombatInAdminLandClaims;
}

return griefPrevention.config_pvp_noCombatInAdminSubdivisions;
}

// GriefPrevention returns a live view of its claim list, and the border index reads regions asynchronously.
// A failed snapshot is retried by the next border index refresh, so an empty result is safe here.
private List<Claim> snapshotClaims() {
try {
return List.copyOf(GriefPrevention.instance.dataStore.getClaims());
}
catch (ConcurrentModificationException exception) {
return List.of();
}
}

}
Loading