Make floor restore instant and play sounds per-player instead of at a fixed location
Build / build (push) Successful in 1m13s
Build / build (push) Successful in 1m13s
This commit is contained in:
@@ -142,10 +142,11 @@ disabled, deleted, or the plugin shuts down, so it never leaks entities.
|
|||||||
## Configuration overview
|
## Configuration overview
|
||||||
|
|
||||||
- **`config.yml`** — global settings: `ui.*` toggles for scoreboard/bossbar/titles/actionbar,
|
- **`config.yml`** — global settings: `ui.*` toggles for scoreboard/bossbar/titles/actionbar,
|
||||||
`sounds.*` (Bukkit `Sound` enum names; invalid names are logged and skipped, never crash
|
`sounds.*` (Bukkit `Sound` enum names, played directly to each participating player rather
|
||||||
the plugin), `performance.floor-blocks-per-tick` (batch size for floor *generation* and
|
than at one world location, so distance never mutes them; invalid names are logged and
|
||||||
*restoration*, spread across ticks — the round-end removal of non-target blocks is always
|
skipped, never crash the plugin), `performance.floor-blocks-per-tick` (reserved for
|
||||||
instantaneous, all at once, by design),
|
future/optional batched floor operations — round-end removal and each round's floor reset
|
||||||
|
are always instantaneous, all blocks at once, by design),
|
||||||
`defaults.*` (used only when `/bp create` seeds a new arena), `default-floor-materials`
|
`defaults.*` (used only when `/bp create` seeds a new arena), `default-floor-materials`
|
||||||
(the full 16-color concrete palette by default), `rewards.winner.commands`, and
|
(the full 16-color concrete palette by default), `rewards.winner.commands`, and
|
||||||
`integrations.placeholderapi`.
|
`integrations.placeholderapi`.
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ public class Arena {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processRoundEnd() {
|
private void processRoundEnd() {
|
||||||
plugin.getSoundUtil().play(config.getSpawn(), plugin.getConfigManager().getSound("floor-disappear"), 1f, 1f);
|
playToParticipants("floor-disappear");
|
||||||
floorManager.removeNonTarget(currentTarget, plugin.getConfigManager().getFloorBatchBlocksPerTick(), () -> {
|
floorManager.removeNonTarget(currentTarget, plugin.getConfigManager().getFloorBatchBlocksPerTick(), () -> {
|
||||||
BukkitTask delay = plugin.getServer().getScheduler().runTaskLater(plugin, this::evaluateEliminations,
|
BukkitTask delay = plugin.getServer().getScheduler().runTaskLater(plugin, this::evaluateEliminations,
|
||||||
config.getFloorRemoveDelaySeconds() * 20L);
|
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() {
|
private void evaluateEliminations() {
|
||||||
List<EliminationLogic.PlayerFloorState<UUID, Material>> states = new ArrayList<>();
|
List<EliminationLogic.PlayerFloorState<UUID, Material>> states = new ArrayList<>();
|
||||||
for (UUID uuid : players) {
|
for (UUID uuid : players) {
|
||||||
@@ -406,7 +419,10 @@ public class Arena {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BukkitTask restoreDelay = plugin.getServer().getScheduler().runTaskLater(plugin, () ->
|
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);
|
config.getFloorRestoreDelaySeconds() * 20L);
|
||||||
tasks.add(restoreDelay);
|
tasks.add(restoreDelay);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,11 @@ public class FloorManager {
|
|||||||
return new ArrayList<>(layout.values());
|
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) {
|
public void restoreFull(int blocksPerTick, Runnable onComplete) {
|
||||||
World world = config.getWorld();
|
World world = config.getWorld();
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
@@ -99,26 +103,12 @@ public class FloorManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cancelActiveTask();
|
cancelActiveTask();
|
||||||
Deque<Map.Entry<String, Material>> queue = new ArrayDeque<>(layout.entrySet());
|
for (Map.Entry<String, Material> entry : layout.entrySet()) {
|
||||||
org.bukkit.scheduler.BukkitRunnable runnable = new org.bukkit.scheduler.BukkitRunnable() {
|
setBlock(world, entry.getKey(), entry.getValue());
|
||||||
@Override
|
}
|
||||||
public void run() {
|
if (onComplete != null) {
|
||||||
int processed = 0;
|
onComplete.run();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user