Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/moderation #63

Merged
merged 57 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
1ba1ee6
Update javadocs
Foxikle May 15, 2024
1398f0a
update method name
Foxikle May 16, 2024
98cca4e
Delete duplicate class
Foxikle May 27, 2024
eebd88d
Fix access to methods
Foxikle May 27, 2024
e309113
Create command to ban players
Foxikle Jun 4, 2024
09fa9d2
Add redis config options
Foxikle Jun 4, 2024
9b635c5
Delete file
Foxikle Jun 4, 2024
fa16888
Create object holding data about a ban
Foxikle Jun 4, 2024
5d55741
Create enum holding ban reasons
Foxikle Jun 4, 2024
1c6e928
Create audit logging
Foxikle Jun 4, 2024
119a313
Player caching
Foxikle Jun 4, 2024
b899d73
Update listeners with new functionality
Foxikle Jun 4, 2024
06ba6d0
Rename to mysql database
Foxikle Jun 4, 2024
1dd3407
create object with player data
Foxikle Jun 4, 2024
0b004a6
Update methods to message more things
Foxikle Jun 4, 2024
bc646fa
Rename to mysql database
Foxikle Jun 4, 2024
c1fa953
Add RedisDatabase
Foxikle Jun 4, 2024
8a0753f
Create a util class that parses durations and stuff
Foxikle Jun 4, 2024
f6cd509
Create kick reasons for use later
Foxikle Jun 4, 2024
cb06a75
Create a class that does message formatting
Foxikle Jun 4, 2024
28f6a20
Publish cytosis to a repo
Foxikle Jun 4, 2024
863a84d
Update stuff, generate server ids, reformatting
Foxikle Jun 4, 2024
57138c8
Add shutdown methods
Foxikle Jun 4, 2024
a6a44f7
Update settings
Foxikle Jun 4, 2024
8878116
Delete duplicated file and remove lines
webhead1104 May 10, 2024
b8fa826
Polar
webhead1104 May 13, 2024
4a01dfb
Polar
webhead1104 May 15, 2024
747a9c9
Update dependency dev.hollowcube:polar to v1.9.3
renovate[bot] May 15, 2024
044c181
Add player logging
webhead1104 May 16, 2024
0e7b327
Fix typo
webhead1104 May 16, 2024
0e01e2d
Change error messages
webhead1104 May 16, 2024
8829cbf
Rename cytonic_player_joins table
webhead1104 May 16, 2024
77da3dd
Rename playerJoin to logPlayerJoin
webhead1104 May 16, 2024
b246388
Changing back to intellij
webhead1104 May 22, 2024
cef6023
Fix typo
webhead1104 May 24, 2024
a764e9c
Update minestom
webhead1104 May 25, 2024
4c710a2
Chat Channels and formatting
webhead1104 May 25, 2024
6f4de76
Add todo
webhead1104 May 25, 2024
4d54105
Change channel type
webhead1104 May 25, 2024
4f4f81f
Add a variable for the chat channel exchange
webhead1104 May 25, 2024
4a4cb71
Fix indentation
webhead1104 May 27, 2024
788bc80
Fix massive bug
webhead1104 May 28, 2024
282103a
Update dependency dev.hollowcube:polar to v1.9.4
renovate[bot] May 28, 2024
a6dfe1d
Create command to ban players
Foxikle Jun 4, 2024
f4c03bc
Delete file
Foxikle Jun 4, 2024
05bd6d6
Update listeners with new functionality
Foxikle Jun 4, 2024
2922617
Update methods to message more things
Foxikle Jun 4, 2024
b46231b
Rename to mysql database
Foxikle Jun 4, 2024
5dc776c
Add RedisDatabase
Foxikle Jun 4, 2024
0a77e8b
Update stuff, generate server ids, reformatting
Foxikle Jun 4, 2024
874cbe4
Update settings
Foxikle Jun 4, 2024
37aae8e
Delete old database object
Foxikle Jun 4, 2024
37b0085
Merging
Foxikle Jun 4, 2024
93f817a
Fix merging shenanigans
Foxikle Jun 5, 2024
9bca703
Merge branch 'feat/moderation' of https://github.com/Foxikle/Cytosis
Foxikle Jun 5, 2024
6d4a935
Merge branch 'feat/moderation' of https://github.com/Foxikle/Cytosis …
Foxikle Jun 5, 2024
df5d314
Fix merging shenanigans
Foxikle Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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