Make floor restore instant and play sounds per-player instead of at a fixed location
Build / build (push) Successful in 1m13s

This commit is contained in:
Michael Burgess
2026-08-07 08:20:15 -04:00
parent 07d210d8db
commit 86f118f9e6
3 changed files with 34 additions and 27 deletions
@@ -358,7 +358,7 @@ public class Arena {
}
private void processRoundEnd() {
plugin.getSoundUtil().play(config.getSpawn(), plugin.getConfigManager().getSound("floor-disappear"), 1f, 1f);
playToParticipants("floor-disappear");
floorManager.removeNonTarget(currentTarget, plugin.getConfigManager().getFloorBatchBlocksPerTick(), () -> {
BukkitTask delay = plugin.getServer().getScheduler().runTaskLater(plugin, this::evaluateEliminations,
config.getFloorRemoveDelaySeconds() * 20L);
@@ -366,6 +366,19 @@ public class Arena {
});
}
/** Plays a configured sound directly to every current player/spectator (each at their own
* location), instead of once at a single world coordinate — Bukkit's location-based
* playSound falls off with distance, so anyone far from that one spot would hear nothing. */
private void playToParticipants(String soundKey) {
String soundName = plugin.getConfigManager().getSound(soundKey);
for (UUID uuid : allParticipants()) {
Player p = plugin.getServer().getPlayer(uuid);
if (p != null) {
plugin.getSoundUtil().play(p, soundName, 1f, 1f);
}
}
}
private void evaluateEliminations() {
List<EliminationLogic.PlayerFloorState<UUID, Material>> states = new ArrayList<>();
for (UUID uuid : players) {
@@ -406,7 +419,10 @@ public class Arena {
}
BukkitTask restoreDelay = plugin.getServer().getScheduler().runTaskLater(plugin, () ->
floorManager.restoreFull(plugin.getConfigManager().getFloorBatchBlocksPerTick(), this::startNextRound),
floorManager.restoreFull(plugin.getConfigManager().getFloorBatchBlocksPerTick(), () -> {
playToParticipants("round-complete");
startNextRound();
}),
config.getFloorRestoreDelaySeconds() * 20L);
tasks.add(restoreDelay);
}
@@ -89,7 +89,11 @@ public class FloorManager {
return new ArrayList<>(layout.values());
}
/** Places every block from the stored layout, batched across ticks. */
/**
* Places every block from the stored layout, all within a single tick, so the floor
* visibly resets instantly at the start of each round instead of filling in gradually.
* See {@link #removeNonTarget} for the same instant-vs-batched rationale.
*/
public void restoreFull(int blocksPerTick, Runnable onComplete) {
World world = config.getWorld();
if (world == null) {
@@ -99,26 +103,12 @@ public class FloorManager {
return;
}
cancelActiveTask();
Deque<Map.Entry<String, Material>> queue = new ArrayDeque<>(layout.entrySet());
org.bukkit.scheduler.BukkitRunnable runnable = new org.bukkit.scheduler.BukkitRunnable() {
@Override
public void run() {
int processed = 0;
while (processed < blocksPerTick && !queue.isEmpty()) {
Map.Entry<String, Material> entry = queue.poll();
setBlock(world, entry.getKey(), entry.getValue());
processed++;
}
if (queue.isEmpty()) {
cancel();
activeTask = null;
if (onComplete != null) {
onComplete.run();
}
}
}
};
activeTask = runnable.runTaskTimer(plugin, 0L, 1L);
for (Map.Entry<String, Material> entry : layout.entrySet()) {
setBlock(world, entry.getKey(), entry.getValue());
}
if (onComplete != null) {
onComplete.run();
}
}
/**