diff --git a/pom.xml b/pom.xml index 920cf68..3785dba 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ ru.simsonic rscUtilityLibrary - 2.0.1 + 2.0.2 compile jar diff --git a/src/main/java/ru/simsonic/rscPermissions/API/Settings.java b/src/main/java/ru/simsonic/rscPermissions/API/Settings.java index e1b9914..a8a0b04 100644 --- a/src/main/java/ru/simsonic/rscPermissions/API/Settings.java +++ b/src/main/java/ru/simsonic/rscPermissions/API/Settings.java @@ -1,5 +1,5 @@ package ru.simsonic.rscPermissions.API; -import ru.simsonic.rscPermissions.ConnectionHelper; +import ru.simsonic.rscUtilityLibrary.ConnectionMySQL.ConnectionParams; public interface Settings { @@ -19,5 +19,5 @@ public interface Settings public long getRegionFinderGranularity(); public int getAutoReloadDelayTicks(); public boolean isUseMetrics(); - public ConnectionHelper getConnectionChain(); + public ConnectionParams getConnectionParams(); } diff --git a/src/main/java/ru/simsonic/rscPermissions/ActionThreads.java b/src/main/java/ru/simsonic/rscPermissions/ActionThreads.java new file mode 100644 index 0000000..0b5f333 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/ActionThreads.java @@ -0,0 +1,15 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package ru.simsonic.rscPermissions; + +/** + * + * @author simsonic + */ +public class ActionThreads +{ + +} diff --git a/src/main/java/ru/simsonic/rscPermissions/Backends/Backend.java b/src/main/java/ru/simsonic/rscPermissions/Backends/Backend.java deleted file mode 100644 index 064f682..0000000 --- a/src/main/java/ru/simsonic/rscPermissions/Backends/Backend.java +++ /dev/null @@ -1,17 +0,0 @@ -package ru.simsonic.rscPermissions.Backends; -import ru.simsonic.rscPermissions.DataTypes.RowEntity; -import ru.simsonic.rscPermissions.DataTypes.RowInheritance; -import ru.simsonic.rscPermissions.DataTypes.RowPermission; -import ru.simsonic.rscPermissions.InternalCache.AbstractPermissionsCache; - -public interface Backend -{ - public abstract void fetchIntoCache(AbstractPermissionsCache cache); - public abstract RowEntity[] fetchEntities(); - public abstract RowPermission[] fetchPermissions(); - public abstract RowInheritance[] fetchInheritance(); - - public abstract void insertExampleRows(); - public abstract void updateEntityText(String entity, boolean entity_type, String text, boolean isPrefix); - public abstract void addUserParentGroup(String user, String newGroup); -} diff --git a/src/main/java/ru/simsonic/rscPermissions/Backends/BackendMySQL.java b/src/main/java/ru/simsonic/rscPermissions/Backends/BackendDatabase.java similarity index 84% rename from src/main/java/ru/simsonic/rscPermissions/Backends/BackendMySQL.java rename to src/main/java/ru/simsonic/rscPermissions/Backends/BackendDatabase.java index 80b61f4..d132001 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Backends/BackendMySQL.java +++ b/src/main/java/ru/simsonic/rscPermissions/Backends/BackendDatabase.java @@ -8,42 +8,42 @@ import ru.simsonic.rscPermissions.DataTypes.EntityType; import ru.simsonic.rscPermissions.DataTypes.RowEntity; import ru.simsonic.rscPermissions.DataTypes.RowInheritance; import ru.simsonic.rscPermissions.DataTypes.RowPermission; -import ru.simsonic.rscPermissions.InternalCache.AbstractPermissionsCache; import ru.simsonic.rscPermissions.BukkitPluginMain; +import ru.simsonic.rscPermissions.DataTypes.DatabaseContents; import ru.simsonic.rscUtilityLibrary.ConnectionMySQL; -public class BackendMySQL extends ConnectionMySQL implements Backend +public class BackendDatabase extends ConnectionMySQL { protected final BukkitPluginMain rscp; - public BackendMySQL(BukkitPluginMain plugin) + public BackendDatabase(BukkitPluginMain plugin) { + super(BukkitPluginMain.consoleLog); this.rscp = plugin; } - public synchronized void Initialize(String database, String username, String password, String prefixes) - { - super.Initialize("rscp:MySQL", database, username, password, prefixes); - } @Override - public synchronized boolean Connect() + public synchronized boolean connect() { - return super.Connect() + return super.connect() && executeUpdateT("Initialize_main_v1") && executeUpdateT("Cleanup_tables"); } - @Override - public synchronized void fetchIntoCache(AbstractPermissionsCache cache) + public synchronized DatabaseContents retrieveContents() { executeUpdateT("Cleanup_tables"); + final DatabaseContents contents = new DatabaseContents(); + contents.entities = fetchEntities(); + contents.permissions = fetchPermissions(); + contents.inheritance = fetchInheritance(); BukkitPluginMain.consoleLog.log(Level.INFO, "[rscp] Fetched {0} entities, {1} permissions and {2} inheritances", new Integer[] { - cache.ImportEntities(fetchEntities()), - cache.ImportPermissions(fetchPermissions()), - cache.ImportInheritance(fetchInheritance()) + contents.entities.length, + contents.permissions.length, + contents.inheritance.length, }); + return contents; } - @Override public synchronized RowEntity[] fetchEntities() { final ArrayList result = new ArrayList<>(); @@ -67,7 +67,6 @@ public class BackendMySQL extends ConnectionMySQL implements Backend } return result.toArray(new RowEntity[result.size()]); } - @Override public synchronized RowPermission[] fetchPermissions() { final ArrayList result = new ArrayList<>(); @@ -99,7 +98,6 @@ public class BackendMySQL extends ConnectionMySQL implements Backend } return result.toArray(new RowPermission[result.size()]); } - @Override public synchronized RowInheritance[] fetchInheritance() { final ArrayList result = new ArrayList<>(); @@ -132,12 +130,10 @@ public class BackendMySQL extends ConnectionMySQL implements Backend } return result.toArray(new RowInheritance[result.size()]); } - @Override public synchronized void insertExampleRows() { executeUpdateT("Insert_example_rows_v1"); } - @Override public synchronized void updateEntityText(String entity, boolean entity_type, String text, boolean isPrefix) { if("".equals(entity)) @@ -150,7 +146,6 @@ public class BackendMySQL extends ConnectionMySQL implements Backend setupQueryTemplate("{TEXT}", (text != null) ? "'" + text + "'" : "NULL"); executeUpdateT("Update_entity_text"); } - @Override public synchronized void addUserParentGroup(String user, String newGroup) { setupQueryTemplate("{USER}", user); diff --git a/src/main/java/ru/simsonic/rscPermissions/Backends/BackendJson.java b/src/main/java/ru/simsonic/rscPermissions/Backends/BackendJson.java index 28c9701..4baf9ea 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Backends/BackendJson.java +++ b/src/main/java/ru/simsonic/rscPermissions/Backends/BackendJson.java @@ -6,46 +6,60 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.nio.charset.Charset; +import ru.simsonic.rscPermissions.DataTypes.DatabaseContents; import ru.simsonic.rscPermissions.DataTypes.RowEntity; import ru.simsonic.rscPermissions.DataTypes.RowInheritance; import ru.simsonic.rscPermissions.DataTypes.RowPermission; public class BackendJson { + private final File workingDir; + public BackendJson(File workingDir) + { + this.workingDir = workingDir; + } + public synchronized DatabaseContents retrieveContents() + { + final DatabaseContents result = new DatabaseContents(); + result.entities = fetchEntities(); + result.permissions = fetchPermissions(); + result.inheritance = fetchInheritance(); + return result; + } private final static String localEntitiesFile = "entities.json"; private final static String localPermissionsFile = "permissions.json"; private final static String localInheritanceFile = "inheritance.json"; - public RowEntity[] fetchEntities() + private RowEntity[] fetchEntities() { final Gson gson = new Gson(); try { JsonReader jr = new JsonReader(new InputStreamReader(new FileInputStream( - new File(localEntitiesFile)), Charset.forName("UTF-8"))); + new File(workingDir, localEntitiesFile)), Charset.forName("UTF-8"))); return gson.fromJson(jr, RowEntity[].class); } catch(FileNotFoundException ex) { } return null; } - public RowPermission[] fetchPermissions() + private RowPermission[] fetchPermissions() { final Gson gson = new Gson(); try { JsonReader jr = new JsonReader(new InputStreamReader(new FileInputStream( - new File(localEntitiesFile)), Charset.forName("UTF-8"))); + new File(workingDir, localEntitiesFile)), Charset.forName("UTF-8"))); return gson.fromJson(jr, RowPermission[].class); } catch(FileNotFoundException ex) { } return null; } - public RowInheritance[] fetchInheritance() + private RowInheritance[] fetchInheritance() { final Gson gson = new Gson(); try { JsonReader jr = new JsonReader(new InputStreamReader(new FileInputStream( - new File(localEntitiesFile)), Charset.forName("UTF-8"))); + new File(workingDir, localEntitiesFile)), Charset.forName("UTF-8"))); return gson.fromJson(jr, RowInheritance[].class); } catch(FileNotFoundException ex) { } diff --git a/src/main/java/ru/simsonic/rscPermissions/BridgeForBukkitAPI.java b/src/main/java/ru/simsonic/rscPermissions/BridgeForBukkitAPI.java index 09e78ee..510af52 100644 --- a/src/main/java/ru/simsonic/rscPermissions/BridgeForBukkitAPI.java +++ b/src/main/java/ru/simsonic/rscPermissions/BridgeForBukkitAPI.java @@ -4,10 +4,14 @@ import ru.simsonic.rscPermissions.Bukkit.VaultPermission; public class BridgeForBukkitAPI { - private final BukkitPluginMain rscp; - private final VaultPermission vaultPermission; - private final VaultChat vaultChat; private static BridgeForBukkitAPI instance; + public static BridgeForBukkitAPI getInstance() + { + return instance; + } + private final BukkitPluginMain rscp; + private final VaultPermission vaultPermission; + private final VaultChat vaultChat; protected BridgeForBukkitAPI(BukkitPluginMain plugin) { BridgeForBukkitAPI.instance = BridgeForBukkitAPI.this; @@ -15,10 +19,6 @@ public class BridgeForBukkitAPI this.vaultPermission = new VaultPermission(this); this.vaultChat = new VaultChat(this, vaultPermission); } - public static BridgeForBukkitAPI getInstance() - { - return instance; - } public org.bukkit.plugin.java.JavaPlugin getPlugin() { return this.rscp; diff --git a/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPermissions.java b/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPermissionManager.java similarity index 84% rename from src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPermissions.java rename to src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPermissionManager.java index ed249fc..f431b0e 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPermissions.java +++ b/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPermissionManager.java @@ -11,10 +11,10 @@ import ru.simsonic.rscPermissions.InternalCache.ResolutionParams; import ru.simsonic.rscPermissions.InternalCache.ResolutionResult; import ru.simsonic.rscUtilityLibrary.RestartableThread; -public class BukkitPermissions extends RestartableThread +public class BukkitPermissionManager extends RestartableThread { private final BukkitPluginMain rscp; - public BukkitPermissions(BukkitPluginMain plugin) + public BukkitPermissionManager(BukkitPluginMain plugin) { this.rscp = plugin; } @@ -23,8 +23,29 @@ public class BukkitPermissions extends RestartableThread private final HashMap suffixes = new HashMap<>(); private final HashMap persistentPermissions = new HashMap<>(); private final HashMap transientPermissions = new HashMap<>(); - public final HashMap attachments = new HashMap<>(); - public void recalculateOnlinePlayers() + public final HashMap attachments = new HashMap<>(); + public void recalculateOnlinePlayersSync() + { + try + { + Runnable syncTask = new Runnable() + { + @Override + public synchronized void run() + { + rscp.permissionManager.recalculateOnlinePlayersAsync(); + notify(); + } + }; + synchronized(syncTask) + { + rscp.getServer().getScheduler().runTask(rscp, syncTask); + syncTask.wait(); + } + } catch(InterruptedException ex) { + } + } + public void recalculateOnlinePlayersAsync() { updateQueue.addAll(rscp.getServer().getOnlinePlayers()); rscp.scheduleAutoUpdate(); diff --git a/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPluginConfiguration.java b/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPluginConfiguration.java index 83056d6..aa400a7 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPluginConfiguration.java +++ b/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitPluginConfiguration.java @@ -1,14 +1,8 @@ package ru.simsonic.rscPermissions.Bukkit; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; import org.bukkit.configuration.file.FileConfiguration; -import ru.simsonic.rscPermissions.ConnectionHelper; import ru.simsonic.rscPermissions.BukkitPluginMain; import ru.simsonic.rscPermissions.API.Settings; +import ru.simsonic.rscUtilityLibrary.ConnectionMySQL.ConnectionParams; public class BukkitPluginConfiguration implements Settings { @@ -131,39 +125,15 @@ public class BukkitPluginConfiguration implements Settings return nRegionFinderGranularity; } @Override - public ConnectionHelper getConnectionChain() + public ConnectionParams getConnectionParams() { - List> configServers = plugin.getConfig().getMapList("servers"); - List> serverlist = new ArrayList<>(); - for(Iterator> it = configServers.iterator(); it.hasNext();) - { - Map server = (Map)it.next(); - HashMap nodeinfo = new HashMap<>(); - String nodename = (String)server.get("nodename"); - String database = (String)server.get("database"); - String username = (String)server.get("username"); - String password = (String)server.get("password"); - String prefixes = (String)server.get("prefixes"); - String workmode = (String)server.get("workmode"); - if(nodename != null && ! "".equals(nodename)) - { - nodeinfo.put("nodename", nodename); - nodeinfo.put("database", (database != null) ? database : "localhost:3306/minecraft"); - nodeinfo.put("username", (username != null) ? username : "user"); - nodeinfo.put("password", (password != null) ? password : "pass"); - nodeinfo.put("prefixes", (prefixes != null) ? prefixes : "rscp_"); - nodeinfo.put("workmode", (workmode != null) ? workmode : "none"); - serverlist.add(nodeinfo); - } - } - Collections.reverse(serverlist); - ConnectionHelper connPrev = null; - for(HashMap server : serverlist) - { - ConnectionHelper conn = new ConnectionHelper(plugin, connPrev); - conn.Initialize(server.get("database"), server.get("username"), server.get("password"), server.get("prefixes")); - connPrev = conn; - } - return connPrev; + final FileConfiguration config = plugin.getConfig(); + final ConnectionParams result = new ConnectionParams(); + result.nodename = "rscp"; + result.database = config.getString("settings.connection.database", "localhost:3306/minecraft"); + result.username = config.getString("settings.connection.username", "user1"); + result.password = config.getString("settings.connection.password", "pass1"); + result.prefixes = config.getString("settings.connection.prefixes", "rscp_"); + return result; } } diff --git a/src/main/java/ru/simsonic/rscPermissions/RegionListProviders.java b/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitRegionProviders.java similarity index 92% rename from src/main/java/ru/simsonic/rscPermissions/RegionListProviders.java rename to src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitRegionProviders.java index e42044f..848302d 100644 --- a/src/main/java/ru/simsonic/rscPermissions/RegionListProviders.java +++ b/src/main/java/ru/simsonic/rscPermissions/Bukkit/BukkitRegionProviders.java @@ -1,4 +1,4 @@ -package ru.simsonic.rscPermissions; +package ru.simsonic.rscPermissions.Bukkit; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.managers.RegionManager; @@ -16,8 +16,9 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import ru.simsonic.rscPermissions.BukkitPluginMain; -public final class RegionListProviders +public final class BukkitRegionProviders { private final BukkitPluginMain plugin; private Plugin worldguard; @@ -25,7 +26,7 @@ public final class RegionListProviders private final Map> regionsByPlayer = new HashMap<>(); private final Map playerRegionHashes = new HashMap<>(); private final Map playerLastWorld = new HashMap<>(); - public RegionListProviders(BukkitPluginMain rscp) + public BukkitRegionProviders(BukkitPluginMain rscp) { this.plugin = rscp; } diff --git a/src/main/java/ru/simsonic/rscPermissions/RegionUpdateObserver.java b/src/main/java/ru/simsonic/rscPermissions/Bukkit/RegionUpdateObserver.java similarity index 86% rename from src/main/java/ru/simsonic/rscPermissions/RegionUpdateObserver.java rename to src/main/java/ru/simsonic/rscPermissions/Bukkit/RegionUpdateObserver.java index 1aebcbf..59bc028 100644 --- a/src/main/java/ru/simsonic/rscPermissions/RegionUpdateObserver.java +++ b/src/main/java/ru/simsonic/rscPermissions/Bukkit/RegionUpdateObserver.java @@ -1,5 +1,6 @@ -package ru.simsonic.rscPermissions; +package ru.simsonic.rscPermissions.Bukkit; import org.bukkit.entity.Player; +import ru.simsonic.rscPermissions.BukkitPluginMain; import ru.simsonic.rscUtilityLibrary.BukkitListeners.MovingPlayersCatcher; import ru.simsonic.rscUtilityLibrary.RestartableThread; @@ -9,7 +10,7 @@ public class RegionUpdateObserver extends RestartableThread private static final long granularityMax = 10000; private final BukkitPluginMain rscp; private final MovingPlayersCatcher movedPlayers = new MovingPlayersCatcher(); - RegionUpdateObserver(BukkitPluginMain rscp) + public RegionUpdateObserver(BukkitPluginMain rscp) { this.rscp = rscp; } diff --git a/src/main/java/ru/simsonic/rscPermissions/Bukkit/VaultPermission.java b/src/main/java/ru/simsonic/rscPermissions/Bukkit/VaultPermission.java index b54af9c..86beb7b 100644 --- a/src/main/java/ru/simsonic/rscPermissions/Bukkit/VaultPermission.java +++ b/src/main/java/ru/simsonic/rscPermissions/Bukkit/VaultPermission.java @@ -242,4 +242,4 @@ public class VaultPermission extends net.milkbowl.vault.permission.Permission { throw new UnsupportedOperationException("This method is still unsupported. Sorry."); } -} \ No newline at end of file +} diff --git a/src/main/java/ru/simsonic/rscPermissions/BukkitPluginMain.java b/src/main/java/ru/simsonic/rscPermissions/BukkitPluginMain.java index c53b560..cb49ef2 100644 --- a/src/main/java/ru/simsonic/rscPermissions/BukkitPluginMain.java +++ b/src/main/java/ru/simsonic/rscPermissions/BukkitPluginMain.java @@ -1,15 +1,20 @@ package ru.simsonic.rscPermissions; +import ru.simsonic.rscPermissions.Bukkit.BukkitRegionProviders; +import ru.simsonic.rscPermissions.Bukkit.RegionUpdateObserver; import ru.simsonic.rscPermissions.Bukkit.BukkitMaintenance; import ru.simsonic.rscPermissions.API.Settings; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; import org.mcstats.MetricsLite; -import ru.simsonic.rscPermissions.Bukkit.BukkitPermissions; +import ru.simsonic.rscPermissions.Backends.BackendDatabase; +import ru.simsonic.rscPermissions.Backends.BackendJson; +import ru.simsonic.rscPermissions.Bukkit.BukkitPermissionManager; import ru.simsonic.rscPermissions.Bukkit.BukkitPluginConfiguration; import ru.simsonic.rscPermissions.Bukkit.PlayerEventsListener; import ru.simsonic.rscPermissions.InternalCache.InternalCache; @@ -18,18 +23,19 @@ import ru.simsonic.rscUtilityLibrary.TextProcessing.GenericChatCodes; public final class BukkitPluginMain extends JavaPlugin { - private static final String chatPrefix = "{_YL}[rscp] {GOLD}"; - public static final Logger consoleLog = Logger.getLogger("Minecraft"); + private static final String chatPrefix = "{YELLOW}[rscp] {GOLD}"; + public static final Logger consoleLog = Bukkit.getLogger(); public final Settings settings = new BukkitPluginConfiguration(this); private final BridgeForBukkitAPI bridgeForBukkit = new BridgeForBukkitAPI(this); - public final PlayerEventsListener listener = new PlayerEventsListener(this); + public final PlayerEventsListener bukkitListener = new PlayerEventsListener(this); + public final BackendJson fileCache = new BackendJson(getDataFolder()); + public final BackendDatabase connection = new BackendDatabase(this); public final InternalCache internalCache = new InternalCache(this); - public final BukkitPermissions permissionManager = new BukkitPermissions(this); - public final RegionListProviders regionListProvider = new RegionListProviders(this); + public final BukkitPermissionManager permissionManager = new BukkitPermissionManager(this); + public final BukkitRegionProviders regionListProvider = new BukkitRegionProviders(this); private final RegionUpdateObserver regionUpdateObserver = new RegionUpdateObserver(this); public final CommandHelper commandHelper = new CommandHelper(this); public final BukkitMaintenance maintenance = new BukkitMaintenance(this); - public ConnectionHelper connectionList; private MetricsLite metrics; @Override public void onLoad() @@ -42,13 +48,7 @@ public final class BukkitPluginMain extends JavaPlugin public void onEnable() { settings.readSettings(); - connectionList = settings.getConnectionChain(); - if(connectionList == null) - { - consoleLog.log(Level.WARNING, "[rscp] No MySQL servers were specified in config.yml, disabling..."); - getServer().getPluginManager().disablePlugin(this); - return; - } + connection.initialize(settings.getConnectionParams()); // Register event's dispatcher getServer().getPluginManager().registerEvents(maintenance, this); regionUpdateObserver.registerListeners(); @@ -58,7 +58,7 @@ public final class BukkitPluginMain extends JavaPlugin internalCache.setDefaultGroup(settings.getDefaultGroup()); permissionManager.start(); regionUpdateObserver.start(); - connectionList.threadFetchTablesData(); + commandHelper.threadFetchTablesData(); // Metrics if(settings.isUseMetrics()) { @@ -79,9 +79,8 @@ public final class BukkitPluginMain extends JavaPlugin getServer().getServicesManager().unregisterAll(this); regionUpdateObserver.stop(); permissionManager.stop(); - // cache.clear(); - connectionList.Disconnect(); - connectionList = null; + internalCache.clear(); + connection.disconnect(); regionListProvider.deintegrate(); metrics = null; consoleLog.info("[rscp] rscPermissions has been disabled."); @@ -98,7 +97,7 @@ public final class BukkitPluginMain extends JavaPlugin @Override public void run() { - connectionList.threadFetchTablesData(); + commandHelper.threadFetchTablesData.start(); } }, delay); } diff --git a/src/main/java/ru/simsonic/rscPermissions/CommandHelper.java b/src/main/java/ru/simsonic/rscPermissions/CommandHelper.java index 66d56b0..bf08d08 100644 --- a/src/main/java/ru/simsonic/rscPermissions/CommandHelper.java +++ b/src/main/java/ru/simsonic/rscPermissions/CommandHelper.java @@ -2,19 +2,89 @@ package ru.simsonic.rscPermissions; import java.util.ArrayList; import java.util.Collections; import java.util.Map; +import java.util.logging.Level; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionAttachment; +import ru.simsonic.rscPermissions.DataTypes.DatabaseContents; import ru.simsonic.rscPermissions.Importers.PermissionsEx_YAML; import ru.simsonic.rscUtilityLibrary.CommandProcessing.CommandAnswerException; +import ru.simsonic.rscUtilityLibrary.RestartableThread; public class CommandHelper { - private final BukkitPluginMain plugin; + private final BukkitPluginMain rscp; public CommandHelper(final BukkitPluginMain rscp) { - this.plugin = rscp; + this.rscp = rscp; + } + public final RestartableThread threadFetchTablesData = new RestartableThread() + { + @Override + public void run() + { + final DatabaseContents contents = rscp.connection.retrieveContents(); + rscp.internalCache.fill(contents); + rscp.permissionManager.recalculateOnlinePlayersSync(); + } + }; + public Thread threadMigrateFromPExSQL(final CommandSender sender) + { + final Thread result = new Thread() + { + @Override + public void run() + { + try + { + setName("rscp:MigrateFromPExSQL"); + rscp.connection.executeUpdateT("Migrate_from_PermissionsEx"); + threadFetchTablesData.join(); + rscp.getServer().getScheduler().runTask(rscp, new Runnable() + { + @Override + public void run() + { + rscp.formattedMessage(sender, "Migration from PermissionsEx (MySQL backend) done!"); + rscp.formattedMessage(sender, "Check the latest database row for new data."); + } + }); + } catch(InterruptedException ex) + { + BukkitPluginMain.consoleLog.log(Level.SEVERE, "[rscp] Exception in MigrateFromPExSQL(): {0}", ex); + } + } + }; + result.start(); + return result; + } + public RestartableThread threadInsertExampleRows(final CommandSender sender) + { + final RestartableThread threadInsertExampleRows = new RestartableThread() + { + @Override + public void run() + { + Thread.currentThread().setName("rscp:InsertExampleRows"); + rscp.connection.insertExampleRows(); + rscp.getServer().getScheduler().runTask(rscp, new Runnable() + { + @Override + public void run() + { + sender.sendMessage("Database tables were filled with example rows."); + } + }); + } + }; + threadInsertExampleRows.start(); + return threadInsertExampleRows; + } + public RestartableThread threadFetchTablesData() + { + threadFetchTablesData.start(); + return threadFetchTablesData; } public void onCommand(CommandSender sender, Command cmd, String label, String[] args) throws CommandAnswerException { @@ -40,11 +110,11 @@ public class CommandHelper help.add("/rscp (help) {_LS}-- show these notes"); if(help.size() > 0) help.add(0, "{MAGENTA}Usage:"); - help.add(0, plugin.getDescription().getName() + " v" + plugin.getDescription().getVersion()); + help.add(0, rscp.getDescription().getName() + " v" + rscp.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()); + help.add(2, "{_DS}Current serverId is \'{_LS}" + rscp.getServer().getServerId() + "{_DS}\' (server.properties)"); + help.add("{_LG}" + rscp.getDescription().getWebsite()); if(args.length == 0) throw new CommandAnswerException(help); switch(args[0].toLowerCase()) @@ -61,9 +131,9 @@ public class CommandHelper { final String mMode = (args.length >= 2) ? args[1] : "default"; String mmon = "Maintenance mode enabled"; - mmon = plugin.getConfig().getString("language.maintenance.locked.default.mmon", mmon); - mmon = plugin.getConfig().getString("language.maintenance.locked." + mMode + ".mmon", mmon); - plugin.maintenance.setMaintenanceMode(mMode); + mmon = rscp.getConfig().getString("language.maintenance.locked.default.mmon", mmon); + mmon = rscp.getConfig().getString("language.maintenance.locked." + mMode + ".mmon", mmon); + rscp.maintenance.setMaintenanceMode(mMode); throw new CommandAnswerException(mmon); } return; @@ -72,8 +142,8 @@ public class CommandHelper if(sender.hasPermission("rscp.lock")) { String mmoff = "Maintenance mode disabled"; - mmoff = plugin.getConfig().getString("language.maintenance.unlocked", mmoff); - plugin.maintenance.setMaintenanceMode(null); + mmoff = rscp.getConfig().getString("language.maintenance.unlocked", mmoff); + rscp.maintenance.setMaintenanceMode(null); throw new CommandAnswerException(mmoff); } break; @@ -81,7 +151,7 @@ public class CommandHelper /* rscp examplerows */ if(sender.hasPermission("rscp.admin")) { - plugin.connectionList.threadInsertExampleRows(sender); + threadInsertExampleRows(sender); throw new CommandAnswerException("Example rows have been added into database."); } return; @@ -96,8 +166,8 @@ public class CommandHelper if(args.length == 2) break; // TO DO HERE - PermissionsEx_YAML importer_pex = new PermissionsEx_YAML(plugin, args[2]); - plugin.connectionList.threadFetchTablesData(); + PermissionsEx_YAML importer_pex = new PermissionsEx_YAML(rscp, args[2]); + threadFetchTablesData(); throw new CommandAnswerException(new String[] { "Data has been imported successfully!", @@ -107,7 +177,7 @@ public class CommandHelper "{_DR}{_B}FAKE :p - all this is undone yet!", }); case "pex-sql": - plugin.connectionList.threadMigrateFromPExSQL(sender); + threadMigrateFromPExSQL(sender); throw new CommandAnswerException("Trying to import PEX database into rscPermissions..."); } throw new CommandAnswerException(new String[] @@ -123,7 +193,7 @@ public class CommandHelper /* rscp fetch */ if(sender.hasPermission("rscp.admin.reload")) { - plugin.connectionList.threadFetchTablesData(); + threadFetchTablesData(); throw new CommandAnswerException("Tables have been fetched."); } return; @@ -131,8 +201,8 @@ public class CommandHelper /* rscp reload */ if(sender.hasPermission("rscp.admin.reload")) { - plugin.getServer().getPluginManager().disablePlugin(plugin); - plugin.getServer().getPluginManager().enablePlugin(plugin); + rscp.getServer().getPluginManager().disablePlugin(rscp); + rscp.getServer().getPluginManager().enablePlugin(rscp); throw new CommandAnswerException("Plugin has been reloaded."); } return; @@ -162,7 +232,7 @@ public class CommandHelper }; if(args.length < 3) throw new CommandAnswerException(help); - final Player player = plugin.getServer().getPlayerExact(args[1]); + final Player player = rscp.getServer().getPlayerExact(args[1]); if(player == null) throw new CommandAnswerException("Player should be online"); final ArrayList list = new ArrayList<>(); @@ -175,7 +245,7 @@ public class CommandHelper { case "permissions": list.add("{MAGENTA}Permission list for {_YL}" + player.getName()); - final PermissionAttachment pa = plugin.permissionManager.attachments.get(player); + final PermissionAttachment pa = rscp.permissionManager.attachments.get(player); if(pa == null) break; final Map pv = pa.getPermissions(); diff --git a/src/main/java/ru/simsonic/rscPermissions/ConnectionHelper.java b/src/main/java/ru/simsonic/rscPermissions/ConnectionHelper.java deleted file mode 100644 index 2bbb15d..0000000 --- a/src/main/java/ru/simsonic/rscPermissions/ConnectionHelper.java +++ /dev/null @@ -1,128 +0,0 @@ -package ru.simsonic.rscPermissions; -import java.util.logging.Level; -import org.bukkit.command.CommandSender; -import org.bukkit.scheduler.BukkitRunnable; -import ru.simsonic.rscPermissions.Backends.BackendMySQL; -import ru.simsonic.rscUtilityLibrary.ConnectionMySQL; - -public class ConnectionHelper extends BackendMySQL -{ - private ConnectionHelper nextInChain = null; - public ConnectionHelper(BukkitPluginMain 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(rscp.internalCache); - // Update permissions for online players - try - { - Runnable syncTask = new Runnable() - { - @Override - public synchronized void run() - { - rscp.permissionManager.recalculateOnlinePlayers(); - notify(); - } - }; - synchronized(syncTask) - { - rscp.getServer().getScheduler().runTask(rscp, syncTask); - syncTask.wait(); - } - } catch(InterruptedException ex) { - BukkitPluginMain.consoleLog.log(Level.SEVERE, "[rscp] Exception in FetchTables(): {0}", ex); - } - // rscp.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) - return; - backend.insertExampleRows(); - rscp.getServer().getScheduler().runTask(rscp, 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) - return; - backend.executeUpdate(loadResourceSQLT("Migrate_from_PermissionsEx")); - threadFetchTablesData().join(); - rscp.getServer().getScheduler().runTask(rscp, new BukkitRunnable() - { - @Override - public void run() - { - rscp.formattedMessage(sender, "Migration from PermissionsEx (MySQL backend) done!"); - rscp.formattedMessage(sender, "Check the latest database row for new data."); - } - }); - } catch(InterruptedException ex) { - BukkitPluginMain.consoleLog.log(Level.SEVERE, "[rscp] Exception in MigrateFromPExSQL(): {0}", ex); - } - } - }; - result.start(); - return result; - } -} diff --git a/src/main/java/ru/simsonic/rscPermissions/DataTypes/DatabaseContents.java b/src/main/java/ru/simsonic/rscPermissions/DataTypes/DatabaseContents.java new file mode 100644 index 0000000..d63cedd --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/DataTypes/DatabaseContents.java @@ -0,0 +1,36 @@ +package ru.simsonic.rscPermissions.DataTypes; +import java.util.ArrayList; + +public class DatabaseContents +{ + public RowEntity entities[]; + public RowPermission permissions[]; + public RowInheritance inheritance[]; + public void normalize() + { + // Entities + final ArrayList listE = new ArrayList<>(); + if(entities != null) + for(RowEntity rowE : entities) + { + listE.add(rowE); + } + entities = listE.toArray(new RowEntity[listE.size()]); + // Permissions + final ArrayList listP = new ArrayList<>(); + if(permissions != null) + for(RowPermission rowP : permissions) + { + listP.add(rowP); + } + permissions = listP.toArray(new RowPermission[listP.size()]); + // Inheritance + final ArrayList listI = new ArrayList<>(); + if(inheritance != null) + for(RowInheritance rowI : inheritance) + { + listI.add(rowI); + } + inheritance = listI.toArray(new RowInheritance[listI.size()]); + } +} diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/AbstractPermissionsCache.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/AbstractPermissionsCache.java deleted file mode 100644 index e006df6..0000000 --- a/src/main/java/ru/simsonic/rscPermissions/InternalCache/AbstractPermissionsCache.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.simsonic.rscPermissions.InternalCache; -import ru.simsonic.rscPermissions.DataTypes.RowEntity; -import ru.simsonic.rscPermissions.DataTypes.RowInheritance; -import ru.simsonic.rscPermissions.DataTypes.RowPermission; - -public interface AbstractPermissionsCache -{ - public int ImportEntities(RowEntity[] rows); - public int ImportPermissions(RowPermission[] rows); - public int ImportInheritance(RowInheritance[] rows); -} diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/InternalCache.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/InternalCache.java index 739756a..485998a 100644 --- a/src/main/java/ru/simsonic/rscPermissions/InternalCache/InternalCache.java +++ b/src/main/java/ru/simsonic/rscPermissions/InternalCache/InternalCache.java @@ -9,8 +9,9 @@ import ru.simsonic.rscPermissions.DataTypes.RowInheritance; import ru.simsonic.rscPermissions.DataTypes.RowPermission; import ru.simsonic.rscPermissions.BukkitPluginMain; import ru.simsonic.rscPermissions.API.Settings; +import ru.simsonic.rscPermissions.DataTypes.DatabaseContents; -public class InternalCache implements AbstractPermissionsCache +public class InternalCache { protected final BukkitPluginMain plugin; public InternalCache(BukkitPluginMain rscp) @@ -177,8 +178,13 @@ public class InternalCache implements AbstractPermissionsCache ? row.destination.isRegionApplicable(params.destRegions, instantiator) : false; } - @Override - public synchronized int ImportEntities(RowEntity[] rows) + public synchronized void fill(DatabaseContents contents) + { + importEntities(contents.entities); + importPermissions(contents.permissions); + importInheritance(contents.inheritance); + } + private int importEntities(RowEntity[] rows) { entities_g.clear(); entities_u.clear(); @@ -193,8 +199,7 @@ public class InternalCache implements AbstractPermissionsCache } return entities_g.size() + entities_u.size(); } - @Override - public synchronized int ImportPermissions(RowPermission[] rows) + private int importPermissions(RowPermission[] rows) { permissions_p2g.clear(); permissions_p2u.clear(); @@ -209,8 +214,7 @@ public class InternalCache implements AbstractPermissionsCache } return permissions_p2g.size() + permissions_p2u.size(); } - @Override - public synchronized int ImportInheritance(RowInheritance[] rows) + private int importInheritance(RowInheritance[] rows) { inheritance_g2g.clear(); inheritance_g2u.clear(); @@ -225,4 +229,13 @@ public class InternalCache implements AbstractPermissionsCache } return inheritance_g2g.size() + inheritance_g2u.size(); } + public synchronized void clear() + { + entities_g.clear(); + entities_u.clear(); + permissions_p2g.clear(); + permissions_p2u.clear(); + inheritance_g2g.clear(); + inheritance_g2u.clear(); + } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 96ebe0c..59d9c52 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -10,18 +10,10 @@ settings: integration: worldguard: true residence: true -servers: -- nodename: db-primary-remote - database: localhost:3306/minecraft - username: user1 - password: pass1 - prefixes: rscp_ - workmode: fullaccess -- nodename: db-secondary-local-replication - database: other.server:3306/replication - username: user2 - password: pass2 - prefixes: rscp_ - workmode: none + connection: + database: localhost:3306/minecraft + username: user1 + password: pass1 + prefixes: rscp_ internal: - version: 1 + version: 4 diff --git a/src/main/resources/sqlt/Cleanup_tables.sqlt b/src/main/resources/sqlt/Cleanup_tables.sqlt index fe1d417..ed652e6 100644 --- a/src/main/resources/sqlt/Cleanup_tables.sqlt +++ b/src/main/resources/sqlt/Cleanup_tables.sqlt @@ -1,21 +1,13 @@ -DELETE FROM - `{DATABASE}`.`{PREFIX}entities` +DELETE FROM `{DATABASE}`.`{PREFIX}entities` WHERE ((`prefix` = '' OR `prefix` IS NULL) AND (`suffix` = '' OR `suffix` IS NULL)) OR `lifetime` < CURRENT_TIMESTAMP; -DELETE FROM - `{DATABASE}`.`{PREFIX}permissions` +DELETE FROM `{DATABASE}`.`{PREFIX}permissions` WHERE `lifetime` < CURRENT_TIMESTAMP; -DELETE FROM - `{DATABASE}`.`{PREFIX}inheritance` +DELETE FROM `{DATABASE}`.`{PREFIX}inheritance` WHERE `lifetime` < CURRENT_TIMESTAMP; - -DELETE FROM - `{DATABASE}`.`{PREFIX}ladders` -WHERE - `climber_type` = b'1' AND `rank` = 0; diff --git a/src/main/resources/sqlt/Initialize_main_v1.sqlt b/src/main/resources/sqlt/Initialize_main_v1.sqlt index d27595c..2464168 100644 --- a/src/main/resources/sqlt/Initialize_main_v1.sqlt +++ b/src/main/resources/sqlt/Initialize_main_v1.sqlt @@ -1,10 +1,10 @@ CREATE TABLE IF NOT EXISTS `{DATABASE}`.`{PREFIX}entities` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `entity` VARCHAR(64) NOT NULL, - `entity_type` TINYINT(1) NOT NULL, - `prefix` VARCHAR(48) DEFAULT NULL, - `suffix` VARCHAR(48) DEFAULT NULL, - `lifetime` TIMESTAMP NULL DEFAULT NULL, + `entity` VARCHAR(64) NOT NULL, + `entity_type` TINYINT(1) NOT NULL, + `prefix` VARCHAR(48) DEFAULT NULL, + `suffix` VARCHAR(48) DEFAULT NULL, + `lifetime` TIMESTAMP NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `id_UNIQUE` (`id`), UNIQUE KEY `entity_UNIQUE` (`entity`, `entity_type`) @@ -12,13 +12,13 @@ CREATE TABLE IF NOT EXISTS `{DATABASE}`.`{PREFIX}entities` ( CREATE TABLE IF NOT EXISTS `{DATABASE}`.`{PREFIX}permissions` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `entity` VARCHAR(64) NOT NULL, - `entity_type` TINYINT(1) NOT NULL, - `permission` VARCHAR(255) NOT NULL, - `value` BIT(1) NOT NULL DEFAULT b'1', - `destination` VARCHAR(255) NOT NULL DEFAULT '', - `expirience` SMALLINT(6) NOT NULL DEFAULT 0, - `lifetime` TIMESTAMP NULL DEFAULT NULL, + `entity` VARCHAR(64) NOT NULL, + `entity_type` TINYINT(1) NOT NULL, + `permission` VARCHAR(255) NOT NULL, + `value` BIT(1) NOT NULL DEFAULT b'1', + `destination` VARCHAR(255) NOT NULL DEFAULT '', + `expirience` SMALLINT(6) NOT NULL DEFAULT 0, + `lifetime` TIMESTAMP NULL DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `id_UNIQUE` (`id`), UNIQUE KEY `permission_UNIQUE` (`entity`, `entity_type`, `permission`, `destination`, `expirience`) @@ -26,32 +26,19 @@ CREATE TABLE IF NOT EXISTS `{DATABASE}`.`{PREFIX}permissions` ( CREATE TABLE IF NOT EXISTS `{DATABASE}`.`{PREFIX}inheritance` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `entity` VARCHAR(64) NOT NULL, - `parent` VARCHAR(64) NOT NULL, - `inheritance_type` TINYINT(1) NOT NULL, - `inheritance_priority` SMALLINT(6) NOT NULL DEFAULT '20', - `destination` VARCHAR(255) NOT NULL DEFAULT '', - `expirience` SMALLINT(6) NOT NULL DEFAULT 0, - `lifetime` TIMESTAMP NULL DEFAULT NULL, + `entity` VARCHAR(64) NOT NULL, + `parent` VARCHAR(64) NOT NULL, + `inheritance_type` TINYINT(1) NOT NULL, + `inheritance_priority` SMALLINT(6) NOT NULL DEFAULT '20', + `destination` VARCHAR(255) NOT NULL DEFAULT '', + `expirience` SMALLINT(6) NOT NULL DEFAULT 0, + `lifetime` TIMESTAMP NULL DEFAULT NULL, PRIMARY KEY (`id`, `entity`), UNIQUE KEY `id_UNIQUE` (`id`), UNIQUE KEY `inheritance_UNIQUE` (`entity`, `parent`, `inheritance_type`, `destination`, `expirience`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET='utf8' COLLATE 'utf8_general_ci'; -CREATE TABLE IF NOT EXISTS `{DATABASE}`.`{PREFIX}servers` ( - `serverid` VARCHAR(48) NOT NULL, - `plugin_version` VARCHAR(16) DEFAULT NULL, - `settings_default-group` VARCHAR(64) NOT NULL DEFAULT 'Default', - `settings_treat-asterisk-as-op` BIT(1) NOT NULL DEFAULT b'1', - `settings_auto-reload-delay-sec` INT(10) UNSIGNED NOT NULL DEFAULT '900', - `settings_maintenance-mode` VARCHAR(64) DEFAULT NULL, - `settings_enable-rewards` BIT(1) NOT NULL DEFAULT b'0', - `internal_version` TINYINT(2) UNSIGNED NOT NULL DEFAULT '1', - PRIMARY KEY (`serverid`), - UNIQUE KEY `serverid_UNIQUE` (`serverid`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET='utf8' COLLATE 'utf8_general_ci'; - -/* Merged updates 0.1a -> 0.5.9b -> 0.6b -> 0.8.15b */ +/* Merged updates 0.1a -> 0.5.9b -> 0.6b -> 0.8.15b -> 0.9.2b */ ALTER IGNORE TABLE `{DATABASE}`.`{PREFIX}entities` COLLATE 'utf8_general_ci'; @@ -72,5 +59,5 @@ ALTER IGNORE TABLE `{DATABASE}`.`{PREFIX}inheritance` ALTER IGNORE TABLE `{DATABASE}`.`{PREFIX}servers` COLLATE 'utf8_general_ci'; -ALTER TABLE `{DATABASE}`.`{PREFIX}entities` +ALTER IGNORE TABLE `{DATABASE}`.`{PREFIX}entities` ADD COLUMN `lifetime` TIMESTAMP NULL DEFAULT NULL AFTER `suffix`; diff --git a/src/main/resources/sqlt/Migrate_from_PermissionsEx.sqlt b/src/main/resources/sqlt/Migrate_from_PermissionsEx.sqlt index b36e0e7..da3bfff 100644 --- a/src/main/resources/sqlt/Migrate_from_PermissionsEx.sqlt +++ b/src/main/resources/sqlt/Migrate_from_PermissionsEx.sqlt @@ -54,4 +54,4 @@ INSERT INTO `{DATABASE}`.`{PREFIX}inheritance` WHERE `permission` LIKE 'group-%-until' ORDER BY `type` ASC, `parent` ASC, `name` ASC ON DUPLICATE KEY UPDATE - `lifetime` = VALUES(`lifetime`); \ No newline at end of file + `lifetime` = VALUES(`lifetime`); diff --git a/src/main/resources/sqlt/Update_entity_text.sqlt b/src/main/resources/sqlt/Update_entity_text.sqlt index 413c6b2..3788d05 100644 --- a/src/main/resources/sqlt/Update_entity_text.sqlt +++ b/src/main/resources/sqlt/Update_entity_text.sqlt @@ -3,4 +3,4 @@ INSERT INTO VALUES ('{ENTITY}', b'{ENTITY_TYPE}', {TEXT}) ON DUPLICATE KEY UPDATE - `{TEXT_TYPE}` = VALUES(`{TEXT_TYPE}`); \ No newline at end of file + `{TEXT_TYPE}` = VALUES(`{TEXT_TYPE}`);