Skip to content

Commit

Permalink
Fixes for Folia
Browse files Browse the repository at this point in the history
  • Loading branch information
froobynooby committed Mar 11, 2024
1 parent 4727b23 commit 5bdca4a
Show file tree
Hide file tree
Showing 13 changed files with 222 additions and 56 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ repositories {
dependencies {
testImplementation 'junit:junit:4.13.2'
//compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
compileOnly 'dev.folia:folia-api:1.19.4-R0.1-SNAPSHOT'
compileOnly 'dev.folia:folia-api:1.20.4-R0.1-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.10.9'
implementation 'org.jooq:joor-java-8:0.9.14'
implementation 'com.github.froobynooby:nab-configuration:master-SNAPSHOT' //'com.froobworld:nab-configuration:1.0.2'
implementation 'org.bstats:bstats-bukkit:2.2.1'
implementation 'org.bstats:bstats-bukkit:3.0.2'
}

processResources {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/froobworld/farmcontrol/FarmControl.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void onEnable() {
registerCommands();

new FcMetrics(this, 9692);
hookManager.getSchedulerHook().runRepeatingTask(RemoveRandomMovementAction::cleanUp, 1200, 1200); // Hack to fix leaking entities
hookManager.getSchedulerHook().runRepeatingTask(() -> RemoveRandomMovementAction.cleanUp(this), 1200, 1200); // Hack to fix leaking entities
}

public void reload() throws Exception {
Expand All @@ -77,7 +77,7 @@ public void onDisable() {
farmController.unRegister();
farmController.unload();
}
RemoveRandomMovementAction.cleanUp();
RemoveRandomMovementAction.cleanUp(this);
}

public FcConfig getFcConfig() {
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/froobworld/farmcontrol/HookManager.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.froobworld.farmcontrol;

import com.froobworld.farmcontrol.hook.entitygetter.BukkitEntityGetterHook;
import com.froobworld.farmcontrol.hook.entitygetter.EntityGetterHook;
import com.froobworld.farmcontrol.hook.entitygetter.RegionisedEntityGetterHook;
import com.froobworld.farmcontrol.hook.scheduler.BukkitSchedulerHook;
import com.froobworld.farmcontrol.hook.scheduler.RegionisedSchedulerHook;
import com.froobworld.farmcontrol.hook.scheduler.SchedulerHook;
Expand All @@ -12,6 +15,7 @@ public class HookManager {
private final FarmControl farmControl;
private final TickHook tickHook;
private final SchedulerHook schedulerHook;
private final EntityGetterHook entityGetterHook;
private MsptTracker msptTracker;

public HookManager(FarmControl farmControl) {
Expand All @@ -28,6 +32,11 @@ public HookManager(FarmControl farmControl) {
} else {
tickHook = new BukkitTickHook(schedulerHook);
}
if (RegionisedEntityGetterHook.isCompatible()) {
entityGetterHook = new RegionisedEntityGetterHook(farmControl);
} else {
entityGetterHook = new BukkitEntityGetterHook();
}
if (tickHook != null) {
tickHook.register(farmControl);
}
Expand Down Expand Up @@ -62,4 +71,7 @@ public SchedulerHook getSchedulerHook() {
return schedulerHook;
}

public EntityGetterHook getEntityGetterHook() {
return entityGetterHook;
}
}
31 changes: 12 additions & 19 deletions src/main/java/com/froobworld/farmcontrol/command/StatusCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.froobworld.farmcontrol.FarmControl;
import com.froobworld.farmcontrol.controller.FarmController;
import com.froobworld.farmcontrol.controller.entity.SnapshotEntity;
import com.froobworld.farmcontrol.data.FcData;
import com.froobworld.farmcontrol.hook.scheduler.ScheduledTask;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
Expand Down Expand Up @@ -47,27 +47,20 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
AtomicInteger affectedCount = new AtomicInteger(0);
Map<String, AtomicInteger> actionCount = new HashMap<>();

CompletableFuture<Void> completableFuture = CompletableFuture.completedFuture(null);
for (Entity entity : world.getEntitiesByClasses(FarmController.ENTITY_CLASSES)) {
entityCount.incrementAndGet();
CompletableFuture<Void> entityFuture = new CompletableFuture();
ScheduledTask scheduledTask = farmControl.getHookManager().getSchedulerHook().runEntityTaskAsap(() -> {
try {
FcData fcData = FcData.get(entity);
if (fcData != null) {
affectedCount.incrementAndGet();
for (String action : fcData.getActions()) {
actionCount.computeIfAbsent(action, a -> new AtomicInteger(0)).incrementAndGet();
}
final CompletableFuture<Void> completableFuture = new CompletableFuture<>();
farmControl.getHookManager().getEntityGetterHook().getSnapshotEntities(world, FarmController.ENTITY_CLASSES).thenAccept(entities -> {
entityCount.set(entities.size());
for (SnapshotEntity entity : entities) {
FcData fcData = entity.getFcData();
if (fcData != null && !fcData.getActions().isEmpty()) {
affectedCount.incrementAndGet();
for (String action : fcData.getActions()) {
actionCount.computeIfAbsent(action, a -> new AtomicInteger(0)).incrementAndGet();
}
} finally {
entityFuture.complete(null);
}
}, () -> entityFuture.complete(null), entity);
if (scheduledTask != null) {
completableFuture = completableFuture.thenCompose(v -> entityFuture);
}
}
completableFuture.complete(null);
});
completableFuture.thenRunAsync(() -> {
sender.sendMessage(ChatColor.GRAY + "Status for world '" + ChatColor.RED + world.getName() + ChatColor.GRAY + "'");
sender.sendMessage("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@
import org.bukkit.World;
import org.bukkit.entity.*;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.*;
import java.util.concurrent.CompletableFuture;

public class FarmController {
public static final Class<?>[] ENTITY_CLASSES = List.of(Mob.class, Vehicle.class, Projectile.class, Item.class).toArray(new Class[0]);
Expand Down Expand Up @@ -88,11 +85,13 @@ public void addWorld(World world) {

public void removeWorld(World world) {
worldTriggerProfilesMap.remove(world);
for (Entity entity : world.getEntities()) {
farmControl.getHookManager().getSchedulerHook().runEntityTaskAsap(
() -> Actioner.undoAllActions(entity, farmControl),
null, entity);
}
farmControl.getHookManager().getEntityGetterHook().getEntities(world).thenAccept(entities -> {
for (Entity entity : entities) {
farmControl.getHookManager().getSchedulerHook().runEntityTaskAsap(
() -> Actioner.undoAllActions(entity, farmControl),
null, entity);
}
});
}

public void register() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.froobworld.farmcontrol.controller.action;

import com.froobworld.farmcontrol.FarmControl;
import com.froobworld.farmcontrol.utils.NmsUtils;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets;
Expand All @@ -25,8 +26,15 @@ public class RemoveRandomMovementAction extends Action {
}
}

public static void cleanUp() {
entityRemovedGoalsMap.entrySet().removeIf(entry -> !entry.getKey().isValid());
public static void cleanUp(FarmControl farmControl) {
List<Mob> mobs = new ArrayList<>(entityRemovedGoalsMap.keySet());
for (Mob mob : mobs) {
farmControl.getHookManager().getSchedulerHook().runEntityTaskAsap(() -> {
if (!mob.isValid()) {
entityRemovedGoalsMap.remove(mob);
}
}, () -> entityRemovedGoalsMap.remove(mob), mob);
}
}

public RemoveRandomMovementAction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
import com.froobworld.farmcontrol.controller.tracker.CycleTracker;
import com.froobworld.farmcontrol.controller.trigger.Trigger;
import com.froobworld.farmcontrol.controller.trigger.UntriggerStrategy;
import com.froobworld.farmcontrol.hook.scheduler.ScheduledTask;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.bukkit.World;
import org.bukkit.entity.*;

import java.util.*;
import java.util.concurrent.CompletableFuture;
Expand Down Expand Up @@ -59,27 +57,15 @@ public void run() {
}

untriggerStrategyMap.entrySet().removeIf(entry -> worldLastTriggerCount.get(world).getOrDefault(entry.getKey(), 0) <= entry.getValue().getMinimumCyclesBeforeUndo());
List<SnapshotEntity> snapshotEntities = new ArrayList<>();
CompletableFuture<Void> completableFuture = CompletableFuture.completedFuture(null);
CompletableFuture<List<SnapshotEntity>> completableFuture = CompletableFuture.completedFuture(null);
if (!profilesToRun.isEmpty() || !untriggerStrategyMap.isEmpty()) {
for (Entity entity : world.getEntitiesByClasses(FarmController.ENTITY_CLASSES)) {
CompletableFuture<Void> entityFuture = new CompletableFuture<>();
ScheduledTask scheduledTask = farmControl.getHookManager().getSchedulerHook().runEntityTaskAsap(() -> {
try {
SnapshotEntity snapshotEntity = new SnapshotEntity(entity);
synchronized (snapshotEntities) {
snapshotEntities.add(snapshotEntity);
}
} finally {
entityFuture.complete(null);
}
}, () -> entityFuture.complete(null), entity);
if (scheduledTask != null) {
completableFuture = completableFuture.thenCompose(v -> entityFuture);
}
}
completableFuture = farmControl.getHookManager().getEntityGetterHook().getSnapshotEntities(world, FarmController.ENTITY_CLASSES);
}
completableFuture.thenRunAsync(() -> {
completableFuture.thenAccept(snapshotEntities -> {
if (snapshotEntities == null || snapshotEntities.isEmpty()) {
cycleTracker.signalCompletion(world);
return;
}
if (!profilesToRun.isEmpty()) {
executorService.submit(new ActionAllocationTask(farmController, world, farmControl.getHookManager().getSchedulerHook(), triggeredTriggers, snapshotEntities, profilesToRun, farmControl.getExclusionManager().getExclusionPredicate(world), farmControl.getActionManager().getActions(), cycleTracker));
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.froobworld.farmcontrol.hook.entitygetter;

import com.froobworld.farmcontrol.controller.entity.SnapshotEntity;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public class BukkitEntityGetterHook implements EntityGetterHook {
@Override
public CompletableFuture<Collection<Entity>> getEntities(World world, Class<?>... classes) {
return CompletableFuture.completedFuture(world.getEntitiesByClasses(classes));
}

@Override
public CompletableFuture<Collection<Entity>> getEntities(World world) {
return CompletableFuture.completedFuture(world.getEntities());
}

@Override
public CompletableFuture<List<SnapshotEntity>> getSnapshotEntities(World world, Class<?>... classes) {
List<SnapshotEntity> snapshotEntities = new ArrayList<>();
for (Entity entity : world.getEntitiesByClasses(classes)) {
snapshotEntities.add(new SnapshotEntity(entity));
}
return CompletableFuture.completedFuture(snapshotEntities);
}

@Override
public CompletableFuture<List<SnapshotEntity>> getSnapshotEntities(World world) {
List<SnapshotEntity> snapshotEntities = new ArrayList<>();
for (Entity entity : world.getEntities()) {
snapshotEntities.add(new SnapshotEntity(entity));
}
return CompletableFuture.completedFuture(snapshotEntities);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.froobworld.farmcontrol.hook.entitygetter;

import com.froobworld.farmcontrol.controller.entity.SnapshotEntity;
import org.bukkit.World;
import org.bukkit.entity.Entity;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public interface EntityGetterHook {

CompletableFuture<Collection<Entity>> getEntities(World world, Class<?>... classes);

CompletableFuture<Collection<Entity>> getEntities(World world);

CompletableFuture<List<SnapshotEntity>> getSnapshotEntities(World world, Class<?>... classes);

CompletableFuture<List<SnapshotEntity>> getSnapshotEntities(World world);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.froobworld.farmcontrol.hook.entitygetter;

import com.froobworld.farmcontrol.FarmControl;
import com.froobworld.farmcontrol.controller.entity.SnapshotEntity;
import com.froobworld.farmcontrol.hook.scheduler.RegionisedSchedulerHook;
import com.google.common.collect.Sets;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Entity;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Function;

public class RegionisedEntityGetterHook implements EntityGetterHook {
private final FarmControl farmControl;

public RegionisedEntityGetterHook(FarmControl farmControl) {
this.farmControl = farmControl;
}

private <T> CompletableFuture<Collection<T>> getMappedEntities(World world, Function<Entity, T> mapper, Class<?>... entityClasses) {
MappedEntityCollector<T> entityCollector = new MappedEntityCollector<>();
CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
for (Chunk chunk : world.getLoadedChunks()) {
CompletableFuture<Void> chunkFuture = new CompletableFuture<>();
Bukkit.getRegionScheduler().execute(farmControl, world, chunk.getX(), chunk.getZ(), () -> {
for (Entity entity : chunk.getEntities()) {
boolean eligible = entityClasses.length == 0;
for (Class<?> entityClass : entityClasses) {
if (entityClass.isAssignableFrom(entity.getClass())) {
eligible = true;
break;
}
}
if (eligible) {
entityCollector.addEntity(entity, mapper.apply(entity));
}
}
chunkFuture.complete(null);
});
future = future.thenCompose(v -> chunkFuture);
}
return future.thenApply(v -> entityCollector.getEntities());
}

@Override
public CompletableFuture<Collection<Entity>> getEntities(World world, Class<?>... entityClasses) {
return getMappedEntities(world, Function.identity(), entityClasses);
}

@Override
public CompletableFuture<Collection<Entity>> getEntities(World world) {
return getMappedEntities(world, Function.identity());
}

@Override
public CompletableFuture<List<SnapshotEntity>> getSnapshotEntities(World world, Class<?>... classes) {
return getMappedEntities(world, SnapshotEntity::new, classes).thenApply(ArrayList::new);
}

@Override
public CompletableFuture<List<SnapshotEntity>> getSnapshotEntities(World world) {
return getMappedEntities(world, SnapshotEntity::new).thenApply(ArrayList::new);
}

public static boolean isCompatible() {
return RegionisedSchedulerHook.isCompatible();
}

private static class MappedEntityCollector<T> {
private final Set<UUID> seenEntities = Sets.newConcurrentHashSet();
private final Collection<T> mappedEntities = new ConcurrentLinkedQueue<>();

public void addEntity(Entity entity, T mappedEntity) {
if (seenEntities.add(entity.getUniqueId())) {
mappedEntities.add(mappedEntity);
}
}

public Collection<T> getEntities() {
return mappedEntities;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ public ScheduledTask runTask(Runnable runnable) {
return new BukkitScheduledTask(Bukkit.getScheduler().runTask(farmControl, runnable).getTaskId());
}

@Override
public ScheduledTask runTaskAsap(Runnable runnable) {
if (Bukkit.isPrimaryThread()) {
runnable.run();
}
return runTask(runnable);
}

@Override
public ScheduledTask runRepeatingTask(Runnable runnable, long initDelay, long period) {
return new BukkitScheduledTask(Bukkit.getScheduler().scheduleSyncRepeatingTask(farmControl, runnable, initDelay, period));
Expand Down
Loading

0 comments on commit 5bdca4a

Please sign in to comment.