Skip to content

Commit

Permalink
Merge pull request #63 from Foxikle/feat/moderation
Browse files Browse the repository at this point in the history
Feat/moderation
  • Loading branch information
webhead1104 authored Jun 5, 2024
2 parents 6f55ec1 + df5d314 commit 4be8d0d
Show file tree
Hide file tree
Showing 26 changed files with 1,255 additions and 452 deletions.
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ dependencies {
implementation("org.tomlj:tomlj:1.1.1") // Config lang
implementation("com.rabbitmq:amqp-client:5.21.0") // Message broker
implementation("dev.hollowcube:polar:1.9.4") // Polar
implementation("com.google.guava:guava:33.2.0-jre") // a lot of things, but mostly caching
implementation("redis.clients:jedis:3.7.0") // redis client
}

tasks.withType<Jar> {
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/net/cytonic/cytosis/CytonicNetwork.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.cytonic.cytosis;

import lombok.Getter;
import net.cytonic.cytosis.data.RedisDatabase;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

/**
* A class that holds data about the status of the Cytonic network
*/
@Getter
public class CytonicNetwork {
private final Set<String> networkPlayers = new HashSet<>();
private final Set<UUID> networkPlayerUUIDs = new HashSet<>();

public void importDataFromRedis(RedisDatabase redisDatabase) {
networkPlayers.clear();
networkPlayerUUIDs.clear();
networkPlayers.addAll(redisDatabase.getOnlinePlayers());
networkPlayerUUIDs.addAll(redisDatabase.getOnlineUUIDs());
}

public void addPlayer(String name, UUID uuid) {
networkPlayers.add(name);
networkPlayerUUIDs.add(uuid);
}

public void removePlayer(String name, UUID uuid) {
networkPlayers.remove(name);
networkPlayerUUIDs.remove(uuid);
}
}
44 changes: 35 additions & 9 deletions src/main/java/net/cytonic/cytosis/Cytosis.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package net.cytonic.cytosis;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import lombok.Getter;
import net.cytonic.cytosis.commands.CommandHandler;
import net.cytonic.cytosis.config.CytosisSettings;
Expand All @@ -29,10 +24,13 @@
import net.minestom.server.instance.block.Block;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.permission.Permission;
import org.jetbrains.annotations.Nullable;

import java.util.*;

@Getter
public class Cytosis {

public static final String SERVER_ID = generateID();
// manager stuff
@Getter
private static MinecraftServer minecraftServer;
Expand Down Expand Up @@ -60,6 +58,9 @@ public class Cytosis {
private static RankManager rankManager;
@Getter
private static ChatManager chatManager;
@Nullable
@Getter
private static CytonicNetwork cytonicNetwork;

private static List<String> FLAGS;

Expand Down Expand Up @@ -129,6 +130,12 @@ public static Optional<Player> getPlayer(String username) {
return Optional.ofNullable(target);
}

/**
* Gets the player if they are on THIS instance, by UUID
*
* @param uuid The uuid to fetch the player by
* @return The optional holding the player if they exist
*/
public static Optional<Player> getPlayer(UUID uuid) {
Player target = null;
for (Player onlinePlayer : getOnlinePlayers()) {
Expand Down Expand Up @@ -159,7 +166,7 @@ public static void loadWorld() {
return;
}
Logger.info(STR."Loading world '\{CytosisSettings.SERVER_WORLD_NAME}'");
databaseManager.getDatabase().getWorld(CytosisSettings.SERVER_WORLD_NAME).whenComplete((polarWorld, throwable) -> {
databaseManager.getMysqlDatabase().getWorld(CytosisSettings.SERVER_WORLD_NAME).whenComplete((polarWorld, throwable) -> {
if (throwable != null) {
Logger.error("An error occurred whilst initializing the world!", throwable);
} else {
Expand All @@ -173,7 +180,7 @@ public static void loadWorld() {
public static void completeNonEssentialTasks(long start) {
Logger.info("Initializing database");
databaseManager = new DatabaseManager();
databaseManager.setupDatabase();
databaseManager.setupDatabases();
Logger.info("Database initialized!");
Logger.info("Setting up event handlers");
eventHandler = new EventHandler(MinecraftServer.getGlobalEventHandler());
Expand All @@ -184,7 +191,7 @@ public static void completeNonEssentialTasks(long start) {

MinecraftServer.getSchedulerManager().buildShutdownTask(() -> {
databaseManager.shutdown();
Logger.info("Good night!");
messagingManager.shutdown();
});

Logger.info("Initializing server commands");
Expand All @@ -205,6 +212,13 @@ public static void completeNonEssentialTasks(long start) {
rankManager = new RankManager();
rankManager.init();

if (CytosisSettings.SERVER_PROXY_MODE) {
Logger.info("Loading network setup!");
cytonicNetwork = new CytonicNetwork();
cytonicNetwork.importDataFromRedis(databaseManager.getRedisDatabase());
}


// Start the server
Logger.info(STR."Server started on port \{CytosisSettings.SERVER_PORT}");
minecraftServer.start("0.0.0.0", CytosisSettings.SERVER_PORT);
Expand All @@ -217,4 +231,16 @@ public static void completeNonEssentialTasks(long start) {
MinecraftServer.stopCleanly();
}
}

private static String generateID() {
//todo: make a check for existing server ids
StringBuilder id = new StringBuilder("Cytosis-");
Random random = new Random();
id.append((char) (random.nextInt(26) + 'a'));
for (int i = 0; i < 4; i++) {
id.append(random.nextInt(10));
}
id.append((char) (random.nextInt(26) + 'a'));
return id.toString();
}
}
10 changes: 10 additions & 0 deletions src/main/java/net/cytonic/cytosis/auditlog/Category.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.cytonic.cytosis.auditlog;

public enum Category {
BAN,
UNBAN,
MUTE,
UNMUTE,
IPBAN,
IPUNBAN
}
6 changes: 6 additions & 0 deletions src/main/java/net/cytonic/cytosis/auditlog/Entry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package net.cytonic.cytosis.auditlog;

import java.util.UUID;

public record Entry(UUID uuid, UUID actor, Category category, String reason) {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.cytonic.cytosis.commands;

import net.cytonic.cytosis.Cytosis;
import net.cytonic.cytosis.commands.moderation.BanCommand;
import net.minestom.server.command.CommandManager;
import net.minestom.server.entity.Player;
import java.util.Scanner;
Expand All @@ -22,9 +23,11 @@ public void registerCytosisCommands() {
CommandManager cm = Cytosis.getCommandManager();
cm.register(new GamemodeCommand());
cm.register(new RankCommand());
cm.register(new BanCommand());
cm.register(new ChatChannelCommand());
}

@SuppressWarnings("UnstableApiUsage")
public void recalculateCommands(Player player) {
player.sendPacket(Cytosis.getCommandManager().createDeclareCommandsPacket(player));
}
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/net/cytonic/cytosis/commands/RankCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@ public RankCommand() {
sender.sendMessage(MM."<red>The player \{context.get(group).getRaw("player")} doesn't exist!");
return;
}

if (player == sender) {
sender.sendMessage(MM."<red>You cannot change your own rank!");
return;
}
Cytosis.getDatabaseManager().getDatabase().getPlayerRank(player.getUuid()).whenComplete((rank, throwable) -> {
Cytosis.getDatabaseManager().getMysqlDatabase().getPlayerRank(player.getUuid()).whenComplete((rank, throwable) -> {
if (throwable != null) {
sender.sendMessage("An error occurred whilst fetching the old rank!");
return;
}

// if it's a console we don't care (There isn't a console impl)
if (sender instanceof Player s) {
PlayerRank senderRank = Cytosis.getRankManager().getPlayerRank(s.getUuid()).orElseThrow();
Expand All @@ -57,13 +59,14 @@ public RankCommand() {
return;
}
}

setRank(player, newRank, sender);
});
}, group);
}

private void setRank(Player player, PlayerRank rank, CommandSender sender) {
Cytosis.getDatabaseManager().getDatabase().setPlayerRank(player.getUuid(), rank).whenComplete((_, t) -> {
Cytosis.getDatabaseManager().getMysqlDatabase().setPlayerRank(player.getUuid(), rank).whenComplete((_, t) -> {
if (t != null) {
sender.sendMessage(MM."<red>An error occurred whilst setting \{player.getUsername()}'s rank! Check the console for more details.");
Logger.error(STR."An error occurred whilst setting \{player.getUsername()}'s rank! Check the console for more details.", t);
Expand All @@ -73,4 +76,4 @@ private void setRank(Player player, PlayerRank rank, CommandSender sender) {
sender.sendMessage(MM."<green>Successfully updated \{player.getUsername()}'s rank!");
});
}
}
}
101 changes: 101 additions & 0 deletions src/main/java/net/cytonic/cytosis/commands/moderation/BanCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package net.cytonic.cytosis.commands.moderation;

import net.cytonic.cytosis.Cytosis;
import net.cytonic.cytosis.auditlog.Category;
import net.cytonic.cytosis.auditlog.Entry;
import net.cytonic.cytosis.enums.BanReason;
import net.cytonic.cytosis.logging.Logger;
import net.cytonic.cytosis.messaging.KickReason;
import net.cytonic.cytosis.utils.BanData;
import net.cytonic.cytosis.utils.DurationParser;
import net.cytonic.cytosis.utils.MessageUtils;
import net.cytonic.cytosis.utils.OfflinePlayer;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.ArgumentEnum;
import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.command.builder.suggestion.SuggestionEntry;
import net.minestom.server.entity.Player;

import java.time.Instant;

import static net.cytonic.cytosis.utils.MiniMessageTemplate.MM;

public class BanCommand extends Command {
public BanCommand() {
super("ban");
setCondition((sender, _) -> sender.hasPermission("cytosis.commands.moderation.ban"));

var playerArg = ArgumentType.Word("target");
System.out.println(playerArg.getSuggestionCallback());
playerArg.setSuggestionCallback((sender, context, suggestion) -> {
if (sender instanceof Player player) {
player.sendActionBar(MM."<green>Fetching online players...");
}
Cytosis.getDatabaseManager().getRedisDatabase().getOnlinePlayers().forEach(player ->
suggestion.addEntry(new SuggestionEntry(player)));
});
var durationArg = ArgumentType.Word("duration");
var reasonArg = ArgumentType.Enum("reason", BanReason.class).setFormat(ArgumentEnum.Format.LOWER_CASED);

var group = ArgumentType.Group("ban-group", playerArg, durationArg, reasonArg);

addSyntax((sender, context) -> {
if (sender instanceof Player actor) {

if (!actor.hasPermission("cytosis.commands.moderation.ban")) {
actor.sendMessage(MM."<red>You don't have permission to use this command!");
}

final String player = context/*.get(group)*/.get(playerArg);
final String reason = context/*.get(group)*/.get(reasonArg).getReason();
final String rawDur = context/*.get(group)*/.get(durationArg);
final Instant dur = DurationParser.parse(rawDur);

if (!Cytosis.getDatabaseManager().getRedisDatabase().getOnlinePlayers().contains(player)) {
sender.sendMessage(MM."<red>The player \{context.get(group).getRaw("player")} doesn't exist!");
return;
}
Cytosis.getDatabaseManager().getMysqlDatabase().findUUIDByName(player).whenComplete((uuid, throwable) -> {
if (throwable != null) {
sender.sendMessage(MM."<red>An error occured whilst finding \{player}!");
Logger.error("error; ", throwable);
return;
}
Cytosis.getDatabaseManager().getMysqlDatabase().isBanned(uuid).whenComplete((banned, throwable1) -> {
if (throwable1 != null) {
sender.sendMessage(MM."<red>An error occured whilst finding if \{player} is banned!");
Logger.error("error; ", throwable1);
return;
}
if (banned.isBanned()) {
sender.sendMessage(MM."<red>\{player} is already banned!");
return;
}
Cytosis.getDatabaseManager().getMysqlDatabase().getPlayerRank(uuid).whenComplete((playerRank, throwable2) -> {
if (throwable2 != null) {
sender.sendMessage(MM."<red>An error occured whilst finding \{player}'s rank!");
Logger.error("error; ", throwable2);
return;
}
OfflinePlayer op = new OfflinePlayer(player, uuid, playerRank);
if (op.hasPermission("cytosis.moderation.ban_immune")) {
sender.sendMessage(MM."<red>\{player} cannot be banned!");
return;
}

Cytosis.getDatabaseManager().getMysqlDatabase().banPlayer(uuid, reason, dur).whenComplete((_, throwable3) -> {
if (throwable3 != null) {
actor.sendMessage(MM."<red>An error occured whilst banning \{player}!");
return;
}
Cytosis.getMessagingManager().getRabbitMQ().kickPlayer(op, KickReason.BANNED, MessageUtils.formatBanMessage(new BanData(reason, dur, true)));
actor.sendMessage(MM."<green>\{player} was successfully banned for \{DurationParser.unparseFull(dur)}.");
Cytosis.getDatabaseManager().getMysqlDatabase().addAuditLogEntry(new Entry(uuid, actor.getUuid(), Category.BAN, reason));
});
});
});
});
}
}, playerArg, durationArg, reasonArg);
}
}
Loading

0 comments on commit 4be8d0d

Please sign in to comment.