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:
@@ -22,33 +22,39 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
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.BoardManager;
|
||||||
import com.volmit.iris.util.board.BoardProvider;
|
import com.volmit.iris.util.board.BoardProvider;
|
||||||
import com.volmit.iris.util.board.BoardSettings;
|
import com.volmit.iris.util.board.BoardSettings;
|
||||||
import com.volmit.iris.util.board.ScoreDirection;
|
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.collection.KMap;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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 {
|
public class BoardSVC implements IrisService, BoardProvider {
|
||||||
private final KMap<Player, PlayerBoard> boards = new KMap<>();
|
private final KMap<Player, PlayerBoard> boards = new KMap<>();
|
||||||
private com.volmit.iris.util.board.BoardManager manager;
|
private ScheduledExecutorService executor;
|
||||||
|
private BoardManager manager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
J.ar(this::tick, 20);
|
executor = Executors.newScheduledThreadPool(0, Thread.ofVirtual().factory());
|
||||||
manager = new BoardManager(Iris.instance, BoardSettings.builder()
|
manager = new BoardManager(Iris.instance, BoardSettings.builder()
|
||||||
.boardProvider(this)
|
.boardProvider(this)
|
||||||
.scoreDirection(ScoreDirection.DOWN)
|
.scoreDirection(ScoreDirection.DOWN)
|
||||||
@@ -57,6 +63,7 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
executor.shutdownNow();
|
||||||
manager.onDisable();
|
manager.onDisable();
|
||||||
boards.clear();
|
boards.clear();
|
||||||
}
|
}
|
||||||
@@ -71,14 +78,22 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
J.s(() -> updatePlayer(e.getPlayer()));
|
J.s(() -> updatePlayer(e.getPlayer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(PlayerQuitEvent e) {
|
||||||
|
remove(e.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
public void updatePlayer(Player p) {
|
public void updatePlayer(Player p) {
|
||||||
if (IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
if (IrisToolbelt.isIrisStudioWorld(p.getWorld())) {
|
||||||
manager.remove(p);
|
manager.remove(p);
|
||||||
manager.setup(p);
|
manager.setup(p);
|
||||||
} else {
|
} else remove(p);
|
||||||
manager.remove(p);
|
}
|
||||||
boards.remove(p);
|
|
||||||
}
|
private void remove(Player player) {
|
||||||
|
manager.remove(player);
|
||||||
|
var board = boards.remove(player);
|
||||||
|
if (board != null) board.task.cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,73 +101,63 @@ public class BoardSVC implements IrisService, BoardProvider {
|
|||||||
return C.GREEN + "Iris";
|
return C.GREEN + "Iris";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick() {
|
|
||||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boards.forEach((k, v) -> v.update());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getLines(Player player) {
|
public List<String> getLines(Player player) {
|
||||||
PlayerBoard pb = boards.computeIfAbsent(player, PlayerBoard::new);
|
return boards.computeIfAbsent(player, PlayerBoard::new).lines;
|
||||||
synchronized (pb.lines) {
|
|
||||||
return pb.lines;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class PlayerBoard {
|
public class PlayerBoard {
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private final CopyOnWriteArrayList<String> lines;
|
private final ScheduledFuture<?> task;
|
||||||
|
private volatile List<String> lines;
|
||||||
|
|
||||||
public PlayerBoard(Player player) {
|
public PlayerBoard(Player player) {
|
||||||
this.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();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
synchronized (lines) {
|
final World world = player.getWorld();
|
||||||
lines.clear();
|
final Location loc = player.getLocation();
|
||||||
|
|
||||||
if (!IrisToolbelt.isIrisStudioWorld(player.getWorld())) {
|
final var access = IrisToolbelt.access(world);
|
||||||
return;
|
if (access == null) return;
|
||||||
}
|
|
||||||
|
|
||||||
Engine engine = IrisToolbelt.access(player.getWorld()).getEngine();
|
final var engine = access.getEngine();
|
||||||
int x = player.getLocation().getBlockX();
|
if (engine == null) return;
|
||||||
int y = player.getLocation().getBlockY() - player.getWorld().getMinHeight();
|
|
||||||
int z = player.getLocation().getBlockZ();
|
|
||||||
|
|
||||||
if(IrisSettings.get().getGeneral().debug){
|
int x = loc.getBlockX();
|
||||||
lines.add("&7&m ");
|
int y = loc.getBlockY() - world.getMinHeight();
|
||||||
lines.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
|
int z = loc.getBlockZ();
|
||||||
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
|
||||||
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
List<String> lines = new ArrayList<>(this.lines.size());
|
||||||
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
lines.add("&7&m ");
|
||||||
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 + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
|
lines.add(C.AQUA + "Cache" + C.GRAY + ": " + Form.f(IrisData.cacheSize()));
|
||||||
lines.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiomeOrMantle(x, y, z).getName());
|
lines.add(C.AQUA + "Mantle" + C.GRAY + ": " + engine.getMantle().getLoadedRegionCount());
|
||||||
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));
|
if (IrisSettings.get().getGeneral().debug) {
|
||||||
lines.add(C.AQUA + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond()));
|
lines.add(C.LIGHT_PURPLE + "Carving" + C.GRAY + ": " + engine.getMantle().isCarved(x,y,z));
|
||||||
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 ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,11 @@ import lombok.NonNull;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scoreboard.DisplaySlot;
|
import org.bukkit.scoreboard.*;
|
||||||
import org.bukkit.scoreboard.Objective;
|
|
||||||
import org.bukkit.scoreboard.Scoreboard;
|
|
||||||
import org.bukkit.scoreboard.Team;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.UnaryOperator;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.IntStream;
|
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 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 {
|
static {
|
||||||
IntStream.range(0, 15).forEach(i -> CACHED_ENTRIES[i] = C.values()[i].toString() + C.RESET);
|
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 BoardSettings boardSettings;
|
||||||
private boolean ready;
|
private boolean ready;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public Board(@NonNull final Player player, final BoardSettings boardSettings) {
|
public Board(@NonNull final Player player, final BoardSettings boardSettings) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.boardSettings = boardSettings;
|
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);
|
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.setAllowFriendlyFire(true);
|
||||||
team.setCanSeeFriendlyInvisibles(false);
|
team.setCanSeeFriendlyInvisibles(false);
|
||||||
team.setPrefix("");
|
team.setPrefix("");
|
||||||
@@ -94,7 +91,8 @@ public class Board {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getting their Scoreboard display from the Scoreboard Provider.
|
// 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) {
|
if (boardSettings.getScoreDirection() == ScoreDirection.UP) {
|
||||||
Collections.reverse(entries);
|
Collections.reverse(entries);
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ public class BoardUpdateTask extends BukkitRunnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user