9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-19 15:09:18 +00:00

use scheduled thread pool for scoreboard svc to prevent freezes

This commit is contained in:
Julian Krings
2025-09-20 15:27:49 +02:00
parent 7c41f86fb3
commit a7d874d37f
3 changed files with 80 additions and 71 deletions

View File

@@ -22,33 +22,39 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.board.BoardManager;
import com.volmit.iris.util.board.BoardProvider;
import com.volmit.iris.util.board.BoardSettings;
import com.volmit.iris.util.board.ScoreDirection;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.scheduling.J;
import lombok.Data;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class BoardSVC implements IrisService, BoardProvider {
private final KMap<Player, PlayerBoard> boards = new KMap<>();
private com.volmit.iris.util.board.BoardManager manager;
private ScheduledExecutorService executor;
private BoardManager manager;
@Override
public void onEnable() {
J.ar(this::tick, 20);
executor = Executors.newScheduledThreadPool(0, Thread.ofVirtual().factory());
manager = new BoardManager(Iris.instance, BoardSettings.builder()
.boardProvider(this)
.scoreDirection(ScoreDirection.DOWN)
@@ -57,6 +63,7 @@ public class BoardSVC implements IrisService, BoardProvider {
@Override
public void onDisable() {
executor.shutdownNow();
manager.onDisable();
boards.clear();
}
@@ -71,14 +78,22 @@ public class BoardSVC implements IrisService, BoardProvider {
J.s(() -> updatePlayer(e.getPlayer()));
}
@EventHandler
public void on(PlayerQuitEvent e) {
remove(e.getPlayer());
}
public void updatePlayer(Player p) {
if (IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
manager.remove(p);
manager.setup(p);
} else {
manager.remove(p);
boards.remove(p);
}
} else remove(p);
}
private void remove(Player player) {
manager.remove(player);
var board = boards.remove(player);
if (board != null) board.task.cancel(true);
}
@Override
@@ -86,73 +101,63 @@ public class BoardSVC implements IrisService, BoardProvider {
return C.GREEN + "Iris";
}
public void tick() {
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
return;
}
boards.forEach((k, v) -> v.update());
}
@Override
public List<String> getLines(Player player) {
PlayerBoard pb = boards.computeIfAbsent(player, PlayerBoard::new);
synchronized (pb.lines) {
return pb.lines;
}
return boards.computeIfAbsent(player, PlayerBoard::new).lines;
}
@Data
public static class PlayerBoard {
public class PlayerBoard {
private final Player player;
private final CopyOnWriteArrayList<String> lines;
private final ScheduledFuture<?> task;
private volatile List<String> lines;
public PlayerBoard(Player player) {
this.player = player;
this.lines = new CopyOnWriteArrayList<>();
this.lines = new ArrayList<>();
this.task = executor.scheduleAtFixedRate(this::tick, 0, 1, TimeUnit.SECONDS);
}
private void tick() {
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
return;
}
update();
}
public void update() {
synchronized (lines) {
lines.clear();
final World world = player.getWorld();
final Location loc = player.getLocation();
if (!IrisToolbelt.isIrisStudioWorld(player.getWorld())) {
return;
}
final var access = IrisToolbelt.access(world);
if (access == null) return;
Engine engine = IrisToolbelt.access(player.getWorld()).getEngine();
int x = player.getLocation().getBlockX();
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
int z = player.getLocation().getBlockZ();
final var engine = access.getEngine();
if (engine == null) return;
if(IrisSettings.get().getGeneral().debug){
lines.add("&7&m ");
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
lines.add("&7&m ");
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
lines.add("&7&m ");
} else {
lines.add("&7&m ");
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
lines.add("&7&m ");
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
lines.add("&7&m ");
}
int x = loc.getBlockX();
int y = loc.getBlockY() - world.getMinHeight();
int z = loc.getBlockZ();
List<String> lines = new ArrayList<>(this.lines.size());
lines.add("&7&m ");
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
if (IrisSettings.get().getGeneral().debug) {
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
}
lines.add("&7&m ");
lines.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
lines.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
lines.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getComplex().getSlopeStream().get(x, z), 2));
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
lines.add("&7&m ");
this.lines = lines;
}
}
}

View File

@@ -23,15 +23,11 @@ import lombok.NonNull;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
import org.bukkit.scoreboard.*;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
/**
@@ -42,7 +38,7 @@ public class Board {
private static final String[] CACHED_ENTRIES = new String[C.values().length];
private static final Function<String, String> APPLY_COLOR_TRANSLATION = s -> C.translateAlternateColorCodes('&', s);
private static final UnaryOperator<String> APPLY_COLOR_TRANSLATION = s -> C.translateAlternateColorCodes('&', s);
static {
IntStream.range(0, 15).forEach(i -> CACHED_ENTRIES[i] = C.values()[i].toString() + C.RESET);
@@ -54,13 +50,14 @@ public class Board {
private BoardSettings boardSettings;
private boolean ready;
@SuppressWarnings("deprecation")
public Board(@NonNull final Player player, final BoardSettings boardSettings) {
this.player = player;
this.boardSettings = boardSettings;
this.objective = this.getScoreboard().getObjective("board") == null ? this.getScoreboard().registerNewObjective("board", "dummy") : this.getScoreboard().getObjective("board");
var obj = getScoreboard().getObjective("board");
this.objective = obj == null ? this.getScoreboard().registerNewObjective("board", Criteria.DUMMY, "Iris") : obj;
this.objective.setDisplaySlot(DisplaySlot.SIDEBAR);
Team team = this.getScoreboard().getTeam("board") == null ? this.getScoreboard().registerNewTeam("board") : this.getScoreboard().getTeam("board");
Team team = getScoreboard().getTeam("board");
team = team == null ? getScoreboard().registerNewTeam("board") : team;
team.setAllowFriendlyFire(true);
team.setCanSeeFriendlyInvisibles(false);
team.setPrefix("");
@@ -94,7 +91,8 @@ public class Board {
}
// Getting their Scoreboard display from the Scoreboard Provider.
final List<String> entries = boardSettings.getBoardProvider().getLines(player).stream().map(APPLY_COLOR_TRANSLATION).collect(Collectors.toList());
final List<String> entries = boardSettings.getBoardProvider().getLines(player);
entries.replaceAll(APPLY_COLOR_TRANSLATION);
if (boardSettings.getScoreDirection() == ScoreDirection.UP) {
Collections.reverse(entries);

View File

@@ -38,6 +38,12 @@ public class BoardUpdateTask extends BukkitRunnable {
@Override
public void run() {
boardManager.getScoreboards().entrySet().stream().filter(entrySet -> PLAYER_IS_ONLINE.test(entrySet.getKey())).forEach(entrySet -> entrySet.getValue().update());
for (var entry : boardManager.getScoreboards().entrySet()) {
if (!PLAYER_IS_ONLINE.test(entry.getKey())) {
continue;
}
entry.getValue().update();
}
}
}