From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Wed, 31 Jul 2024 12:05:39 +0800 Subject: [PATCH] Add a simple tpsbar diff --git a/src/main/java/me/earthme/luminol/commands/TpsBarCommand.java b/src/main/java/me/earthme/luminol/commands/TpsBarCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..01677f210fae53a108bfe194189cb4c233e9fa47 --- /dev/null +++ b/src/main/java/me/earthme/luminol/commands/TpsBarCommand.java @@ -0,0 +1,50 @@ +package me.earthme.luminol.commands; + +import me.earthme.luminol.config.modules.misc.TpsBarConfig; +import me.earthme.luminol.functions.GlobalServerTpsBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.util.RGBLike; +import org.bukkit.ChatColor; +import org.bukkit.Color; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class TpsBarCommand extends Command { + public TpsBarCommand(@NotNull String name) { + super(name); + this.setPermission("luminol.commands.tpsbar"); + this.setDescription("Show the tps and mspt through a bossbar"); + this.setUsage("/tpsbar"); + } + + @Override + public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args) { + if (!testPermission(sender)){ + return true; + } + + if (!TpsBarConfig.tpsbarEnabled){ + sender.sendMessage(Component.text("Tpsbar was already disabled!").color(TextColor.color(255,0,0))); + return true; + } + + if (!(sender instanceof Player player)){ + sender.sendMessage(Component.text("Only player can use this command!").color(TextColor.color(255,0,0))); + return true; + } + + if (GlobalServerTpsBar.isPlayerVisible(player)) { + player.sendMessage(Component.text("Disabled tps bar").color(TextColor.color(0,255,0))); + GlobalServerTpsBar.setVisibilityForPlayer(player,false); + return true; + } + + player.sendMessage(Component.text("Enabled tps bar").color(TextColor.color(0,255,0))); + GlobalServerTpsBar.setVisibilityForPlayer(player,true); + + return true; + } +} diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..aafb2f5052c7c8e5971a47308253badb3027093c --- /dev/null +++ b/src/main/java/me/earthme/luminol/config/modules/misc/TpsBarConfig.java @@ -0,0 +1,49 @@ +package me.earthme.luminol.config.modules.misc; + +import com.electronwill.nightconfig.core.file.CommentedFileConfig; +import me.earthme.luminol.commands.TpsBarCommand; +import me.earthme.luminol.config.*; +import me.earthme.luminol.functions.GlobalServerTpsBar; +import org.bukkit.Bukkit; + +import java.util.List; + +public class TpsBarConfig implements IConfigModule { + @ConfigInfo(baseName = "enabled") + public static boolean tpsbarEnabled = false; + @ConfigInfo(baseName = "format") + public static String tpsBarFormat = "TPS: MSPT: Ping: ms"; + @ConfigInfo(baseName = "tps_color_list") + public static List tpsColors = List.of("GREEN","YELLOW","RED","PURPLE"); + @ConfigInfo(baseName = "ping_color_list") + public static List pingColors = List.of("GREEN","YELLOW","RED","PURPLE"); + @ConfigInfo(baseName = "update_interval_ticks") + public static int updateInterval = 15; + + @DoNotLoad + private static boolean inited = false; + + @Override + public EnumConfigCategory getCategory() { + return EnumConfigCategory.MISC; + } + + @Override + public String getBaseName() { + return "tpsbar"; + } + + @Override + public void onLoaded(CommentedFileConfig configInstance){ + if (tpsbarEnabled){ + GlobalServerTpsBar.init(); + }else{ + GlobalServerTpsBar.cancelBarUpdateTask(); + } + + if (!inited){ + Bukkit.getCommandMap().register("tpsbar","luminol",new TpsBarCommand("tpsbar")); + inited = true; + } + } +} diff --git a/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java new file mode 100644 index 0000000000000000000000000000000000000000..de2f03d6e771c09e8da2da454b7ec4a16c0a17ab --- /dev/null +++ b/src/main/java/me/earthme/luminol/functions/GlobalServerTpsBar.java @@ -0,0 +1,214 @@ +package me.earthme.luminol.functions; + +import com.google.common.collect.Maps; +import com.mojang.logging.LogUtils; +import io.papermc.paper.threadedregions.ThreadedRegionizer; +import io.papermc.paper.threadedregions.TickData; +import io.papermc.paper.threadedregions.TickRegionScheduler; +import io.papermc.paper.threadedregions.TickRegions; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import me.earthme.luminol.config.modules.misc.TpsBarConfig; +import me.earthme.luminol.utils.NullPlugin; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; + +import java.util.*; + +public class GlobalServerTpsBar { + protected static final NullPlugin NULL_PLUGIN = new NullPlugin(); + protected static final Map uuid2Bossbars = Maps.newConcurrentMap(); + protected static final Map scheduledTasks = new HashMap<>(); + + protected static volatile ScheduledTask scannerTask = null; + private static final Logger logger = LogUtils.getLogger(); + + public static void init(){ + cancelBarUpdateTask(); + + scannerTask = Bukkit.getGlobalRegionScheduler().runAtFixedRate(NULL_PLUGIN, unused -> { + try { + update(); + cleanUp(); + }catch (Exception e){ + logger.error(e.getLocalizedMessage()); + } + }, 1, TpsBarConfig.updateInterval); + } + + public static void cancelBarUpdateTask(){ + if (scannerTask == null || scannerTask.isCancelled()){ + return; + } + + scannerTask.cancel(); + + for (ScheduledTask task : scheduledTasks.values()) { + if (!task.isCancelled()) { + task.cancel(); + } + } + } + + public static boolean isPlayerVisible(Player player){ + return ((CraftPlayer) player).getHandle().isTpsBarVisible; + } + + public static void setVisibilityForPlayer(Player target,boolean canSee){ + ((CraftPlayer) target).getHandle().isTpsBarVisible = canSee; + } + + private static void update(){ + for (Player player : Bukkit.getOnlinePlayers()) { + scheduledTasks.computeIfAbsent(player.getUniqueId(), unused -> createBossBarForPlayer(player)); + } + } + + private static void cleanUp() { + final List toCleanUp = new ArrayList<>(); + + for (Map.Entry toCheck : scheduledTasks.entrySet()) { + if (toCheck.getValue().isCancelled()) { + toCleanUp.add(toCheck.getKey()); + } + } + + for (UUID uuid : toCleanUp) { + scheduledTasks.remove(uuid); + } + } + + public static ScheduledTask createBossBarForPlayer(@NotNull Player apiPlayer) { + final UUID playerUUID = apiPlayer.getUniqueId(); + + return apiPlayer.getScheduler().runAtFixedRate(NULL_PLUGIN, (n) -> { + if (!isPlayerVisible(apiPlayer)) { + final BossBar removed = uuid2Bossbars.remove(playerUUID); + + if (removed != null) { + apiPlayer.hideBossBar(removed); + } + return; + } + + final ThreadedRegionizer.ThreadedRegion region = TickRegionScheduler.getCurrentRegion(); + final TickData.TickReportData reportData = region.getData().getRegionSchedulingHandle().getTickReport5s(System.nanoTime()); + + + BossBar targetBossbar = uuid2Bossbars.computeIfAbsent( + playerUUID, + unused -> BossBar.bossBar(Component.text(""),0.0F, BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(3)), BossBar.Overlay.NOTCHED_20) + ); + + apiPlayer.showBossBar(targetBossbar); + + if (reportData != null){ + final TickData.SegmentData tpsData = reportData.tpsData().segmentAll(); + final double mspt = reportData.timePerTickData().segmentAll().average() / 1.0E6; + + updateTpsBar(tpsData.average(), mspt, targetBossbar, apiPlayer); + } + }, () -> { + final BossBar removed = uuid2Bossbars.remove(playerUUID); // Auto clean up it + + if (removed != null) { + apiPlayer.hideBossBar(removed); + } + }, 1, TpsBarConfig.updateInterval); + } + + private static void updateTpsBar(double tps, double mspt, @NotNull BossBar bar, @NotNull Player player){ + bar.name(MiniMessage.miniMessage().deserialize( + TpsBarConfig.tpsBarFormat, + Placeholder.component("tps",getTpsComponent(tps)), + Placeholder.component("mspt",getMsptComponent(mspt)), + Placeholder.component("ping",getPingComponent(player.getPing())) + )); + bar.color(barColorFromTps(tps)); + bar.progress((float) Math.min((float)1,Math.max(mspt / 50,0))); + } + + private static @NotNull Component getPingComponent(int ping){ + final BossBar.Color colorBukkit = barColorFromPing(ping); + final String colorString = colorBukkit.name(); + + final String content = "<%s>"; + final String replaced = String.format(content,colorString,colorString); + + return MiniMessage.miniMessage().deserialize(replaced,Placeholder.parsed("text", String.valueOf(ping))); + } + + private static BossBar.Color barColorFromPing(int ping){ + if (ping == -1){ + return BossBar.Color.valueOf(TpsBarConfig.pingColors.get(3)); + } + + if (ping <= 80){ + return BossBar.Color.valueOf(TpsBarConfig.pingColors.get(0)); + } + + if (ping <= 160){ + return BossBar.Color.valueOf(TpsBarConfig.pingColors.get(1)); + } + + return BossBar.Color.valueOf(TpsBarConfig.pingColors.get(2)); + } + + private static @NotNull Component getMsptComponent(double mspt){ + final BossBar.Color colorBukkit = barColorFromMspt(mspt); + final String colorString = colorBukkit.name(); + + final String content = "<%s>"; + final String replaced = String.format(content,colorString,colorString); + + return MiniMessage.miniMessage().deserialize(replaced,Placeholder.parsed("text", String.format("%.2f", mspt))); + } + + private static BossBar.Color barColorFromMspt(double mspt){ + if (mspt == -1){ + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(3)); + } + + if (mspt <= 25){ + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(0)); + } + + if (mspt <= 50){ + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(1)); + } + + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(2)); + } + + private static @NotNull Component getTpsComponent(double tps){ + final BossBar.Color colorBukkit = barColorFromTps(tps); + final String colorString = colorBukkit.name(); + + final String content = "<%s>"; + final String replaced = String.format(content,colorString,colorString); + + return MiniMessage.miniMessage().deserialize(replaced,Placeholder.parsed("text", String.format("%.2f", tps))); + } + + private static BossBar.Color barColorFromTps(double tps){ + if (tps == -1){ + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(3)); + } + + if (tps >= 18){ + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(0)); + } + + if (tps >= 15){ + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(1)); + } + + return BossBar.Color.valueOf(TpsBarConfig.tpsColors.get(2)); + } +} diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java index e3c8deea68ef49bcd07359e243a12afb57cbcf52..279bc6eede3a1ae77b810f0553efe36adeeefaa4 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -802,6 +802,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @Override public void stopServer() { + me.earthme.luminol.functions.GlobalServerTpsBar.cancelBarUpdateTask(); //Luminol - Tpsbar super.stopServer(); //Util.shutdownExecutors(); // Paper - moved into super SkullBlockEntity.clear(); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index 23f852ede94bce4d000c8fcaa8fba5d4800b533c..0752d13febc5f1831ae58f7216fba89e1290c780 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -327,7 +327,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple public com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent public @Nullable String clientBrandName = null; // Paper - Brand support public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event - + public volatile boolean isTpsBarVisible = false; //Luminol - Tps bar // Paper start - rewrite chunk system private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader; private final ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder viewDistanceHolder = new ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.ViewDistanceHolder(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index b0e93050839ce00b057e3a9bf3bdf8dd5e0662cf..c39e9ea1ce46864623a6d15027ce337611e6b712 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -2414,6 +2414,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { handle.expToDrop = data.getInt("expToDrop"); handle.keepLevel = data.getBoolean("keepLevel"); } + //Luminol start - Tpsbar + getHandle().isTpsBarVisible = data.getBoolean("tpsbarVisible"); + //Luminol end } } @@ -2435,6 +2438,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { data.putLong("lastPlayed", System.currentTimeMillis()); data.putString("lastKnownName", handle.getScoreboardName()); + //Luminol start - Tpsbar + data.putBoolean("tpsbarVisible",handle.isTpsBarVisible); + //Luminol end // Paper start - persist for use in offline save data if (!nbttagcompound.contains("Paper")) { nbttagcompound.put("Paper", new CompoundTag());