1
0
This commit is contained in:
Lee
2024-04-05 20:30:29 +01:00
parent 4e4e122f31
commit 0d329cfead
15 changed files with 244 additions and 61 deletions

16
pom.xml
View File

@ -138,28 +138,24 @@
<version>2.11.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>6.5.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-java</artifactId>
<version>7.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.9.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.vexsoftware</groupId>
<artifactId>nuvotifier-universal</artifactId>
@ -167,5 +163,17 @@
<systemPath>${basedir}/lib/nuvotifier.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>5.0.0-beta.21</version>
<exclusions>
<exclusion>
<groupId>club.minnced</groupId>
<artifactId>opus-java</artifactId>
</exclusion>
</exclusions>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,6 +1,7 @@
package cc.fascinated;
import cc.fascinated.account.AccountManager;
import cc.fascinated.bot.DiscordBot;
import cc.fascinated.chat.ChatManager;
import cc.fascinated.command.CommandManager;
import cc.fascinated.commandspy.CommandSpyManager;
@ -27,11 +28,13 @@ public class Aetheria extends JavaPlugin {
@Getter
private static final BuildData buildData = new BuildData();
/**
* The instance of the plugin.
*/
public static Aetheria INSTANCE;
public static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(2, 8, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
public static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(2, 8, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
public Aetheria() {
INSTANCE = this;
@ -45,7 +48,6 @@ public class Aetheria extends JavaPlugin {
Lang.clear();
new AccountManager();
new EventManager();
new CommandManager();
new WorldSizeManager();
@ -58,5 +60,6 @@ public class Aetheria extends JavaPlugin {
new RenderDistanceManager();
new VoteManager();
new StaffChatManager();
new DiscordBot();
}
}

View File

@ -69,7 +69,7 @@ public class Account {
*/
private long lastLogin;
public Account(UUID uuid) {
public Account(UUID uuid, String name) {
//log.info("Loading account for " + uuid);
boolean newAccount = false;
@ -100,7 +100,7 @@ public class Account {
this.lastLogin = config.getLong("lastLogin");
this.lastLogin = System.currentTimeMillis(); // Update last login
this.name = Bukkit.getOfflinePlayer(uuid).getName();
this.name = name; // Update the name
// Load profiles
this.playerColorProfile = new PlayerColorProfile(this, this.getProfileSection(playerColorProfileId));
@ -204,6 +204,16 @@ public class Account {
return getPlayer().isOp();
}
/**
* Set if the player has the permission.
*
* @param permission the permission to check
* @return if the player has the permission
*/
public boolean hasPermission(String permission) {
return getPlayer().hasPermission(permission);
}
/**
* Saves the account to disk.
*

View File

@ -2,16 +2,18 @@ package cc.fascinated.account;
import cc.fascinated.Aetheria;
import cc.fascinated.account.command.SaveAccountsCommand;
import cc.fascinated.bot.DiscordBot;
import cc.fascinated.bot.DiscordChannel;
import cc.fascinated.command.CommandManager;
import cc.fascinated.config.Config;
import cc.fascinated.config.Lang;
import cc.fascinated.playercolor.PlayerColorProfile;
import cc.fascinated.utils.DiscordWebhook;
import cc.fascinated.utils.Manager;
import cc.fascinated.utils.Priority;
import cc.fascinated.utils.Style;
import com.viaversion.viaversion.api.Via;
import lombok.extern.log4j.Log4j2;
import net.dv8tion.jda.api.EmbedBuilder;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -20,7 +22,8 @@ import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.io.IOException;
import java.awt.*;
import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -38,7 +41,7 @@ public class AccountManager extends Manager implements Listener {
if (isAccountLoaded(player.getUniqueId())) { // Don't load the account if it's already loaded
continue;
}
loadAccount(player.getUniqueId());
loadAccount(player.getUniqueId(), player.getName());
}
Bukkit.getAsyncScheduler().runAtFixedRate(Aetheria.INSTANCE, (task) -> {
@ -46,6 +49,21 @@ public class AccountManager extends Manager implements Listener {
}, SAVE_INTERVAL, SAVE_INTERVAL, TimeUnit.MINUTES);
}
/**
* Gets a list of all online accounts.
*
* @return the online accounts
*/
public static List<Account> getOnlineAccounts() {
List<Account> accounts = new ArrayList<>();
for (Account account : ACCOUNTS.values()) {
if (account.isOnline()) {
accounts.add(account);
}
}
return accounts;
}
/**
* Gets the account for the specified player.
*
@ -60,9 +78,10 @@ public class AccountManager extends Manager implements Listener {
* Registers an account for the specified player.
*
* @param uuid the player's UUID
* @param name the player's name
*/
private static void loadAccount(UUID uuid) {
Account account = new Account(uuid);
private static void loadAccount(UUID uuid, String name) {
Account account = new Account(uuid, name);
ACCOUNTS.put(uuid, account);
}
@ -105,10 +124,11 @@ public class AccountManager extends Manager implements Listener {
@EventHandler
public void onAsyncPlayerPreLoginEvent(AsyncPlayerPreLoginEvent event) {
UUID uuid = event.getUniqueId();
String name = event.getName();
if (isAccountLoaded(uuid)) { // Account already loaded
return;
}
loadAccount(uuid); // Load the account into memory
loadAccount(uuid, name); // Load the account into memory
}
@Override
@ -119,22 +139,13 @@ public class AccountManager extends Manager implements Listener {
if (!account.getPlayer().hasPlayedBefore()) {
joinMessage = Lang.FIRST_JOIN_MESSAGE.getAsString();
// Send a notification to the discord log channel
Aetheria.EXECUTOR.execute(() -> {
// todo: re-code this it's so ugly
DiscordWebhook discordWebhook = new DiscordWebhook(Config.DISCORD_LOG_WEBHOOK.getAsString());
DiscordWebhook.EmbedObject embed = new DiscordWebhook.EmbedObject();
embed.setTitle("New Player Joined");
embed.addField("Name", account.getName(), true);
embed.addField("UUID", account.getUuid().toString(), true);
discordWebhook.addEmbed(embed);
try {
discordWebhook.execute();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
DiscordBot.sendEmbed(DiscordChannel.PLAYER_LOGS, new EmbedBuilder()
.setThumbnail("https://crafatar.com/avatars/" + account.getUuid())
.setColor(Color.GREEN)
.setTitle("New Player Joined")
.addField("Player", account.getName(), true)
.addField("UUID", account.getUuid().toString(), true)
);
}
event.joinMessage(Style.getMiniMessage().deserialize(joinMessage
.replace("%player%", account.getName())

View File

@ -0,0 +1,16 @@
package cc.fascinated.account.command;
import cc.fascinated.account.Account;
import cc.fascinated.command.Command;
public class DeleteAccountCommand extends Command {
public DeleteAccountCommand() {
super("deleteaccount", "aetheria.command.deleteaccount");
}
@Override
public void execute(Account account, String[] args) {
}
}

View File

@ -0,0 +1,105 @@
package cc.fascinated.bot;
import cc.fascinated.config.Config;
import cc.fascinated.utils.Manager;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import org.bukkit.Bukkit;
import java.util.Timer;
import java.util.TimerTask;
@Getter @Log4j2
public class DiscordBot extends Manager {
/**
* How often we should update the Discord presence.
*/
private final int statusUpdateInterval = 1000 * 60 * 5;
/**
* The Discord bot instance.
*/
@Getter
private static JDA jda;
/**
* The thread that the bot runs on.
*/
private final Thread thread;
public DiscordBot() {
this.thread = new Thread(() -> {
log.info("Starting Discord bot...");
JDABuilder builder = JDABuilder.createDefault(Config.DISCORD_TOKEN.getAsString());
builder.disableCache(
CacheFlag.MEMBER_OVERRIDES,
CacheFlag.VOICE_STATE,
CacheFlag.ACTIVITY
);
try {
jda = builder.build();
jda.awaitReady();
log.info("Discord bot started successfully.");
} catch (Exception ex) {
log.error("Failed to start Discord bot.", ex);
return;
}
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
int playerCount = Bukkit.getOnlinePlayers().size();
jda.getPresence().setPresence(OnlineStatus.ONLINE, Activity.watching("over " + playerCount + " players"));
}
}, 0, statusUpdateInterval);
});
this.thread.setName("DiscordBot");
this.thread.start();
}
/**
* Sends a message to the Discord channel.
*
* @param channel the channel
* @param message the message
*/
public static void sendMessage(DiscordChannel channel, String message) {
TextChannel textChannel = jda.getTextChannelById(channel.getId());
if (textChannel == null) {
log.error("Could not find the text channel with the ID " + channel.getId());
return;
}
textChannel.sendMessage(message).queue();
}
/**
* Sends an embed to the Discord channel.
*
* @param channel the channel
* @param embed the embed
*/
public static void sendEmbed(DiscordChannel channel, EmbedBuilder embed) {
TextChannel textChannel = jda.getTextChannelById(channel.getId());
if (textChannel == null) {
log.error("Could not find the text channel with the ID " + channel.getId());
return;
}
textChannel.sendMessageEmbeds(embed.build()).queue();
}
@Override
public void onAetheriaDisable() {
log.info("Shutting down Discord bot...");
jda.shutdownNow();
}
}

View File

@ -0,0 +1,16 @@
package cc.fascinated.bot;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter @RequiredArgsConstructor
public enum DiscordChannel {
PLAYER_LOGS("1223161810157568020"),
VOTE_LOGS("1225868584522219570");
/**
* The ID of the Discord channel.
*/
private final String id;
}

View File

@ -54,7 +54,7 @@ public abstract class Command implements CommandExecutor, TabCompleter {
}
@Override
public boolean onCommand(@NotNull CommandSender commandSender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) {
public final boolean onCommand(@NotNull CommandSender commandSender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (this.permission != null && !commandSender.hasPermission(permission)) {
commandSender.sendMessage("§cYou do not have permission to execute this command.");
return true;
@ -67,7 +67,7 @@ public abstract class Command implements CommandExecutor, TabCompleter {
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender commandSender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) {
public final @Nullable List<String> onTabComplete(@NotNull CommandSender commandSender, org.bukkit.command.@NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (this.permission != null && !commandSender.hasPermission(permission)) {
return null;
}

View File

@ -14,6 +14,11 @@ public class CommandManager {
registerCommand(new GitCommand());
}
/**
* Registers a command.
*
* @param command The command to register.
*/
public static void registerCommand(Command command) {
if (command == null) {
throw new IllegalArgumentException("Command cannot be null.");

View File

@ -14,7 +14,7 @@ public enum Config {
INFLUXDB_TOKEN("influxdb.token"),
INFLUXDB_ORG("influxdb.org"),
INFLUXDB_BUCKET("influxdb.bucket"),
DISCORD_LOG_WEBHOOK("discord.log-webhook"),
DISCORD_TOKEN("discord.token"),
MOTD_HEADER("motd.header"),
MOTD_FORMAT("motd.format"),
MOTD_LIST("motd.motds"),

View File

@ -20,15 +20,6 @@ public class PlayerColorManager extends Manager {
*/
@Getter
private static final List<NamedTextColor> validColors = List.of(
// NamedTextColor.RED,
// NamedTextColor.GREEN,
// NamedTextColor.BLUE,
// NamedTextColor.YELLOW,
// NamedTextColor.AQUA,
// NamedTextColor.DARK_AQUA,
// NamedTextColor.GRAY,
// NamedTextColor.LIGHT_PURPLE,
// NamedTextColor.WHITE
NamedTextColor.DARK_BLUE,
NamedTextColor.DARK_GREEN,
NamedTextColor.DARK_AQUA,

View File

@ -1,11 +1,33 @@
package cc.fascinated.staffchat;
import cc.fascinated.account.Account;
import cc.fascinated.account.AccountManager;
import cc.fascinated.config.Lang;
import cc.fascinated.staffchat.command.StaffChatCommand;
import cc.fascinated.utils.Manager;
import org.bukkit.Bukkit;
public class StaffChatManager extends Manager {
public StaffChatManager() {
registerCommand(new StaffChatCommand());
}
/**
* Sends a message to all staff members.
*
* @param sender the account who sent the message
* @param message the message to send
*/
public static void sendMessage(Account sender, String message) {
AccountManager.getOnlineAccounts().stream()
.filter(account -> account.hasPermission("aetheria.command.staffchat"))
.forEach(account -> {
account.sendMessage(Lang.STAFF_CHAT_FORMAT.getAsString()
.replace("%player%", sender.getPlayer().getName())
.replace("%message%", message)
.replace("player-color", sender.getPlayerColorProfile().getColor().toString())
);
});
}
}

View File

@ -1,10 +1,9 @@
package cc.fascinated.staffchat.command;
import cc.fascinated.account.Account;
import cc.fascinated.account.AccountManager;
import cc.fascinated.command.Command;
import cc.fascinated.config.Lang;
import org.bukkit.Bukkit;
import cc.fascinated.staffchat.StaffChatManager;
public class StaffChatCommand extends Command {
@ -18,21 +17,6 @@ public class StaffChatCommand extends Command {
account.sendMessage(Lang.STAFF_CHAT_USAGE.getAsString());
return;
}
StringBuilder message = new StringBuilder();
for (String arg : args) {
message.append(arg).append(" ");
}
Bukkit.getOnlinePlayers().stream()
.filter(player -> player.hasPermission("aetheria.command.staffchat"))
.forEach(player -> {
Account staffAccount = AccountManager.getAccount(player.getUniqueId());
staffAccount.sendMessage(Lang.STAFF_CHAT_FORMAT.getAsString()
.replace("%player%", account.getPlayer().getName())
.replace("%message%", message.toString())
.replace("player-color", account.getPlayerColorProfile().getColor().toString())
);
});
StaffChatManager.sendMessage(account, String.join(" ", args));
}
}

View File

@ -1,6 +1,8 @@
package cc.fascinated.vote;
import cc.fascinated.account.Account;
import cc.fascinated.bot.DiscordBot;
import cc.fascinated.bot.DiscordChannel;
import cc.fascinated.command.CommandManager;
import cc.fascinated.config.Lang;
import cc.fascinated.playercolor.PlayerColorProfile;
@ -8,6 +10,9 @@ import cc.fascinated.utils.Manager;
import cc.fascinated.utils.MessageUtils;
import cc.fascinated.vote.command.VoteStatsCommand;
import com.vexsoftware.votifier.model.VotifierEvent;
import net.dv8tion.jda.api.EmbedBuilder;
import java.awt.*;
public class VoteManager extends Manager {
@ -28,5 +33,12 @@ public class VoteManager extends Manager {
account.sendMessage(Lang.VOTE_VOTED.getAsString()
.replace("%votes%", voteProfile.getTotalVotes() + "")
);
DiscordBot.sendEmbed(DiscordChannel.VOTE_LOGS, new EmbedBuilder()
.setTitle("Player Voted")
.setColor(Color.GREEN)
.addField("Player", account.getPlayer().getName(), true)
.addField("Votes", voteProfile.getTotalVotes() + "", true)
);
}
}

View File

@ -5,7 +5,7 @@ influxdb:
bucket: "aetheria"
discord:
log-webhook: "https://discord.com/api/webhooks/1223162714822807572/jkqXHdcf4ov7MTC4fxx8MI2rSCoQTHONua8VOJa3ie5OtHBthqd5MGM7WGd7oHF52OOm"
token: "MTEyOTEyMDY0NTk3Mjc2Njc3MA.G7VXPL.8iDzdTxScweAKByKnwY6PFcK07AehFfNvf_2Hk"
version-warning:
min-version: 763 # 1.20