Bear Necessities

This commit is contained in:
Paldiu 2023-01-28 01:20:00 -06:00
parent f007e11530
commit 82b70fb0f2
12 changed files with 423 additions and 5 deletions

View File

@ -21,6 +21,7 @@ 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'
shadow 'io.projectreactor:reactor-core:3.4.10'
compileOnly 'io.papermc.paper:paper-api:1.19.3-R0.1-SNAPSHOT'
}

View File

@ -8,6 +8,8 @@ import mc.unraveled.reforged.plugin.Traverse;
import mc.unraveled.reforged.util.Utilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -26,13 +28,13 @@ public class BanCMD extends AbstractCommandBase {
@Override
public Component cmd(CommandSender sender, String[] args) {
if (args.length < 2) {
return Component.text("Usage: /ban <player> <reason> [duration]");
return Component.text("Usage: /ban <player> <duration> <reason>");
}
BanManager manager = getPlugin().getBanManager();
OfflinePlayer target = (getPlugin().getServer().getPlayer(args[0]) != null) ? getPlugin().getServer().getPlayer(args[0]) : getPlugin().getServer().getOfflinePlayer(args[0]);
String reason = args[1];
String duration = args.length > 2 ? args[2] : String.valueOf(60 * 24L);
String duration = args[1];
String reason = StringUtils.join(ArrayUtils.subarray(args, 2, args.length - 1), " ");
Date expiry = Utilities.parseDate(duration);
String expiryString = Utilities.parseDateToString(expiry);
@ -41,6 +43,10 @@ public class BanCMD extends AbstractCommandBase {
return MessageDefaults.MSG_NOT_FOUND;
}
if (reason.isEmpty() || duration.isEmpty()) {
return Component.text("Usage: /ban <player> <duration> <reason>");
}
manager.unbake();
SimpleBan ban = new SimpleBan(target, sender, reason, Utilities.parseDate(duration), true);

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.data.InfractionData;
import mc.unraveled.reforged.data.PlayerData;
import mc.unraveled.reforged.plugin.Traverse;
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;
@CommandInfo(name = "mute", description = "Mute a player.", usage = "/mute <player> <duration>")
public class MuteCMD extends AbstractCommandBase {
public MuteCMD(@NotNull Traverse plugin) {
super(plugin, "mute");
}
@Override
public Component cmd(CommandSender sender, String[] args) {
if (args.length != 2) {
return Component.text("Usage: /mute <player> <duration>");
}
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
return MessageDefaults.MSG_NOT_FOUND;
}
PlayerData pData = getPlugin().getDataManager().getPlayerData(target.getUniqueId());
if (pData == null) throw new IllegalStateException("PlayerData is null!");
InfractionData infData = pData.getInfractionData();
if (infData == null) throw new IllegalStateException("InfractionData is null!");
if (!infData.isMuted()) {
infData.setMuted(true);
return Component.text("You have muted " + target.getName() + " for " + args[1] + " seconds.");
} else {
return Component.text("Target is already muted.");
}
}
}

View File

@ -0,0 +1,75 @@
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.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@Getter
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) {
this.fileName = fileName;
this.plugin = plugin;
this.dataFolder = dataFolder;
this.yamlFile = new File(dataFolder, fileName);
if (copyDefaults) {
plugin.saveResource(fileName, true);
}
bake();
}
Yaml(@NotNull Traverse plugin, String fileName, boolean copyDefaults) {
this(plugin, fileName, plugin.getDataFolder(), copyDefaults);
}
Yaml(@NotNull Traverse plugin, String fileName) {
this(plugin, fileName, false);
}
/**
* Makes the file read only after saving to disk.
*/
@SneakyThrows
@Override
public void bake() {
if (baked) return;
super.save(yamlFile);
if (yamlFile.setWritable(false)) {
getPlugin().getLogger().info("Baked " + getFileName());
baked = true;
} else {
getPlugin().getLogger().warning("Failed to bake " + getFileName());
}
}
/**
* Allows read and write access to the file.
*/
@Override
public void unbake() {
if (!baked) return;
if (yamlFile.setWritable(true)) {
getPlugin().getLogger().info("Unbaked " + getFileName());
baked = false;
} else {
getPlugin().getLogger().warning("Failed to unbake " + getFileName());
}
}
}

View File

@ -0,0 +1,96 @@
package mc.unraveled.reforged.config;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.plugin.Traverse;
import org.bukkit.configuration.InvalidConfigurationException;
import org.jetbrains.annotations.NotNull;
import java.io.File;
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;
public YamlManager(Traverse plugin) {
this.plugin = plugin;
}
public Builder bldr() {
return new Builder(plugin);
}
public void insert(Yaml yaml) {
configurations.add(yaml);
}
public void eject(Yaml yaml) {
configurations.remove(yaml);
}
@SneakyThrows
public void load(@NotNull Yaml yaml) {
yaml.load(yaml.getYamlFile());
}
@SneakyThrows
public void save(@NotNull Yaml yaml) {
yaml.save(yaml.getYamlFile());
}
public void loadAll() {
configurations.forEach(y -> {
try {
y.load(y.getYamlFile());
} catch (IOException | InvalidConfigurationException e) {
getPlugin().getLogger().severe("Failed to load " + y.getYamlFile().getName() + "!");
getPlugin().getLogger().severe(e.getMessage());
}
});
}
public void saveAll() {
configurations.forEach(y -> {
try {
y.save(y.getYamlFile());
} catch (IOException e) {
getPlugin().getLogger().severe("Failed to save " + y.getYamlFile().getName() + "!");
getPlugin().getLogger().severe(e.getMessage());
}
});
}
public static class Builder {
private final Traverse plugin;
private String fileName;
private File dataFolder;
private boolean copyDefaults;
public Builder(Traverse plugin) {
this.plugin = plugin;
}
public Builder fileName(String fileName) {
this.fileName = fileName;
return this;
}
public Builder dataFolder(File dataFolder) {
this.dataFolder = dataFolder;
return this;
}
public Builder copyDefaults(boolean copyDefaults) {
this.copyDefaults = copyDefaults;
return this;
}
public Yaml build() {
return new Yaml(plugin, fileName, dataFolder, copyDefaults){};
}
}
}

