From b94e3522ca9d6d54bff07779aa88f2ac3205bb90 Mon Sep 17 00:00:00 2001 From: TylerS1066 Date: Tue, 20 Aug 2024 18:12:33 -0500 Subject: [PATCH] Revert "Use processing for wrecks (#686)" (#698) This reverts commit 9ccfe24bcbf1fc6890f3ea06a1b45507ecfe04cf. --- .../net/countercraft/movecraft/Movecraft.java | 8 -- .../movecraft/async/AsyncManager.java | 92 ++++++++++++++++--- .../movecraft/craft/CraftManager.java | 2 +- .../movecraft/features/fading/FadeTask.java | 42 --------- .../features/fading/WreckManager.java | 45 --------- .../movecraft/features/fading/WreckTask.java | 73 --------------- .../processing/effects/DeferredEffect.java | 36 -------- .../processing/effects/SetBlockEffect.java | 24 +---- .../movecraft/MovecraftLocation.java | 20 ---- .../movecraft/processing/WorldManager.java | 5 +- .../movecraft/processing/effects/Effect.java | 69 ++------------ .../movecraft/util/CollectorUtils.java | 16 ---- 12 files changed, 93 insertions(+), 339 deletions(-) delete mode 100644 Movecraft/src/main/java/net/countercraft/movecraft/features/fading/FadeTask.java delete mode 100644 Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckManager.java delete mode 100644 Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckTask.java delete mode 100644 Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/DeferredEffect.java delete mode 100644 api/src/main/java/net/countercraft/movecraft/util/CollectorUtils.java diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java b/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java index fe69859c1..d5f6eabbb 100644 --- a/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java +++ b/Movecraft/src/main/java/net/countercraft/movecraft/Movecraft.java @@ -27,7 +27,6 @@ import net.countercraft.movecraft.features.contacts.ContactsCommand; import net.countercraft.movecraft.features.contacts.ContactsManager; import net.countercraft.movecraft.features.contacts.ContactsSign; -import net.countercraft.movecraft.features.fading.WreckManager; import net.countercraft.movecraft.features.status.StatusManager; import net.countercraft.movecraft.features.status.StatusSign; import net.countercraft.movecraft.listener.*; @@ -58,7 +57,6 @@ public class Movecraft extends JavaPlugin { private WorldHandler worldHandler; private SmoothTeleport smoothTeleport; private AsyncManager asyncManager; - private WreckManager wreckManager; public static synchronized Movecraft getInstance() { return instance; @@ -191,10 +189,8 @@ public void onEnable() { asyncManager.runTaskTimer(this, 0, 1); MapUpdateManager.getInstance().runTaskTimer(this, 0, 1); - CraftManager.initialize(datapackInitialized); Bukkit.getScheduler().runTaskTimer(this, WorldManager.INSTANCE::run, 0,1); - wreckManager = new WreckManager(WorldManager.INSTANCE); getServer().getPluginManager().registerEvents(new InteractListener(), this); @@ -336,8 +332,4 @@ public SmoothTeleport getSmoothTeleport() { public AsyncManager getAsyncManager() { return asyncManager; } - - public @NotNull WreckManager getWreckManager(){ - return wreckManager; - } } diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/async/AsyncManager.java b/Movecraft/src/main/java/net/countercraft/movecraft/async/AsyncManager.java index 7825b86e2..fc2cfe889 100644 --- a/Movecraft/src/main/java/net/countercraft/movecraft/async/AsyncManager.java +++ b/Movecraft/src/main/java/net/countercraft/movecraft/async/AsyncManager.java @@ -23,26 +23,24 @@ import net.countercraft.movecraft.MovecraftLocation; import net.countercraft.movecraft.async.rotation.RotationTask; import net.countercraft.movecraft.async.translation.TranslationTask; -import net.countercraft.movecraft.craft.Craft; -import net.countercraft.movecraft.craft.CraftManager; -import net.countercraft.movecraft.craft.PilotedCraft; -import net.countercraft.movecraft.craft.PlayerCraft; -import net.countercraft.movecraft.craft.SinkingCraft; +import net.countercraft.movecraft.config.Settings; +import net.countercraft.movecraft.craft.*; import net.countercraft.movecraft.craft.type.CraftType; import net.countercraft.movecraft.events.CraftReleaseEvent; import net.countercraft.movecraft.mapUpdater.MapUpdateManager; +import net.countercraft.movecraft.mapUpdater.update.BlockCreateCommand; +import net.countercraft.movecraft.mapUpdater.update.UpdateCommand; +import net.countercraft.movecraft.util.hitboxes.HitBox; import net.kyori.adventure.text.Component; +import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; +import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -51,8 +49,14 @@ public class AsyncManager extends BukkitRunnable { private final Map ownershipMap = new HashMap<>(); private final BlockingQueue finishedAlgorithms = new LinkedBlockingQueue<>(); private final Set clearanceSet = new HashSet<>(); + private final Map wrecks = new HashMap<>(); + private final Map wreckWorlds = new HashMap<>(); + private final Map> wreckPhases = new HashMap<>(); + private final Map> processedFadeLocs = new HashMap<>(); private final Map cooldownCache = new WeakHashMap<>(); + private long lastFadeCheck = 0; + public AsyncManager() {} public void submitTask(AsyncTask task, Craft c) { @@ -67,6 +71,15 @@ public void submitCompletedTask(AsyncTask task) { finishedAlgorithms.add(task); } + public void addWreck(Craft craft){ + if(craft.getCollapsedHitBox().isEmpty() || Settings.FadeWrecksAfter == 0){ + return; + } + wrecks.put(craft.getCollapsedHitBox(), System.currentTimeMillis()); + wreckWorlds.put(craft.getCollapsedHitBox(), craft.getWorld()); + wreckPhases.put(craft.getCollapsedHitBox(), craft.getPhaseBlocks()); + } + private void processAlgorithmQueue() { int runLength = 10; int queueLength = finishedAlgorithms.size(); @@ -312,11 +325,68 @@ private void processSinking() { } } + private void processFadingBlocks() { + if (Settings.FadeWrecksAfter == 0) + return; + long ticksElapsed = (System.currentTimeMillis() - lastFadeCheck) / 50; + if (ticksElapsed <= Settings.FadeTickCooldown) + return; + + List processed = new ArrayList<>(); + for(Map.Entry entry : wrecks.entrySet()){ + if (Settings.FadeWrecksAfter * 1000L > System.currentTimeMillis() - entry.getValue()) + continue; + + final HitBox hitBox = entry.getKey(); + final Map phaseBlocks = wreckPhases.get(hitBox); + final World world = wreckWorlds.get(hitBox); + List commands = new ArrayList<>(); + int fadedBlocks = 0; + if (!processedFadeLocs.containsKey(world)) + processedFadeLocs.put(world, new HashSet<>()); + + int maxFadeBlocks = (int) (hitBox.size() * (Settings.FadePercentageOfWreckPerCycle / 100.0)); + //Iterate hitbox as a set to get more random locations + for (MovecraftLocation location : hitBox.asSet()){ + if (processedFadeLocs.get(world).contains(location)) + continue; + + if (fadedBlocks >= maxFadeBlocks) + break; + + final Location bLoc = location.toBukkit(world); + if ((Settings.FadeWrecksAfter + + Settings.ExtraFadeTimePerBlock.getOrDefault(bLoc.getBlock().getType(), 0)) + * 1000L > System.currentTimeMillis() - entry.getValue()) + continue; + + fadedBlocks++; + processedFadeLocs.get(world).add(location); + BlockData phaseBlock = phaseBlocks.getOrDefault(bLoc, Material.AIR.createBlockData()); + commands.add(new BlockCreateCommand(world, location, phaseBlock)); + } + MapUpdateManager.getInstance().scheduleUpdates(commands); + if (!processedFadeLocs.get(world).containsAll(hitBox.asSet())) + continue; + + processed.add(hitBox); + processedFadeLocs.get(world).removeAll(hitBox.asSet()); + } + for(HitBox hitBox : processed) { + wrecks.remove(hitBox); + wreckPhases.remove(hitBox); + wreckWorlds.remove(hitBox); + } + + lastFadeCheck = System.currentTimeMillis(); + } + public void run() { clearAll(); processCruise(); processSinking(); + processFadingBlocks(); processAlgorithmQueue(); // now cleanup craft that are bugged and have not moved in the past 60 seconds, diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/craft/CraftManager.java b/Movecraft/src/main/java/net/countercraft/movecraft/craft/CraftManager.java index 1db3db008..ec586acd2 100644 --- a/Movecraft/src/main/java/net/countercraft/movecraft/craft/CraftManager.java +++ b/Movecraft/src/main/java/net/countercraft/movecraft/craft/CraftManager.java @@ -244,7 +244,7 @@ public void release(@NotNull Craft craft, @NotNull CraftReleaseEvent.Reason reas craft.getHitBox().getMinZ()) ); } - Movecraft.getInstance().getWreckManager().queueWreck(craft); + Movecraft.getInstance().getAsyncManager().addWreck(craft); } //region Craft management diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/FadeTask.java b/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/FadeTask.java deleted file mode 100644 index a8ae5f1b8..000000000 --- a/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/FadeTask.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.countercraft.movecraft.features.fading; - -import net.countercraft.movecraft.MovecraftLocation; -import net.countercraft.movecraft.processing.MovecraftWorld; -import net.countercraft.movecraft.processing.WorldManager; -import net.countercraft.movecraft.processing.effects.Effect; -import net.countercraft.movecraft.processing.effects.SetBlockEffect; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.block.data.BlockData; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; -import java.util.function.Supplier; - -/** - * Fades a block if the data for the intended block has not been mutated since creation. - */ -public class FadeTask implements Supplier { - private final @NotNull BlockData compareData; - private final @NotNull BlockData setData; - private final @NotNull MovecraftWorld world; - private final @NotNull MovecraftLocation location; - - public FadeTask(@NotNull BlockData compareData, @NotNull BlockData setData, @NotNull MovecraftWorld world, @NotNull MovecraftLocation location){ - this.compareData = compareData; - this.setData = setData; - this.world = world; - this.location = location; - } - - @Override - public Effect get() { - var testData = world.getData(location); - - return () -> Objects.requireNonNull(Bukkit.getWorld(world.getWorldUUID())) - .getChunkAtAsync(location.toBukkit(null)) - .thenRunAsync(() -> WorldManager.INSTANCE.submit(() -> testData.equals(compareData) - ? new SetBlockEffect(world, location, setData) - : null)); - } -} diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckManager.java b/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckManager.java deleted file mode 100644 index ee12262df..000000000 --- a/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckManager.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.countercraft.movecraft.features.fading; - -import net.countercraft.movecraft.config.Settings; -import net.countercraft.movecraft.craft.Craft; -import net.countercraft.movecraft.processing.WorldManager; -import net.countercraft.movecraft.util.MathUtils; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * Singleton for handling wreck disposal - */ -public class WreckManager { - private final @NotNull WorldManager worldManager; - - public WreckManager(@NotNull WorldManager worldManager){ - this.worldManager = Objects.requireNonNull(worldManager); - } - - /** - * Queue a wreck to be considered terminally destroyed, and hence appropriate for systems such as fading. - * - * @param craft the craft to handle as a wreck - */ - public void queueWreck(@NotNull Craft craft){ - if(craft.getCollapsedHitBox().isEmpty() || Settings.FadeWrecksAfter == 0){ - return; - } - - worldManager.submit(new WreckTask( - craft.getCollapsedHitBox(), - craft.getMovecraftWorld(), - craft - .getPhaseBlocks() - .entrySet() - .stream() - .collect(Collectors.toMap( - entry -> MathUtils.bukkit2MovecraftLoc(entry.getKey()), - Map.Entry::getValue - )))); - } -} diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckTask.java b/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckTask.java deleted file mode 100644 index 5df495527..000000000 --- a/Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckTask.java +++ /dev/null @@ -1,73 +0,0 @@ -package net.countercraft.movecraft.features.fading; - -import net.countercraft.movecraft.MovecraftLocation; -import net.countercraft.movecraft.config.Settings; -import net.countercraft.movecraft.processing.MovecraftWorld; -import net.countercraft.movecraft.processing.WorldManager; -import net.countercraft.movecraft.processing.effects.DeferredEffect; -import net.countercraft.movecraft.processing.effects.Effect; -import net.countercraft.movecraft.util.CollectorUtils; -import net.countercraft.movecraft.util.hitboxes.HitBox; -import org.bukkit.Material; -import org.bukkit.block.data.BlockData; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ForkJoinTask; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -public class WreckTask implements Supplier { - - private final @NotNull HitBox hitBox; - private final @NotNull Map phaseBlocks; - private final @NotNull MovecraftWorld world; - private final int fadeDelayTicks; - private final int maximumFadeDurationTicks; - - public WreckTask(@NotNull HitBox wreck, @NotNull MovecraftWorld world, @NotNull Map phaseBlocks){ - this.hitBox = Objects.requireNonNull(wreck); - this.phaseBlocks = Objects.requireNonNull(phaseBlocks); - this.world = Objects.requireNonNull(world); - this.fadeDelayTicks = Settings.FadeWrecksAfter * 20; - this.maximumFadeDurationTicks = (int) (Settings.FadeTickCooldown * (100.0 / Settings.FadePercentageOfWreckPerCycle)); - } - - @Override - public Effect get() { - var updates = hitBox - .asSet() - .stream() - .collect(Collectors.groupingBy(location -> location.scalarDivide(16).hadamardProduct(1,0,1), CollectorUtils.toHitBox())) - .values() - .stream() - .map(slice -> ForkJoinTask.adapt(() -> partialUpdate(slice))) - .toList(); - - return ForkJoinTask - .invokeAll(updates) - .stream() - .map(ForkJoinTask::join) - .reduce(Effect.NONE, Effect::andThen); - } - - private @NotNull Effect partialUpdate(@NotNull HitBox slice){ - Effect accumulator = Effect.NONE; - for (MovecraftLocation location : slice){ - // Get the existing data - final BlockData data = world.getData(location); - // Determine the replacement data - BlockData replacementData = phaseBlocks.getOrDefault(location, Material.AIR.createBlockData()); - // Calculate ticks until replacement - long fadeTicks = this.fadeDelayTicks; - fadeTicks += (int) (Math.random() * maximumFadeDurationTicks); - fadeTicks += 20L * Settings.ExtraFadeTimePerBlock.getOrDefault(data.getMaterial(), 0); - // Deffer replacement until time delay elapses - accumulator = accumulator.andThen(new DeferredEffect(fadeTicks, () -> WorldManager.INSTANCE.submit(new FadeTask(data, replacementData, world, location)))); - } - - // TODO: Determine if we need to reduce the spread of deferred effects due to runnable overhead - return accumulator; - } -} diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/DeferredEffect.java b/Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/DeferredEffect.java deleted file mode 100644 index ee0864345..000000000 --- a/Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/DeferredEffect.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.countercraft.movecraft.processing.effects; - -import net.countercraft.movecraft.Movecraft; -import net.countercraft.movecraft.processing.WorldManager; -import org.bukkit.scheduler.BukkitRunnable; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; - -/** - * A wrapper effect that allows delaying the execution of a provided effect by a number of ticks. - */ -public class DeferredEffect implements Effect { - private final long delayTicks; - private final @NotNull Effect effect; - - public DeferredEffect(long delayTicks, @NotNull Effect effect){ - this.delayTicks = delayTicks; - this.effect = Objects.requireNonNull(effect); - } - - @Override - public void run() { - new BukkitRunnable(){ - @Override - public void run() { - WorldManager.INSTANCE.submit(() -> effect); - } - }.runTaskLaterAsynchronously(Movecraft.getInstance(), delayTicks); - } - - @Override - public boolean isAsync() { - return true; - } -} diff --git a/Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/SetBlockEffect.java b/Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/SetBlockEffect.java index c31e93944..82aca582c 100644 --- a/Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/SetBlockEffect.java +++ b/Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/SetBlockEffect.java @@ -1,36 +1,16 @@ package net.countercraft.movecraft.processing.effects; import net.countercraft.movecraft.MovecraftLocation; -import net.countercraft.movecraft.mapUpdater.update.BlockCreateCommand; -import net.countercraft.movecraft.processing.MovecraftWorld; -import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.block.data.BlockData; -import org.jetbrains.annotations.NotNull; -import java.util.Objects; - -/** - * Sets a block based on the provided data. - */ public final class SetBlockEffect implements Effect { - private final @NotNull MovecraftWorld world; - private final @NotNull MovecraftLocation location; - private final @NotNull BlockData data; + public SetBlockEffect(World world, MovecraftLocation location, Material material){ - public SetBlockEffect(@NotNull MovecraftWorld world, @NotNull MovecraftLocation location, @NotNull BlockData data){ - this.world = world; - this.location = location; - this.data = data; } @Override public void run() { - World bukkitWorld = Objects.requireNonNull( - Bukkit.getWorld(world.getWorldUUID()), - "Failed to access base World from MovecraftWorld"); - // TODO: Reverse indirection - new BlockCreateCommand(bukkitWorld, location, data).doUpdate(); } } diff --git a/api/src/main/java/net/countercraft/movecraft/MovecraftLocation.java b/api/src/main/java/net/countercraft/movecraft/MovecraftLocation.java index 1f3486f43..1636dec68 100644 --- a/api/src/main/java/net/countercraft/movecraft/MovecraftLocation.java +++ b/api/src/main/java/net/countercraft/movecraft/MovecraftLocation.java @@ -88,26 +88,6 @@ public MovecraftLocation subtract(MovecraftLocation l) { return new MovecraftLocation(getX() - l.getX(), getY() - l.getY(), getZ() - l.getZ()); } - public MovecraftLocation hadamardProduct(int x, int y, int z){ - return new MovecraftLocation(this.x*x, this.y*y, this.z*z); - } - - public MovecraftLocation hadamardProduct(MovecraftLocation location){ - return hadamardProduct(location.x, location.y, location.z); - } - - public MovecraftLocation scalarMultiply(int multiplier){ - return new MovecraftLocation(x * multiplier, y * multiplier, z * multiplier); - } - - public MovecraftLocation scalarDivide(int divisor){ - return new MovecraftLocation(x / divisor, y / divisor, z/divisor); - } - - public MovecraftLocation scalarMod(int modulus){ - return new MovecraftLocation(x % modulus, y & modulus, z % modulus); - } - /** * * Gives the euclidean distance between this MovecraftLocation and another MovecraftLocation diff --git a/api/src/main/java/net/countercraft/movecraft/processing/WorldManager.java b/api/src/main/java/net/countercraft/movecraft/processing/WorldManager.java index 74378240d..ecef2e3df 100644 --- a/api/src/main/java/net/countercraft/movecraft/processing/WorldManager.java +++ b/api/src/main/java/net/countercraft/movecraft/processing/WorldManager.java @@ -4,7 +4,6 @@ import net.countercraft.movecraft.util.CompletableFutureTask; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -33,7 +32,7 @@ public String toString(){ }; private final ConcurrentLinkedQueue worldChanges = new ConcurrentLinkedQueue<>(); - private final ConcurrentLinkedQueue> tasks = new ConcurrentLinkedQueue<>(); + private final ConcurrentLinkedQueue> tasks = new ConcurrentLinkedQueue<>(); private final BlockingQueue currentTasks = new LinkedBlockingQueue<>(); private volatile boolean running = false; @@ -123,7 +122,7 @@ public void submit(Runnable task){ }); } - public void submit(Supplier<@Nullable Effect> task){ + public void submit(Supplier task){ tasks.add(task); } diff --git a/api/src/main/java/net/countercraft/movecraft/processing/effects/Effect.java b/api/src/main/java/net/countercraft/movecraft/processing/effects/Effect.java index f12d2f458..284ddbff4 100644 --- a/api/src/main/java/net/countercraft/movecraft/processing/effects/Effect.java +++ b/api/src/main/java/net/countercraft/movecraft/processing/effects/Effect.java @@ -1,79 +1,24 @@ package net.countercraft.movecraft.processing.effects; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; - @FunctionalInterface public interface Effect { - /** - * A no-op effect for use in systems where a non-null effect is needed - */ - Effect NONE = new Effect() { - @Override - public void run() { - // No-op - } - - @Override - public boolean isAsync() { - return true; - } - - @Override - public @NotNull Effect andThen(@Nullable Effect chain){ - return chain == null ? this : chain; - } - }; - void run(); default boolean isAsync(){ return false; } - default @NotNull Effect andThen(@Nullable Effect chain){ - return new AndEffect(this, chain); - } - - class AndEffect implements Effect { - private final List effects = new ArrayList<>(); - - public AndEffect(Effect... effects){ - for (Effect effect : effects) { - andThen(effect); - } - } - - @Override - public void run() { - effects.forEach(Effect::run); - } - - @Override - public @NotNull Effect andThen(@Nullable Effect chain) { - if(this == chain){ - // copy if chaining to self to prevent concurrent modification - effects.addAll(effects.stream().toList()); - - return this; - } else if(chain instanceof AndEffect andChain){ - // Merge other AndChain instances - effects.addAll(andChain.effects); - - return this; - } else if(chain == NONE || chain == null){ - // Skip NONE - return this; - } - - // Otherwise add to current chain - effects.add(chain); - + default @NotNull + Effect andThen(@Nullable Effect chain){ + if(chain == null){ return this; } + return () -> { + this.run(); + chain.run(); + }; } } diff --git a/api/src/main/java/net/countercraft/movecraft/util/CollectorUtils.java b/api/src/main/java/net/countercraft/movecraft/util/CollectorUtils.java deleted file mode 100644 index f98c4c4da..000000000 --- a/api/src/main/java/net/countercraft/movecraft/util/CollectorUtils.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.countercraft.movecraft.util; - -import net.countercraft.movecraft.MovecraftLocation; -import net.countercraft.movecraft.util.hitboxes.BitmapHitBox; - -import java.util.stream.Collector; - -public class CollectorUtils { - /** - * Provides a collector for reducing streams of MovecraftLocations to HitBox instances - * @return A HitBox containing all collected MovecraftLocations - */ - public static Collector toHitBox(){ - return Collector.of(BitmapHitBox::new, BitmapHitBox::add, BitmapHitBox::union, t->t); - } -}