Compare commits
4 commits
529a61ecbb
...
d8c392c5af
Author | SHA1 | Date | |
---|---|---|---|
d8c392c5af | |||
f05457fb8a | |||
e0a217eb68 | |||
e957f88883 |
12 changed files with 172 additions and 111 deletions
17
README.md
17
README.md
|
@ -53,19 +53,4 @@ Sleeping doesn't skip night, but speeds it up. The more players, the faster it g
|
|||
### Instant sleep
|
||||
One can instantly skip, but only a part of the night. \
|
||||
There's 5 players on the server. A night is 10 minutes long. \
|
||||
Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping
|
||||
|
||||
# Commands
|
||||
### /chat
|
||||
Changes chatroom
|
||||
|
||||
### /chatmanage
|
||||
`tweaks724.chatmanage` \
|
||||
Manages chatroom, like create, delete etc.
|
||||
|
||||
### /ping
|
||||
Displays your ping. **Ping is calculated by the plugin.**
|
||||
|
||||
### /pomodoro
|
||||
`tweaks724.pomodoro` \
|
||||
Manage your pomodoro. `/pom start` to start, `stop` to stop, no arguments to forward
|
||||
Each player can instantly skip 2 minutes of the night at any time, even if others aren't sleeping
|
|
@ -10,6 +10,8 @@ import org.bukkit.configuration.file.FileConfiguration;
|
|||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public record TweaksConfig(
|
||||
boolean isProtocolLib,
|
||||
|
||||
boolean worldborderHide,
|
||||
|
||||
boolean brandEnabled,
|
||||
|
@ -54,6 +56,8 @@ public record TweaksConfig(
|
|||
plugin.saveDefaultConfig();
|
||||
FileConfiguration config = plugin.getConfig();
|
||||
|
||||
boolean isProtocolLib = plugin.getServer().getPluginManager().getPlugin("ProtocolLib") != null;
|
||||
|
||||
int configVersion = config.getInt("magic number don't modify this", 0);
|
||||
RuntimeException exception = new RuntimeException("Config version is %d, expected %d".formatted(configVersion, CONFIG_VERSION));
|
||||
if (configVersion == 0) {
|
||||
|
@ -98,6 +102,7 @@ public record TweaksConfig(
|
|||
boolean sleepInstant = config.getBoolean("sleep.instant");
|
||||
|
||||
TweaksConfig.config = new TweaksConfig(
|
||||
isProtocolLib,
|
||||
hideWorldBorder,
|
||||
brandEnabled, brandText, brandShowPing, brandShowMspt,
|
||||
doorEnabled, doorDoubleOpen, doorKnocking,
|
||||
|
|
|
@ -52,6 +52,7 @@ public class TweaksPlugin extends JavaPlugin {
|
|||
|
||||
new PingChecker(this).init();
|
||||
Objects.requireNonNull(getCommand("ping")).setExecutor(new PingCommands());
|
||||
Objects.requireNonNull(getCommand("dkick")).setExecutor(new PingCommands());
|
||||
|
||||
/*if (getServer().getPluginManager().getPlugin("voicechat") != null) {
|
||||
new MusicPlayer(this).init();
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2024 Minecon724
|
||||
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
||||
* in the project root for the full license text.
|
||||
*/
|
||||
|
||||
package eu.m724.tweaks.ping;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class CookiePingChecker extends BukkitRunnable {
|
||||
private final Plugin plugin;
|
||||
|
||||
private final NamespacedKey namespacedKey = NamespacedKey.fromString("chk_ping");
|
||||
|
||||
CookiePingChecker(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.runTaskTimerAsynchronously(plugin, 0, 40); // 2 secs
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
plugin.getServer().getOnlinePlayers().forEach(player -> {
|
||||
long start = System.nanoTime();
|
||||
player.retrieveCookie(namespacedKey).thenAccept(v -> {
|
||||
PlayerPingStorage.submitPing(player, System.nanoTime() - start);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -78,14 +78,14 @@ public class F3NameListener {
|
|||
String sep = text.isEmpty() ? "" : " | ";
|
||||
|
||||
if (showMspt) {
|
||||
double mspt = PlayerPingStorage.getMillisPerTick();
|
||||
double mspt = PlayerPing.getMillisPerTick();
|
||||
if (mspt > 50.05) { // mspt is at least like 50.01 because of some measuring overheads (I think)
|
||||
_text += sep + "%.2f mspt".formatted(mspt);
|
||||
}
|
||||
}
|
||||
|
||||
if (showPing) {
|
||||
_text += sep + "%.2f ms".formatted(PlayerPingStorage.getPingMillis(player));
|
||||
_text += sep + "%.2f ms".formatted(PlayerPing.getPingMillis(player));
|
||||
}
|
||||
|
||||
return _text;
|
||||
|
|
|
@ -15,7 +15,7 @@ public class MsptChecker extends BukkitRunnable {
|
|||
@Override
|
||||
public void run() {
|
||||
long now = System.nanoTime();
|
||||
PlayerPingStorage.submitNspt((now - lastLoop) / 100);
|
||||
PlayerPing.nspt = (now - lastLoop) / 100;
|
||||
lastLoop = now;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
package eu.m724.tweaks.ping;
|
||||
|
||||
import eu.m724.tweaks.TweaksConfig;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class PingChecker {
|
||||
|
@ -16,7 +17,14 @@ public class PingChecker {
|
|||
}
|
||||
|
||||
public void init() {
|
||||
new CookiePingChecker(plugin).start();
|
||||
|
||||
if (TweaksConfig.getConfig().isProtocolLib()) {
|
||||
plugin.getLogger().info("Using ProtocolLib for checking ping");
|
||||
new ProtocolPingChecker(plugin).start();
|
||||
} else {
|
||||
plugin.getLogger().info("Using Spigot for checking ping");
|
||||
}
|
||||
|
||||
new MsptChecker().init(plugin); // TODO should this be here
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
|
||||
package eu.m724.tweaks.ping;
|
||||
|
||||
import eu.m724.tweaks.TweaksConfig;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -21,9 +23,33 @@ public class PingCommands implements CommandExecutor {
|
|||
if (command.getName().equals("ping")) {
|
||||
Player player = (Player) sender;
|
||||
BaseComponent[] component = new ComponentBuilder("Ping: ").color(ChatColor.GOLD)
|
||||
.append("%.2fms".formatted(PlayerPingStorage.getPingMillis(player))).color(ChatColor.AQUA)
|
||||
.append("%.2fms".formatted(PlayerPing.getPingMillis(player))).color(ChatColor.AQUA)
|
||||
.create();
|
||||
player.spigot().sendMessage(component);
|
||||
} else if (command.getName().equals("dkick")) {
|
||||
if (!TweaksConfig.getConfig().isProtocolLib()) {
|
||||
sender.sendMessage("This feature is not available");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage("Include one or more player names");
|
||||
} else {
|
||||
for (String name : args) {
|
||||
Player player = Bukkit.getPlayer(name);
|
||||
if (player == null) {
|
||||
sender.sendMessage("Player %s is not online".formatted(name));
|
||||
}
|
||||
if (PlayerPing.kick(player)) {
|
||||
if (player.getName().equals(sender.getName())) {
|
||||
sender.sendMessage("Kicking yourself? Very well");
|
||||
}
|
||||
sender.sendMessage("Player %s will be kicked shortly".formatted(name));
|
||||
} else {
|
||||
sender.sendMessage("Player %s is already queued".formatted(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
51
src/main/java/eu/m724/tweaks/ping/PlayerPing.java
Normal file
51
src/main/java/eu/m724/tweaks/ping/PlayerPing.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2024 Minecon724
|
||||
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
||||
* in the project root for the full license text.
|
||||
*/
|
||||
|
||||
package eu.m724.tweaks.ping;
|
||||
|
||||
import eu.m724.tweaks.TweaksConfig;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class PlayerPing {
|
||||
// if protocol lib is installed we use our own checker
|
||||
private static final boolean external = TweaksConfig.getConfig().isProtocolLib();
|
||||
|
||||
// TODO remove this feature because why
|
||||
static final Set<Player> kickQueue = ConcurrentHashMap.newKeySet();
|
||||
|
||||
// current player latencies, in nanos
|
||||
static final Map<Player, Long> pings = new ConcurrentHashMap<>();
|
||||
// nanoseconds per tick
|
||||
static volatile long nspt = 0L;
|
||||
|
||||
public static long getPingNanos(Player player) {
|
||||
if (!external) {
|
||||
return (long) player.getPing() * 1000000;
|
||||
} else {
|
||||
return pings.getOrDefault(player, -1L);
|
||||
}
|
||||
}
|
||||
|
||||
public static double getPingMillis(Player player) {
|
||||
return getPingNanos(player) / 1000000.0; // a mil ns in ms
|
||||
}
|
||||
|
||||
public static long getNanosPerTick() {
|
||||
return nspt;
|
||||
}
|
||||
|
||||
public static double getMillisPerTick() {
|
||||
return nspt / 1000000.0; // a mil ns in ms
|
||||
}
|
||||
|
||||
public static boolean kick(Player player) {
|
||||
return kickQueue.add(player);
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2024 Minecon724
|
||||
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
||||
* in the project root for the full license text.
|
||||
*/
|
||||
|
||||
package eu.m724.tweaks.ping;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class PlayerPingStorage {
|
||||
// current player latencies, in queue of nanos
|
||||
private static final Map<Player, Long> pings = new ConcurrentHashMap<>();
|
||||
private static final Map<Player, Integer> pingsCount = new ConcurrentHashMap<>();
|
||||
|
||||
// nanoseconds per tick
|
||||
private static volatile long nspt = 0L;
|
||||
|
||||
public static long getPingNanos(Player player) {
|
||||
return pings.getOrDefault(player, 0L);
|
||||
}
|
||||
|
||||
public static double getPingMillis(Player player) {
|
||||
return getPingNanos(player) / 1000000.0; // a mil ns in ms
|
||||
}
|
||||
|
||||
public static long getNanosPerTick() {
|
||||
return nspt;
|
||||
}
|
||||
|
||||
public static double getMillisPerTick() {
|
||||
return nspt / 1000000.0; // a mil ns in ms
|
||||
}
|
||||
|
||||
static void submitPing(Player player, long currentPing) {
|
||||
int count = pingsCount.getOrDefault(player, 0);
|
||||
long average = pings.getOrDefault(player, 0L);
|
||||
|
||||
if (count < 5) {
|
||||
average = ((average * count) + currentPing) / (count + 1);
|
||||
pingsCount.put(player, count + 1);
|
||||
} else {
|
||||
average += (currentPing - average) / 5;
|
||||
}
|
||||
|
||||
pings.put(player, average);
|
||||
}
|
||||
|
||||
static void submitNspt(long currentNspt) {
|
||||
nspt = currentNspt;
|
||||
}
|
||||
}
|
72
src/main/java/eu/m724/tweaks/ping/ProtocolPingChecker.java
Normal file
72
src/main/java/eu/m724/tweaks/ping/ProtocolPingChecker.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2024 Minecon724
|
||||
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
||||
* in the project root for the full license text.
|
||||
*/
|
||||
|
||||
package eu.m724.tweaks.ping;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.wrappers.MinecraftKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ProtocolPingChecker extends BukkitRunnable {
|
||||
// this is in nanoseconds
|
||||
private final Map<Player, Long> pending = new ConcurrentHashMap<>();
|
||||
private final Plugin plugin;
|
||||
|
||||
ProtocolPingChecker(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
|
||||
plugin,
|
||||
ListenerPriority.NORMAL,
|
||||
PacketType.Play.Client.COOKIE_RESPONSE
|
||||
) {
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent event) {
|
||||
// below line checks, whether the first (and sole) identifier field in the packet is minecraft:chk_ping
|
||||
if (event.getPacket().getMinecraftKeys().read(0).getKey().equals("chk_ping")) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
long start = pending.remove(player);
|
||||
PlayerPing.pings.put(player, System.nanoTime() - start);
|
||||
|
||||
// gotta cancel because the server will kick
|
||||
if (!PlayerPing.kickQueue.contains(player)) {
|
||||
event.setCancelled(true);
|
||||
} else {
|
||||
PlayerPing.kickQueue.remove(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.runTaskTimerAsynchronously(plugin, 0, 200); // 10 secs
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
plugin.getServer().getOnlinePlayers().forEach(player -> {
|
||||
// dropped packets happen so timing out a request after 30 seconds
|
||||
if (System.nanoTime() - pending.getOrDefault(player, 0L) < 30000000000L) return;
|
||||
pending.put(player, System.nanoTime()); // here or at the bottom? probably doesn't matter
|
||||
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.COOKIE_REQUEST);
|
||||
packet.getMinecraftKeys().write(0, new MinecraftKey("chk_ping"));
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -19,6 +19,9 @@ commands:
|
|||
aliases: [cm, crm]
|
||||
ping:
|
||||
description: Your ping
|
||||
dkick:
|
||||
description: Kick a player discreetly
|
||||
permission: tweaks724.dkick
|
||||
pomodoro:
|
||||
description: Pomodoro management
|
||||
permission: tweaks724.pomodoro
|
||||
|
|
Loading…
Reference in a new issue