Skip to content

Commit

Permalink
GH-184 Refactor Knockback Mechanic and Add Support for Deny Entry flag (
Browse files Browse the repository at this point in the history
#184)

* Initial commit

* fix spaces

* fix spaces

* Add Kamicjusz's changes. Normalize knockback vector, fix message.

* Set cooldown for messages

* Resolve half of suggestions

* Remove delay and add PVP regions blockade.

* Improve performance of WorldGuardRegionProvider.

* Use lambda

* Resolve @vLuckyyy review

---------

Co-authored-by: Rollczi <[email protected]>
  • Loading branch information
CitralFlo and Rollczi authored Sep 22, 2024
1 parent fe25699 commit 20a4e4a
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ public BridgeService(PluginConfig pluginConfig, PluginManager pluginManager, Log

public void init(FightManager fightManager, Server server) {
this.initialize("WorldGuard",
() -> this.regionProvider = new WorldGuardRegionProvider(this.pluginConfig.settings.blockedRegions),
() -> this.regionProvider = new WorldGuardRegionProvider(this.pluginConfig.settings.blockedRegions, this.pluginConfig),
() -> {
this.regionProvider = new DefaultRegionProvider(this.pluginConfig.settings.blockedRegionRadius);
this.regionProvider = new DefaultRegionProvider(this.pluginConfig.settings.blockedRegionRadius);

this.logger.warning("WorldGuard is not installed, set to default region provider.");
});
this.logger.warning("WorldGuard is not installed, set to default region provider.");
});

this.initialize("PlaceholderAPI",
() -> new FightTagPlaceholder(fightManager, server, plugin).register(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,15 @@ public static class Settings extends OkaeriConfig {
@Comment("# List of regions to block")
public List<String> blockedRegions = Collections.singletonList("your_region");

@Comment("# Set the knock multiplier for the blocked region")
public double blockedRegionKnockMultiplier = 1.2;
@Comment({
"# Set the knock multiplier for the blocked region",
"# Values can be decimal. Do NOT use negative values.",
"# Setting it around 1 knocks the player around 2-4 blocks away."
})
public double blockedRegionKnockMultiplier = 1;

@Comment({"# Should the player be prevented from entering regions with WorldGuard flag PVP set to DENY "})
public boolean shouldPreventPvpRegions = true;

@Comment("# Set the radius of the blocked region if you aren't using WorldGuard basen on default spawn region!")
public int blockedRegionRadius = 10;
Expand Down Expand Up @@ -196,7 +203,7 @@ public static class Messages extends OkaeriConfig {
public String blockPlacingBlockedDuringCombat = "&cYou cannot place {MODE} {Y} coordinate during combat!";

@Comment("# Message sent when player tries to enter a region")
public String cantEnterOnRegion = "&cYou can't enter on this region during combat!";
public String cantEnterOnRegion = "&cYou can't enter this region during combat!";

public static class AdminMessages extends OkaeriConfig {
@Comment("# Message sent when the configuration is reloaded")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ public void send(CommandSender sender, Notification notification, Formatter form

case BOSS_BAR -> {
BossBarNotification bossBarNotification = (BossBarNotification) notification;

BossBar bossBar = bossBarNotification.create(message);

audience.showBossBar(bossBar);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.eternalcode.combat.region;

import java.util.Optional;
import org.bukkit.Location;
import org.bukkit.util.BlockVector;

public class DefaultRegionProvider implements RegionProvider {

Expand All @@ -11,31 +13,24 @@ public DefaultRegionProvider(int radius) {
}

@Override
public boolean isInRegion(Location location) {
public Optional<Region> getRegion(Location location) {
Location spawnLocation = location.getWorld().getSpawnLocation();
double x = spawnLocation.getX();
double z = spawnLocation.getZ();

Point min = new Point(x - this.radius, z - this.radius);
Point max = new Point(x + this.radius, z + this.radius);
BlockVector min = new BlockVector(x - this.radius, 0, z - this.radius);
BlockVector max = new BlockVector(x + this.radius, 0, z + this.radius);

return this.contains(min, max, location.getX(), location.getZ());
}
if (this.contains(min, max, location.getX(), location.getZ())) {
return Optional.of(() -> new Location(location.getWorld(), x, location.getY(), z));
}

@Override
public Location getRegionCenter(Location location) {
Location spawnLocation = location.getWorld().getSpawnLocation();
double x = spawnLocation.getX();
double z = spawnLocation.getZ();

return new Location(location.getWorld(), x, location.getY(), z);
return Optional.empty();
}

public boolean contains(Point min, Point max, double x, double z) {
return x >= min.x() && x < max.x()
&& z >= min.z() && z < max.z();
private boolean contains(BlockVector min, BlockVector max, double x, double z) {
return x >= min.getX() && x < max.getX()
&& z >= min.getZ() && z < max.getZ();
}

public record Point(double x, double z) {}

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

import org.bukkit.Location;

public interface Region {

Location getCenter();

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.notification.NotificationAnnouncer;
import java.util.Optional;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
Expand Down Expand Up @@ -44,17 +45,22 @@ void onPlayerMove(PlayerMoveEvent event) {
int zFrom = locationFrom.getBlockZ();

if (xTo != xFrom || yTo != yFrom || zTo != zFrom) {
if (!this.regionProvider.isInRegion(locationTo)) {
Optional<Region> regionOptional = regionProvider.getRegion(locationTo);
if (regionOptional.isEmpty()) {
return;
}

Location spawnLocation = this.regionProvider.getRegionCenter(locationTo);
Location playerLocation = player.getLocation().subtract(spawnLocation);
double distance = playerLocation.distance(spawnLocation);
Vector knockback = new Vector(0, 3, 0).multiply(this.pluginConfig.settings.blockedRegionKnockMultiplier / distance);
Vector vector = playerLocation.toVector().add(knockback);
Region region = regionOptional.get();
Location centerOfRegion = region.getCenter();
Location subtract = player.getLocation().subtract(centerOfRegion);

player.setVelocity(vector);
Vector knockbackVector = new Vector(subtract.getX(), 0, subtract.getZ()).normalize();
Vector configuredVector = new Vector(
this.pluginConfig.settings.blockedRegionKnockMultiplier,
0.5,
this.pluginConfig.settings.blockedRegionKnockMultiplier);

player.setVelocity(knockbackVector.multiply(configuredVector));

this.announcer.sendMessage(player, this.pluginConfig.messages.cantEnterOnRegion);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.eternalcode.combat.region;

import java.util.Optional;
import org.bukkit.Location;

public interface RegionProvider {

boolean isInRegion(Location location);
Optional<Region> getRegion(Location location);

Location getRegionCenter(Location location);
default boolean isInRegion(Location location) {
return getRegion(location).isPresent();
}

}
Original file line number Diff line number Diff line change
@@ -1,69 +1,75 @@
package com.eternalcode.combat.region;

import com.eternalcode.combat.config.implementation.PluginConfig;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import java.util.Optional;
import java.util.TreeSet;
import org.bukkit.Location;

import java.util.List;

public class WorldGuardRegionProvider implements RegionProvider {

private final List<String> regions;
private final RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
private final TreeSet<String> regions = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
private final PluginConfig pluginConfig;

public WorldGuardRegionProvider(List<String> regions) {
this.regions = regions;
public WorldGuardRegionProvider(List<String> regions, PluginConfig pluginConfig) {
this.regions.addAll(regions);
this.pluginConfig = pluginConfig;
}

@Override
public boolean isInRegion(Location location) {
return this.regions.stream().anyMatch(region -> this.isInCombatRegion(location, region));
}

@Override
public Location getRegionCenter(Location location) {
RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery regionQuery = regionContainer.createQuery();
public Optional<Region> getRegion(Location location) {
RegionQuery regionQuery = this.regionContainer.createQuery();
ApplicableRegionSet applicableRegions = regionQuery.getApplicableRegions(BukkitAdapter.adapt(location));

double minX = 0;
double maxX = 0;
double minZ = 0;
double maxZ = 0;

for (ProtectedRegion region : applicableRegions.getRegions()) {
BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();

if (min.getX() < minX) {
minX = min.getX();
}
if (max.getX() > maxX) {
maxX = max.getX();
}
if (min.getZ() < minZ) {
minZ = min.getZ();
}
if (max.getZ() > maxZ) {
maxZ = max.getZ();
if (!isCombatRegion(region)) {
continue;
}

return Optional.of(new RegionImpl(location, region));
}

return Optional.empty();
}

private boolean isCombatRegion(ProtectedRegion region) {
if (this.regions.contains(region.getId())) {
return true;
}

double x = (maxX - minX) / 2 + minX;
double z = (maxZ - minZ) / 2 + minZ;
if (this.pluginConfig.settings.shouldPreventPvpRegions) {
StateFlag.State flag = region.getFlag(Flags.PVP);

if (flag != null) {
return flag.equals(StateFlag.State.DENY);
}
}

return new Location(location.getWorld(), x, location.getY(), z);
return false;
}

private boolean isInCombatRegion(Location location, String regionName) {
RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery regionQuery = regionContainer.createQuery();
ApplicableRegionSet applicableRegions = regionQuery.getApplicableRegions(BukkitAdapter.adapt(location));
private record RegionImpl(Location contextLocation, ProtectedRegion region) implements Region {
@Override
public Location getCenter() {
BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();

return applicableRegions.getRegions().stream().anyMatch(region -> region.getId().equalsIgnoreCase(regionName));
double x = (double) (min.getX() + max.getX()) / 2;
double z = (double) (min.getZ() + max.getZ()) / 2;

return new Location(contextLocation.getWorld(), x, contextLocation.getY(), z);
}
}

}

0 comments on commit 20a4e4a

Please sign in to comment.