Pretty much finished

This commit is contained in:
Paldiu 2023-01-26 16:26:48 -06:00
parent d2e4f6669a
commit 4205be4aae
10 changed files with 463 additions and 24 deletions

View File

@ -10,14 +10,14 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class LocalizedBanList implements Locker, Baker { public final class BanManager implements Locker, Baker {
private final Traverse plugin; private final Traverse plugin;
private Set<AbstractBan> storedBans; // This should only be reassigned by the baker. private Set<AbstractBan> storedBans; // This should only be reassigned by the baker.
private boolean baked = false; // This should only be reassigned by the baker. private boolean baked = false; // This should only be reassigned by the baker.
@SneakyThrows @SneakyThrows
public LocalizedBanList(Traverse plugin) { public BanManager(Traverse plugin) {
this.storedBans = new HashSet<>(); this.storedBans = new HashSet<>();
this.plugin = plugin; this.plugin = plugin;

View File

@ -0,0 +1,101 @@
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.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public final class DataManager implements Baker, Locker {
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.
public DataManager(Traverse plugin) {
this.plugin = plugin;
DBUser user = new DBUser(plugin.getSQLManager().establish());
user.createTable();
playerDataCache.addAll(user.all());
user.close();
bake();
}
@Nullable
public PlayerData getPlayerData(String playerName) {
return playerDataCache.stream()
.filter(data -> data.getUserName().equals(playerName))
.findFirst()
.orElse(null);
}
@Nullable
public PlayerData getPlayerData(UUID uuid) {
return playerDataCache.stream()
.filter(data -> data.getUuid().equals(uuid))
.findFirst()
.orElse(null);
}
public void addPlayerData(PlayerData data) {
if (baked) throw new IllegalStateException("Cannot add player data while the data manager is baked.");
playerDataCache.add(data);
}
public void removePlayerData(PlayerData data) {
if (baked) throw new IllegalStateException("Cannot remove player data while the data 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.");
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.");
playerDataCache.removeIf(data -> data.getUserName().equals(playerName));
}
public void saveData(PlayerData data) {
DBUser user = new DBUser(plugin.getSQLManager().establish());
user.insert(data);
}
@SneakyThrows
@Override
public void bake() {
if (baked) return;
synchronized (lock()) {
this.playerDataCache = playerDataCache.stream().collect(Collectors.toUnmodifiableSet());
lock().wait(1000);
}
this.baked = true;
lock().notify();
}
@SneakyThrows
@Override
public void unbake() {
if (!baked) return;
synchronized (lock()) {
this.playerDataCache = new HashSet<>(playerDataCache);
lock().wait(1000);
}
this.baked = false;
lock().notify();
}
}

View File

@ -0,0 +1,19 @@
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;
private Rank rank;
private long playtime;
private int coins;
private Date lastLogin;
}

View File

@ -0,0 +1,33 @@
package mc.unraveled.reforged.data;
import mc.unraveled.reforged.permission.Rank;
import mc.unraveled.reforged.plugin.Traverse;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import java.time.Instant;
import java.util.Date;
public class PlayerDataListener implements Listener {
private final Traverse plugin;
public PlayerDataListener(Traverse plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
this.plugin = plugin;
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
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()));
plugin.getDataManager().addPlayerData(data);
}
data.setLastLogin(Date.from(Instant.now()));
}
}

View File

@ -0,0 +1,63 @@
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 {
private final Rank rank;
private Set<String> permissions = new HashSet<>();
private Set<OfflinePlayer> players = new HashSet<>();
private boolean baked = false;
public Group(Rank rank) {
this.rank = rank;
}
public void insert(String permission) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
permissions.add(permission);
}
public void insert(OfflinePlayer player) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
players.add(player);
}
public void eject(String permission) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
permissions.remove(permission);
}
public void eject(OfflinePlayer player) {
if (baked) throw new IllegalStateException("Cannot modify a baked group.");
players.remove(player);
}
@Override
public void bake() {
if (baked) return;
this.permissions = permissions.stream().collect(Collectors.toUnmodifiableSet());
this.players = players.stream().collect(Collectors.toUnmodifiableSet());
this.baked = true;
}
@Override
public void unbake() {
if (!baked) return;
this.permissions = new HashSet<>(permissions);
this.players = new HashSet<>(players);
this.baked = false;
}
}

View File

@ -0,0 +1,104 @@
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.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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 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;
List<String> permissionList;
playerList = groupHandler.getPlayers(rank);
permissionList = groupHandler.getPermissions(rank);
rankTuple = new Tuple<>(rank, playerList, permissionList);
rankQueue.add(rankTuple);
}
groupHandler.close();
bake();
}
public void insert(Rank rank, List<OfflinePlayer> player, List<String> args) {
rankQueue.add(new Tuple<>(rank, player, args));
}
public void eject(Rank rank, List<OfflinePlayer> player, List<String> args) {
rankQueue.remove(new Tuple<>(rank, player, args));
}
public void insertPermission(Rank rank, String permission) {
rankQueue.stream()
.filter(tuple -> tuple.getFirst().equals(rank))
.forEach(tuple -> tuple.getThird().add(permission));
}
public void ejectPermission(Rank rank, String permission) {
rankQueue.stream()
.filter(tuple -> tuple.getFirst().equals(rank))
.forEach(tuple -> tuple.getThird().remove(permission));
}
@Override
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();
Group group = new Group(rank);
for (OfflinePlayer p : players) {
group.insert(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();
}
baked = false;
lock().notify();
}
}

View File

