Add support for tracks

This commit is contained in:
Luck
2016-07-15 22:44:25 +01:00
Unverified
parent 90b6f41f13
commit 874a90253b
44 changed files with 1585 additions and 59 deletions
@@ -4,6 +4,7 @@ import lombok.Getter;
import lombok.Setter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.UUID;
@@ -45,7 +46,7 @@ public abstract class Datastore {
}
/*
These methods will block the thread that they're ran on.
These methods are called immediately and in the same thread as they are called in.
*/
public abstract void init();
public abstract void shutdown();
@@ -57,16 +58,19 @@ public abstract class Datastore {
public abstract boolean loadAllGroups();
public abstract boolean saveGroup(Group group);
public abstract boolean deleteGroup(Group group);
public abstract boolean createAndLoadTrack(String name);
public abstract boolean loadTrack(String name);
public abstract boolean loadAllTracks();
public abstract boolean saveTrack(Track track);
public abstract boolean deleteTrack(Track track);
public abstract boolean saveUUIDData(String username, UUID uuid);
public abstract UUID getUUID(String username);
/*
These methods will return as soon as they are called. The callback will be ran when the task is complete
They therefore will not block the thread that they're ran on
Callbacks are ran on the main server thread (if applicable)
These methods will schedule the operation to run async. The callback will be ran when the task is complete.
Callbacks are ran on the main Bukkit server thread (if applicable)
*/
public void loadOrCreateUser(UUID uuid, String username, Callback callback) {
doAsync(() -> runCallback(loadOrCreateUser(uuid, username), callback));
@@ -100,6 +104,26 @@ public abstract class Datastore {
doAsync(() -> runCallback(deleteGroup(group), callback));
}
public void createAndLoadTrack(String name, Callback callback) {
doAsync(() -> runCallback(createAndLoadTrack(name), callback));
}
public void loadTrack(String name, Callback callback) {
doAsync(() -> runCallback(loadTrack(name), callback));
}
public void loadAllTracks(Callback callback) {
doAsync(() -> runCallback(loadAllTracks(), callback));
}
public void saveTrack(Track track, Callback callback) {
doAsync(() -> runCallback(saveTrack(track), callback));
}
public void deleteTrack(Track track, Callback callback) {
doAsync(() -> runCallback(deleteTrack(track), callback));
}
public void saveUUIDData(String username, UUID uuid, Callback callback) {
doAsync(() -> runCallback(saveUUIDData(username, uuid), callback));
}
@@ -5,6 +5,7 @@ import com.google.gson.stream.JsonWriter;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.io.*;
@@ -20,6 +21,7 @@ public class FlatfileDatastore extends Datastore {
private final File pluginDir;
private File usersDir;
private File groupsDir;
private File tracksDir;
private File uuidData;
public FlatfileDatastore(LuckPermsPlugin plugin, File pluginDir) {
@@ -107,6 +109,9 @@ public class FlatfileDatastore extends Datastore {
groupsDir = new File(data, "groups");
groupsDir.mkdir();
tracksDir = new File(data, "tracks");
tracksDir.mkdir();
uuidData = new File(data, "uuidcache.txt");
uuidData.createNewFile();
}
@@ -365,6 +370,132 @@ public class FlatfileDatastore extends Datastore {
return true;
}
@Override
public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
List<String> groups = new ArrayList<>();
File trackFile = new File(tracksDir, name + ".json");
if (!trackFile.exists()) {
try {
trackFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
boolean success = doWrite(trackFile, writer -> {
writer.beginObject();
writer.name("name").value(track.getName());
writer.name("groups");
writer.beginArray();
for (String s : track.getGroups()) {
writer.value(s);
}
writer.endArray();
writer.endObject();
return true;
});
if (!success) return false;
}
boolean success = doRead(trackFile, reader -> {
reader.beginObject();
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); // groups record
reader.beginArray();
while (reader.hasNext()) {
groups.add(reader.nextString());
}
reader.endArray();
reader.endObject();
return true;
});
track.setGroups(groups);
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
List<String> groups = new ArrayList<>();
File trackFile = new File(tracksDir, name + ".json");
if (!trackFile.exists()) {
return false;
}
boolean success = doRead(trackFile, reader -> {
reader.beginObject();
reader.nextName(); // name record
reader.nextString(); // name
reader.nextName(); // groups record
reader.beginArray();
while (reader.hasNext()) {
groups.add(reader.nextString());
}
reader.endArray();
reader.endObject();
return true;
});
track.setGroups(groups);
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadAllTracks() {
String[] fileNames = tracksDir.list((dir, name) -> name.endsWith(".json"));
if (fileNames == null) return false;
List<String> tracks = Arrays.stream(fileNames).map(s -> s.substring(0, s.length() - 5)).collect(Collectors.toList());
plugin.getTrackManager().unloadAll();
tracks.forEach(this::loadTrack);
return true;
}
@Override
public boolean saveTrack(Track track) {
File trackFile = new File(tracksDir, track.getName() + ".json");
if (!trackFile.exists()) {
try {
trackFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
boolean success = doWrite(trackFile, writer -> {
writer.beginObject();
writer.name("name").value(track.getName());
writer.name("groups");
writer.beginArray();
for (String s : track.getGroups()) {
writer.value(s);
}
writer.endArray();
writer.endObject();
return true;
});
return success;
}
@Override
public boolean deleteTrack(Track track) {
File trackFile = new File(tracksDir, track.getName() + ".json");
if (trackFile.exists()) {
trackFile.delete();
}
return true;
}
private Map<String, String> getUUIDCache() {
Map<String, String> cache = new HashMap<>();
@@ -13,6 +13,7 @@ public class MySQLDatastore extends SQLDatastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;";
private final MySQLConfiguration configuration;
private HikariDataSource hikari;
@@ -39,7 +40,7 @@ public class MySQLDatastore extends SQLDatastore {
hikari.addDataSourceProperty("user", username);
hikari.addDataSourceProperty("password", password);
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS)) {
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed.");
shutdown();
} else {
@@ -8,6 +8,8 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.groups.GroupManager;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.tracks.TrackManager;
import me.lucko.luckperms.users.User;
import java.lang.reflect.Type;
@@ -24,6 +26,7 @@ import java.util.UUID;
abstract class SQLDatastore extends Datastore {
private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>(){}.getType();
private static final Type T_TYPE = new TypeToken<List<String>>(){}.getType();
private static final String USER_INSERT = "INSERT INTO lp_users VALUES(?, ?, ?, ?)";
private static final String USER_SELECT = "SELECT * FROM lp_users WHERE uuid=?";
@@ -35,6 +38,12 @@ abstract class SQLDatastore extends Datastore {
private static final String GROUP_UPDATE = "UPDATE lp_groups SET perms=? WHERE name=?";
private static final String GROUP_DELETE = "DELETE FROM lp_groups WHERE name=?";
private static final String TRACK_INSERT = "INSERT INTO lp_tracks VALUES(?, ?)";
private static final String TRACK_SELECT = "SELECT groups FROM lp_tracks WHERE name=?";
private static final String TRACK_SELECT_ALL = "SELECT * FROM lp_tracks";
private static final String TRACK_UPDATE = "UPDATE lp_tracks SET groups=? WHERE name=?";
private static final String TRACK_DELETE = "DELETE FROM lp_tracks WHERE name=?";
private static final String UUIDCACHE_INSERT = "INSERT INTO lp_uuid VALUES(?, ?)";
private static final String UUIDCACHE_SELECT = "SELECT uuid FROM lp_uuid WHERE name=?";
private static final String UUIDCACHE_UPDATE = "UPDATE lp_uuid SET uuid=? WHERE name=?";
@@ -303,6 +312,111 @@ abstract class SQLDatastore extends Datastore {
return success;
}
@Override
public boolean createAndLoadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
boolean success = runQuery(new QueryRS(TRACK_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, track.getName());
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
boolean success = true;
if (!resultSet.next()) {
success = runQuery(new QueryPS(TRACK_INSERT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, track.getName());
preparedStatement.setString(2, gson.toJson(track.getGroups()));
}
});
} else {
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
}
return success;
}
});
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadTrack(String name) {
Track track = plugin.getTrackManager().makeTrack(name);
boolean success = runQuery(new QueryRS(TRACK_SELECT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, name);
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
return true;
}
return false;
}
});
if (success) plugin.getTrackManager().updateOrSetTrack(track);
return success;
}
@Override
public boolean loadAllTracks() {
List<Track> tracks = new ArrayList<>();
boolean success = runQuery(new QueryRS(TRACK_SELECT_ALL) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
}
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
Track track = plugin.getTrackManager().makeTrack(resultSet.getString("name"));
track.setGroups(gson.fromJson(resultSet.getString("groups"), T_TYPE));
tracks.add(track);
}
return true;
}
});
if (success) {
TrackManager tm = plugin.getTrackManager();
tm.unloadAll();
tracks.forEach(tm::setTrack);
}
return success;
}
@Override
public boolean saveTrack(Track track) {
boolean success = runQuery(new QueryPS(TRACK_UPDATE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, gson.toJson(track.getGroups()));
preparedStatement.setString(2, track.getName());
}
});
return success;
}
@Override
public boolean deleteTrack(Track track) {
boolean success = runQuery(new QueryPS(TRACK_DELETE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, track.getName());
}
});
return success;
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) {
@@ -13,6 +13,7 @@ public class SQLiteDatastore extends SQLDatastore {
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));";
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`));";
private static final String CREATETABLE_GROUPS = "CREATE TABLE IF NOT EXISTS `lp_groups` (`name` VARCHAR(36) NOT NULL, `perms` TEXT NULL, PRIMARY KEY (`name`));";
private static final String CREATETABLE_TRACKS = "CREATE TABLE IF NOT EXISTS `lp_tracks` (`name` VARCHAR(36) NOT NULL, `groups` TEXT NULL, PRIMARY KEY (`name`));";
private final File file;
private Connection connection = null;
@@ -24,7 +25,7 @@ public class SQLiteDatastore extends SQLDatastore {
@Override
public void init() {
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS)) {
if (!setupTables(CREATETABLE_UUID, CREATETABLE_USERS, CREATETABLE_GROUPS, CREATETABLE_TRACKS)) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed.");
shutdown();
} else {