Fishnets and Baubles

This commit is contained in:
Paul Reilly 2023-03-17 22:11:00 -05:00
parent 8f84583e4e
commit 31b0a8a3fe
50 changed files with 1489 additions and 550 deletions

View File

@ -23,8 +23,6 @@ repositories {
}
dependencies {
implementation 'org.projectlombok:lombok:1.18.20'
implementation 'org.postgresql:postgresql:42.2.20'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'com.github.Milkbowl:VaultAPI:1.7.1'
implementation 'com.google.code.gson:gson:2.8.7'

View File

View File

@ -0,0 +1,14 @@
# The SQL driver to use.
driver=jdbc
# The type of database to use.
databaseType=mysql
# The database host.
host=localhost
# The database port.
port=5432
# The database file name.
databaseFile=database.db
# The database username.
username=admin
# The database password.
password=default

View File

@ -0,0 +1,10 @@
name: Traverse
version: '1.0.0'
main: mc.unraveled.reforged.plugin.Traverse
api-version: 1.19
authors: [ SimplexDevelopment ]
description: "A plugin designed for the Unraveled: Reforged server."
website: https://github.com/SimplexDevelopment/Traverse
depend: [ Vault ]
softdepend: [ EssentialsX, EssentialsXSpawn ]

Binary file not shown.

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path: reactor-core-3.4.10.jar reactive-streams-1.0.3.jar

View File

@ -1,9 +0,0 @@
package mc.unraveled.reforged.api;
public interface Locker {
Object lock = new Object();
default Object lock() {
return lock;
}
}

View File

@ -1,13 +1,12 @@
package mc.unraveled.reforged.banning;
import lombok.Getter;
import mc.unraveled.reforged.api.Serializable;
import mc.unraveled.reforged.util.Pair;
import mc.unraveled.reforged.util.Utilities;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@Getter
public abstract class AbstractBan implements Serializable<AbstractBan> {
private final String uuid;
private final String ip;
@ -38,6 +37,38 @@ public abstract class AbstractBan implements Serializable<AbstractBan> {
);
}
public String getUuid() {
return uuid;
}
public String getIp() {
return ip;
}
public String getSource() {
return source;
}
public String getReason() {
return reason;
}
public long getPropagated() {
return propagated;
}
public long getExpiry() {
return expiry;
}
public List<Pair<String, String>> getContentPairs() {
return contentPairs;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
@ -48,8 +79,7 @@ public abstract class AbstractBan implements Serializable<AbstractBan> {
}
@Override
public AbstractBan deserialize(String formatted) {
char delimiter = ':';
public AbstractBan deserialize(@NotNull String formatted) {
char end = ';';
char uuid = 'u';
char ip = 'i';

View File

@ -1,46 +1,44 @@
package mc.unraveled.reforged.banning;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.api.Baker;
import mc.unraveled.reforged.api.Locker;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.storage.DBBan;
import mc.unraveled.reforged.storage.DBUser;
import org.bukkit.OfflinePlayer;
import java.sql.Date;
import java.time.Instant;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
public final class BanManager implements Locker, Baker {
@Getter
public final class BanManager implements Baker {
private final Traverse plugin;
private Set<AbstractBan> storedBans; // This should only be reassigned by the baker.
@Getter
private boolean baked = false; // This should only be reassigned by the baker.
@SneakyThrows
public BanManager(Traverse plugin) {
this.storedBans = new HashSet<>();
this.plugin = plugin;
synchronized (lock()) {
DBBan banHandler = new DBBan(plugin.getSQLManager().establish());
storedBans.addAll(banHandler.all());
banHandler.close();
lock().wait(1000);
}
DBBan banHandler = new DBBan(plugin.getSQLManager().establish());
storedBans.addAll(banHandler.all());
banHandler.close();
bake();
}
public Traverse getPlugin() {
return plugin;
}
public boolean isBaked() {
return baked;
}
public void insert(AbstractBan ban) {
if (baked) throw new IllegalStateException("Cannot insert into a baked list.");
lock().notify();
storedBans.add(ban);
DBBan db = new DBBan(plugin.getSQLManager().establish());
db.insert(ban);
@ -50,8 +48,7 @@ public final class BanManager implements Locker, Baker {
public void eject(AbstractBan ban) {
if (baked) throw new IllegalStateException("Cannot eject from a baked list.");
lock().notify();
storedBans.remove(ban);
DBBan db = new DBBan(plugin.getSQLManager().establish());
db.delete(ban);
db.close();
@ -66,13 +63,22 @@ public final class BanManager implements Locker, Baker {
public boolean isBanned(OfflinePlayer player) {
return storedBans.stream()
.filter(AbstractBan::isActive)
.filter(ban -> {
Date date = new Date(ban.getExpiry());
if (date.before(Date.from(Instant.now()))) {
eject(ban);
return false;
} else {
return true;
}
})
.anyMatch(ban -> ban.getUuid().equalsIgnoreCase(
player.getUniqueId().toString()));
}
public void save() {
if (!baked) throw new IllegalStateException("Cannot save an unbaked list.");
lock().notify();
DBBan banHandler = new DBBan(plugin.getSQLManager().establish());
storedBans.forEach(banHandler::insert);
@ -83,7 +89,6 @@ public final class BanManager implements Locker, Baker {
public void bake() {
if (baked) return;
lock().notify();
storedBans = storedBans.stream().collect(Collectors.toUnmodifiableSet());
baked = true;
@ -93,7 +98,6 @@ public final class BanManager implements Locker, Baker {
public void unbake() {
if (!baked) return;
lock().notify();
storedBans = new HashSet<>(storedBans);
baked = false;

View File

@ -0,0 +1,67 @@
package mc.unraveled.reforged.command;
import mc.unraveled.reforged.api.annotations.CommandInfo;
import mc.unraveled.reforged.banning.AbstractBan;
import mc.unraveled.reforged.command.base.AbstractCommandBase;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.util.ComponentBuilder;
import mc.unraveled.reforged.util.Utilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@CommandInfo(
name = "baninfo",
description = "Shows information about a ban",
usage = "/baninfo <player>",
aliases = {"bi", "bandata"}
)
public class BanInfoCMD extends AbstractCommandBase {
public BanInfoCMD(@NotNull Traverse plugin) {
super(plugin, "baninfo");
}
@Override
public Component cmd(CommandSender sender, String[] args) {
if (args.length != 1) {
return Component.text("Usage: /baninfo <player>");
}
OfflinePlayer player = getPlugin().getServer().getOfflinePlayer(args[0]);
AbstractBan ban = getPlugin().getBanManager().getBan(player);
if (ban == null) {
return Component.text("That player is not banned.");
}
NamedTextColor GENERAL = NamedTextColor.YELLOW;
NamedTextColor INFO = NamedTextColor.GREEN;
NamedTextColor DETAIL = NamedTextColor.RED;
return ComponentBuilder.begin()
.append("Ban info for ", GENERAL)
.append(player.getName(), DETAIL)
.append(":", GENERAL)
.append("\nUUID: ", INFO)
.append(ban.getUuid(), DETAIL)
.append("\nIP: ", INFO)
.append(ban.getIp(), DETAIL)
.append("\nReason: ", INFO)
.append(ban.getReason(), DETAIL)
.append("\nBanned by: ", INFO)
.append(ban.getSource(), DETAIL)
.append("\nBanned on: ", INFO)
.append(ban.getPropagated(), DETAIL)
.append("\nExpires on: ", INFO)
.append(ban.getExpiry(), DETAIL).build();
}
@Override
public List<String> tab(CommandSender sender, String[] args) {
return Utilities.playerCompletions(args[0]);
}
}

View File

@ -44,7 +44,7 @@ public class GroupCMD extends AbstractCommandBase {
Arrays.stream(ranks)
.filter(rank -> rank.getAttachment().getName().equalsIgnoreCase(group))
.findFirst()
.ifPresentOrElse(rankContext::setContext, () -> invalid.set(true));
.ifPresentOrElse(rankContext::setState, () -> invalid.set(true));
if (invalid.get()) return Component.text("Invalid group!").color(NamedTextColor.RED);
@ -79,24 +79,24 @@ public class GroupCMD extends AbstractCommandBase {
}
if (actionType) {
manager.insertPlayer(rankContext.getContext(), player);
manager.insertPlayer(rankContext.getState(), player);
manager.bake();
manager.save();
return Component.text("Added player " + player.getName() + " to group " + group + "!").color(NamedTextColor.GREEN);
} else {
manager.ejectPlayer(rankContext.getContext(), player);
manager.ejectPlayer(rankContext.getState(), player);
manager.bake();
manager.save();
return Component.text("Removed player " + player.getName() + " from group " + group + "!").color(NamedTextColor.GREEN);
}
case "permission":
if (actionType) {
manager.insertPermission(rankContext.getContext(), value);
manager.insertPermission(rankContext.getState(), value);
manager.bake();
manager.save();
return Component.text("Added permission " + value + " to group " + group + "!").color(NamedTextColor.GREEN);
} else {
manager.ejectPermission(rankContext.getContext(), value);
manager.ejectPermission(rankContext.getState(), value);
manager.bake();
manager.save();
return Component.text("Removed permission " + value + " from group " + group + "!").color(NamedTextColor.GREEN);

View File

@ -1,4 +0,0 @@
package mc.unraveled.reforged.command;
public class JailCMD {
}

View File

@ -0,0 +1,44 @@
package mc.unraveled.reforged.command;
import mc.unraveled.reforged.api.annotations.CommandInfo;
import mc.unraveled.reforged.command.base.AbstractCommandBase;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.util.Utilities;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@CommandInfo(name = "kick",
description = "Kick a player.",
usage = "/kick <player> <reason>",
aliases = {"k"})
public class KickCMD extends AbstractCommandBase {
public KickCMD(@NotNull Traverse plugin) {
super(plugin, "kick", true);
}
@Override
public Component cmd(CommandSender sender, String[] args) {
if (args.length < 2) return Component.text("Usage: /kick <player> <reason>");
Player target = Bukkit.getPlayer(args[0]);
if (target == null) return MessageDefaults.MSG_NOT_FOUND;
String reason = String.join(" ", args).substring(args[0].length() + 1);
target.kick(Component.text(reason));
broadcast(target.getName() + " has been kicked for " + reason + ".");
return Component.text("You have kicked " + target.getName() + " for " + reason + ".");
}
@Override
public List<String> tab(CommandSender sender, String[] args) {
if (args.length == 1) return Utilities.playerCompletions(args[0]);
return super.tab(sender, args);
}
}

View File

@ -1,4 +1,72 @@
package mc.unraveled.reforged.command;
public class LockCMD {
import mc.unraveled.reforged.api.annotations.CommandInfo;
import mc.unraveled.reforged.command.base.AbstractCommandBase;
import mc.unraveled.reforged.data.InfractionData;
import mc.unraveled.reforged.data.PlayerData;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.util.Utilities;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@CommandInfo(
name = "lock",
usage = "/<command> <player> <on | off>",
description = "Prevents a player from inputting any actions."
)
public class LockCMD extends AbstractCommandBase {
public LockCMD(@NotNull Traverse plugin) {
super(plugin, "lock");
}
@Override
public Component cmd(CommandSender sender, String[] args) {
if (args.length != 2) {
return Component.text("Usage: /lock <player> <on | off>");
}
Player player = Bukkit.getPlayer(args[0]);
if (player == null) {
return Component.text("Player not found.");
}
PlayerData data = getPlugin().getDataManager().getPlayerData(player.getUniqueId());
if (data == null) {
return Component.text("PlayerData for target user cannot be found!");
}
switch (args[1]) {
case "on" -> {
data.getInfractionData().setLocked(true);
data.getInfractionData().increment();
return Component.text("Locked " + player.getName() + ".");
}
case "off" -> {
data.getInfractionData().setLocked(false);
return Component.text("Unlocked " + player.getName() + ".");
}
default -> {
return Component.text("Usage: /lock <player> <on | off>");
}
}
}
@Override
public List<String> tab(CommandSender sender, String[] args) {
if (args.length == 1) {
return Utilities.playerCompletions(args[0]);
}
if (args.length == 2) {
return Utilities.stringCompletions(args[1], "on", "off");
}
return super.tab(sender, args);
}
}

View File

@ -1,6 +1,7 @@
package mc.unraveled.reforged.command.base;
package mc.unraveled.reforged.command;
import mc.unraveled.reforged.api.annotations.CommandInfo;
import mc.unraveled.reforged.command.base.AbstractCommandBase;
import mc.unraveled.reforged.data.InfractionData;
import mc.unraveled.reforged.data.PlayerData;
import mc.unraveled.reforged.permission.Rank;
@ -24,7 +25,7 @@ public class PlayerDataCMD extends AbstractCommandBase {
@Override
public Component cmd(CommandSender sender, String[] args) {
switch (args.length) {
case 0:
case 0 -> {
if (sender instanceof Player player) {
PlayerData data = getPlugin().getDataManager().getPlayerData(player.getUniqueId());
@ -46,8 +47,8 @@ public class PlayerDataCMD extends AbstractCommandBase {
return Component.text(sb);
} else return Component.text("This command can only be used by players!");
case 2:
}
case 2 -> {
if (args[1].equalsIgnoreCase("info")) {
Player target = getPlugin().getServer().getPlayer(args[0]);
if (target == null) return MessageDefaults.MSG_NOT_FOUND;
@ -73,7 +74,8 @@ public class PlayerDataCMD extends AbstractCommandBase {
} else {
return usage();
}
case 3:
}
case 3 -> {
if (args[1].equalsIgnoreCase("reset")) {
Player target = getPlugin().getServer().getPlayer(args[0]);
if (target == null) return MessageDefaults.MSG_NOT_FOUND;
@ -127,10 +129,10 @@ public class PlayerDataCMD extends AbstractCommandBase {
return Component.text("Invalid data type!").color(NamedTextColor.RED);
}
}
case 4:
}
case 4 -> {
Player target = getPlugin().getServer().getPlayer(args[0]);
if (target == null) return MessageDefaults.MSG_NOT_FOUND;
if (args[1].equalsIgnoreCase("set")) {
switch (args[2]) {
case "rank":
@ -183,9 +185,12 @@ public class PlayerDataCMD extends AbstractCommandBase {
} else {
return usage();
}
default:
}
default -> {
return usage();
}
}
return null;
}
private Component usage() {

View File

@ -0,0 +1,46 @@
package mc.unraveled.reforged.command;
import mc.unraveled.reforged.api.annotations.CommandInfo;
import mc.unraveled.reforged.command.base.AbstractCommandBase;
import mc.unraveled.reforged.plugin.Traverse;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@CommandInfo(name = "staffchat",
description = "Toggle staff chat.",
usage = "/staffchat [message]",
aliases = {"sc", "ac", "o"})
public class StaffChatCMD extends AbstractCommandBase {
public StaffChatCMD(@NotNull Traverse plugin) {
super(plugin, "staff", true);
}
@Override
public Component cmd(CommandSender sender, String[] args) {
if (args.length == 0) {
if (sender instanceof ConsoleCommandSender) {
return Component.text("You must be in game to toggle staff chat.");
}
getPlugin().getStaffChat().toggleChat(((Player) sender).getUniqueId());
boolean chatStat = getPlugin().getStaffChat().inChat(((Player) sender).getUniqueId());
return Component.text("Staff chat toggled " + (chatStat ? "on" : "off") + ".");
}
String message = String.join(" ", args);
getPlugin().getStaffChat().distribute(sender, message);
return null;
}
@Override
public List<String> tab(CommandSender sender, String[] args) {
return super.tab(sender, args);
}
}

View File

@ -1,6 +1,5 @@
package mc.unraveled.reforged.command.base;
import lombok.Getter;
import mc.unraveled.reforged.api.ICommandBase;
import mc.unraveled.reforged.permission.TPermission;
import mc.unraveled.reforged.plugin.Traverse;
@ -12,7 +11,6 @@ import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -20,7 +18,6 @@ import java.util.List;
import java.util.UUID;
public abstract class AbstractCommandBase extends TPermission implements ICommandBase {
@Getter
private final Traverse plugin;
/**
@ -29,7 +26,7 @@ public abstract class AbstractCommandBase extends TPermission implements IComman
* @param permissionMessage The message to send when the user does not have the permission to run the command.
* @param allowConsole Whether to allow the command to be run anywhere, or only in game.
*/
public AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission, String permissionMessage, boolean allowConsole) {
protected AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission, String permissionMessage, boolean allowConsole) {
super(permission, permissionMessage, allowConsole);
this.plugin = plugin;
}
@ -39,7 +36,7 @@ public abstract class AbstractCommandBase extends TPermission implements IComman
* @param permission The permission the user should have to run the command
* @param permissionMessage The message to send when the user does not have the permission to run the command.
*/
public AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission, String permissionMessage) {
protected AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission, String permissionMessage) {
this(plugin, permission, permissionMessage, true);
}
@ -48,20 +45,24 @@ public abstract class AbstractCommandBase extends TPermission implements IComman
* @param permission The permission the user should have to run the command
* @param allowConsole Whether to allow the command to be run anywhere, or only in game.
*/
public AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission, boolean allowConsole) {
this(plugin, permission, "You do not have permission to use this command!", allowConsole);
protected AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission, boolean allowConsole) {
this(plugin, permission, MessageDefaults.MSG_NO_PERMS.toString(), allowConsole);
}
/**
* @param plugin The plugin that owns this command
* @param permission The permission the user should have to run the command
*/
public AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission) {
this(plugin, permission, "You do not have permission to use this command!", true);
protected AbstractCommandBase(@NotNull Traverse plugin, @NotNull String permission) {
this(plugin, permission, MessageDefaults.MSG_NO_PERMS.toString(), true);
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String lbl, String[] args) {
if (lbl.equalsIgnoreCase("")) {
return false;
}
if (!hasPermission(sender)) {
sender.sendMessage(MessageDefaults.MSG_NO_PERMS);
return true;
@ -132,12 +133,8 @@ public abstract class AbstractCommandBase extends TPermission implements IComman
Bukkit.getServer().broadcast(msg(text, color));
}
public void enablePlugin(Plugin plugin) {
Bukkit.getServer().getPluginManager().enablePlugin(plugin);
}
public void disablePlugin(Plugin plugin) {
Bukkit.getServer().getPluginManager().disablePlugin(plugin);
public Traverse getPlugin() {
return plugin;
}
protected static class MessageDefaults {
@ -149,5 +146,8 @@ public abstract class AbstractCommandBase extends TPermission implements IComman
public static final Component MSG_NOT_ENOUGH_ARGS = Component.text("Not enough arguments.").color(NamedTextColor.RED);
public static final Component MUTED = Component.text("You are muted!").color(NamedTextColor.RED);
public static final Component BANNED = Component.text("You are banned!").color(NamedTextColor.RED);
private MessageDefaults() {
throw new AssertionError();
}
}
}

View File

@ -1,22 +1,20 @@
package mc.unraveled.reforged.config;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.api.Baker;
import mc.unraveled.reforged.plugin.Traverse;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
@Getter
public abstract class Yaml extends YamlConfiguration implements Baker {
private final String fileName;
private final File dataFolder;
private final Traverse plugin;
private final File yamlFile;
@Getter
private boolean baked = false;
Yaml(@NotNull Traverse plugin, String fileName, File dataFolder, boolean copyDefaults) {
@ -40,15 +38,38 @@ public abstract class Yaml extends YamlConfiguration implements Baker {
this(plugin, fileName, false);
}
public String getFileName() {
return fileName;
}
public File getDataFolder() {
return dataFolder;
}
public Traverse getPlugin() {
return plugin;
}
public File getYamlFile() {
return yamlFile;
}
public boolean isBaked() {
return baked;
}
/**
* Makes the file read only after saving to disk.
*/
@SneakyThrows
@Override
public void bake() {
if (baked) return;
super.save(yamlFile);
try {
super.save(yamlFile);
} catch (IOException e) {
Bukkit.getLogger().severe(e.getMessage());
}
if (yamlFile.setWritable(false)) {
getPlugin().getLogger().info("Baked " + getFileName());
@ -73,17 +94,23 @@ public abstract class Yaml extends YamlConfiguration implements Baker {
}
}
@SneakyThrows
public void saveToFile() {
unbake();
super.save(yamlFile);
try {
super.save(yamlFile);
} catch (IOException e) {
Bukkit.getLogger().severe(e.getMessage());
}
bake();
}
@SneakyThrows
public void loadFromFile() {
unbake();
super.load(yamlFile);
try {
super.load(yamlFile);
} catch (IOException | InvalidConfigurationException e) {
Bukkit.getLogger().severe(e.getMessage());
}
bake();
}
}

View File

@ -1,8 +1,7 @@
package mc.unraveled.reforged.config;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.plugin.Traverse;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.jetbrains.annotations.NotNull;
@ -11,7 +10,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Getter
public class YamlManager {
private final List<Yaml> configurations = new ArrayList<>();
private final Traverse plugin;
@ -20,6 +18,14 @@ public class YamlManager {
this.plugin = plugin;
}
public List<Yaml> getConfigurations() {
return configurations;
}
public Traverse getPlugin() {
return plugin;
}
public Builder bldr() {
return new Builder(plugin);
}
@ -32,14 +38,20 @@ public class YamlManager {
configurations.remove(yaml);
}
@SneakyThrows
public void load(@NotNull Yaml yaml) {
yaml.load(yaml.getYamlFile());
try {
yaml.load(yaml.getYamlFile());
} catch (IOException | InvalidConfigurationException e) {
Bukkit.getLogger().severe("Failed to load " + yaml.getYamlFile().getName() + "!");
}
}
@SneakyThrows
public void save(@NotNull Yaml yaml) {
yaml.save(yaml.getYamlFile());
try {
yaml.save(yaml.getYamlFile());
} catch (IOException e) {
Bukkit.getLogger().severe("Failed to save " + yaml.getYamlFile().getName() + "!");
}
}
public void loadAll() {

View File

@ -1,11 +1,8 @@
package mc.unraveled.reforged.data;
import lombok.SneakyThrows;
import mc.unraveled.reforged.api.Baker;
import mc.unraveled.reforged.api.Locker;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.storage.DBUser;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
@ -13,7 +10,8 @@ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public final class DataManager implements Baker, Locker {
public final class DataManager implements Baker {
public static final String MANAGER_IS_BAKED = "Cannot remove player data while the data manager is baked.";
private final Traverse plugin;
private Set<PlayerData> playerDataCache = new HashSet<>(); // Should only be set by the baker.
private boolean baked = false; // Should only be set by the baker.
@ -57,19 +55,19 @@ public final class DataManager implements Baker, Locker {
}
public void removePlayerData(PlayerData data) {
if (baked) throw new IllegalStateException("Cannot remove player data while the data manager is baked.");
if (baked) throw new IllegalStateException(MANAGER_IS_BAKED);
playerDataCache.remove(data);
}
public void removePlayerData(UUID uuid) {
if (baked) throw new IllegalStateException("Cannot remove player data while the data manager is baked.");
if (baked) throw new IllegalStateException(MANAGER_IS_BAKED);
playerDataCache.removeIf(data -> data.getUuid().equals(uuid));
}
public void removePlayerData(String playerName) {
if (baked) throw new IllegalStateException("Cannot remove player data while the data manager is baked.");
if (baked) throw new IllegalStateException(MANAGER_IS_BAKED);
playerDataCache.removeIf(data -> data.getUserName().equals(playerName));
}
@ -86,31 +84,21 @@ public final class DataManager implements Baker, Locker {
user.close();
}
@SneakyThrows
@Override
public void bake() {
if (baked) return;
synchronized (lock()) {
this.playerDataCache = playerDataCache.stream().collect(Collectors.toUnmodifiableSet());
lock().wait(1000);
}
this.playerDataCache = playerDataCache.stream().collect(Collectors.toUnmodifiableSet());
this.baked = true;
lock().notify();
}
@SneakyThrows
@Override
public void unbake() {
if (!baked) return;
synchronized (lock()) {
this.playerDataCache = new HashSet<>(playerDataCache);
lock().wait(1000);
}
this.playerDataCache = new HashSet<>(playerDataCache);
this.baked = false;
lock().notify();
}
}

View File

@ -1,7 +1,5 @@
package mc.unraveled.reforged.data;
import lombok.Getter;
import lombok.Setter;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.storage.DBInfraction;
import org.bukkit.OfflinePlayer;
@ -12,29 +10,13 @@ import java.util.HashMap;
import java.util.Map;
public class InfractionData {
private static final Map<OfflinePlayer, InfractionData> playerInfractionDataMap = new HashMap<>() {{
DBInfraction infraction = new DBInfraction(JavaPlugin.getPlugin(Traverse.class).getSQLManager().establish());
for (InfractionData data : infraction.getInfractionsList()) {
put(data.getPlayer(), data);
}
}};
private static final Map<OfflinePlayer, InfractionData> playerInfractionDataMap = new HashMap<>();
@Getter
private final OfflinePlayer player;
@Getter
private int infractions = 0;
@Getter
@Setter
private boolean muted = false;
@Getter
@Setter
private boolean frozen = false;
@Getter
@Setter
private boolean locked = false;
@Getter
@Setter
private boolean jailed = false;
public InfractionData(OfflinePlayer player) {
@ -48,6 +30,11 @@ public class InfractionData {
this.frozen = frozen;
this.locked = locked;
this.jailed = jailed;
DBInfraction infraction = new DBInfraction(JavaPlugin.getPlugin(Traverse.class).getSQLManager().establish());
for (InfractionData data : infraction.getInfractionsList()) {
playerInfractionDataMap.put(data.getPlayer(), data);
}
}
public static InfractionData getCachedInfractionData(OfflinePlayer player) {
@ -61,6 +48,50 @@ public class InfractionData {
return data;
}
public OfflinePlayer getPlayer() {
return player;
}
public int getInfractions() {
return infractions;
}
public void setInfractions(int infractions) {
this.infractions = infractions;
}
public boolean isMuted() {
return muted;
}
public void setMuted(boolean muted) {
this.muted = muted;
}
public boolean isFrozen() {
return frozen;
}
public void setFrozen(boolean frozen) {
this.frozen = frozen;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public boolean isJailed() {
return jailed;
}
public void setJailed(boolean jailed) {
this.jailed = jailed;
}
public void increment() {
infractions++;
}

View File

@ -1,14 +1,22 @@
package mc.unraveled.reforged.data;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.kyori.adventure.text.Component;
/**
* Login Message Information Bean
*/
@Data
@NoArgsConstructor
public class LoginInfo {
private Component loginMessage;
public LoginInfo() {
this.loginMessage = Component.empty();
}
public Component getLoginMessage() {
return loginMessage;
}
public void setLoginMessage(Component loginMessage) {
this.loginMessage = loginMessage;
}
}

View File

@ -1,30 +1,27 @@
package mc.unraveled.reforged.data;
import lombok.Getter;
import mc.unraveled.reforged.api.Baker;
import mc.unraveled.reforged.listening.AbstractListener;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.storage.DBUser;
import mc.unraveled.reforged.util.Pair;
import net.kyori.adventure.text.Component;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
@Getter
public class LoginManager implements Baker {
private final Traverse plugin;
private Set<Pair<OfflinePlayer, LoginInfo>> dataSet = new HashSet<>(); // VALUE ONLY MODIFIED BY BAKER
private boolean baked = false;
public LoginManager(Traverse plugin) {
public LoginManager(@NotNull Traverse plugin) {
this.plugin = plugin;
DBUser user = new DBUser(plugin.getSQLManager().establish());
@ -36,6 +33,18 @@ public class LoginManager implements Baker {
new LoginListener(plugin);
}
public Traverse getPlugin() {
return plugin;
}
public Set<Pair<OfflinePlayer, LoginInfo>> getDataSet() {
return dataSet;
}
public boolean isBaked() {
return baked;
}
public void add(OfflinePlayer player, LoginInfo data) {
dataSet.add(new Pair<>(player, data));
}

View File

@ -1,14 +1,10 @@
package mc.unraveled.reforged.data;
import lombok.AllArgsConstructor;
import lombok.Data;
import mc.unraveled.reforged.permission.Rank;
import java.util.Date;
import java.util.UUID;
@Data
@AllArgsConstructor
public class PlayerData {
private UUID uuid;
private String userName;
@ -18,4 +14,79 @@ public class PlayerData {
private Date lastLogin;
private String loginMessage;
private InfractionData infractionData;
public PlayerData(PlayerDataBuilder builder) {
this.uuid = builder.getUuid();
this.userName = builder.getUserName();
this.rank = builder.getRank();
this.playtime = builder.getPlaytime();
this.coins = builder.getCoins();
this.lastLogin = builder.getLastLogin();
this.loginMessage = builder.getLoginMessage();
this.infractionData = builder.getInfractionData();
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Rank getRank() {
return rank;
}
public void setRank(Rank rank) {
this.rank = rank;
}
public long getPlaytime() {
return playtime;
}
public void setPlaytime(long playtime) {
this.playtime = playtime;
}
public int getCoins() {
return coins;
}
public void setCoins(int coins) {
this.coins = coins;
}
public Date getLastLogin() {
return lastLogin;
}
public void setLastLogin(Date lastLogin) {
this.lastLogin = lastLogin;
}
public String getLoginMessage() {
return loginMessage;
}
public void setLoginMessage(String loginMessage) {
this.loginMessage = loginMessage;
}
public InfractionData getInfractionData() {
return infractionData;
}
public void setInfractionData(InfractionData infractionData) {
this.infractionData = infractionData;
}
}

View File

@ -0,0 +1,93 @@
package mc.unraveled.reforged.data;
import mc.unraveled.reforged.permission.Rank;
import java.util.Date;
import java.util.UUID;
public class PlayerDataBuilder {
private UUID uuid;
private String userName;
private Rank rank;
private long playtime;
private int coins;
private Date lastLogin;
private String loginMessage;
private InfractionData infractionData;
UUID getUuid() {
return uuid;
}
public PlayerDataBuilder setUuid(UUID uuid) {
this.uuid = uuid;
return this;
}
String getUserName() {
return userName;
}
public PlayerDataBuilder setUserName(String userName) {
this.userName = userName;
return this;
}
Rank getRank() {
return rank;
}
public PlayerDataBuilder setRank(Rank rank) {
this.rank = rank;
return this;
}
long getPlaytime() {
return playtime;
}
public PlayerDataBuilder setPlaytime(long playtime) {
this.playtime = playtime;
return this;
}
int getCoins() {
return coins;
}
public PlayerDataBuilder setCoins(int coins) {
this.coins = coins;
return this;
}
Date getLastLogin() {
return lastLogin;
}
public PlayerDataBuilder setLastLogin(Date lastLogin) {
this.lastLogin = lastLogin;
return this;
}
String getLoginMessage() {
return loginMessage;
}
public PlayerDataBuilder setLoginMessage(String loginMessage) {
this.loginMessage = loginMessage;
return this;
}
InfractionData getInfractionData() {
return infractionData;
}
public PlayerDataBuilder setInfractionData(InfractionData infractionData) {
this.infractionData = infractionData;
return this;
}
public PlayerDataBuilder compile() {
return this;
}
}

View File

@ -0,0 +1,50 @@
package mc.unraveled.reforged.data;
import mc.unraveled.reforged.permission.RankAttachment;
import mc.unraveled.reforged.plugin.Traverse;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class StaffChat {
private final Set<UUID> playersInChat = new HashSet<>();
private final Traverse plugin;
public StaffChat(Traverse plugin) {
this.plugin = plugin;
}
public boolean inChat(UUID uuid) {
return playersInChat.contains(uuid);
}
public void toggleChat(UUID uuid) {
if (inChat(uuid)) {
playersInChat.remove(uuid);
} else {
playersInChat.add(uuid);
}
}
public Component formatStaffChatMessage(CommandSender player, String message) {
RankAttachment rank = plugin.getRankManager().getRank(player).getAttachment();
String legacyStaffFormat = "&8[&bStaff&8]&r";
String playerName = "&c" + player.getName() + "&r";
String rankFormat = "&8[" + rank.getColor() + rank.getTag() + "&8]&r";
String appended = String.format("%s %s %s: %s", legacyStaffFormat, playerName, rankFormat, message);
return LegacyComponentSerializer.legacyAmpersand().deserialize(appended);
}
public void distribute(CommandSender source, String message) {
plugin.getServer().getOnlinePlayers().stream()
.filter(player -> player.hasPermission("traverse.staff"))
.forEach(player -> player.sendMessage(formatStaffChatMessage(source, message)));
}
}

View File

@ -1,6 +1,5 @@
package mc.unraveled.reforged.economy;
import lombok.Getter;
import mc.unraveled.reforged.plugin.Traverse;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
@ -9,20 +8,16 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.*;
@Getter
public class EconomyManager {
private final RegisteredServiceProvider<Economy> rsp;
private final Map<Player, List<EconomyRequest>> requests = new HashMap<>(); // This is NOT persistent.
private final Map<UUID, List<EconomyRequest>> requests = new HashMap<>(); // This is NOT persistent.
private final Economy economy;
public EconomyManager(@NotNull Traverse plugin) {
if (plugin.getServer().getPluginManager().getPlugin("Vault") == null)
throw new RuntimeException("Vault is REQUIRED!");
throw new MissingResourceException("Vault is REQUIRED!", "Vault", "VaultAPI");
rsp = plugin.getServer().getServicesManager().getRegistration(Economy.class);
@ -31,6 +26,18 @@ public class EconomyManager {
economy = rsp.getProvider();
}
public RegisteredServiceProvider<Economy> getRsp() {
return rsp;
}
public Map<UUID, List<EconomyRequest>> getRequests() {
return requests;
}
public Economy getEconomy() {
return economy;
}
public EconomyResponse newAccount(OfflinePlayer player) {
return economy.createBank(player.getName(), player);
}
@ -42,10 +49,10 @@ public class EconomyManager {
public EconomyRequest request(@NotNull OfflinePlayer from, @NotNull OfflinePlayer to, int amount) {
EconomyRequest request = new EconomyRequest(this, (Player) from, (Player) to, amount);
if (requests.containsKey(to)) {
requests.get(to).add(request);
if (requests.containsKey(to.getUniqueId())) {
requests.get(to.getUniqueId()).add(request);
} else {
requests.put((Player) to, List.of(request));
requests.put(to.getUniqueId(), List.of(request));
}
return request;

View File

@ -1,18 +1,13 @@
package mc.unraveled.reforged.economy;
import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.text.Component;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.entity.Player;
public class EconomyRequest {
@Getter
private final Player sender;
@Getter
private final Player target;
@Getter
private final int amount;
private final EconomyManager economy;
@ -23,6 +18,18 @@ public class EconomyRequest {
this.economy = economy;
}
public Player getSender() {
return sender;
}
public Player getTarget() {
return target;
}
public int getAmount() {
return amount;
}
public EconomyResponse accept() {
EconomyResponse r = economy.withdraw(target, amount);
if (r.transactionSuccess()) {
@ -34,7 +41,7 @@ public class EconomyRequest {
sender.sendMessage(Component.text("Your request has been accepted."));
target.sendMessage(Component.text("You have accepted " + sender.getName() + "'s request."));
economy.getRequests().get(target).remove(this);
economy.getRequests().get(target.getUniqueId()).remove(this);
return r;
}
@ -43,6 +50,6 @@ public class EconomyRequest {
sender.sendMessage(Component.text("Your request has been denied."));
target.sendMessage(Component.text("You have denied " + sender.getName() + "'s request."));
economy.getRequests().get(target).remove(this);
economy.getRequests().get(target.getUniqueId()).remove(this);
}
}

View File

@ -0,0 +1,20 @@
package mc.unraveled.reforged.gui;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
public abstract class AbstractInventory {
private final Inventory inventory;
protected AbstractInventory(String title, InventoryType type) {
this.inventory = Bukkit.createInventory(null, type, Component.text(title));
}
public Inventory getInventory() {
return inventory;
}
public abstract void update();
}

View File

@ -1,10 +1,16 @@
package mc.unraveled.reforged.listening;
import lombok.Data;
import mc.unraveled.reforged.plugin.Traverse;
import org.bukkit.event.Listener;
@Data
public class AbstractListener implements Listener {
private final Traverse plugin;
public AbstractListener(Traverse plugin) {
this.plugin = plugin;
}
public Traverse getPlugin() {
return plugin;
}
}

View File

@ -2,6 +2,7 @@ package mc.unraveled.reforged.listening;
import mc.unraveled.reforged.data.InfractionData;
import mc.unraveled.reforged.data.PlayerData;
import mc.unraveled.reforged.data.PlayerDataBuilder;
import mc.unraveled.reforged.permission.Rank;
import mc.unraveled.reforged.plugin.Traverse;
import org.bukkit.entity.Player;
@ -22,14 +23,17 @@ public class PlayerDataListener extends AbstractListener {
PlayerData data = getPlugin().getDataManager().getPlayerData(player.getUniqueId());
if (data == null) {
data = new PlayerData(player.getUniqueId(),
player.getName(),
Rank.NON_OP,
0L,
0,
Date.from(Instant.now()),
null,
InfractionData.getCachedInfractionData(player));
PlayerDataBuilder builder = new PlayerDataBuilder()
.setUuid(player.getUniqueId())
.setUserName(player.getName())
.setRank(Rank.NON_OP)
.setPlaytime(0L)
.setCoins(0)
.setLastLogin(Date.from(Instant.now()))
.setLoginMessage(null)
.setInfractionData(InfractionData.getCachedInfractionData(player))
.compile();
data = new PlayerData(builder);
getPlugin().getDataManager().addPlayerData(data);
}

View File

@ -0,0 +1,28 @@
package mc.unraveled.reforged.listening;
import io.papermc.paper.event.player.AsyncChatEvent;
import mc.unraveled.reforged.plugin.Traverse;
import net.kyori.adventure.text.Component;
import org.bukkit.event.EventHandler;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class StaffChatListener extends AbstractListener {
public StaffChatListener(Traverse plugin) {
super(plugin);
}
@EventHandler
public void onPlayerChat(AsyncChatEvent event) {
if (getPlugin().getStaffChat().inChat(event.getPlayer().getUniqueId())) {
Component message = event.message();
event.setCancelled(true);
getPlugin().getServer().getOnlinePlayers().stream()
.filter(player -> player.hasPermission("traverse.staff"))
.forEach(player -> player.sendMessage(message));
}
}
}

View File

@ -1,16 +1,15 @@
package mc.unraveled.reforged.permission;
import lombok.Data;
import mc.unraveled.reforged.api.Baker;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
@Data
public class Group implements Baker {
public static final String BAKED_GROUP = "Cannot modify a baked group.";
private final Rank rank;
private Set<String> permissions = new HashSet<>();
private Set<OfflinePlayer> players = new HashSet<>();
@ -20,23 +19,43 @@ public class Group implements Baker {
this.rank = rank;
}
public Rank getRank() {
return rank;
}
public Set<String> getPermissions() {
return permissions;
}
public Set<OfflinePlayer> getPlayers() {
return players;
}
public boolean isBaked() {
return baked;
}
public void setBaked(boolean baked) {
this.baked = baked;
}
public void insert(String permission) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
if (baked) throw new IllegalStateException(BAKED_GROUP);
permissions.add(permission);
}
public void insert(OfflinePlayer player) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
if (baked) throw new IllegalStateException(BAKED_GROUP);
players.add(player);
}
public void eject(String permission) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
if (baked) throw new IllegalStateException(BAKED_GROUP);
permissions.remove(permission);
}
public void eject(OfflinePlayer player) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
if (baked) throw new IllegalStateException(BAKED_GROUP);
players.remove(player);
}

View File

@ -4,6 +4,7 @@ import mc.unraveled.reforged.util.BasicColors;
import net.kyori.adventure.text.format.TextColor;
public enum Rank {
CONSOLE("console", "RCON", BasicColors.PURPLE.getColor(), 8),
EXECUTIVE("executive", "Exec", BasicColors.DARK_RED.getColor(), 7),
DEV("developer", "Dev", BasicColors.PURPLE.getColor(), 6),
ADMIN("admin", "Admin", BasicColors.GOLD.getColor(), 5),

View File

@ -1,38 +1,38 @@
package mc.unraveled.reforged.permission;
import lombok.Getter;
import mc.unraveled.reforged.api.Baker;
import mc.unraveled.reforged.api.Locker;
import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.storage.DBGroup;
import mc.unraveled.reforged.util.Tuple;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class RankManager implements Baker {
public class RankManager implements Baker, Locker {
@Getter
private final Traverse plugin;
private List<Tuple<Rank, List<OfflinePlayer>, List<String>>> rankQueue = new ArrayList<>();
private List<Group> bakedGroups = new ArrayList<>();
private final List<Tuple<Rank, List<UUID>, List<String>>> rankQueue = new ArrayList<>();
private final List<Group> bakedGroups = new ArrayList<>();
private boolean baked = false;
public RankManager(@NotNull Traverse plugin) {
this.plugin = plugin;
lock().notify();
DBGroup groupHandler = new DBGroup(plugin.getSQLManager().establish());
Arrays.stream(Rank.values()).forEach(groupHandler::createTable);
Rank[] ranks = Rank.values();
for (Rank rank : ranks) {
Tuple<Rank, List<OfflinePlayer>, List<String>> rankTuple;
List<OfflinePlayer> playerList;
Tuple<Rank, List<UUID>, List<String>> rankTuple;
List<UUID> playerList;
List<String> permissionList;
playerList = groupHandler.getPlayers(rank);
@ -46,12 +46,28 @@ public class RankManager implements Baker, Locker {
bake();
}
public void insert(Rank rank, List<OfflinePlayer> player, List<String> args) {
rankQueue.add(new Tuple<>(rank, player, args));
public Traverse getPlugin() {
return plugin;
}
public void eject(Rank rank, List<OfflinePlayer> player, List<String> args) {
rankQueue.remove(new Tuple<>(rank, player, args));
public void insert(Rank rank, List<UUID> playerList, List<String> args) {
rankQueue.add(new Tuple<>(rank, playerList, args));
}
public void eject(Rank rank, List<UUID> playerList, List<String> args) {
rankQueue.remove(new Tuple<>(rank, playerList, args));
}
public Rank getRank(CommandSender player) {
if (player instanceof ConsoleCommandSender) return Rank.CONSOLE;
Player c = (Player) player;
return rankQueue.stream()
.filter(tuple -> tuple.getSecond().contains(c.getUniqueId()))
.findFirst()
.map(Tuple::getFirst)
.orElse(Rank.NON_OP);
}
public void insertPermission(Rank rank, String permission) {
@ -69,13 +85,13 @@ public class RankManager implements Baker, Locker {
public void insertPlayer(Rank rank, OfflinePlayer player) {
rankQueue.stream()
.filter(tuple -> tuple.getFirst().equals(rank))
.forEach(tuple -> tuple.getSecond().add(player));
.forEach(tuple -> tuple.getSecond().add(player.getUniqueId()));
}
public void ejectPlayer(Rank rank, OfflinePlayer player) {
rankQueue.stream()
.filter(tuple -> tuple.getFirst().equals(rank))
.forEach(tuple -> tuple.getSecond().remove(player));
.forEach(tuple -> tuple.getSecond().remove(player.getUniqueId()));
}
public void save() {
@ -98,36 +114,30 @@ public class RankManager implements Baker, Locker {
public void bake() {
if (baked) return;
synchronized (lock()) {
rankQueue.forEach(tuple -> {
Rank rank = tuple.getFirst();
List<OfflinePlayer> players = tuple.getSecond();
List<String> permissions = tuple.getThird();
rankQueue.forEach(tuple -> {
Rank rank = tuple.getFirst();
List<UUID> players = tuple.getSecond();
List<String> permissions = tuple.getThird();
Group group = new Group(rank);
for (OfflinePlayer p : players) {
group.insert(p);
}
for (String arg : permissions) {
group.insert(arg);
}
bakedGroups.add(group);
});
}
Group group = new Group(rank);
for (UUID p : players) {
group.insert(Bukkit.getOfflinePlayer(p));
}
for (String arg : permissions) {
group.insert(arg);
}
bakedGroups.add(group);
});
baked = true;
lock().notify();
}
@Override
public void unbake() {
if (!baked) return;
synchronized (lock()) {
bakedGroups.clear();
}
bakedGroups.clear();
baked = false;
lock().notify();
}
}

View File

@ -12,7 +12,7 @@ public abstract class TPermission {
* @param permissionMessage The message to send when the user does not have the permission to run the command.
* @param allowConsole Whether to allow the command to be run anywhere, or only in game.
*/
public TPermission(String permission, String permissionMessage, boolean allowConsole) {
protected TPermission(String permission, String permissionMessage, boolean allowConsole) {
this.permission = "traverse." + permission;
this.permissionMessage = permissionMessage;
this.allowConsole = allowConsole;

View File

@ -1,8 +1,5 @@
package mc.unraveled.reforged.plugin;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.api.Locker;
import mc.unraveled.reforged.banning.BanManager;
import mc.unraveled.reforged.command.*;
import mc.unraveled.reforged.command.base.CommandLoader;
@ -10,52 +7,104 @@ import mc.unraveled.reforged.config.Yaml;
import mc.unraveled.reforged.config.YamlManager;
import mc.unraveled.reforged.data.DataManager;
import mc.unraveled.reforged.data.LoginManager;
import mc.unraveled.reforged.data.StaffChat;
import mc.unraveled.reforged.economy.EconomyManager;
import mc.unraveled.reforged.listening.InfractionListener;
import mc.unraveled.reforged.listening.PlayerDataListener;
import mc.unraveled.reforged.listening.StaffChatListener;
import mc.unraveled.reforged.permission.RankManager;
import mc.unraveled.reforged.service.base.Scheduling;
import mc.unraveled.reforged.service.base.ServicePool;
import mc.unraveled.reforged.storage.DBConnectionHandler;
import mc.unraveled.reforged.storage.DBProperties;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
public final class Traverse extends JavaPlugin implements Locker {
public final class Traverse extends JavaPlugin {
// Secondary variable declaration.
private final String CONFIG_FILE = "config.yml";
private final File CONFIG = new File(getDataFolder(), CONFIG_FILE);
// Primary variable declaration.
@Getter
private DBConnectionHandler SQLManager;
@Getter
private DataManager dataManager;
@Getter
private CommandLoader commandLoader;
@Getter
private BanManager banManager;
@Getter
private RankManager rankManager;
@Getter
private Scheduling scheduler;
@Getter
private ServicePool PIPELINE;
@Getter
private EconomyManager economyManager;
@Getter
private LoginManager loginManager;
@Getter
private YamlManager yamlManager;
@Getter
private Yaml yamlConfig;
private StaffChat staffChat;
public DBConnectionHandler getSQLManager() {
return SQLManager;
}
public DataManager getDataManager() {
return dataManager;
}
public CommandLoader getCommandLoader() {
return commandLoader;
}
public BanManager getBanManager() {
return banManager;
}
public RankManager getRankManager() {
return rankManager;
}
public Scheduling getScheduler() {
return scheduler;
}
public ServicePool getPIPELINE() {
return PIPELINE;
}
public EconomyManager getEconomyManager() {
return economyManager;
}
public LoginManager getLoginManager() {
return loginManager;
}
public YamlManager getYamlManager() {
return yamlManager;
}
public Yaml getYamlConfig() {
return yamlConfig;
}
public StaffChat getStaffChat() {
return staffChat;
}
@Override
@SneakyThrows
public void onEnable() {
this.SQLManager = new DBConnectionHandler(new DBProperties("db.properties"));
this.dataManager = new DataManager(this);
this.commandLoader = new CommandLoader(this, "TRAVERSE");
this.dataManager = new DataManager(this);
this.banManager = new BanManager(this);
this.rankManager = new RankManager(this);
this.scheduler = new Scheduling(this);
@ -63,6 +112,7 @@ public final class Traverse extends JavaPlugin implements Locker {
this.economyManager = new EconomyManager(this);
this.loginManager = new LoginManager(this);
this.yamlManager = new YamlManager(this);
this.staffChat = new StaffChat(this);
registerCommands();
registerListeners();
@ -78,48 +128,55 @@ public final class Traverse extends JavaPlugin implements Locker {
// Plugin shutdown logic
}
@SneakyThrows
public void registerCommands() {
synchronized (lock()) {
getCommandLoader().register(
new BanCMD(this),
new BankCMD(this),
new EntityPurgeCMD(this),
new GroupCMD(this),
new MuteCMD(this),
new PardonCMD(this),
new TraverseCMD(this),
new UnmuteCMD(this)
);
lock().wait(1000);
}
getCommandLoader().register(
new BanCMD(this),
new BanInfoCMD(this),
new BankCMD(this),
new EntityPurgeCMD(this),
new GroupCMD(this),
new KickCMD(this),
new LockCMD(this),
new MuteCMD(this),
new PardonCMD(this),
new PlayerDataCMD(this),
new StaffChatCMD(this),
new TraverseCMD(this),
new UnmuteCMD(this)
);
lock().notify();
getCommandLoader().load();
}
public void registerListeners() {
new InfractionListener(this);
getServer().getPluginManager().registerEvents(new InfractionListener(this), this);
getServer().getPluginManager().registerEvents(new StaffChatListener(this), this);
getServer().getPluginManager().registerEvents(new PlayerDataListener(this), this);
}
@SneakyThrows
public void registerConfig() {
Yaml yaml;
if (CONFIG.createNewFile()) {
yaml = getYamlManager().bldr()
.fileName(CONFIG_FILE)
.dataFolder(getDataFolder())
.copyDefaults(true)
.build();
} else {
yaml = getYamlManager().bldr()
.fileName(CONFIG_FILE)
.dataFolder(getDataFolder())
.copyDefaults(false)
.build();
try {
if (CONFIG.createNewFile()) {
yaml = getYamlManager().bldr()
.fileName(CONFIG_FILE)
.dataFolder(getDataFolder())
.copyDefaults(true)
.build();
} else {
yaml = getYamlManager().bldr()
.fileName(CONFIG_FILE)
.dataFolder(getDataFolder())
.copyDefaults(false)
.build();
}
} catch (IOException e) {
Bukkit.getLogger().severe("Could not create config.yml!");
e.printStackTrace();
return;
}
this.yamlConfig = yaml;
this.yamlConfig = yaml;
getYamlConfig().loadFromFile();
}
}

View File

@ -1,7 +1,5 @@
package mc.unraveled.reforged.service;
import lombok.Getter;
import lombok.Setter;
import mc.unraveled.reforged.data.InfractionData;
import mc.unraveled.reforged.service.base.AbstractService;
import mc.unraveled.reforged.service.base.ServicePool;
@ -10,13 +8,16 @@ import org.jetbrains.annotations.Nullable;
import reactor.core.publisher.Mono;
public class MuteService extends AbstractService {
@Setter
private InfractionData infractionData = null;
public MuteService(@Nullable ServicePool parentPool, @NotNull String service_name, long delay) {
super(parentPool, service_name, delay);
}
public void setInfractionData(InfractionData infractionData) {
this.infractionData = infractionData;
}
@Override
public int getServiceId() {
return 0;

View File

@ -48,7 +48,7 @@ public abstract class AbstractService implements IService {
*
* @param service_name A namespaced key which can be used to identify the service.
*/
public AbstractService(@NotNull String service_name) {
protected AbstractService(@NotNull String service_name) {
this((new ServicePool("defaultPool" + Scheduling.denom, JavaPlugin.getPlugin(Traverse.class))),
service_name,
0L,

View File

@ -1,114 +1,128 @@
package mc.unraveled.reforged.storage;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.banning.AbstractBan;
import mc.unraveled.reforged.banning.SimpleBan;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@Getter
public class DBBan {
@Getter
private Connection connection;
public DBBan(Connection connection) {
this.connection = connection;
}
@SneakyThrows
public void createTable() {
PreparedStatement statement = getConnection().prepareStatement("CREATE TABLE IF NOT EXISTS bans (uuid VARCHAR(36), ip VARCHAR(16), reason VARCHAR(64), banned_by VARCHAR(16), banned_at BIGINT, expires_at BIGINT, active BOOLEAN, PRIMARY KEY (uuid));");
statement.executeUpdate();
try (PreparedStatement statement = getConnection()
.prepareStatement("CREATE TABLE IF NOT EXISTS bans (uuid VARCHAR(36), ip VARCHAR(16), reason VARCHAR(64), banned_by VARCHAR(16), banned_at BIGINT, expires_at BIGINT, active BOOLEAN, PRIMARY KEY (uuid));")) {
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe(e.getMessage());
}
}
@SneakyThrows
public void insert(@NotNull AbstractBan ban) {
PreparedStatement statement = getConnection().prepareStatement("IF NOT EXISTS (SELECT 1 FROM bans WHERE uuid = ?) " +
"BEGIN INSERT INTO bans (uuid, ip, reason, banned_by, banned_at, expires_at, active) VALUES (?, ?, ?, ?, ?, ?, ?) END " +
"ELSE BEGIN UPDATE bans SET ip = ?, reason = ?, banned_by = ?, banned_at = ?, expires_at = ?, active = ? WHERE uuid = ? END;");
statement.setString(1, ban.getUuid());
statement.setString(2, ban.getUuid());
statement.setString(3, ban.getIp());
statement.setString(4, ban.getReason());
statement.setString(5, ban.getSource());
statement.setLong(6, ban.getPropagated());
statement.setLong(7, ban.getExpiry());
statement.setBoolean(8, ban.isActive());
statement.setString(9, ban.getIp());
statement.setString(10, ban.getReason());
statement.setString(11, ban.getSource());
statement.setLong(12, ban.getPropagated());
statement.setLong(13, ban.getExpiry());
statement.setBoolean(14, ban.isActive());
statement.setString(15, ban.getUuid());
statement.executeUpdate();
try (PreparedStatement statement = getConnection()
.prepareStatement("INSERT INTO bans (uuid, ip, reason, banned_by, banned_at, expires_at, active) VALUES (?, ?, ?, ?, ?, ?, ?);")) {
statement.setString(1, ban.getUuid());
statement.setString(2, ban.getIp());
statement.setString(3, ban.getReason());
statement.setString(4, ban.getSource());
statement.setLong(5, ban.getPropagated());
statement.setLong(6, ban.getExpiry());
statement.setBoolean(7, ban.isActive());
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe(e.getMessage());
}
}
@SneakyThrows
@Nullable
public AbstractBan getBan(@NotNull UUID uuid) {
PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM bans WHERE uuid = ?;");
statement.setString(1, uuid.toString());
ResultSet rs = statement.executeQuery();
if (rs.next()) {
return new SimpleBan(rs.getString("uuid"),
rs.getString("ip"),
rs.getString("reason"),
rs.getString("banned_by"),
rs.getLong("banned_at"),
rs.getLong("expires_at"),
rs.getBoolean("active"));
try (PreparedStatement statement = getConnection()
.prepareStatement("SELECT * FROM bans WHERE uuid = ?;")) {
statement.setString(1, uuid.toString());
try (ResultSet rs = statement.executeQuery()) {
if (rs.next()) {
return new SimpleBan(rs.getString("uuid"),
rs.getString("ip"),
rs.getString("reason"),
rs.getString("banned_by"),
rs.getLong("banned_at"),
rs.getLong("expires_at"),
rs.getBoolean("active"));
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe(e.getMessage());
}
return null;
}
@SneakyThrows
public List<AbstractBan> all() {
PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM bans;");
ResultSet rs = statement.executeQuery();
List<AbstractBan> bans = new ArrayList<>();
while (rs.next()) {
bans.add(new SimpleBan(rs.getString("uuid"),
rs.getString("ip"),
rs.getString("reason"),
rs.getString("banned_by"),
rs.getLong("banned_at"),
rs.getLong("expires_at"),
rs.getBoolean("active")));
try (PreparedStatement statement = getConnection()
.prepareStatement("SELECT * FROM bans;")) {
try (ResultSet rs = statement.executeQuery()) {
while (rs.next()) {
bans.add(new SimpleBan(rs.getString("uuid"),
rs.getString("ip"),
rs.getString("reason"),
rs.getString("banned_by"),
rs.getLong("banned_at"),
rs.getLong("expires_at"),
rs.getBoolean("active")));
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe(e.getMessage());
}
return bans;
}
@SneakyThrows
public void delete(@NotNull AbstractBan ban) {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM bans WHERE uuid = ?;");
statement.setString(1, ban.getUuid());
statement.executeUpdate();
try (PreparedStatement statement = getConnection()
.prepareStatement("DELETE FROM bans WHERE uuid = ?;")) {
statement.setString(1, ban.getUuid());
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe(e.getMessage());
}
}
@SneakyThrows
public void deleteAll() {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM bans;");
statement.executeUpdate();
try (PreparedStatement statement = getConnection()
.prepareStatement("DELETE FROM bans;")) {
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe(e.getMessage());
}
}
@SneakyThrows
public void close() {
getConnection().close();
try {
getConnection().close();
} catch (SQLException e) {
Bukkit.getLogger().severe(e.getMessage());
}
this.connection = null;
}
public void open(Connection connection) {
this.connection = connection;
}
public Connection getConnection() {
return connection;
}
}

View File

@ -1,31 +1,44 @@
package mc.unraveled.reforged.storage;
import lombok.SneakyThrows;
import org.bukkit.Bukkit;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnectionHandler {
private final DBProperties properties;
public DBConnectionHandler(DBProperties properties) throws SQLException {
public DBConnectionHandler(DBProperties properties) {
this.properties = properties;
}
@SneakyThrows
public Connection establish() {
return DriverManager.getConnection(properties.getUrl(), properties.getUsername(), properties.getPassword());
try {
return DriverManager.getConnection(properties.getUrl(), properties.getUsername(), properties.getPassword());
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to establish connection: " + e.getMessage());
return null;
}
}
@SneakyThrows
public ContextConnection establishContext() {
return new ContextConnection(DriverManager.getConnection(properties.getUrl(), properties.getUsername(), properties.getPassword()));
try {
return new ContextConnection(DriverManager.getConnection(properties.getUrl(), properties.getUsername(), properties.getPassword()));
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to establish connection: " + e.getMessage());
return null;
}
}
public record ContextConnection(Connection connection) implements AutoCloseable {
@SneakyThrows
@Override
public void close() {
connection.close();
try {
connection.close();
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to close connection: " + e.getMessage());
}
}
}
}

View File

@ -1,92 +1,111 @@
package mc.unraveled.reforged.storage;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.permission.Rank;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class DBGroup {
@Getter
private Connection connection;
public DBGroup(Connection connection) {
this.connection = connection;
}
@SneakyThrows
public void createTable(Rank rank) {
PreparedStatement statement = getConnection().prepareStatement("CREATE TABLE IF NOT EXISTS " + rank.getAttachment().getName() + " (uuid VARCHAR(36), permissions VARCHAR(64));");
statement.execute();
try (PreparedStatement statement = getConnection().prepareStatement("CREATE TABLE IF NOT EXISTS " + rank.getAttachment().getName() + " (uuid VARCHAR(36), permissions VARCHAR(64));")) {
statement.execute();
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to create table: " + e.getMessage());
}
}
@SneakyThrows
public void addPermission(Rank rank, String permission) {
PreparedStatement statement = getConnection().prepareStatement("INSERT INTO " + rank.getAttachment().getName() + " (permissions) VALUES (?);");
statement.setString(1, permission);
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("INSERT INTO " + rank.getAttachment().getName() + " (permissions) VALUES (?);")) {
statement.setString(1, permission);
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to add permission: " + e.getMessage());
}
}
@SneakyThrows
public void removePermission(Rank rank, String permission) {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM " + rank.getAttachment().getName() + " WHERE permissions = ?;");
statement.setString(1, permission);
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("DELETE FROM " + rank.getAttachment().getName() + " WHERE permissions = ?;")) {
statement.setString(1, permission);
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to remove permission: " + e.getMessage());
}
}
@SneakyThrows
public List<String> getPermissions(Rank rank) {
List<String> permissions = new ArrayList<>();
PreparedStatement statement = getConnection().prepareStatement("SELECT permissions FROM " + rank.getAttachment().getName() + ";");
ResultSet rs = statement.executeQuery();
while (rs.next()) {
permissions.add(rs.getString("permissions"));
try (PreparedStatement statement = getConnection().prepareStatement("SELECT permissions FROM " + rank.getAttachment().getName() + ";")) {
ResultSet rs = statement.executeQuery();
while (rs.next()) {
permissions.add(rs.getString("permissions"));
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to get permissions: " + e.getMessage());
}
return permissions;
}
@SneakyThrows
public void addPlayer(Rank rank, OfflinePlayer player) {
PreparedStatement statement = getConnection().prepareStatement("INSERT INTO " + rank.getAttachment().getName() + " (uuid) VALUES (?);");
statement.setString(1, player.getUniqueId().toString());
statement.executeUpdate();
}
@SneakyThrows
public void removePlayer(Rank rank, OfflinePlayer player) {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM " + rank.getAttachment().getName() + " WHERE uuid = ?;");
statement.setString(1, player.getUniqueId().toString());
statement.executeUpdate();
}
@SneakyThrows
public List<OfflinePlayer> getPlayers(Rank rank) {
List<OfflinePlayer> players = new ArrayList<>();
PreparedStatement statement = getConnection().prepareStatement("SELECT uuid FROM " + rank.getAttachment().getName() + ";");
ResultSet rs = statement.executeQuery();
while (rs.next()) {
UUID uuid = UUID.fromString(rs.getString("uuid"));
players.add(Bukkit.getOfflinePlayer(uuid));
public void addPlayer(@NotNull Rank rank, @NotNull OfflinePlayer player) {
try (PreparedStatement statement = getConnection().prepareStatement("INSERT INTO " + rank.getAttachment().getName() + " (uuid) VALUES (?);")) {
statement.setString(1, player.getUniqueId().toString());
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to add player: " + e.getMessage());
}
}
public void removePlayer(@NotNull Rank rank, @NotNull OfflinePlayer player) {
try (PreparedStatement statement = getConnection().prepareStatement("DELETE FROM " + rank.getAttachment().getName() + " WHERE uuid = ?;")) {
statement.setString(1, player.getUniqueId().toString());
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to remove player: " + e.getMessage());
}
}
public List<UUID> getPlayers(Rank rank) {
List<UUID> players = new ArrayList<>();
try (PreparedStatement statement = getConnection().prepareStatement("SELECT uuid FROM " + rank.getAttachment().getName() + ";")) {
ResultSet rs = statement.executeQuery();
while (rs.next()) {
UUID uuid = UUID.fromString(rs.getString("uuid"));
players.add(uuid);
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to get players: " + e.getMessage());
}
return players;
}
@SneakyThrows
public void close() {
getConnection().close();
try {
getConnection().close();
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to close connection: " + e.getMessage());
}
}
public void open(Connection connection) {
this.connection = connection;
}
public Connection getConnection() {
return connection;
}
}

View File

@ -1,6 +1,5 @@
package mc.unraveled.reforged.storage;
import lombok.SneakyThrows;
import mc.unraveled.reforged.data.InfractionData;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@ -9,96 +8,112 @@ import org.bukkit.entity.Player;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class DBInfraction {
private final String INSERT = "INSERT INTO infractions (uuid, infractions, muted, frozen, locked, jailed) VALUES (?, ?, ?, ?, ?, ?);";
private final String UPDATE = "UPDATE infractions SET infractions = ?, muted = ?, frozen = ?, locked = ?, jailed = ? WHERE uuid = ?;";
private final String SELECT = "SELECT * FROM infractions;";
private final String SELECT_UUID = "SELECT * FROM infractions WHERE uuid = ?;";
private final String DELETE = "DELETE FROM infractions WHERE uuid = ?;";
private final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS infractions (uuid VARCHAR(36), infractions INT, muted BOOLEAN, frozen BOOLEAN, locked BOOLEAN, jailed BOOLEAN, PRIMARY KEY (uuid));";
private final Connection connection;
private final String INF = "infractions";
public DBInfraction(Connection connection) {
this.connection = connection;
}
@SneakyThrows
public void createTable() {
PreparedStatement statement = connection.prepareStatement(CREATE_TABLE);
statement.executeUpdate();
String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS infractions (uuid VARCHAR(36), infractions INT, muted BOOLEAN, frozen BOOLEAN, locked BOOLEAN, jailed BOOLEAN, PRIMARY KEY (uuid));";
try (PreparedStatement statement = connection.prepareStatement(CREATE_TABLE)) {
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Error while creating infractions table");
}
}
@SneakyThrows
public void insert(Player player, InfractionData data) {
PreparedStatement statement = connection.prepareStatement(SQLConst.IF("infractions", "uuid") +
String INSERT = "INSERT INTO infractions (uuid, infractions, muted, frozen, locked, jailed) VALUES (?, ?, ?, ?, ?, ?);";
String UPDATE = "UPDATE infractions SET infractions = ?, muted = ?, frozen = ?, locked = ?, jailed = ? WHERE uuid = ?;";
try (PreparedStatement statement = connection.prepareStatement(SQLConst.IF(INF, "uuid", player.getUniqueId().toString()) +
SQLConst.BEGIN +
INSERT +
SQLConst.END_SPACE +
SQLConst.ELSE +
UPDATE +
SQLConst.END +
SQLConst.SEMICOLON);
statement.setString(1, player.getUniqueId().toString());
statement.setString(2, player.getUniqueId().toString());
statement.setInt(3, data.getInfractions());
statement.setBoolean(4, data.isMuted());
statement.setBoolean(5, data.isFrozen());
statement.setBoolean(6, data.isLocked());
statement.setBoolean(7, data.isJailed());
statement.setInt(8, data.getInfractions());
statement.setBoolean(9, data.isMuted());
statement.setBoolean(10, data.isFrozen());
statement.setBoolean(11, data.isLocked());
statement.setBoolean(12, data.isJailed());
statement.setString(13, player.getUniqueId().toString());
statement.executeUpdate();
SQLConst.SEMICOLON)) {
statement.setString(1, player.getUniqueId().toString());
statement.setInt(2, data.getInfractions());
statement.setBoolean(3, data.isMuted());
statement.setBoolean(4, data.isFrozen());
statement.setBoolean(5, data.isLocked());
statement.setBoolean(6, data.isJailed());
statement.setInt(7, data.getInfractions());
statement.setBoolean(8, data.isMuted());
statement.setBoolean(9, data.isFrozen());
statement.setBoolean(10, data.isLocked());
statement.setBoolean(11, data.isJailed());
statement.setString(12, player.getUniqueId().toString());
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Error while inserting " + player.getName());
}
}
@SneakyThrows
public void eject(Player player) {
PreparedStatement statement = connection.prepareStatement(DELETE);
statement.setString(1, player.getUniqueId().toString());
statement.executeUpdate();
String DELETE = "DELETE FROM infractions WHERE uuid = ?;";
try (PreparedStatement statement = connection.prepareStatement(DELETE)) {
statement.setString(1, player.getUniqueId().toString());
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Error while ejecting " + player.getName());
}
}
@SneakyThrows
public List<InfractionData> getInfractionsList() {
List<InfractionData> temp = new ArrayList<>();
PreparedStatement statement = connection.prepareStatement(SELECT);
ResultSet rs = statement.executeQuery();
while (rs.next()) {
OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("uuid")));
int infractions = rs.getInt("infractions");
boolean muted = rs.getBoolean("muted");
boolean frozen = rs.getBoolean("frozen");
boolean locked = rs.getBoolean("locked");
boolean jailed = rs.getBoolean("jailed");
String SELECT = "SELECT * FROM infractions;";
try (PreparedStatement statement = connection.prepareStatement(SELECT);
ResultSet rs = statement.executeQuery()) {
while (rs.next()) {
OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("uuid")));
int infractions = rs.getInt(INF);
boolean muted = rs.getBoolean("muted");
boolean frozen = rs.getBoolean("frozen");
boolean locked = rs.getBoolean("locked");
boolean jailed = rs.getBoolean("jailed");
temp.add(new InfractionData(player, infractions, muted, frozen, locked, jailed));
temp.add(new InfractionData(player, infractions, muted, frozen, locked, jailed));
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Error while getting infractions list");
}
return temp;
}
@SneakyThrows
public InfractionData getInfraction(String uuid) {
PreparedStatement statement = connection.prepareStatement(SELECT_UUID);
statement.setString(1, uuid);
ResultSet rs = statement.executeQuery();
if (rs.next()) {
return new InfractionData(Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("uuid"))), rs.getInt("infractions"), rs.getBoolean("muted"), rs.getBoolean("frozen"), rs.getBoolean("locked"), rs.getBoolean("jailed"));
String SELECT_UUID = "SELECT * FROM infractions WHERE uuid = ?;";
try (PreparedStatement statement = connection.prepareStatement(SELECT_UUID)) {
statement.setString(1, uuid);
try (ResultSet rs = statement.executeQuery()) {
if (rs.next()) {
return new InfractionData(Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("uuid"))), rs.getInt(INF), rs.getBoolean("muted"), rs.getBoolean("frozen"), rs.getBoolean("locked"), rs.getBoolean("jailed"));
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Error while getting infraction data for " + uuid);
}
return new InfractionData(Bukkit.getOfflinePlayer(UUID.fromString(uuid)));
}
@SneakyThrows
public void close() {
connection.close();
try {
connection.close();
} catch (SQLException e) {
Bukkit.getLogger().severe("Error while closing connection");
}
}
}

View File

@ -1,12 +1,11 @@
package mc.unraveled.reforged.storage;
import lombok.Getter;
import org.bukkit.Bukkit;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
@Getter
public class DBProperties {
private final Properties properties;
private final String url;
@ -20,10 +19,10 @@ public class DBProperties {
public DBProperties(String fileName) {
properties = new Properties();
try {
properties.load(new FileInputStream(fileName));
try (FileInputStream fileInputStream = new FileInputStream(fileName)) {
properties.load(fileInputStream);
} catch (IOException e) {
e.printStackTrace();
Bukkit.getLogger().severe("Could not load database properties file!");
}
driver = properties.getProperty("driver");
databaseType = properties.getProperty("databaseType");
@ -34,4 +33,40 @@ public class DBProperties {
password = properties.getProperty("password");
url = driver + ":" + databaseType + "://" + host + ":" + port + "/" + databaseFile;
}
public Properties getProperties() {
return properties;
}
public String getUrl() {
return url;
}
public String getDriver() {
return driver;
}
public String getDatabaseType() {
return databaseType;
}
public String getDatabaseFile() {
return databaseFile;
}
public String getHost() {
return host;
}
public String getPort() {
return port;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}

View File

@ -1,10 +1,9 @@
package mc.unraveled.reforged.storage;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.data.InfractionData;
import mc.unraveled.reforged.data.LoginInfo;
import mc.unraveled.reforged.data.PlayerData;
import mc.unraveled.reforged.data.PlayerDataBuilder;
import mc.unraveled.reforged.permission.Rank;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
@ -14,186 +13,228 @@ import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
public class DBUser {
@Getter
private Connection connection;
public static final String LOGIN_MESSAGE = "login_message";
private final String COIN_LITERAL = "coins";
private final Connection connection;
public DBUser(Connection connection) {
this.connection = connection;
}
@SneakyThrows
public void createTable() {
PreparedStatement statement = getConnection().prepareStatement("CREATE TABLE IF NOT EXISTS users (uuid VARCHAR(36), username VARCHAR(16), rank VARCHAR(64), play_time BIGINT, coins BIGINT, last_login BIGINT, login_message VARCHAR(64), PRIMARY KEY (uuid));");
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("CREATE TABLE IF NOT EXISTS users (uuid VARCHAR(36), username VARCHAR(16), rank VARCHAR(64), play_time BIGINT, coins BIGINT, last_login BIGINT, login_message VARCHAR(64), PRIMARY KEY (uuid));")) {
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not create users table!");
}
}
@SneakyThrows
public void insert(@NotNull PlayerData playerData) {
PreparedStatement statement = getConnection().prepareStatement("IF NOT EXISTS (SELECT 1 FROM users WHERE uuid = ?) " +
try (PreparedStatement statement = getConnection().prepareStatement("IF NOT EXISTS (SELECT 1 FROM users WHERE uuid = ?) " +
"BEGIN INSERT INTO users (uuid, username, rank, play_time, coins, last_login, login_message) VALUES (?, ?, ?, ?, ?, ?, ?) END " +
"ELSE BEGIN UPDATE users SET username = ?, rank = ?, play_time = ?, coins = ?, last_login = ?, login_message = ?, WHERE uuid = ? END;");
"ELSE BEGIN UPDATE users SET username = ?, rank = ?, play_time = ?, coins = ?, last_login = ?, login_message = ?, WHERE uuid = ? END;")) {
statement.setString(1, playerData.getUuid().toString());
statement.setString(2, playerData.getUuid().toString());
statement.setString(3, playerData.getUserName());
statement.setString(4, playerData.getRank().name());
statement.setLong(5, playerData.getPlaytime());
statement.setInt(6, playerData.getCoins());
statement.setLong(7, playerData.getLastLogin().getTime());
statement.setString(8, playerData.getLoginMessage());
statement.setString(9, playerData.getUserName());
statement.setString(10, playerData.getRank().name());
statement.setLong(11, playerData.getPlaytime());
statement.setInt(12, playerData.getCoins());
statement.setLong(13, playerData.getLastLogin().getTime());
statement.setString(14, playerData.getLoginMessage());
statement.setString(15, playerData.getUuid().toString());
statement.setString(1, playerData.getUuid().toString());
statement.setString(2, playerData.getUuid().toString());
statement.setString(3, playerData.getUserName());
statement.setString(4, playerData.getRank().name());
statement.setLong(5, playerData.getPlaytime());
statement.setInt(6, playerData.getCoins());
statement.setLong(7, playerData.getLastLogin().getTime());
statement.setString(8, playerData.getLoginMessage());
statement.setString(9, playerData.getUserName());
statement.setString(10, playerData.getRank().name());
statement.setLong(11, playerData.getPlaytime());
statement.setInt(12, playerData.getCoins());
statement.setLong(13, playerData.getLastLogin().getTime());
statement.setString(14, playerData.getLoginMessage());
statement.setString(15, playerData.getUuid().toString());
statement.executeUpdate();
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not insert player data into users table!");
}
}
@SneakyThrows
public void delete(@NotNull PlayerData playerData) {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM users WHERE uuid = ?;");
statement.setString(1, playerData.getUuid().toString());
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("DELETE FROM users WHERE uuid = ?;")) {
statement.setString(1, playerData.getUuid().toString());
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not delete player data from users table!");
}
}
@SneakyThrows
public void deleteAll() {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM users;");
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("DELETE FROM users;")) {
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not delete all player data from users table!");
}
}
@SneakyThrows
public void setLastLogin(String uuid, long lastLogin) {
PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET last_login = ? WHERE uuid = ?;");
statement.setLong(1, lastLogin);
statement.setString(2, uuid);
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET last_login = ? WHERE uuid = ?;")) {
statement.setLong(1, lastLogin);
statement.setString(2, uuid);
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not update last login for player " + uuid + "!");
}
}
@SneakyThrows
public Date getLastLogin(String uuid) {
PreparedStatement statement = getConnection().prepareStatement("SELECT last_login FROM users WHERE uuid = ?;");
statement.setString(1, uuid);
ResultSet resultSet = statement.executeQuery();
long lastLogin = 0;
AtomicLong lastLogin = new AtomicLong(0L);
while (resultSet.next()) {
lastLogin = resultSet.getLong("last_login");
try (PreparedStatement statement = getConnection().prepareStatement("SELECT last_login FROM users WHERE uuid = ?;")) {
statement.setString(1, uuid);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
lastLogin.set(resultSet.getLong("last_login"));
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not get last login for player " + uuid + "!");
}
return new Date(lastLogin);
return new Date(lastLogin.get());
}
@SneakyThrows
public void setCoins(String uuid, int coins) {
PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET coins = ? WHERE uuid = ?;");
statement.setInt(1, coins);
statement.setString(2, uuid);
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET coins = ? WHERE uuid = ?;")) {
statement.setInt(1, coins);
statement.setString(2, uuid);
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not update coins for player " + uuid + "!");
}
}
@SneakyThrows
public int getCoins(String uuid) {
PreparedStatement statement = getConnection().prepareStatement("SELECT coins FROM users WHERE uuid = ?;");
statement.setString(1, uuid);
ResultSet resultSet = statement.executeQuery();
int coins = 0;
AtomicInteger coins = new AtomicInteger(0);
while (resultSet.next()) {
coins = resultSet.getInt("coins");
try (PreparedStatement statement = getConnection().prepareStatement("SELECT coins FROM users WHERE uuid = ?;")) {
statement.setString(1, uuid);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
coins.set(resultSet.getInt(COIN_LITERAL));
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not get coins for player " + uuid + "!");
}
return coins;
return coins.get();
}
@SneakyThrows
public void setRank(String uuid, @NotNull Rank rank) {
PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET rank = ? WHERE uuid = ?;");
statement.setString(1, rank.name());
statement.setString(2, uuid);
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET rank = ? WHERE uuid = ?;")) {
statement.setString(1, rank.name());
statement.setString(2, uuid);
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not update rank for player " + uuid + "!");
}
}
@SneakyThrows
public Rank getRank(String uuid) {
PreparedStatement statement = getConnection().prepareStatement("SELECT rank FROM users WHERE uuid = ?;");
statement.setString(1, uuid);
ResultSet resultSet = statement.executeQuery();
Rank rank = Rank.NON_OP;
AtomicReference<Rank> rank = new AtomicReference<>(Rank.NON_OP);
while (resultSet.next()) {
rank = Rank.valueOf(resultSet.getString("rank"));
try (PreparedStatement statement = getConnection().prepareStatement("SELECT rank FROM users WHERE uuid = ?;")) {
statement.setString(1, uuid);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
rank.set(Rank.valueOf(resultSet.getString("rank")));
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not get rank for player " + uuid + "!");
}
return rank;
return rank.get();
}
@SneakyThrows
public void setLoginMessage(String uuid, String message) {
PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET login_message = ? WHERE uuid = ?;");
statement.setString(1, message);
statement.setString(2, uuid);
statement.executeUpdate();
try (PreparedStatement statement = getConnection().prepareStatement("UPDATE users SET login_message = ? WHERE uuid = ?;")) {
statement.setString(1, message);
statement.setString(2, uuid);
statement.executeUpdate();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not update login message for player " + uuid + "!");
}
}
@SneakyThrows
public Map<OfflinePlayer, LoginInfo> getLoginMessages() {
PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM users;");
ResultSet resultSet = statement.executeQuery();
Map<OfflinePlayer, LoginInfo> loginInfoMap = new HashMap<>();
while (resultSet.next()) {
OfflinePlayer player = Bukkit.getPlayer(UUID.fromString(resultSet.getString("uuid")));
LoginInfo loginInfo = new LoginInfo();
loginInfoMap.put(player, loginInfo);
try (PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM users;")) {
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
OfflinePlayer player = Bukkit.getPlayer(UUID.fromString(resultSet.getString("uuid")));
LoginInfo loginInfo = new LoginInfo();
loginInfo.setLoginMessage(Component.text(resultSet.getString(LOGIN_MESSAGE)));
loginInfoMap.put(player, loginInfo);
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not get login messages!");
}
return loginInfoMap;
}
@SneakyThrows
public LoginInfo getLoginInfo(String uuid) {
PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM users WHERE uuid = ?;");
statement.setString(1, uuid);
ResultSet resultSet = statement.executeQuery();
LoginInfo loginInfo = new LoginInfo();
while (resultSet.next()) {
Component c = Component.text(resultSet.getString("login_message"));
loginInfo.setLoginMessage(c);
try (PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM users WHERE uuid = ?;")) {
statement.setString(1, uuid);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
Component c = Component.text(resultSet.getString(LOGIN_MESSAGE));
loginInfo.setLoginMessage(c);
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not get login message for player " + uuid + "!");
}
return loginInfo;
}
@SneakyThrows
public List<PlayerData> all() {
PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM users;");
ResultSet resultSet = statement.executeQuery();
List<PlayerData> dataList = new ArrayList<>();
InfractionData data = InfractionData.getCachedInfractionData(Bukkit.getOfflinePlayer(UUID.fromString(resultSet.getString("uuid"))));
while (resultSet.next()) {
PlayerData playerData = new PlayerData(UUID.fromString(resultSet.getString("uuid")),
resultSet.getString("username"),
Rank.valueOf(resultSet.getString("rank")),
resultSet.getLong("play_time"),
resultSet.getInt("coins"),
new Date(resultSet.getLong("last_login")),
resultSet.getString("login_message"),
data);
dataList.add(playerData);
try (PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM users;")) {
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
PlayerDataBuilder playerDataBuilder = new PlayerDataBuilder().setUuid(UUID.fromString(resultSet.getString("uuid"))).setUserName(resultSet.getString("username")).setRank(Rank.valueOf(resultSet.getString("rank"))).setPlaytime(resultSet.getLong("play_time")).setCoins(resultSet.getInt(COIN_LITERAL)).setLastLogin(new Date(resultSet.getLong("last_login"))).setLoginMessage(resultSet.getString(LOGIN_MESSAGE)).setInfractionData(InfractionData.getCachedInfractionData(Bukkit.getOfflinePlayer(UUID.fromString(resultSet.getString("uuid"))))).compile();
PlayerData playerData = new PlayerData(playerDataBuilder);
dataList.add(playerData);
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not get all player data from users table!");
}
return dataList;
}
@SneakyThrows
public void close() {
getConnection().close();
try {
getConnection().close();
} catch (SQLException e) {
Bukkit.getLogger().severe("Could not close database connection!");
}
}
public Connection getConnection() {
return connection;
}
}

View File

@ -15,7 +15,7 @@ public final class SQLConst {
return "IF NOT EXISTS (SELECT * FROM " + v + ") ";
}
public static String IF(String v, String u) {
return "IF NOT EXISTS (SELECT * FROM " + v + " WHERE " + u + " = ?) ";
public static String IF(String v, String u, String literal) {
return "IF NOT EXISTS (SELECT * FROM " + v + " WHERE " + u + " = " + literal + ") ";
}
}

View File

@ -0,0 +1,40 @@
package mc.unraveled.reforged.util;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
public class ComponentBuilder {
private Component master = Component.empty();
public static ComponentBuilder begin() {
return new ComponentBuilder();
}
public ComponentBuilder append(String text) {
Component i = Component.text(text);
master = master.append(i);
return this;
}
public ComponentBuilder append(String text, NamedTextColor color) {
Component i = Component.text(text, color);
master = master.append(i);
return this;
}
public ComponentBuilder append(long value) {
Component i = Component.text(value);
master = master.append(i);
return this;
}
public ComponentBuilder append(long value, NamedTextColor color) {
Component i = Component.text(value, color);
master = master.append(i);
return this;
}
public Component build() {
return master;
}
}

View File

@ -1,10 +1,17 @@
package mc.unraveled.reforged.util;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Context<S> {
private S context;
private S state;
public Context(S state) {
this.state = state;
}
public S getState() {
return state;
}
public void setState(S state) {
this.state = state;
}
}

View File

@ -0,0 +1,30 @@
package mc.unraveled.reforged.util;
import org.bukkit.entity.Player;
public class Lock {
private volatile boolean locked = false;
private final Player player;
public Lock(Player player) {
this.player = player;
}
public void lock() {
locked = true;
while (locked) {
Thread.onSpinWait();
player.openInventory(player.getInventory());
player.closeInventory();
}
}
public void unlock() {
locked = false;
}
public boolean isLocked() {
return locked;
}
}

View File

@ -1,7 +1,7 @@
# The SQL driver to use.
driver=jdbc
# The type of database to use.
databaseType=postgresql
databaseType=mysql
# The database host.
host=localhost
# The database port.