@ -1,37 +1,41 @@
package mc.unraveled.reforged.plugin; package mc.unraveled.reforged.plugin;
import lombok.Getter;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import mc.unraveled.reforged.permission.Rank; import mc.unraveled.reforged.banning.BanManager;
import mc.unraveled.reforged.command.base.CommandLoader;
import mc.unraveled.reforged.data.DataManager;
import mc.unraveled.reforged.permission.RankManager;
import mc.unraveled.reforged.storage.DBConnectionHandler; import mc.unraveled.reforged.storage.DBConnectionHandler;
import mc.unraveled.reforged.storage.DBGroup;
import mc.unraveled.reforged.storage.DBProperties; import mc.unraveled.reforged.storage.DBProperties;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.util.Arrays;
public final class Traverse extends JavaPlugin { public final class Traverse extends JavaPlugin {
private DBConnectionHandler handler; // Primary variable declaration.
@Getter
private DBConnectionHandler SQLManager;
@Getter
private DataManager dataManager;
@Getter
private CommandLoader commandLoader;
@Getter
private BanManager banManager;
@Getter
private RankManager rankManager;
@Override @Override
@SneakyThrows
public void onEnable() { public void onEnable() {
initDatabaseGroups(); this.SQLManager = new DBConnectionHandler(new DBProperties("db.properties"));
this.dataManager = new DataManager(this);
this.commandLoader = new CommandLoader(this, "TRAVERSE");
this.banManager = new BanManager(this);
this.rankManager = new RankManager(this);
} }
@Override @Override
public void onDisable() { public void onDisable() {
// Plugin shutdown logic // Plugin shutdown logic
} }
@SneakyThrows
private void initDatabaseGroups() {
handler = new DBConnectionHandler(new DBProperties("groups.properties"));
DBGroup groupHandler = new DBGroup(handler.establish());
Arrays.stream(Rank.values()).forEach(groupHandler::createTable);
groupHandler.close();
}
public DBConnectionHandler getSQLManager() {
return handler;
}
} }

View File

@ -30,7 +30,7 @@ public class DBBan {
} }
@SneakyThrows @SneakyThrows
public void addBan(AbstractBan ban) { public void insert(@NotNull AbstractBan ban) {
PreparedStatement statement = getConnection().prepareStatement("INSERT INTO bans (uuid, ip, reason, banned_by, banned_at, expires_at, active) VALUES (?, ?, ?, ?, ?, ?, ?);"); 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(1, ban.getUuid());
statement.setString(2, ban.getIp()); statement.setString(2, ban.getIp());
@ -77,11 +77,38 @@ public class DBBan {
return bans; return bans;
} }
@SneakyThrows
public void update(@NotNull AbstractBan ban) {
PreparedStatement statement = getConnection().prepareStatement("UPDATE bans SET reason = ?, banned_by = ?, banned_at = ?, expires_at = ?, active = ? WHERE uuid = ?;");
statement.setString(1, ban.getReason());
statement.setString(2, ban.getSource());
statement.setLong(3, ban.getPropogated());
statement.setLong(4, ban.getExpiry());
statement.setBoolean(5, ban.isActive());
statement.setString(6, ban.getUuid());
statement.executeUpdate();
}
@SneakyThrows
public void delete(@NotNull AbstractBan ban) {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM bans WHERE uuid = ?;");
statement.setString(1, ban.getUuid());
statement.executeUpdate();
}
@SneakyThrows
public void deleteAll() {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM bans;");
statement.executeUpdate();
}
@SneakyThrows @SneakyThrows
public void close() { public void close() {
getConnection().close(); getConnection().close();
this.connection = null;
} }
public void open(Connection connection) {
this.connection = connection;
}
} }

View File

@ -0,0 +1,88 @@
package mc.unraveled.reforged.storage;
import lombok.Getter;
import lombok.SneakyThrows;
import mc.unraveled.reforged.data.PlayerData;
import mc.unraveled.reforged.permission.Rank;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
public class DBUser {
@Getter
private 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, PRIMARY KEY (uuid));");
statement.executeUpdate();
}
@SneakyThrows
public void insert(@NotNull PlayerData playerData) {
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) VALUES (?, ?, ?, ?, ?, ?) END " +
"ELSE BEGIN (UPDATE users SET username = ?, rank = ?, play_time = ?, coins = ?, last_login = ? 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.getUserName());
statement.setString(9, playerData.getRank().name());
statement.setLong(10, playerData.getPlaytime());
statement.setInt(11, playerData.getCoins());
statement.setLong(12, playerData.getLastLogin().getTime());
statement.setString(13, playerData.getUuid().toString());
statement.executeUpdate();
}
@SneakyThrows
public void delete(@NotNull PlayerData playerData) {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM users WHERE uuid = ?;");
statement.setString(1, playerData.getUuid().toString());
statement.executeUpdate();
}
@SneakyThrows
public void deleteAll() {
PreparedStatement statement = getConnection().prepareStatement("DELETE FROM users;");
statement.executeUpdate();
}
@SneakyThrows
public List<PlayerData> all() {
PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM users;");
ResultSet resultSet = statement.executeQuery();
List<PlayerData> dataList = new ArrayList<>();
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")));
dataList.add(playerData);
}
return dataList;
}
@SneakyThrows
public void close() {
getConnection().close();
}
}

View File

@ -7,7 +7,7 @@ host=localhost
# The database port. # The database port.
port=5432 port=5432
# The database file name. # The database file name.
databaseFile=groups.db databaseFile=database.db
# The database username. # The database username.
username=admin username=admin
# The database password. # The database password.