diff --git a/Figures for documentation/Resolution of permission tree.PNG b/Figures for documentation/Resolution of permission tree.PNG new file mode 100644 index 0000000..ffe7147 Binary files /dev/null and b/Figures for documentation/Resolution of permission tree.PNG differ diff --git a/Figures for documentation/Resolution of permission tree.pptx b/Figures for documentation/Resolution of permission tree.pptx new file mode 100644 index 0000000..c63d4aa Binary files /dev/null and b/Figures for documentation/Resolution of permission tree.pptx differ diff --git a/Figures for documentation/rscPermissions-WebUI Concept.png b/Figures for documentation/rscPermissions-WebUI Concept.png new file mode 100644 index 0000000..286ac97 Binary files /dev/null and b/Figures for documentation/rscPermissions-WebUI Concept.png differ diff --git a/nb-configuration.xml b/nb-configuration.xml new file mode 100644 index 0000000..b9cdb90 --- /dev/null +++ b/nb-configuration.xml @@ -0,0 +1,18 @@ + + + + + + ______JDK_1.7_Update_51 + + diff --git a/nbactions.xml b/nbactions.xml new file mode 100644 index 0000000..9177298 --- /dev/null +++ b/nbactions.xml @@ -0,0 +1,46 @@ + + + + run + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -classpath %classpath ru.simsonic.rscPermissions.MainPluginClass + java + + + + debug + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath ru.simsonic.rscPermissions.MainPluginClass + java + true + + + + profile + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -classpath %classpath ru.simsonic.rscPermissions.MainPluginClass + java + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..67284fe --- /dev/null +++ b/pom.xml @@ -0,0 +1,170 @@ + + 4.0.0 + + ru.simsonic + rscPermissions + 0.8.10b + jar + + rscPermissions + http://maven.apache.org + + + UTF-8 + + + + ${project.artifactId}_v${project.version} + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + true + false + true + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + false + + + .* + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.2 + + + package + + shade + + + true + + + ru.simsonic:rscAPI + + + false + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + + public + true + + + + + + src/main/resources + true + + + + + + + bukkit-repo + http://repo.bukkit.org/content/groups/public + + + + sk89q-repo + http://maven.sk89q.com/repo/ + + + Residence + http://ci.drtshock.net/plugin/repository/everything/ + + + + + voxile.ru + http://ci.voxile.ru/plugin/repository/everything/ + + + + + mysql + mysql-connector-java + 5.1.30 + runtime + + + org.bukkit + bukkit + 1.7.5-R0.1-SNAPSHOT + provided + jar + + + com.sk89q + worldedit + 5.6 + compile + jar + + + com.sk89q + worldguard + 5.9.1-SNAPSHOT + provided + jar + + + net.t00thpick1 + Residence + 3.0-SNAPSHOT + provided + jar + + + ru.simsonic + rscAPI + 1.2.0 + compile + jar + + + \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/AsyncPlayerInfo.java b/src/main/java/ru/simsonic/rscPermissions/AsyncPlayerInfo.java new file mode 100644 index 0000000..763a7c1 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/AsyncPlayerInfo.java @@ -0,0 +1,97 @@ +package ru.simsonic.rscPermissions; +import java.util.Set; +import java.util.UUID; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; +import ru.simsonic.rscPermissions.LocalCacheTree.ResolutionLeaf; + +public class AsyncPlayerInfo +{ + public Player player; + public String name; + public UUID uuid; + public int expirience; + public Location location; + public Set regions; + public AsyncPlayerInfo() + { + } + public AsyncPlayerInfo(String playerName) + { + this.name = playerName; + } + public AsyncPlayerInfo(UUID playerUniqueId) + { + this.uuid = playerUniqueId; + } + public AsyncPlayerInfo(Player player, Set regions) + { + if(player != null) + { + this.player = player; + try + { + // minecraft <= 1.7 + this.name = player.getName(); + } catch(RuntimeException | NoSuchMethodError ex) { + // minecraft >= 1.8 + } + try + { + // minecraft >= 1.8 + this.uuid = player.getUniqueId(); + } catch(RuntimeException | NoSuchMethodError ex) { + // minecraft <= 1.7 + } + this.expirience = player.getLevel(); + this.location = player.getLocation(); + this.regions = regions; + } + } + public boolean isPlayerEntityApplicable(String entity) + { + // Test by UUID (minecraft >= 1.8) + try + { + if(this.uuid.compareTo(UUID.fromString(entity)) == 0) + return true; + } catch(RuntimeException ex) { + // Server doesn't support this yet + } + // Test by name (minecraft <= 1.7) + try + { + if(this.name.equalsIgnoreCase(entity)) + return true; + } catch(RuntimeException ex) { + // Server already doesn't support this + } + return false; + } + public boolean isPlayerPermissionApplicable(RowPermission row) + { + if(isPlayerEntityApplicable(row.entity) || "".equals(row.entity)) + return (row.destination.IsLocationApplicable(location, regions, null) && row.expirience <= expirience); + return false; + } + public boolean isGroupPermissionApplicable(RowPermission row, ResolutionLeaf leaf) + { + if(row.entity.equalsIgnoreCase(leaf.group) || "".equals(row.entity)) + return (row.destination.IsLocationApplicable(location, regions, leaf.instance) && row.expirience <= expirience); + return false; + } + public boolean isPlayerInheritanceApplicable(RowInheritance row) + { + if(isPlayerEntityApplicable(row.entity)) + return (row.destination.IsLocationApplicable(location, regions, row.instance) && row.expirience <= expirience); + return false; + } + public boolean isGroupInheritanceApplicable(RowInheritance row, ResolutionLeaf leaf) + { + if(row.entity.equalsIgnoreCase(leaf.group)) + return (row.destination.IsLocationApplicable(location, regions, leaf.instance) && row.expirience <= expirience); + return false; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/Backends/Backend.java b/src/main/java/ru/simsonic/rscPermissions/Backends/Backend.java new file mode 100644 index 0000000..fb77218 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/Backends/Backend.java @@ -0,0 +1,26 @@ +package ru.simsonic.rscPermissions.Backends; +import ru.simsonic.rscPermissions.DataTypes.RowEntity; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowLadder; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; +import ru.simsonic.rscPermissions.DataTypes.RowServer; +import ru.simsonic.rscPermissions.LocalCacheData; + +public interface Backend +{ + public abstract boolean canRead(); + public abstract boolean canWrite(); + + public abstract void fetchIntoCache(LocalCacheData cache); + public abstract RowEntity[] fetchEntities(); + public abstract RowPermission[] fetchPermissions(); + public abstract RowInheritance[] fetchInheritance(); + public abstract RowLadder[] fetchLadders(); + public abstract RowServer[] fetchServers(); + + public abstract void insertExampleRows(); + public abstract void updateEntityText(String entity, boolean entity_type, String text, boolean isPrefix); + public abstract void setUserRank(String user, String ladder, int rank); + public abstract void dropUserFromLadder(String user, String ladder); + public abstract void addUserParentGroup(String user, String newGroup); +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/Backends/BackendMySQL.java b/src/main/java/ru/simsonic/rscPermissions/Backends/BackendMySQL.java new file mode 100644 index 0000000..79137d8 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/Backends/BackendMySQL.java @@ -0,0 +1,351 @@ +package ru.simsonic.rscPermissions.Backends; +import ru.simsonic.utilities.*; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.logging.Level; +import ru.simsonic.rscPermissions.DataTypes.Destination; +import ru.simsonic.rscPermissions.DataTypes.RowEntity; +import ru.simsonic.rscPermissions.DataTypes.RowEntity.EntityType; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowLadder; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; +import ru.simsonic.rscPermissions.DataTypes.RowReward; +import ru.simsonic.rscPermissions.DataTypes.RowServer; +import ru.simsonic.rscPermissions.LocalCacheData; +import ru.simsonic.rscPermissions.MainPluginClass; +import ru.simsonic.rscPermissions.Rewards; +import ru.simsonic.rscPermissions.Settings; + +public class BackendMySQL extends ConnectionMySQL implements Backend +{ + protected final MainPluginClass plugin; + protected static enum WorkMode { read, write, none, } + protected WorkMode RememberWork; + public BackendMySQL(MainPluginClass plugin) + { + this.plugin = plugin; + } + public synchronized void Initialize(String name, String database, String username, String password, String workmode, String prefixes) + { + super.Initialize(name, database, username, password, prefixes); + switch(workmode.toLowerCase()) + { + case "fullaccess": + RememberWork = WorkMode.write; + break; + case "readonly": + RememberWork = WorkMode.read; + break; + case "none": + default: + RememberWork = WorkMode.none; + break; + } + } + @Override + public synchronized boolean canRead() + { + return (RememberWork != WorkMode.none) ? (isConnected() ? true : Connect()) : false; + } + @Override + public synchronized boolean canWrite() + { + return (RememberWork == WorkMode.write) ? (isConnected() ? true : Connect()) : false; + } + @Override + public synchronized boolean Connect() + { + if(RememberWork == WorkMode.none) + return false; + if(super.Connect()) + { + createTablesIfNotExist(); + cleanupTables(); + updateServerInfo(); + return true; + } + return false; + } + @Override + public synchronized ResultSet executeQuery(String query) + { + if(canRead() == false) + return null; + return super.executeQuery(query); + } + @Override + public synchronized boolean executeUpdate(String query) + { + if(canWrite() == false) + return false; + return super.executeUpdate(query); + } + private void createTablesIfNotExist() + { + executeUpdate(loadResourceSQLT("Initialize_main_v1")); + if(plugin.settings.isRewardsEnabled()) + executeUpdate(loadResourceSQLT("Initialize_rewards_v1")); + } + private void cleanupTables() + { + executeUpdate(loadResourceSQLT("Cleanup_tables")); + } + private void updateServerInfo() + { + final String mMode = plugin.settings.getMaintenanceMode(); + setupQueryTemplate("{SERVERID}", plugin.getServer().getServerId()); + setupQueryTemplate("{PLUGIN_VER}", plugin.getDescription().getVersion()); + setupQueryTemplate("{DEFAULT}", plugin.settings.getDefaultGroup()); + setupQueryTemplate("{OP}", plugin.settings.isAsteriskOP() ? "1" : "0"); + setupQueryTemplate("{DELAY}", Integer.toString(plugin.settings.getAutoReloadDelayTicks() / 20)); + setupQueryTemplate("{mMode}", "".equals(mMode) ? "NULL" : "\"" + mMode + "\""); + setupQueryTemplate("{USE_R}", plugin.settings.isRewardsEnabled() ? "1" : "0"); + setupQueryTemplate("{CFG_VER}", Integer.toString(plugin.settings.CurrentVersion)); + executeUpdate(loadResourceSQLT("Update_server_info")); + } + @Override + public synchronized void fetchIntoCache(LocalCacheData cache) + { + cleanupTables(); + MainPluginClass.consoleLog.log(Level.INFO, + "[rscp] Fetched {0}e, {1}p, {2}i, {3}l, {4}s from \"{5}\".", + new Object[] + { + Integer.toString(cache.ImportEntities(fetchEntities())), + Integer.toString(cache.ImportPermissions(fetchPermissions())), + Integer.toString(cache.ImportInheritance(fetchInheritance())), + Integer.toString(cache.ImportLadders(fetchLadders())), + Integer.toString(cache.ImportServers(fetchServers())), + RememberName, + }); + } + @Override + public synchronized RowEntity[] fetchEntities() + { + final ArrayList result = new ArrayList<>(); + final ResultSet rs = executeQuery("SELECT * FROM `{DATABASE}`.`{PREFIX}entities`;"); + try + { + while(rs.next()) + { + RowEntity row = new RowEntity(); + row.id = rs.getInt("id"); + row.entity = rs.getString("entity"); + row.entity_type = EntityType.byValue(rs.getInt("entity_type")); + row.prefix = rs.getString("prefix"); + row.suffix = rs.getString("suffix"); + result.add(row); + } + rs.close(); + } catch(SQLException ex) { + MainPluginClass.consoleLog.log(Level.WARNING, "[rscp] Exception in rs2e(): {0}", ex.getLocalizedMessage()); + } + return result.toArray(new RowEntity[result.size()]); + } + @Override + public synchronized RowPermission[] fetchPermissions() + { + final ArrayList result = new ArrayList<>(); + final ResultSet rs = executeQuery("SELECT * FROM `{DATABASE}`.`{PREFIX}permissions`;"); + final String serverId = plugin.getServer().getServerId(); + try + { + while(rs.next()) + { + for(Destination destination : Destination.ParseDestinations(rs.getString("destination"))) + { + if(destination.IsServerIdApplicable(serverId) == false) + continue; + RowPermission row = new RowPermission(); + row.id = rs.getInt("id"); + row.entity = rs.getString("entity"); + row.entity_type = EntityType.byValue(rs.getInt("entity_type")); + row.permission = rs.getString("permission"); + row.value = rs.getBoolean("value"); + row.destination = destination; + row.expirience = rs.getInt("expirience"); + row.lifetime = rs.getTimestamp("lifetime"); + result.add(row); + } + } + rs.close(); + } catch(SQLException ex) { + MainPluginClass.consoleLog.log(Level.WARNING, "[rscp] Exception in rs2p(): {0}", ex.getLocalizedMessage()); + } + return result.toArray(new RowPermission[result.size()]); + } + @Override + public synchronized RowInheritance[] fetchInheritance() + { + final ArrayList result = new ArrayList<>(); + final ResultSet rs = executeQuery("SELECT * FROM `{DATABASE}`.`{PREFIX}inheritance`;"); + final String serverId = plugin.getServer().getServerId(); + try + { + while(rs.next()) + { + for(Destination destination : Destination.ParseDestinations(rs.getString("destination"))) + { + if(destination.IsServerIdApplicable(serverId) == false) + continue; + RowInheritance row = new RowInheritance(); + row.id = rs.getInt("id"); + row.entity = rs.getString("entity"); + row.parent = rs.getString("parent"); + String[] breaked = row.parent.split(Settings.separatorRegExp); + if(breaked.length == 2) + { + row.parent = breaked[0]; + row.instance = breaked[1]; + } + row.child_type = EntityType.byValue(rs.getInt("inheritance_type")); + row.priority = rs.getInt("inheritance_priority"); + row.destination = destination; + row.expirience = rs.getInt("expirience"); + row.lifetime = rs.getTimestamp("lifetime"); + result.add(row); + } + } + rs.close(); + } catch(SQLException ex) { + MainPluginClass.consoleLog.log(Level.WARNING, "[rscp] Exception in rs2i(): {0}", ex.getLocalizedMessage()); + } + return result.toArray(new RowInheritance[result.size()]); + } + @Override + public synchronized RowLadder[] fetchLadders() + { + final ArrayList result = new ArrayList<>(); + final ResultSet rs = executeQuery("SELECT * FROM `{DATABASE}`.`{PREFIX}ladders`;"); + try + { + while(rs.next()) + { + RowLadder row = new RowLadder(); + row.id = rs.getInt("id"); + row.climber = rs.getString("climber"); + if("".equals(row.climber)) + row.climber = null; + row.climber_type = EntityType.byValue(rs.getInt("climber_type")); + row.ladder = rs.getString("ladder"); + String[] breaked = row.ladder.split(Settings.separatorRegExp); + if(breaked.length == 2) + { + row.ladder = breaked[0]; + row.instance = breaked[1]; + } + row.rank = rs.getInt("rank"); + result.add(row); + } + rs.close(); + } catch(SQLException ex) { + MainPluginClass.consoleLog.log(Level.WARNING, "[rscp] Exception in rs2l(): {0}", ex.getLocalizedMessage()); + } + return result.toArray(new RowLadder[result.size()]); + } + @Override + public synchronized RowServer[] fetchServers() + { + final ArrayList result = new ArrayList<>(); + final ResultSet rs = executeQuery("SELECT * FROM `{DATABASE}`.`{PREFIX}servers`;"); + try + { + while(rs.next()) + { + RowServer row = new RowServer(); + row.serverId = rs.getString("serverId"); + // PARSE OTHER COLUMNS HERE + result.add(row); + } + rs.close(); + } catch(SQLException ex) { + MainPluginClass.consoleLog.log(Level.WARNING, "[rscp] Exception in rs2s(): {0}", ex.getLocalizedMessage()); + } + return result.toArray(new RowServer[result.size()]); + } + public synchronized void fetchRewards(Rewards rewardHelper) + { + final ArrayList result = new ArrayList<>(); + final ResultSet rs = executeQuery("SELECT * FROM `{DATABASE}`.`{PREFIX}rewards`;"); + try + { + while(rs.next()) + { + RowReward row = new RowReward(); + row.id = rs.getInt("id"); + row.user = rs.getString("user").toLowerCase(); + row.code = rs.getString("code"); + row.activated = rs.getBoolean("activated"); + if(row.activated) + continue; + row.activated_timestamp = rs.getTimestamp("activated_timestamp"); + row.execute_commands = rs.getString("execute_commands"); + row.command_permissions = rs.getString("command_permissions"); + row.add_group = rs.getString("add_group"); + row.add_group_destination = rs.getString("add_group_destination"); + row.add_group_expirience = rs.getInt("add_group_expirience"); + row.add_group_interval = rs.getString("add_group_interval"); + result.add(row); + } + rs.close(); + } catch(SQLException ex) { + MainPluginClass.consoleLog.log(Level.WARNING, "[rscp] Exception in rs2r(): {0}", ex.getLocalizedMessage()); + } + MainPluginClass.consoleLog.log(Level.INFO, "[rscp] Fetched {0} unused reward codes.", + Integer.toString(result.size())); + rewardHelper.ImportRewards(result.toArray(new RowReward[result.size()])); + } + @Override + public synchronized void insertExampleRows() + { + executeUpdate(loadResourceSQLT("Insert_example_rows_v1")); + } + @Override + public synchronized void updateEntityText(String entity, boolean entity_type, String text, boolean isPrefix) + { + if("".equals(entity)) + return; + if("".equals(text) || "\"\"".equals(text)) + text = null; + setupQueryTemplate("{ENTITY}", entity); + setupQueryTemplate("{ENTITY_TYPE}", entity_type ? "1" : "0"); + setupQueryTemplate("{TEXT_TYPE}", isPrefix ? "prefix" : "suffix"); + setupQueryTemplate("{TEXT}", (text != null) ? "'" + text + "'" : "NULL"); + executeUpdate(loadResourceSQLT("Update_entity_text")); + } + @Override + public synchronized void setUserRank(String user, String ladder, int rank) + { + if("".equals(user) || "".equals(ladder)) + return; + setupQueryTemplate("{USER}", user); + setupQueryTemplate("{LADDER}", ladder); + setupQueryTemplate("{RANK}", Integer.toString(rank)); + executeUpdate(loadResourceSQLT("Set_user_rank")); + } + @Override + public synchronized void dropUserFromLadder(String user, String ladder) + { + String instance = ""; + String[] breaked = ladder.split(Settings.separatorRegExp); + if(breaked.length == 2) + { + ladder = breaked[0]; + instance = breaked[1]; + } + if("".equals(user) || "".equals(ladder)) + return; + setupQueryTemplate("{USER}", user); + setupQueryTemplate("{LADDER}", ladder); + setupQueryTemplate("{INSTANCE}", instance); + executeUpdate(loadResourceSQLT("Drop_user_from_ladder")); + } + @Override + public synchronized void addUserParentGroup(String user, String newGroup) + { + setupQueryTemplate("{USER}", user); + setupQueryTemplate("{PARENT}", newGroup); + executeUpdate("INSERT INTO `{DATABASE}`.`{PREFIX}inheritance` (`entity`, `parent`, `inheritance_type`) VALUES ('{USER}', '{PARENT}', b'1');"); + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/CommandHelper.java b/src/main/java/ru/simsonic/rscPermissions/CommandHelper.java new file mode 100644 index 0000000..d117b4a --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/CommandHelper.java @@ -0,0 +1,331 @@ +package ru.simsonic.rscPermissions; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.permissions.PermissionAttachment; +import ru.simsonic.rscPermissions.Importers.PermissionsEx_YAML; + +public class CommandHelper +{ + private final MainPluginClass plugin; + public final Rewards rewardHelper; + public final Ladders ladderHelper; + public CommandHelper(final MainPluginClass rscp) + { + this.plugin = rscp; + rewardHelper = new Rewards(rscp); + ladderHelper = new Ladders(rscp); + } + public void onCommand(CommandSender sender, Command cmd, String label, String[] args) throws CommandHelperAnswerException + { + switch(cmd.getName().toLowerCase()) + { + case "rscp": + onCommandHub(sender, args); + return; + case "promote": + if(args.length >= 1) + { + ladderHelper.executePromotion(sender, args[0], (args.length >= 2) ? args[1] : null, true); + return; + } + throw new CommandHelperAnswerException("/promote "); + case "demote": + if(args.length >= 1) + { + ladderHelper.executePromotion(sender, args[0], (args.length >= 2) ? args[1] : null, false); + return; + } + throw new CommandHelperAnswerException("/demote "); + case "reward": + if(sender instanceof Player) + { + String reward = (args.length >= 1) ? args[0] : null; + rewardHelper.executeReward((Player)sender, reward); + return; + } + throw new CommandHelperAnswerException("This command cannot be run from console."); + } + } + private void onCommandHub(CommandSender sender, String[] args) throws CommandHelperAnswerException + { + final ArrayList help = new ArrayList<>(); + if(sender.hasPermission("rscp.admin")) + { + help.add("/rscp (user|group|ladder) -- PermissionsEx-like admin commands"); + help.add("/rscp (promote|demote) -- admin promotion/demotion commands"); + } + if(sender.hasPermission("rscp.admin.lock")) + help.add("/rscp (lock|unlock) -- maintenance mode control"); + if(sender.hasPermission("rscp.admin")) + { + help.add("/rscp (examplerows|import) -- possible useful things"); + help.add("/rscp (debug|fetch|reload) -- admin stuff"); + } + help.add("/rscp (help) -- show these notes"); + if(help.size() > 0) + help.add(0, "{MAGENTA}Usage:"); + help.add(0, plugin.getDescription().getName() + " v" + plugin.getDescription().getVersion()); + help.add(1, "Perfect Superperms manager for multiserver environments"); + if(sender.hasPermission("rscp.admin")) + help.add(2, "{_DS}Current serverId is \'{_LS}" + plugin.getServer().getServerId() + "{_DS}\' (server.properties)"); + help.add("{_LG}" + plugin.getDescription().getWebsite()); + if(args.length == 0) + throw new CommandHelperAnswerException(help); + switch(args[0].toLowerCase()) + { + case "user": + onCommandHubUser(sender, args); + return; + case "group": + onCommandHubGroup(sender, args); + return; + case "ladder": + onCommandHubLadder(sender, args); + return; + case "promote": + /* rscp promote */ + if(args.length < 3) + throw new CommandHelperAnswerException("/rscp promote "); + ladderHelper.executePromotion(sender, args[1], args[2], true); + return; + case "demote": + /* rscp demote */ + if(args.length < 3) + throw new CommandHelperAnswerException("/rscp demote "); + ladderHelper.executePromotion(sender, args[1], args[2], false); + return; + case "lock": + /* rscp lock [mMode] */ + if(sender.hasPermission("rscp.lock")) + { + final String mMode = (args.length >= 2) ? args[1] : "default"; + String mmon = "Maintenance mode enabled"; + mmon = plugin.getConfig().getString("language.mModes.locked.default.mmon", mmon); + mmon = plugin.getConfig().getString("language.mModes.locked." + mMode + ".mmon", mmon); + plugin.maintenance.setMaintenanceMode(mMode); + throw new CommandHelperAnswerException(mmon); + } + return; + case "unlock": + /* rscp unlock */ + if(sender.hasPermission("rscp.lock")) + { + String mmoff = "Maintenance mode disabled"; + mmoff = plugin.getConfig().getString("language.mModes.unlocked", mmoff); + plugin.maintenance.setMaintenanceMode(null); + throw new CommandHelperAnswerException(mmoff); + } + break; + case "examplerows": + /* rscp examplerows */ + if(sender.hasPermission("rscp.admin")) + { + plugin.connectionList.threadInsertExampleRows(sender); + throw new CommandHelperAnswerException("Example rows have been added into database."); + } + return; + case "import": + /* rscp import pex */ + if(sender.hasPermission("rscp.admin")) + { + if(args.length > 1) + switch(args[1].toLowerCase()) + { + case "pex-yaml": + if(args.length == 2) + break; + // TO DO HERE + PermissionsEx_YAML importer_pex = new PermissionsEx_YAML(plugin, args[2]); + plugin.connectionList.threadFetchTablesData(); + throw new CommandHelperAnswerException(new String[] + { + "Data has been imported successfully!", + "Entities: {MAGENTA}" + Integer.toString(importer_pex.getEntities().length), + "Permissions: {MAGENTA}" + Integer.toString(importer_pex.getPermissions().length), + "Inheritance: {MAGENTA}" + Integer.toString(importer_pex.getInheritance().length), + "Ladders: {MAGENTA}" + Integer.toString(importer_pex.getLadders().length), + "{_DR}{_B}FAKE :p - all this is undone yet!", + }); + case "pex-sql": + plugin.connectionList.threadMigrateFromPExSQL(sender); + throw new CommandHelperAnswerException("Trying to import PEX database into rscPermissions..."); + } + throw new CommandHelperAnswerException(new String[] + { + "Usage: {GOLD}/rscp import [options]", + "Available importers:", + "{_LR}pex-yaml{_LS} (PermissionsEx)", + "{_LG}pex-sql{_LS} (PermissionsEx)", + }); + } + return; + case "fetch": + /* rscp fetch */ + if(sender.hasPermission("rscp.admin.reload")) + { + plugin.connectionList.threadFetchTablesData(); + throw new CommandHelperAnswerException("Tables have been fetched."); + } + return; + case "reload": + /* rscp reload */ + if(sender.hasPermission("rscp.admin.reload")) + { + plugin.getServer().getPluginManager().disablePlugin(plugin); + plugin.getServer().getPluginManager().enablePlugin(plugin); + throw new CommandHelperAnswerException("Plugin has been reloaded."); + } + return; + case "update": + /* rscp update */ + if(sender.hasPermission("rscp.admin")) + throw new CommandHelperAnswerException(plugin.doUpdate(sender)); + return; + case "debug": + /* rscp debug [yes|on|no|off|toggle] */ + if(sender.hasPermission("rscp.admin")) + throw new CommandHelperAnswerException("Not implemented yet."); + return; + case "help": + default: + throw new CommandHelperAnswerException(help); + } + } + private void onCommandHubUser(CommandSender sender, String[] args) throws CommandHelperAnswerException + { + if(sender.hasPermission("rscp.admin") == false) + throw new CommandHelperAnswerException("Not enough permissions."); + final String[] help = new String[] + { + "rscPermissions command hub (user section).", + "{MAGENTA}Usage:", + "/rscp user list permissions", + "/rscp user list groups", + // "/rscp user list ranks", + "/rscp user prefix [prefix]", + "/rscp user suffix [suffix]", + }; + if(args.length < 3) + throw new CommandHelperAnswerException(help); + final Player player = plugin.getServer().getPlayerExact(args[1]); + if(player == null) + throw new CommandHelperAnswerException("Player should be online"); + final ArrayList list = new ArrayList<>(); + switch(args[2].toLowerCase()) + { + case "list": + if(args.length < 4) + throw new CommandHelperAnswerException(help); + switch(args[3].toLowerCase()) + { + case "permissions": + list.add("{MAGENTA}Permission list for {_YL}" + player.getName()); + final PermissionAttachment pa = plugin.attachments.get(player); + if(pa == null) + break; + final Map pv = pa.getPermissions(); + if(pv == null) + break; + final ArrayList sorted_keys = new ArrayList<>(pv.keySet()); + Collections.sort(sorted_keys); + for(String perm : sorted_keys) + if(pv.containsKey(perm)) + list.add((pv.get(perm) ? "{_LG}" : "{_LR}") + perm); + throw new CommandHelperAnswerException(list); + case "groups": + list.add("{MAGENTA}Group list for {_YL}" + player.getName() + "{MAGENTA}:"); + ArrayList groups = plugin.cache.getUserGroups(player.getName()); + for(String group : groups) + list.add("{_LG}" + group); + throw new CommandHelperAnswerException(list); + /* + case "ranks": + list.add("{MAGENTA}Ranks of player {_YL}" + player.getName() + "{MAGENTA}:"); + throw new CommandHelperAnswerException(list); + */ + } + throw new CommandHelperAnswerException(list); + case "prefix": + if(args.length > 3) + { + plugin.API.setPlayerPrefix(null, player.getName(), args[3]); + list.add("{MAGENTA}Prefix for user {_YL}" + player.getName() + + " {MAGENTA}has been set to \"{_R}" + plugin.cache.userGetPrefix(player.getName()) + "{MAGENTA}\"."); + } else + list.add("{MAGENTA}Prefix for user {_YL}" + player.getName() + + " {MAGENTA}is \"{_R}" + plugin.cache.userGetPrefix(player.getName()) + "{MAGENTA}\"."); + throw new CommandHelperAnswerException(list); + case "suffix": + if(args.length > 3) + { + plugin.API.setPlayerSuffix(null, player.getName(), args[3]); + list.add("{MAGENTA}Suffix for user {_YL}" + player.getName() + + " {MAGENTA}has been set to \"{_R}" + plugin.cache.userGetSuffix(player.getName()) + "{MAGENTA}\"."); + } else + list.add("{MAGENTA}Suffix for user {_YL}" + player.getName() + + " {MAGENTA}is \"{_R}" + plugin.cache.userGetSuffix(player.getName()) + "{MAGENTA}\"."); + throw new CommandHelperAnswerException(list); + } + } + private void onCommandHubGroup(CommandSender sender, String[] args) throws CommandHelperAnswerException + { + if(sender.hasPermission("rscp.admin") == false) + throw new CommandHelperAnswerException("Not enough permissions."); + final String[] help = new String[] + { + "rscPermissions command hub (group section).", + "{MAGENTA}Usage:", + // "/rscp group list permissions", + // "/rscp group list ranks", + "/rscp group prefix [prefix]", + "/rscp group suffix [suffix]", + }; + if(args.length < 3) + throw new CommandHelperAnswerException(help); + final String group = args[1]; + final ArrayList list = new ArrayList<>(); + switch(args[2].toLowerCase()) + { + case "prefix": + if(args.length > 3) + { + plugin.API.setGroupPrefix(null, group, args[3]); + list.add("{MAGENTA}Prefix for group {_YL}" + group + + " {MAGENTA}has been set to \"{_R}" + plugin.cache.groupGetPrefix(group) + "{MAGENTA}\"."); + } else + list.add("{MAGENTA}Prefix for group {_YL}" + group + + " {MAGENTA}is \"{_R}" + plugin.cache.groupGetPrefix(group) + "{MAGENTA}\"."); + throw new CommandHelperAnswerException(list); + case "suffix": + if(args.length > 3) + { + plugin.API.setGroupSuffix(null, group, args[3]); + list.add("{MAGENTA}Suffix for group {_YL}" + group + + " {MAGENTA}has been set to \"{_R}" + plugin.cache.groupGetSuffix(group) + "{MAGENTA}\"."); + } else + list.add("{MAGENTA}Suffix for group {_YL}" + group + + " {MAGENTA}is \"{_R}" + plugin.cache.groupGetSuffix(group) + "{MAGENTA}\"."); + throw new CommandHelperAnswerException(list); + } + } + private void onCommandHubLadder(CommandSender sender, String[] args) throws CommandHelperAnswerException + { + if(sender.hasPermission("rscp.admin") == false) + throw new CommandHelperAnswerException("Not enough permissions."); + final String[] help = new String[] + { + "rscPermissions command hub (ladder section).", + "{MAGENTA}Usage:", + // "/rscp ladder list groups", + // "/rscp ladder list users", + }; + if(args.length < 3) + throw new CommandHelperAnswerException(help); + final String ladder = args[1]; + throw new CommandHelperAnswerException("dummy :p)"); + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/CommandHelperAnswerException.java b/src/main/java/ru/simsonic/rscPermissions/CommandHelperAnswerException.java new file mode 100644 index 0000000..4ec68bf --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/CommandHelperAnswerException.java @@ -0,0 +1,23 @@ +package ru.simsonic.rscPermissions; +import java.util.List; + +public class CommandHelperAnswerException extends Exception +{ + private final String[] message; + public CommandHelperAnswerException(String message) + { + this.message = new String[]{message}; + } + public CommandHelperAnswerException(String[] messages) + { + this.message = messages; + } + public CommandHelperAnswerException(List messages) + { + this.message = messages.toArray(new String[messages.size()]); + } + public String[] getMessageArray() + { + return message; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/ConnectionHelper.java b/src/main/java/ru/simsonic/rscPermissions/ConnectionHelper.java new file mode 100644 index 0000000..8480796 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/ConnectionHelper.java @@ -0,0 +1,130 @@ +package ru.simsonic.rscPermissions; +import ru.simsonic.utilities.ConnectionMySQL; +import java.util.logging.Level; +import org.bukkit.command.CommandSender; +import org.bukkit.scheduler.BukkitRunnable; +import ru.simsonic.rscPermissions.Backends.BackendMySQL; + +public class ConnectionHelper extends BackendMySQL +{ + private ConnectionHelper nextInChain = null; + public ConnectionHelper(MainPluginClass rscp, ConnectionHelper nextInChain) + { + super(rscp); + this.nextInChain = nextInChain; + } + protected synchronized BackendMySQL findConnectedNode() + { + for(ConnectionHelper result = this; result != null; result = result.nextInChain) + if(result.isConnected()) + return (BackendMySQL)result; + return null; + } + @Override + public void Disconnect() + { + if(nextInChain != null) + { + nextInChain.Disconnect(); + nextInChain = null; + } + super.Disconnect(); + } + public Thread threadFetchTablesData() + { + final Thread result = new Thread() + { + @Override + public void run() + { + // Fetch tables + final ConnectionMySQL connection = findConnectedNode(); + if(connection == null) + return; + fetchIntoCache(plugin.cache); + if(plugin.settings.isRewardsEnabled()) + fetchRewards(plugin.commandExecutor.rewardHelper); + // Update permissions for online players + try + { + Runnable syncTask = new Runnable() + { + @Override + public synchronized void run() + { + plugin.recalculateOnlinePlayers(); + notify(); + } + }; + synchronized(syncTask) + { + plugin.getServer().getScheduler().runTask(plugin, syncTask); + syncTask.wait(); + } + } catch(InterruptedException ex) { + MainPluginClass.consoleLog.log(Level.SEVERE, "[rscp] Exception in FetchTables(): {0}", ex.getLocalizedMessage()); + } + plugin.cache.calculateStartupPermissions(); + } + }; + result.start(); + return result; + } + public Thread threadInsertExampleRows(final CommandSender sender) + { + final Thread result = new Thread() + { + @Override + public void run() + { + setName("InsertExampleRows"); + final BackendMySQL backend = findConnectedNode(); + if(backend == null || !backend.canWrite()) + return; + backend.insertExampleRows(); + plugin.getServer().getScheduler().runTask(plugin, new Runnable() + { + @Override + public void run() + { + sender.sendMessage("Database tables were filled with example rows."); + } + }); + } + }; + result.start(); + return result; + } + public Thread threadMigrateFromPExSQL(final CommandSender sender) + { + final Thread result = new Thread() + { + @Override + public void run() + { + try + { + setName("MigrateFromPExSQL"); + final BackendMySQL backend = findConnectedNode(); + if(backend == null || !backend.canWrite()) + return; + backend.executeUpdate(loadResourceSQLT("Migrate_from_PermissionsEx")); + threadFetchTablesData().join(); + plugin.getServer().getScheduler().runTask(plugin, new BukkitRunnable() + { + @Override + public void run() + { + plugin.Message(sender, "Migration from PermissionsEx (MySQL backend) done!"); + plugin.Message(sender, "Check the latest database row for new data."); + } + }); + } catch(InterruptedException ex) { + MainPluginClass.consoleLog.log(Level.SEVERE, "[rscp] Exception in MigrateFromPExSQL(): {0}", ex.getLocalizedMessage()); + } + } + }; + result.start(); + return result; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/AbstractRow.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/AbstractRow.java new file mode 100644 index 0000000..13e5a93 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/AbstractRow.java @@ -0,0 +1,20 @@ +package ru.simsonic.rscPermissions.DataTypes; +import java.util.regex.Pattern; + +public abstract class AbstractRow +{ + public int id = 0; + public static enum Table + { + entities, permissions, inheritance, ladders, unknown; + } + public abstract Table getTable(); + private static final Pattern patternUUID = Pattern.compile( + "" + "(?:[a-f\\d]{8}(?:-[a-f\\d]{4}){3}-[a-f\\d]{12})" + ""); + private static boolean isCorrectUUID(String entityName) + { + if(entityName == null) + return false; + return patternUUID.matcher("" + entityName.toLowerCase() + "").find(); + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/Destination.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/Destination.java new file mode 100644 index 0000000..f65526e --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/Destination.java @@ -0,0 +1,106 @@ +package ru.simsonic.rscPermissions.DataTypes; +import java.util.ArrayList; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.bukkit.Location; +import org.bukkit.World; +import ru.simsonic.rscPermissions.Settings; +import ru.simsonic.utilities.LanguageUtility; + +public class Destination +{ + private final String region; + private final String world; + private final String serverId; + private Destination() + { + this.region = null; + this.world = null; + this.serverId = null; + } + private Destination(String region, String world, String serverId) + { + this.region = region; + this.world = world; + this.serverId = serverId; + } + public boolean IsServerIdApplicable(String serverId) + { + return wildcardTesting(serverId, this.serverId); + } + public boolean IsLocationApplicable(Location location, Set regions, String instantiator) + { + if(location != null) + { + if(location.getWorld() != null) + if(IsWorldApplicable(location.getWorld(), instantiator)) + return IsRegionApplicable(regions, instantiator); + } else { + if(this.world == null) + return IsRegionApplicable(regions, instantiator); + } + return false; + } + private boolean IsWorldApplicable(World world, String instantiator) + { + if(this.world == null || "".equals(this.world) || "*".equals(this.world)) + return true; + final String instantiated = (instantiator != null && !"".equals(instantiator)) ? + this.world.replaceAll(Settings.instantiatorRegExp, instantiator) : + this.world; + return wildcardTesting(world.getName(), instantiated); + } + private boolean IsRegionApplicable(Set regions, String instantiator) + { + if(this.region == null || "".equals(this.region) || "*".equals(this.region)) + return true; + final String instantiated = (instantiator != null && !"".equals(instantiator)) ? + this.region.replaceAll(Settings.instantiatorRegExp, instantiator) : + this.region; + for(String regionId : regions) + if(wildcardTesting(regionId, instantiated)) + return true; + return false; + } + private static boolean wildcardTesting(String testing, String pattern) + { + if(pattern == null || "".equals(pattern)) + return true; + if(testing == null || "".equals(testing)) + return false; + return LanguageUtility.wildcardMatch( + "" + testing.toLowerCase() + "", + "" + pattern.toLowerCase() + ""); + } + public static Destination[] ParseDestinations(String destinations) + { + if(destinations == null) + return new Destination[] { new Destination() }; + if(destinations.isEmpty()) + return new Destination[] { new Destination() }; + final String[] destinationsList = destinations.split("\\s*(?:;|,|\\r|\\n)+\\s*"); + final ArrayList result = new ArrayList(destinationsList.length); + for(int nDestination = 0; nDestination < destinationsList.length; nDestination += 1) + if(destinationsList[nDestination].isEmpty() == false) + result.add(ParseDestination(destinationsList[nDestination])); + return result.toArray(new Destination[result.size()]); + } + private static final Pattern patternDestination = Pattern.compile( + "" + "(?:((?:\\w|\\*|\\?)*):)?((?:\\w|\\*|\\?)*)?(?:@((?:\\w|\\*|\\?)*))?" + ""); + private static Destination ParseDestination(String destination) + { + Matcher match = patternDestination.matcher("" + destination + ""); + if(match.find()) + { + final String group1 = match.group(1); + final String group2 = match.group(2); + final String group3 = match.group(3); + final String region = (group1 == null || "".equals(group1)) ? "*" : group1; + final String world = (group2 == null || "".equals(group2)) ? "*" : group2; + final String serverId = (group3 == null || "".equals(group3)) ? "*" : group3; + return new Destination(region, world, serverId); + } + return new Destination(); + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowEntity.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowEntity.java new file mode 100644 index 0000000..3f1c1b4 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowEntity.java @@ -0,0 +1,33 @@ +package ru.simsonic.rscPermissions.DataTypes; + +public class RowEntity extends AbstractRow +{ + public enum EntityType + { + groupName(0), + playerName(1), + playerUniqueId(2), + unknown(-1); + public static EntityType byValue(int value) + { + for(EntityType constant : EntityType.values()) + if(constant.value == value) + return constant; + return unknown; + } + private final int value; + private EntityType(int value) + { + this.value = value; + } + } + public String entity; + public EntityType entity_type; + public String prefix; + public String suffix; + @Override + public Table getTable() + { + return Table.entities; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowInheritance.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowInheritance.java new file mode 100644 index 0000000..fab1f37 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowInheritance.java @@ -0,0 +1,25 @@ +package ru.simsonic.rscPermissions.DataTypes; +import java.sql.Timestamp; +import ru.simsonic.rscPermissions.DataTypes.RowEntity.EntityType; + +public class RowInheritance extends AbstractRow implements Comparable +{ + public String entity; + public String parent; + public String instance; + public EntityType child_type; + public int priority; + public Destination destination; + public int expirience; + public Timestamp lifetime; + @Override + public int compareTo(RowInheritance t) + { + return (priority != t.priority) ? priority - t.priority : parent.compareTo(t.parent); + } + @Override + public Table getTable() + { + return Table.inheritance; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowLadder.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowLadder.java new file mode 100644 index 0000000..f496673 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowLadder.java @@ -0,0 +1,45 @@ +package ru.simsonic.rscPermissions.DataTypes; +import ru.simsonic.rscPermissions.DataTypes.RowEntity.EntityType; + +public class RowLadder extends AbstractRow implements Comparable +{ + public String climber; + public EntityType climber_type; + public String ladder; + public String instance; + public int rank; + @Override + public int compareTo(RowLadder t) + { + return rank - t.rank; + } + public RowLadder nextNode; + public RowLadder prevNode; + public int getLadderTopRank() + { + int result = rank; + for(RowLadder row = nextNode; row != null; row = nextNode) + result = row.rank; + return result; + } + public int getLadderBottomRank() + { + int result = rank; + for(RowLadder row = prevNode; row != null; row = prevNode) + result = row.rank; + return result; + } + public RowLadder getActualNode(int userRank) + { + RowLadder result = this; + for(; result.nextNode != null; result = result.nextNode) + if(result.nextNode.rank > userRank) + break; + return result; + } + @Override + public Table getTable() + { + return Table.ladders; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowPermission.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowPermission.java new file mode 100644 index 0000000..95412a8 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowPermission.java @@ -0,0 +1,19 @@ +package ru.simsonic.rscPermissions.DataTypes; +import java.sql.Timestamp; +import ru.simsonic.rscPermissions.DataTypes.RowEntity.EntityType; + +public class RowPermission extends AbstractRow +{ + public String entity; + public EntityType entity_type; + public String permission; + public boolean value; + public Destination destination; + public int expirience; + public Timestamp lifetime; + @Override + public Table getTable() + { + return Table.permissions; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowReward.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowReward.java new file mode 100644 index 0000000..d306885 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowReward.java @@ -0,0 +1,17 @@ +package ru.simsonic.rscPermissions.DataTypes; +import java.sql.Timestamp; + +public class RowReward +{ + public int id; + public String user; + public String code; + public boolean activated; + public Timestamp activated_timestamp; + public String execute_commands; + public String command_permissions; + public String add_group; + public String add_group_destination; + public int add_group_expirience; + public String add_group_interval; +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowServer.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowServer.java new file mode 100644 index 0000000..20860dc --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/RowServer.java @@ -0,0 +1,6 @@ +package ru.simsonic.rscPermissions.DataTypes; + +public class RowServer +{ + public String serverId; +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/Importers/BaseImporter.java b/src/main/java/ru/simsonic/rscPermissions/Importers/BaseImporter.java new file mode 100644 index 0000000..0eb4b0e --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/Importers/BaseImporter.java @@ -0,0 +1,27 @@ +package ru.simsonic.rscPermissions.Importers; +import java.util.ArrayList; +import ru.simsonic.rscPermissions.DataTypes.*; + +public abstract class BaseImporter +{ + protected ArrayList imported_e = new ArrayList<>(); + protected ArrayList imported_p = new ArrayList<>(); + protected ArrayList imported_i = new ArrayList<>(); + protected ArrayList imported_l = new ArrayList<>(); + public RowEntity[] getEntities() + { + return imported_e.toArray(new RowEntity[imported_e.size()]); + } + public RowPermission[] getPermissions() + { + return imported_p.toArray(new RowPermission[imported_p.size()]); + } + public RowInheritance[] getInheritance() + { + return imported_i.toArray(new RowInheritance[imported_i.size()]); + } + public RowLadder[] getLadders() + { + return imported_l.toArray(new RowLadder[imported_l.size()]); + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/Importers/PermissionsEx_YAML.java b/src/main/java/ru/simsonic/rscPermissions/Importers/PermissionsEx_YAML.java new file mode 100644 index 0000000..a4940c5 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/Importers/PermissionsEx_YAML.java @@ -0,0 +1,23 @@ +package ru.simsonic.rscPermissions.Importers; +import java.io.File; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.Plugin; + +public final class PermissionsEx_YAML extends BaseImporter +{ + public PermissionsEx_YAML(Plugin plugin, String fileName) + { + if(fileName == null || "".equals(fileName)) + fileName = "permissions.yml"; + try + { + final FileConfiguration config = YamlConfiguration.loadConfiguration(new File(plugin.getDataFolder(), fileName)); + final ConfigurationSection csGroups = config.getConfigurationSection("groups"); + final ConfigurationSection csUsers = config.getConfigurationSection("users"); + final ConfigurationSection csWorlds = config.getConfigurationSection("worlds"); + } catch(NullPointerException ex) { + } + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/Ladders.java b/src/main/java/ru/simsonic/rscPermissions/Ladders.java new file mode 100644 index 0000000..9386580 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/Ladders.java @@ -0,0 +1,120 @@ +package ru.simsonic.rscPermissions; +import java.util.ArrayList; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import ru.simsonic.rscPermissions.Backends.BackendMySQL; +import ru.simsonic.rscPermissions.DataTypes.RowLadder; + +public class Ladders +{ + private final MainPluginClass plugin; + public Ladders(MainPluginClass rscp) + { + this.plugin = rscp; + } + public String[] executePromotion(CommandSender sender, String user, String ladder, boolean bPromote) + { + if(plugin.connectionList == null) + return null; + final BackendMySQL connection = plugin.connectionList.findConnectedNode(); + if(connection == null || !connection.canWrite()) + return null; + if("".equals(user) || (user == null)) + return new String[] { (bPromote ? "/promote" : "/demote") + " " }; + if("".equals(ladder) || (ladder == null)) + return new String[] { "You should specify ladder to promote on." }; + final Player player = plugin.getServer().getPlayerExact(user); + if(player == null) + return new String[] { "Player must be online." }; + String template = ladder; + String instance = ""; + String[] breaked = ladder.split(Settings.separatorRegExp); + if(breaked.length == 2) + { + template = breaked[0].toLowerCase(); + instance = breaked[1]; + } + final String perm_onself = bPromote ? "rscp.promote-self." : "rscp.demote-self."; + final String perm_sender = bPromote ? "rscp.promote." : "rscp.demote."; + final String perm_target = bPromote ? "rscp.promotable." : "rscp.demotable."; + boolean bOS = sender.hasPermission(perm_onself + "*"); + boolean bSP = sender.hasPermission(perm_sender + "*"); + boolean bUP = player.hasPermission(perm_target + "*"); + if(!"".equals(instance)) + { + bOS = bOS || sender.hasPermission(perm_onself + template + ".*"); + bOS = bOS || sender.hasPermission(perm_onself + template + "." + instance.toLowerCase()); + bSP = bSP || sender.hasPermission(perm_sender + template + ".*"); + bSP = bSP || sender.hasPermission(perm_sender + template + "." + instance.toLowerCase()); + bUP = bUP || player.hasPermission(perm_target + template + ".*"); + bUP = bUP || player.hasPermission(perm_target + template + "." + instance.toLowerCase()); + } else { + bOS = bOS || sender.hasPermission(perm_onself + template); + bSP = bSP || sender.hasPermission(perm_sender + template); + bUP = bUP || player.hasPermission(perm_target + template); + } + if(sender instanceof Player) + if(player != (Player)sender) + bOS = false; + boolean bPromotionAllowed = bOS || (bSP && bUP) || sender.hasPermission("rscp.admin.promote"); + if(bPromotionAllowed == false) + { + if(bSP == false) + return new String[] { "You are not allowed to promote/demote on this ladder." }; + if(bUP == false) + return new String[] { "Player is not promotable on this ladder." }; + } + int rank = plugin.cache.getUserRank(user, template, instance); + final ArrayList ladderArray = plugin.cache.buildLadderTemplate(template); + if(ladderArray.isEmpty()) + return new String[] { "There is no such ladder." }; + RowLadder position = ladderArray.get(0).getActualNode(rank); + if(bPromote) + { + if(position.nextNode != null) + position = position.nextNode; + } else + if(position.prevNode != null) + position = position.prevNode; + if(position.instance != null) + if(Settings.instantiator.equals(position.instance)) + { + if("".equals(instance)) + return new String[] { "Operation requires ladder instance (