added networking statistics, refactored aggregates back to appliances

This commit is contained in:
Elias Müller 2024-08-23 23:17:02 +02:00
parent eb2c0505f5
commit c01ae32f1f
14 changed files with 193 additions and 29 deletions

View File

@ -1,6 +1,6 @@
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.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;

View File

@ -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);
}
}

View File

@ -1,5 +1,6 @@
package eu.mhsl.craftattack.spawn.appliance;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.api.HttpServer;
import eu.mhsl.craftattack.spawn.config.Configuration;
import org.bukkit.Bukkit;
@ -78,6 +79,10 @@ public abstract class Appliance {
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) {
PluginCommand command = plugin.getCommand(name);
if(command != null && executor != null) {

View File

@ -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.AdminMarkerListener;
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.function.Supplier;
public class DisplayName extends Aggregate {
public class DisplayName extends Appliance {
public void update(Player player) {
TextColor playerColor = queryAppliance(AdminMarker.class).getPlayerColor(player);
List<Supplier<Component>> prefixes = List.of(

View File

@ -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 org.bukkit.event.EventHandler;

View File

@ -1,7 +1,7 @@
package eu.mhsl.craftattack.spawn.appliances.outlawed;
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.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.whitelist.Whitelist;
@ -33,8 +33,7 @@ public class Outlawed extends Appliance {
super("outlawed");
Bukkit.getScheduler().runTaskTimerAsynchronously(
Main.instance(),
() -> {
playerStatusMap.forEach((player, status) -> {
() -> playerStatusMap.forEach((player, status) -> {
if(!player.isOnline()) return;
if(status != Status.FORCED) return;
try {
@ -42,8 +41,7 @@ public class Outlawed extends Appliance {
} catch (DisconnectInfo.Throwable e) {
Bukkit.getScheduler().runTask(Main.instance(), () -> e.getDisconnectScreen().applyKick(player));
}
});
},
}),
20*60,
20*60*5
);

View File

@ -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.ProjectStartCommand;
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.config.Configuration;
import eu.mhsl.craftattack.spawn.util.entity.PlayerUtils;
@ -174,7 +175,10 @@ public class ProjectStart extends Appliance {
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new PlayerInvincibleListener());
return List.of(
new PlayerInvincibleListener(),
new NoAdvancementsListener()
);
}
@Override

View File

@ -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);
}
}
}

View File

@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.tablist;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
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.IteratorUtil;
import eu.mhsl.craftattack.spawn.util.text.RainbowComponent;
@ -14,15 +15,22 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.time.Duration;
import java.util.List;
public class Tablist extends Appliance {
private final int refreshRate = Ticks.TICKS_PER_SECOND * 3;
private final RainbowComponent serverName = new RainbowComponent(" CraftAttack 7 ", 7, 3);
private NetworkMonitor networkMonitor;
public Tablist() {
super("tablist");
}
@Override
public void onEnable() {
this.networkMonitor = new NetworkMonitor(localConfig().getString("interface"), Duration.ofSeconds(1));
Bukkit.getScheduler().runTaskTimerAsynchronously(
Main.instance(),
() -> 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) {
updateHeader(player);
updateFooter(player);
@ -43,6 +56,10 @@ public class Tablist extends Appliance {
.append(Component.text("mhsl.eu", NamedTextColor.GOLD)).appendNewline().appendNewline()
.append(ComponentUtil.getFormattedMSPT()).appendNewline().appendNewline()
.append(ComponentUtil.getFormattedPing(player)).appendNewline()
.append(ComponentUtil.getFormattedNetworkStats(
this.networkMonitor.getTraffic(),
this.networkMonitor.getPackets())
).appendNewline()
);
}

View File

@ -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);
}
}
}

View File

@ -1,5 +1,6 @@
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.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
@ -86,4 +87,18 @@ public class ComponentUtil {
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();
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -46,3 +46,6 @@ playerLimit:
whitelist:
api: https://mhsl.eu/craftattack/api/user
tablist:
interface: eth0