View File

@ -69,6 +69,7 @@ public final class DataManager implements Baker, Locker {
public void saveData(PlayerData data) {
DBUser user = new DBUser(plugin.getSQLManager().establish());
user.insert(data);
user.close();
}
@SneakyThrows

View File

@ -0,0 +1,71 @@
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;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
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.getStoredInfractionsFromUUID()) {
put(data.getPlayer(), data);
}
}};
@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) {
this.player = player;
}
public InfractionData(OfflinePlayer player, int infractions, boolean muted, boolean frozen, boolean locked, boolean jailed) {
this.player = player.getPlayer();
this.infractions = infractions;
this.muted = muted;
this.frozen = frozen;
this.locked = locked;
this.jailed = jailed;
}
public static InfractionData getCachedInfractionData(OfflinePlayer player) {
return playerInfractionDataMap.computeIfAbsent(player, InfractionData::new);
}
public static InfractionData getInfractionFromDB(@NotNull OfflinePlayer player) {
DBInfraction infraction = new DBInfraction(JavaPlugin.getPlugin(Traverse.class).getSQLManager().establish());
InfractionData data = infraction.getInfraction(player.getUniqueId().toString());
infraction.close();
return data;
}
public void increment() {
infractions++;
}
public void decrement() {
infractions--;
}
}

View File

@ -16,4 +16,5 @@ public class PlayerData {
private long playtime;
private int coins;
private Date lastLogin;
private InfractionData infractionData;
}

View File

@ -24,7 +24,7 @@ public class PlayerDataListener implements Listener {
PlayerData data = plugin.getDataManager().getPlayerData(player.getUniqueId());
if (data == null) {
data = new PlayerData(player.getUniqueId(), player.getName(), Rank.NON_OP, 0L, 0, Date.from(Instant.now()));
data = new PlayerData(player.getUniqueId(), player.getName(), Rank.NON_OP, 0L, 0, Date.from(Instant.now()), InfractionData.getCachedInfractionData(player));
plugin.getDataManager().addPlayerData(data);
}

View File

@ -0,0 +1,97 @@
package mc.unraveled.reforged.storage;
import lombok.SneakyThrows;
import mc.unraveled.reforged.data.InfractionData;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
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;
public DBInfraction(Connection connection) {
this.connection = connection;
}
@SneakyThrows
public void createTable() {
PreparedStatement statement = connection.prepareStatement(CREATE_TABLE);
statement.executeUpdate();
}
@SneakyThrows
public void insert(Player player, InfractionData data) {
PreparedStatement statement = connection.prepareStatement(SQLConst.IF("infractions", "uuid") +
SQLConst.BEGIN +
INSERT +
SQLConst.END_SPACE +
SQLConst.ELSE +
UPDATE +
SQLConst.END +
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.executeUpdate();
}
@SneakyThrows
public void eject(Player player) {
PreparedStatement statement = connection.prepareStatement(DELETE);
statement.setString(1, player.getUniqueId().toString());
statement.executeUpdate();
}
@SneakyThrows
public List<InfractionData> getStoredInfractionsFromUUID() {
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");
temp.add(new InfractionData(player, infractions, muted, frozen, locked, jailed));
}
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"));
}
return new InfractionData(Bukkit.getOfflinePlayer(UUID.fromString(uuid)));
}
@SneakyThrows
public void close() {
connection.close();
}
}

View File

@ -2,8 +2,10 @@ package mc.unraveled.reforged.storage;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.data.InfractionData;
import mc.unraveled.reforged.data.PlayerData;
import mc.unraveled.reforged.permission.Rank;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
@ -69,13 +71,16 @@ public class DBUser {
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")));
new Date(resultSet.getLong("last_login")),
data);
dataList.add(playerData);
}
return dataList;

View File

@ -0,0 +1,21 @@
package mc.unraveled.reforged.storage;
public final class SQLConst {
private SQLConst() {
throw new AssertionError();
}
public static final String BEGIN = "BEGIN ";
public static final String END = "END";
public static final String END_SPACE = "END ";
public static final String SEMICOLON = ";";
public static final String ELSE = "ELSE ";
public static String IF(String v) {
return "IF NOT EXISTS (SELECT * FROM " + v + ") ";
}
public static String IF(String v, String u) {
return "IF NOT EXISTS (SELECT * FROM " + v + " WHERE " + u + " = ?) ";
}
}