-
-
Notifications
You must be signed in to change notification settings - Fork 81
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use processing for wrecks (again) (#699)
* Use processing for wrecks * Don't use Tick * Parallelize on chunks * Clamp y axis to 0 to avoid batching on sub-chunk * Fix axis modifier and add annotations * Add doc comments * Add more efficient NONE::andThen imp * Fix bugs * Update total duration to match previous and use floor * seconds to tick conversion * Fold repeated AndThen calls * load chunks * Fix 1.18.2 async chunk deadlock --------- Co-authored-by: ohnoey <[email protected]>
- Loading branch information
1 parent
b94e352
commit 9ddedc7
Showing
13 changed files
with
344 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
Movecraft/src/main/java/net/countercraft/movecraft/features/fading/FadeTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
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<Effect> { | ||
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)); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
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 | ||
)))); | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
Movecraft/src/main/java/net/countercraft/movecraft/features/fading/WreckTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
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<Effect> { | ||
|
||
private final @NotNull HitBox hitBox; | ||
private final @NotNull Map<MovecraftLocation, BlockData> phaseBlocks; | ||
private final @NotNull MovecraftWorld world; | ||
private final int fadeDelayTicks; | ||
private final int maximumFadeDurationTicks; | ||
|
||
public WreckTask(@NotNull HitBox wreck, @NotNull MovecraftWorld world, @NotNull Map<MovecraftLocation, BlockData> 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; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
Movecraft/src/main/java/net/countercraft/movecraft/processing/effects/DeferredEffect.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
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; | ||
} | ||
} |
Oops, something went wrong.