Skip to content

Commit

Permalink
turn entity targetting and pathfinding into physics modules
Browse files Browse the repository at this point in the history
  • Loading branch information
xGinko committed Aug 5, 2024
1 parent 98b3d6c commit e68f123
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 131 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package me.xginko.aef.modules.lagpreventions;
package me.xginko.aef.modules.lagpreventions.physics;

import com.cryptomorin.xseries.XEntityType;
import io.github.thatsmusic99.configurationmaster.api.ConfigSection;
import me.xginko.aef.modules.AEFModule;
import me.xginko.aef.utils.LocationUtil;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.util.NumberConversions;
Expand All @@ -17,39 +16,51 @@
import java.util.Map;
import java.util.TreeMap;

public class TargetDistanceLimit extends AEFModule implements Listener {
public class EntityTargeting extends PhysicsModule implements Listener {

private final Map<EntityType, Double> limitedTypes = new EnumMap<>(EntityType.class);
private final double globalMaxDistanceSquared;
private final boolean logIsEnabled, globalDistanceEnabled, perTypeDistanceEnabled;
private final int limit;
private final boolean globalDistanceEnabled, perTypeDistanceEnabled;

public TargetDistanceLimit() {
super("lag-preventions.target-distance-limits");
this.logIsEnabled = config.getBoolean(configPath + ".log", false);
this.globalDistanceEnabled = config.getBoolean(configPath + ".global-limit.enable", false);
public EntityTargeting() {
super("entity-targeting",
true,
1500.0,
18000,
20000,
14.0,
120.0
);
this.config.addComment(configPath+".enable", """
Limits entities targeting other entities within a configurable radius\s
and timeframe to help reduce lag by cancelling burst activity hotspots.""");
this.limit = config.getInt(configPath + ".entity-target-event-limit", 512, """
Maximum number of times an entity can target another entity within the\s
configured timeframe before the area will be put on cooldown.""");

this.globalDistanceEnabled = config.getBoolean(configPath + ".distance-limit.global-limit.enable", false);
this.globalMaxDistanceSquared = NumberConversions.square(
config.getDouble(configPath + ".global-limit.max-target-distance", 20.0, """
config.getDouble(configPath + ".distance-limit.global-limit.max-target-distance", 20.0, """
The max distance no target should exceed.\s
You want this to be higher than your highest max distance\s
for a specific mob."""));
this.perTypeDistanceEnabled = config.getBoolean(configPath + ".custom-limits.enable", true);

this.perTypeDistanceEnabled = config.getBoolean(configPath + ".distance-limit.custom-limits.enable", true);
Map<XEntityType, Double> defaults = new EnumMap<>(XEntityType.class);
defaults.put(XEntityType.ZOMBIE, 6.0);
defaults.put(XEntityType.SKELETON, 6.0);
defaults.put(XEntityType.WITHER_SKELETON, 8.0);
defaults.put(XEntityType.ZOMBIE_VILLAGER, 10.0);
defaults.put(XEntityType.ZOMBIFIED_PIGLIN, 8.0);
defaults.put(XEntityType.WITHER, 8.0);

Map<String, Object> versionDefaults = new TreeMap<>();
for (Map.Entry<XEntityType, Double> entry : defaults.entrySet()) {
if (entry.getKey().isSupported()) {
versionDefaults.put(entry.getKey().get().name(), entry.getValue());
}
}

ConfigSection section = config.getConfigSection(configPath + ".custom-limits.entities", versionDefaults);
ConfigSection section = config.getConfigSection(configPath + ".distance-limit.custom-limits.entities", versionDefaults);
for (String configuredEntity : section.getKeys(false)) {
try {
Double maxDistanceSquared = NumberConversions.square(Double.parseDouble(section.getString(configuredEntity)));
Expand All @@ -63,34 +74,43 @@ public TargetDistanceLimit() {
}
}

@Override
public void enable() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onEntityTargetAcquire(EntityTargetEvent event) {
Entity targetEntity = event.getTarget();
if (targetEntity == null) return; // If entity un-targets an entity, it's good for us.

@Override
public boolean shouldEnable() {
return config.getBoolean(configPath + ".enable", false);
}
if (isCriticallyLagging()) {
event.setCancelled(true);
onLagExceeded(event);
return;
}

@Override
public void disable() {
HandlerList.unregisterAll(this);
}
Location location = event.getEntity().getLocation();
RegionData regionData = getRegionData(location);

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onTargetAcquire(EntityTargetEvent event) {
final Entity targetEntity = event.getTarget();
if (targetEntity == null) return;
if (regionData.resumeTime.get() > System.currentTimeMillis()) {
event.setCancelled(true);
return;
}

if (regionData.activityCount.incrementAndGet() > limit) {
event.setCancelled(true);
onLimitExceeded(location, regionData, limit);
return;
}

if (!globalDistanceEnabled && !perTypeDistanceEnabled) {
return;
}

final double targetDistanceSquared = event.getEntity().getLocation().distanceSquared(targetEntity.getLocation());
double targetDistanceSquared = event.getEntity().getLocation().distanceSquared(targetEntity.getLocation());

if (globalDistanceEnabled) {
if (targetDistanceSquared > globalMaxDistanceSquared) {
event.setCancelled(true);
event.setTarget(null);
if (logIsEnabled) info("Cancelled target acquire for entity " + event.getEntityType().name() + " at " +
LocationUtil.toString(event.getEntity().getLocation()) +
LocationUtil.toString(location) +
" because target is further than the global limit. Distance: " + Math.sqrt(targetDistanceSquared));
return;
}
Expand All @@ -101,7 +121,7 @@ private void onTargetAcquire(EntityTargetEvent event) {
event.setCancelled(true);
event.setTarget(null);
if (logIsEnabled) info("Cancelled target acquire for entity " + event.getEntityType().name() + " at " +
LocationUtil.toString(event.getEntity().getLocation()) +
LocationUtil.toString(location) +
" because target further than its configured limit. Distance: " + Math.sqrt(targetDistanceSquared));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,68 @@
package me.xginko.aef.modules.lagpreventions;
package me.xginko.aef.modules.lagpreventions.physics;

import com.cryptomorin.xseries.XEntityType;
import com.destroystokyo.paper.event.entity.EntityPathfindEvent;
import io.github.thatsmusic99.configurationmaster.api.ConfigSection;
import me.xginko.aef.modules.AEFModule;
import me.xginko.aef.utils.LocationUtil;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.util.NumberConversions;

import java.util.EnumMap;
import java.util.Map;
import java.util.TreeMap;

public class PathfindingLimits extends AEFModule implements Listener {
public class Pathfinding extends PhysicsModule implements Listener {

private final Map<EntityType, Double> limitedTypes = new EnumMap<>(EntityType.class);
private final boolean logIsEnabled, globalDistanceEnabled, perTypeDistanceEnabled;
private final double globalMaxDistanceSquared;
private final int limit;
private final boolean globalDistanceEnabled, perTypeDistanceEnabled;

public PathfindingLimits() {
super("lag-preventions.pathfinding-limits");
this.logIsEnabled = config.getBoolean(configPath + ".log", false,
"Only meant for debug.");
this.globalDistanceEnabled = config.getBoolean(configPath + ".global-limit.enable", false);
public Pathfinding() {
super(
"entity-pathfinding",
false,
1500.0,
6000,
10000,
14.0,
120.0
);
this.config.addComment(configPath+".enable", """
Limits entities deciding to pathfind to a specific location\s
within a configurable radius and timeframe to help reduce lag\s
by cancelling burst activity hotspots.""");
this.limit = config.getInt(configPath + ".entity-pathfind-event-limit", 512, """
Maximum number of times an entity can decide to start moving\s
towards a location within the configured timeframe before the\s
area will be put on cooldown.""");

this.globalDistanceEnabled = config.getBoolean(configPath + ".distance-limit.global-limit.enable", false);
this.globalMaxDistanceSquared = NumberConversions.square(
config.getDouble(configPath + ".global-limit.max-target-distance", 20.0, """
config.getDouble(configPath + ".distance-limit.global-limit.max-target-distance", 20.0, """
The max distance no mob pathfinding should exceed.\s
You always want this to be higher than your highest max distance\s
for a specific mob."""));
this.perTypeDistanceEnabled = config.getBoolean(configPath + ".custom-limits.enable", true);

this.perTypeDistanceEnabled = config.getBoolean(configPath + ".distance-limit.custom-limits.enable", true);
Map<XEntityType, Double> defaults = new EnumMap<>(XEntityType.class);
defaults.put(XEntityType.ZOMBIE, 6.0);
defaults.put(XEntityType.SKELETON, 6.0);
defaults.put(XEntityType.WITHER_SKELETON, 8.0);
defaults.put(XEntityType.ZOMBIE_VILLAGER, 10.0);
defaults.put(XEntityType.ZOMBIFIED_PIGLIN, 8.0);
defaults.put(XEntityType.WITHER, 8.0);

Map<String, Object> versionDefaults = new TreeMap<>();
for (Map.Entry<XEntityType, Double> entry : defaults.entrySet()) {
if (entry.getKey().isSupported()) {
versionDefaults.put(entry.getKey().get().name(), entry.getValue());
}
}

ConfigSection section = config.getConfigSection(configPath + ".custom-limits.entities", versionDefaults);
ConfigSection section = config.getConfigSection(configPath + ".distance-limit.custom-limits.entities", versionDefaults);
for (String configuredEntity : section.getKeys(false)) {
try {
Double maxDistanceSquared = NumberConversions.square(Double.parseDouble(section.getString(configuredEntity)));
Expand All @@ -63,24 +76,33 @@ public PathfindingLimits() {
}
}

@Override
public void enable() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onEntityPathfind(EntityPathfindEvent event) {
if (isCriticallyLagging()) {
event.setCancelled(true);
onLagExceeded(event);
return;
}

@Override
public boolean shouldEnable() {
return config.getBoolean(configPath + ".enable", false);
}
Location location = event.getEntity().getLocation();
RegionData regionData = getRegionData(location);

@Override
public void disable() {
HandlerList.unregisterAll(this);
}
if (regionData.resumeTime.get() > System.currentTimeMillis()) {
event.setCancelled(true);
return;
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onPathfind(EntityPathfindEvent event) {
final double targetDistanceSquared = event.getEntity().getLocation().distanceSquared(event.getLoc());
if (regionData.activityCount.incrementAndGet() > limit) {
event.setCancelled(true);
onLimitExceeded(location, regionData, limit);
return;
}

if (!globalDistanceEnabled && !perTypeDistanceEnabled) {
return;
}

double targetDistanceSquared = event.getEntity().getLocation().distanceSquared(event.getLoc());

if (globalDistanceEnabled) {
if (targetDistanceSquared > globalMaxDistanceSquared) {
Expand Down
Loading

0 comments on commit e68f123

Please sign in to comment.