added networking statistics, refactored aggregates back to appliances
This commit is contained in:
parent
eb2c0505f5
commit
c01ae32f1f
@ -1,6 +1,6 @@
|
|||||||
package eu.mhsl.craftattack.spawn;
|
package eu.mhsl.craftattack.spawn;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.aggregates.displayName.DisplayName;
|
import eu.mhsl.craftattack.spawn.appliances.displayName.DisplayName;
|
||||||
import eu.mhsl.craftattack.spawn.api.HttpServer;
|
import eu.mhsl.craftattack.spawn.api.HttpServer;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
|
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package eu.mhsl.craftattack.spawn.aggregate;
|
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.Main;
|
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
|
||||||
|
|
||||||
public abstract class Aggregate extends Appliance {
|
|
||||||
public <T extends Appliance> T queryAppliance(Class<T> clazz) {
|
|
||||||
return Main.instance().getAppliance(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliance;
|
package eu.mhsl.craftattack.spawn.appliance;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
import eu.mhsl.craftattack.spawn.api.HttpServer;
|
import eu.mhsl.craftattack.spawn.api.HttpServer;
|
||||||
import eu.mhsl.craftattack.spawn.config.Configuration;
|
import eu.mhsl.craftattack.spawn.config.Configuration;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -78,6 +79,10 @@ public abstract class Appliance {
|
|||||||
eventHandlers().forEach(HandlerList::unregisterAll);
|
eventHandlers().forEach(HandlerList::unregisterAll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T extends Appliance> T queryAppliance(Class<T> clazz) {
|
||||||
|
return Main.instance().getAppliance(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
private void setCommandExecutor(JavaPlugin plugin, String name, ApplianceCommand<?> executor) {
|
private void setCommandExecutor(JavaPlugin plugin, String name, ApplianceCommand<?> executor) {
|
||||||
PluginCommand command = plugin.getCommand(name);
|
PluginCommand command = plugin.getCommand(name);
|
||||||
if(command != null && executor != null) {
|
if(command != null && executor != null) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eu.mhsl.craftattack.spawn.aggregates.displayName;
|
package eu.mhsl.craftattack.spawn.appliances.displayName;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.aggregate.Aggregate;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
|
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarkerListener;
|
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarkerListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
|
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
|
||||||
@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class DisplayName extends Aggregate {
|
public class DisplayName extends Appliance {
|
||||||
public void update(Player player) {
|
public void update(Player player) {
|
||||||
TextColor playerColor = queryAppliance(AdminMarker.class).getPlayerColor(player);
|
TextColor playerColor = queryAppliance(AdminMarker.class).getPlayerColor(player);
|
||||||
List<Supplier<Component>> prefixes = List.of(
|
List<Supplier<Component>> prefixes = List.of(
|
@ -1,4 +1,4 @@
|
|||||||
package eu.mhsl.craftattack.spawn.aggregates.displayName;
|
package eu.mhsl.craftattack.spawn.appliances.displayName;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
@ -1,7 +1,7 @@
|
|||||||
package eu.mhsl.craftattack.spawn.appliances.outlawed;
|
package eu.mhsl.craftattack.spawn.appliances.outlawed;
|
||||||
|
|
||||||
import eu.mhsl.craftattack.spawn.Main;
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
import eu.mhsl.craftattack.spawn.aggregates.displayName.DisplayName;
|
import eu.mhsl.craftattack.spawn.appliances.displayName.DisplayName;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.whitelist.Whitelist;
|
import eu.mhsl.craftattack.spawn.appliances.whitelist.Whitelist;
|
||||||
@ -33,8 +33,7 @@ public class Outlawed extends Appliance {
|
|||||||
super("outlawed");
|
super("outlawed");
|
||||||
Bukkit.getScheduler().runTaskTimerAsynchronously(
|
Bukkit.getScheduler().runTaskTimerAsynchronously(
|
||||||
Main.instance(),
|
Main.instance(),
|
||||||
() -> {
|
() -> playerStatusMap.forEach((player, status) -> {
|
||||||
playerStatusMap.forEach((player, status) -> {
|
|
||||||
if(!player.isOnline()) return;
|
if(!player.isOnline()) return;
|
||||||
if(status != Status.FORCED) return;
|
if(status != Status.FORCED) return;
|
||||||
try {
|
try {
|
||||||
@ -42,8 +41,7 @@ public class Outlawed extends Appliance {
|
|||||||
} catch (DisconnectInfo.Throwable e) {
|
} catch (DisconnectInfo.Throwable e) {
|
||||||
Bukkit.getScheduler().runTask(Main.instance(), () -> e.getDisconnectScreen().applyKick(player));
|
Bukkit.getScheduler().runTask(Main.instance(), () -> e.getDisconnectScreen().applyKick(player));
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
},
|
|
||||||
20*60,
|
20*60,
|
||||||
20*60*5
|
20*60*5
|
||||||
);
|
);
|
||||||
|
@ -5,6 +5,7 @@ import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
|
|||||||
import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartCancelCommand;
|
import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartCancelCommand;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartCommand;
|
import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartCommand;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartResetCommand;
|
import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartResetCommand;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.projectStart.listener.NoAdvancementsListener;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.projectStart.listener.PlayerInvincibleListener;
|
import eu.mhsl.craftattack.spawn.appliances.projectStart.listener.PlayerInvincibleListener;
|
||||||
import eu.mhsl.craftattack.spawn.config.Configuration;
|
import eu.mhsl.craftattack.spawn.config.Configuration;
|
||||||
import eu.mhsl.craftattack.spawn.util.entity.PlayerUtils;
|
import eu.mhsl.craftattack.spawn.util.entity.PlayerUtils;
|
||||||
@ -174,7 +175,10 @@ public class ProjectStart extends Appliance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NotNull List<Listener> eventHandlers() {
|
protected @NotNull List<Listener> eventHandlers() {
|
||||||
return List.of(new PlayerInvincibleListener());
|
return List.of(
|
||||||
|
new PlayerInvincibleListener(),
|
||||||
|
new NoAdvancementsListener()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.appliances.projectStart.listener;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
|
||||||
|
import eu.mhsl.craftattack.spawn.appliances.projectStart.ProjectStart;
|
||||||
|
import org.bukkit.advancement.Advancement;
|
||||||
|
import org.bukkit.advancement.AdvancementProgress;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.player.PlayerAdvancementDoneEvent;
|
||||||
|
|
||||||
|
public class NoAdvancementsListener extends ApplianceListener<ProjectStart> {
|
||||||
|
@EventHandler
|
||||||
|
public void onAdvancement(PlayerAdvancementDoneEvent event) {
|
||||||
|
if(!getAppliance().isEnabled()) return;
|
||||||
|
event.message(null);
|
||||||
|
|
||||||
|
Advancement advancement = event.getAdvancement();
|
||||||
|
AdvancementProgress progress = event.getPlayer().getAdvancementProgress(advancement);
|
||||||
|
for(String criteria : progress.getAwardedCriteria()) {
|
||||||
|
progress.revokeCriteria(criteria);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.tablist;
|
|||||||
import eu.mhsl.craftattack.spawn.Main;
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
import eu.mhsl.craftattack.spawn.appliance.Appliance;
|
||||||
import eu.mhsl.craftattack.spawn.appliances.report.Report;
|
import eu.mhsl.craftattack.spawn.appliances.report.Report;
|
||||||
|
import eu.mhsl.craftattack.spawn.util.statistics.NetworkMonitor;
|
||||||
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
|
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
|
||||||
import eu.mhsl.craftattack.spawn.util.IteratorUtil;
|
import eu.mhsl.craftattack.spawn.util.IteratorUtil;
|
||||||
import eu.mhsl.craftattack.spawn.util.text.RainbowComponent;
|
import eu.mhsl.craftattack.spawn.util.text.RainbowComponent;
|
||||||
@ -14,15 +15,22 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
public class Tablist extends Appliance {
|
public class Tablist extends Appliance {
|
||||||
private final int refreshRate = Ticks.TICKS_PER_SECOND * 3;
|
private final int refreshRate = Ticks.TICKS_PER_SECOND * 3;
|
||||||
private final RainbowComponent serverName = new RainbowComponent(" CraftAttack 7 ", 7, 3);
|
private final RainbowComponent serverName = new RainbowComponent(" CraftAttack 7 ", 7, 3);
|
||||||
|
private NetworkMonitor networkMonitor;
|
||||||
|
|
||||||
|
public Tablist() {
|
||||||
|
super("tablist");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
this.networkMonitor = new NetworkMonitor(localConfig().getString("interface"), Duration.ofSeconds(1));
|
||||||
Bukkit.getScheduler().runTaskTimerAsynchronously(
|
Bukkit.getScheduler().runTaskTimerAsynchronously(
|
||||||
Main.instance(),
|
Main.instance(),
|
||||||
() -> IteratorUtil.onlinePlayers(this::updateHeader),
|
() -> IteratorUtil.onlinePlayers(this::updateHeader),
|
||||||
@ -31,6 +39,11 @@ public class Tablist extends Appliance {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
this.networkMonitor.stop();
|
||||||
|
}
|
||||||
|
|
||||||
public void fullUpdate(Player player) {
|
public void fullUpdate(Player player) {
|
||||||
updateHeader(player);
|
updateHeader(player);
|
||||||
updateFooter(player);
|
updateFooter(player);
|
||||||
@ -43,6 +56,10 @@ public class Tablist extends Appliance {
|
|||||||
.append(Component.text("mhsl.eu", NamedTextColor.GOLD)).appendNewline().appendNewline()
|
.append(Component.text("mhsl.eu", NamedTextColor.GOLD)).appendNewline().appendNewline()
|
||||||
.append(ComponentUtil.getFormattedMSPT()).appendNewline().appendNewline()
|
.append(ComponentUtil.getFormattedMSPT()).appendNewline().appendNewline()
|
||||||
.append(ComponentUtil.getFormattedPing(player)).appendNewline()
|
.append(ComponentUtil.getFormattedPing(player)).appendNewline()
|
||||||
|
.append(ComponentUtil.getFormattedNetworkStats(
|
||||||
|
this.networkMonitor.getTraffic(),
|
||||||
|
this.networkMonitor.getPackets())
|
||||||
|
).appendNewline()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.util.statistics;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.Main;
|
||||||
|
import net.kyori.adventure.util.Ticks;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
public class NetworkMonitor {
|
||||||
|
private long previousRxBytes = 0;
|
||||||
|
private long previousTxBytes = 0;
|
||||||
|
|
||||||
|
private long previousRxPackets = 0;
|
||||||
|
private long previousTxPackets = 0;
|
||||||
|
|
||||||
|
private final String iFace;
|
||||||
|
|
||||||
|
private long rxBytesLastDuration = 0;
|
||||||
|
private long txBytesLastDuration = 0;
|
||||||
|
private long rxPacketsLastDuration = 0;
|
||||||
|
private long txPacketsLastDuration = 0;
|
||||||
|
|
||||||
|
private final BukkitTask updateTask;
|
||||||
|
|
||||||
|
public NetworkMonitor(String iFace, Duration sampleDuration) {
|
||||||
|
this.iFace = iFace;
|
||||||
|
|
||||||
|
this.updateTask = Bukkit.getScheduler().runTaskTimerAsynchronously(
|
||||||
|
Main.instance(),
|
||||||
|
this::update,
|
||||||
|
0,
|
||||||
|
sampleDuration.getSeconds() * Ticks.TICKS_PER_SECOND
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Traffic(long rxBytes, long txBytes) {}
|
||||||
|
public record Packets(long rxCount, long txCount) {}
|
||||||
|
|
||||||
|
public Traffic getTraffic() {
|
||||||
|
return new Traffic(rxBytesLastDuration, txBytesLastDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packets getPackets() {
|
||||||
|
return new Packets(rxPacketsLastDuration, txPacketsLastDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
this.updateTask.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
long rxBytes = getNetworkStatistic("rx_bytes");
|
||||||
|
long txBytes = getNetworkStatistic("tx_bytes");
|
||||||
|
long rxPackets = getNetworkStatistic("rx_packets");
|
||||||
|
long txPackets = getNetworkStatistic("tx_packets");
|
||||||
|
|
||||||
|
this.rxBytesLastDuration = rxBytes - previousRxBytes;
|
||||||
|
this.txBytesLastDuration = txBytes - previousTxBytes;
|
||||||
|
this.rxPacketsLastDuration = rxPackets - previousRxPackets;
|
||||||
|
this.txPacketsLastDuration = txPackets - previousTxPackets;
|
||||||
|
|
||||||
|
this.previousRxBytes = rxBytes;
|
||||||
|
this.previousTxBytes = txBytes;
|
||||||
|
this.previousRxPackets = rxPackets;
|
||||||
|
this.previousTxPackets = txPackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getNetworkStatistic(String statistic) {
|
||||||
|
try {
|
||||||
|
String path = String.format("/sys/class/net/%s/statistics/%s", this.iFace, statistic);
|
||||||
|
String content = new String(Files.readAllBytes(Paths.get(path)));
|
||||||
|
return Long.parseLong(content.trim());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed recieving Network statistic", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package eu.mhsl.craftattack.spawn.util.text;
|
package eu.mhsl.craftattack.spawn.util.text;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.util.statistics.NetworkMonitor;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
@ -86,4 +87,18 @@ public class ComponentUtil {
|
|||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Component getFormattedNetworkStats(NetworkMonitor.Traffic traffic, NetworkMonitor.Packets packets) {
|
||||||
|
return Component.text()
|
||||||
|
.append(Component.text(
|
||||||
|
DataSizeConverter.convertBytesToHumanReadable(traffic.rxBytes()) + " ↓ " + NumberAbbreviation.abbreviateNumber(packets.rxCount()) + "pps",
|
||||||
|
NamedTextColor.GREEN
|
||||||
|
))
|
||||||
|
.append(Component.text(" | ", NamedTextColor.GRAY))
|
||||||
|
.append(Component.text(
|
||||||
|
DataSizeConverter.convertBytesToHumanReadable(traffic.txBytes()) + " ↑ " + NumberAbbreviation.abbreviateNumber(packets.rxCount()) + "pps",
|
||||||
|
NamedTextColor.RED
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.util.text;
|
||||||
|
|
||||||
|
public class DataSizeConverter {
|
||||||
|
public static String convertBytesToHumanReadable(long bytes) {
|
||||||
|
double kbits = bytes * 8.0 / 1000.0;
|
||||||
|
double mbits = kbits / 1000.0;
|
||||||
|
|
||||||
|
if (mbits >= 1) {
|
||||||
|
return String.format("%.2f Mbit", mbits);
|
||||||
|
} else {
|
||||||
|
return String.format("%.2f Kbit", kbits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.util.text;
|
||||||
|
|
||||||
|
public class NumberAbbreviation {
|
||||||
|
public static <T extends Number & Comparable<T>> String abbreviateNumber(T number) {
|
||||||
|
double value = number.doubleValue();
|
||||||
|
if (value >= 1_000_000) {
|
||||||
|
return String.format("%.1fM", value / 1_000_000.0);
|
||||||
|
} else if (value >= 1_000) {
|
||||||
|
return String.format("%.1fk", value / 1_000.0);
|
||||||
|
} else {
|
||||||
|
return number.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -46,3 +46,6 @@ playerLimit:
|
|||||||
|
|
||||||
whitelist:
|
whitelist:
|
||||||
api: https://mhsl.eu/craftattack/api/user
|
api: https://mhsl.eu/craftattack/api/user
|
||||||
|
|
||||||
|
tablist:
|
||||||
|
interface: eth0
|
Loading…
x
Reference in New Issue
Block a user