Skip to content

Commit

Permalink
Breaking changes to ConfigManager, changes to make dependencies more …
Browse files Browse the repository at this point in the history
…reload-safe, optimizations

- ConfigMap#postInit has been removed, as it was causing issues. Create a method called postInit with no arguments.
- ProtectionPolicies will now unregister themselves if the plugin which created them is disabled
- Region#getChunks and Region#getEntities have been optimized because World#getChunkAt is evidently an expensive operation. Chunks are now cached by Regions after one call, and Region#getEntities no longer loads chunks to check for entities unless specified to.
  • Loading branch information
boxbeam committed Aug 6, 2020
1 parent e787029 commit 4c14e6a
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 35 deletions.
3 changes: 2 additions & 1 deletion src/redempt/redlib/commandmanager/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,10 @@ public List<String> tabComplete(CommandSender sender, String alias, String[] arg
if (plugin == null) {
plugin = JavaPlugin.getProvidingPlugin(Class.forName(new Exception().getStackTrace()[1].getClassName()));
}
new EventListener<>(RedLib.getInstance(), PluginDisableEvent.class, e -> {
new EventListener<>(RedLib.getInstance(), PluginDisableEvent.class, (l, e) -> {
if (e.getPlugin().equals(plugin)) {
try {
l.unregister();
Arrays.stream(names).forEach(knownCommands::remove);
} catch (Exception ex) {
ex.printStackTrace();
Expand Down
10 changes: 0 additions & 10 deletions src/redempt/redlib/configmanager/ConfigManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,6 @@
*/
public class ConfigManager {

protected static List<Runnable> postInit = new CopyOnWriteArrayList<>();

/**
* Adds a post-init to be run after your object is initialized for a ConfigMap
* @param r The Runnable to run later
*/
public static void postInit(Runnable r) {
postInit.add(r);
}

/**
* Instantiates a List of Strings inline
* @param strings The Strings to include in the List
Expand Down
14 changes: 12 additions & 2 deletions src/redempt/redlib/configmanager/ConfigMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
Expand All @@ -17,9 +18,17 @@ class ConfigMap<T> extends HashMap<String, T> {
protected ConfigurationSection section;
private ConfigManager manager;
private List<ConfigField> fields = new ArrayList<>();
private Method postInit = null;

public ConfigMap(Class<T> clazz) {
this.clazz = clazz;
for (Method method : clazz.getDeclaredMethods()) {
if (method.getName().equals("postInit") && method.getParameterCount() == 0) {
method.setAccessible(true);
postInit = method;
break;
}
}
}

public void init(ConfigManager manager) {
Expand Down Expand Up @@ -47,13 +56,14 @@ public void load() {
T instance = constructor.newInstance();
fields.forEach(f -> f.load(instance, section));
put(key, instance);
if (postInit != null) {
postInit.invoke(instance);
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
throw new ConfigMapException("Class must have a default constructor with no arguments!");
}
}
ConfigManager.postInit.forEach(Runnable::run);
ConfigManager.postInit.clear();
}

public void save() {
Expand Down
24 changes: 12 additions & 12 deletions src/redempt/redlib/misc/LocationUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public class LocationUtils {
* @return Whether the block type is a hazard
*/
public static boolean isHazard(Material type) {
type = new ItemStack(type).getType();
if (type.toString().contains("LAVA") || type.toString().contains("WATER")) {
return true;
}
Expand All @@ -43,7 +42,7 @@ public static boolean isHazard(Material type) {
*/
public static boolean isSafe(Location loc) {
Block under = loc.clone().subtract(0, 1, 0).getBlock();
if (!isHazard(under.getType()) && isFullBlock(under)) {
if (under.getType().isSolid()) {
Block middle = loc.getBlock();
Block above = loc.clone().add(0, 1, 0).getBlock();
if (!isHazard(middle.getType()) && !isHazard(above.getType())) {
Expand All @@ -55,14 +54,6 @@ public static boolean isSafe(Location loc) {
return false;
}

private static boolean isFullBlock(Block block) {
if (RedLib.midVersion >= 13) {
return block.getType().isSolid() && block.getBoundingBox().getVolume() == 1;
} else {
return block.getType().isOccluding();
}
}

/**
* Gets the nearest safe location to the given location within the given distance passing the given predicate check
* @param loc The location to find the nearest safe location to
Expand All @@ -77,18 +68,27 @@ public static Location getNearestSafeLocation(Location loc, int maxDistance, Pre
loc.setDirection(direction);
return loc;
}
Location nearest = null;
double dist = 0;
for (int y = 0; Math.abs(y) <= maxDistance; y = y == 0 ? 1 : -y - Math.min(Integer.signum(y), 0)) {
for (int x = 0; Math.abs(x) <= maxDistance; x = x == 0 ? 1 : -x - Math.min(Integer.signum(x), 0)) {
for (int z = 0; Math.abs(z) <= maxDistance; z = z == 0 ? 1 : -z - Math.min(Integer.signum(z), 0)) {
Location check = loc.clone().add(x, y, z);
if (isSafe(check) && filter.test(check)) {
check.setDirection(direction);
return check;
double distance = check.distanceSquared(loc);
if (nearest == null || distance < dist) {
nearest = check;
dist = distance;
if (dist <= 1) {
return nearest;
}
}
}
}
}
}
return null;
return nearest;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/redempt/redlib/misc/Path.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ public class Path {
*/
public static List<Location> getPath(Location start, Location end, double step) {
List<Location> locs = new ArrayList<>();
locs.add(start);
Vector v = end.clone().subtract(start).toVector();
v = v.normalize().multiply(step);
Location current = start.clone();
while (current.distance(end) > step) {
locs.add(current.clone());
current = current.add(v);
}
locs.add(end);
return locs;
}

Expand Down
6 changes: 6 additions & 0 deletions src/redempt/redlib/protection/ProtectedRegion.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package redempt.redlib.protection;

import org.bukkit.plugin.Plugin;
import redempt.redlib.protection.ProtectionPolicy.ProtectionType;
import redempt.redlib.region.Region;

Expand All @@ -13,6 +14,11 @@ public class ProtectedRegion {
private Region region;
private ProtectionPolicy policy;

public ProtectedRegion(Plugin plugin, Region region, ProtectionType... types) {
this.region = region;
this.policy = new ProtectionPolicy(plugin, region, b -> region.contains(b.getLocation()), types);
}

public ProtectedRegion(Region region, ProtectionType... types) {
this.region = region;
this.policy = new ProtectionPolicy(region, b -> region.contains(b.getLocation()), types);
Expand Down
29 changes: 29 additions & 0 deletions src/redempt/redlib/protection/ProtectionPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import redempt.redlib.RedLib;
import redempt.redlib.misc.EventListener;
import redempt.redlib.region.Region;
import redempt.redlib.region.RegionMap;

Expand Down Expand Up @@ -120,6 +121,24 @@ public static void registerProtections() {
private Map<ProtectionType, String> messages = new HashMap<>();
private Predicate<Block> protectionCheck;
private Region bounds;
private Plugin plugin;

{
new EventListener<>(RedLib.getInstance(), PluginDisableEvent.class, (l, e) -> {
if (e.getPlugin().equals(plugin)) {
disable();
l.unregister();
}
});
}

protected ProtectionPolicy(Plugin plugin, Region bounds, Predicate<Block> protectionCheck, ProtectionType... protections) {
this.plugin = plugin;
this.bounds = bounds;
Arrays.stream(protections).forEach(this.protections::add);
this.protectionCheck = protectionCheck;
regionMap.set(bounds, this);
}

/**
* Create a ProtectionPolicy to protect blocks
Expand All @@ -128,6 +147,11 @@ public static void registerProtections() {
* @param protections The types of actions to protect against
*/
public ProtectionPolicy(Region bounds, Predicate<Block> protectionCheck, ProtectionType... protections) {
try {
plugin = JavaPlugin.getProvidingPlugin(Class.forName(new Exception().getStackTrace()[1].getClassName()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
this.bounds = bounds;
Arrays.stream(protections).forEach(this.protections::add);
this.protectionCheck = protectionCheck;
Expand All @@ -141,6 +165,11 @@ public ProtectionPolicy(Region bounds, Predicate<Block> protectionCheck, Protect
* @param protections The types of actions to protect against
*/
public ProtectionPolicy(Predicate<Block> protectionCheck, ProtectionType... protections) {
try {
plugin = JavaPlugin.getProvidingPlugin(Class.forName(new Exception().getStackTrace()[1].getClassName()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
this.protectionCheck = protectionCheck;
Arrays.stream(protections).forEach(this.protections::add);
globalPolicies.add(this);
Expand Down
58 changes: 48 additions & 10 deletions src/redempt/redlib/region/Region.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;
import redempt.redlib.RedLib;
import redempt.redlib.protection.ProtectedRegion;
Expand All @@ -29,6 +31,7 @@ public class Region {

protected Location start;
protected Location end;
private Set<Chunk> chunkCache = null;

/**
* Construct a Region using 2 corners
Expand All @@ -55,6 +58,7 @@ protected void setLocations(Location start, Location end) {

this.start = new Location(start.getWorld(), minX, minY, minZ);
this.end = new Location(end.getWorld(), maxX, maxY, maxZ);
chunkCache = null;
}

/**
Expand Down Expand Up @@ -253,6 +257,7 @@ public void expand(BlockFace direction, int amount) {
public void move(Vector v) {
start = start.add(v);
end = end.add(v);
chunkCache = null;
}

/**
Expand All @@ -278,7 +283,13 @@ public void move(int x, int y, int z) {
* @return The {@link ProtectedRegion}
*/
public ProtectedRegion protect(ProtectionType... types) {
return new ProtectedRegion(new Region(this.getStart(), this.getEnd()), types);
try {
Plugin plugin = JavaPlugin.getProvidingPlugin(Class.forName(new Exception().getStackTrace()[1].getClassName()));
return new ProtectedRegion(plugin, new Region(this.getStart(), this.getEnd()), types);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}

/**
Expand Down Expand Up @@ -315,17 +326,22 @@ public boolean overlaps(Region o) {
}

/**
* Gets all entities contained in this Region
* Gets all entities contained in this Region in loaded chunks
* @return The entities in this Region
*/
public List<Entity> getEntities() {
return getEntities(false);
}

/**
* Gets all entities contained in this Region
* @param load Whether to load chunks to check the entities inside them
* @return The entities in this Region
*/
public List<Entity> getEntities(boolean load) {
List<Entity> entities = new ArrayList<>();
for (int cx = start.getChunk().getX(); cx <= end.getChunk().getX(); cx++) {
for (int cz = start.getChunk().getZ(); cz <= end.getChunk().getZ(); cz++) {
Chunk chunk = start.getWorld().getChunkAt(cx, cz);
Arrays.stream(chunk.getEntities()).filter(e -> contains(e.getLocation())).forEach(entities::add);
}
}
Stream<Chunk> chunkStream = load ? getChunks().stream() : getLoadedChunks().stream();
chunkStream.map(Chunk::getEntities).forEach(e -> Arrays.stream(e).filter(en -> this.contains(en.getLocation())).forEach(entities::add));
return entities;
}

Expand All @@ -334,17 +350,39 @@ public List<Entity> getEntities() {
* @return The players in this Region
*/
public List<Player> getPlayers() {
return getEntities().stream().filter(e -> e instanceof Player).map(e -> (Player) e).collect(Collectors.toList());
return getEntities(false).stream().filter(e -> e instanceof Player).map(e -> (Player) e).collect(Collectors.toList());
}

/**
* @return All the Chunks this Region overlaps
*/
public Set<Chunk> getChunks() {
if (chunkCache == null) {
chunkCache = new HashSet<>();
for (int cx = start.getChunk().getX(); cx <= end.getChunk().getX(); cx++) {
for (int cz = start.getChunk().getZ(); cz <= end.getChunk().getZ(); cz++) {
chunkCache.add(start.getWorld().getChunkAt(cx, cz));
}
}
return chunkCache;
}
return chunkCache;
}

/**
* @return All the loaded Chunks this Region overlaps
*/
public Set<Chunk> getLoadedChunks() {
Set<Chunk> chunks = new HashSet<>();
if (chunkCache != null) {
chunkCache.stream().filter(Chunk::isLoaded).forEach(chunks::add);
return chunks;
}
for (int cx = start.getChunk().getX(); cx <= end.getChunk().getX(); cx++) {
for (int cz = start.getChunk().getZ(); cz <= end.getChunk().getZ(); cz++) {
chunks.add(start.getWorld().getChunkAt(cx, cz));
if (start.getWorld().isChunkLoaded(cx, cz)) {
chunks.add(start.getWorld().getChunkAt(cx, cz));
}
}
}
return chunks;
Expand Down

0 comments on commit 4c14e6a

Please sign in to comment.