diff --git a/src/main/java/net/coreprotect/command/TabHandler.java b/src/main/java/net/coreprotect/command/TabHandler.java index 23d019b..7f8acd9 100755 --- a/src/main/java/net/coreprotect/command/TabHandler.java +++ b/src/main/java/net/coreprotect/command/TabHandler.java @@ -22,11 +22,11 @@ import net.coreprotect.config.ConfigHandler; public class TabHandler implements TabCompleter { // private static String[] COMMANDS = new String[] { "help", "inspect", "rollback", "restore", "lookup", "purge", "reload", "status", "near", "undo" }; // max 10! - private static String[] HELP = new String[] { "inspect", "rollback", "restore", "lookup", "purge", "teleport", "status", "params", "users", "time", "radius", "action", "include", "exclude" }; - private static String[] PARAMS = new String[] { "user:", "time:", "radius:", "action:", "include:", "exclude:", "#container" }; - private static String[] ACTIONS = new String[] { "block", "+block", "-block", "click", "kill", "+container", "-container", "container", "chat", "command", "+inventory", "-inventory", "inventory", "item", "+item", "-item", "sign", "session", "+session", "-session", "username" }; - private static String[] NUMBERS = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - private static String[] TIMES = new String[] { "w", "d", "h", "m", "s" }; + private static final String[] HELP = new String[] { "inspect", "rollback", "restore", "lookup", "purge", "teleport", "status", "params", "users", "time", "radius", "action", "include", "exclude" }; + private static final String[] PARAMS = new String[] { "user:", "time:", "radius:", "action:", "include:", "exclude:", "#container" }; + private static final String[] ACTIONS = new String[] { "block", "+block", "-block", "click", "kill", "+container", "-container", "container", "chat", "command", "+inventory", "-inventory", "inventory", "item", "+item", "-item", "sign", "session", "+session", "-session", "username" }; + private static final String[] NUMBERS = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + private static final String[] TIMES = new String[] { "w", "d", "h", "m", "s" }; private static ArrayList materials = null; @Override @@ -34,375 +34,470 @@ public class TabHandler implements TabCompleter { if (!(sender instanceof Player) || args.length == 0) { return null; } + if (args.length == 1) { - String argument = args[0].toLowerCase(Locale.ROOT); - List completions = new ArrayList<>(); - if (sender.hasPermission("coreprotect.help")) { - completions.add("help"); - } - if (sender.hasPermission("coreprotect.inspect")) { - completions.add("inspect"); - } - if (sender.hasPermission("coreprotect.rollback")) { - completions.add("rollback"); - } - if (sender.hasPermission("coreprotect.restore")) { - completions.add("restore"); - } - if (sender.hasPermission("coreprotect.lookup")) { - completions.add("lookup"); - } - if (sender.hasPermission("coreprotect.purge")) { - completions.add("purge"); - } - if (sender.hasPermission("coreprotect.reload")) { - completions.add("reload"); - } - if (sender.hasPermission("coreprotect.status")) { - completions.add("status"); - } - if (sender.hasPermission("coreprotect.lookup.near")) { - completions.add("near"); - } - if (sender.hasPermission("coreprotect.restore")) { - completions.add("undo"); - } - - return StringUtil.copyPartialMatches(argument, completions, new ArrayList<>(completions.size())); + return getFirstLevelCompletions(sender, args[0]); } - else if (args.length > 1) { - String argument0 = args[0].toLowerCase(Locale.ROOT); - String argument1 = args[1].toLowerCase(Locale.ROOT); - String currentArg = args[args.length - 1].toLowerCase(Locale.ROOT).trim(); - String lastArg = args[args.length - 2].toLowerCase(Locale.ROOT).trim(); - boolean hasUser = false; - boolean hasAction = false; - boolean hasInclude = false; - boolean hasExclude = false; - boolean hasRadius = false; - boolean hasTime = false; - boolean hasContainer = false; - boolean hasCount = false; - boolean hasPreview = false; - boolean hasPage = false; - boolean validContainer = false; - boolean pageLookup = false; + String argument0 = args[0].toLowerCase(Locale.ROOT); + String currentArg = args[args.length - 1].toLowerCase(Locale.ROOT).trim(); + String lastArg = args.length > 1 ? args[args.length - 2].toLowerCase(Locale.ROOT).trim() : ""; - if (ConfigHandler.lookupType.get(sender.getName()) != null && ConfigHandler.lookupPage.get(sender.getName()) != null) { - pageLookup = true; - } + ParamState paramState = getParamState(args); - for (int i = 1; i < args.length; i++) { - String arg = args[i].toLowerCase(Locale.ROOT); - if (arg.equals("#container")) { - hasContainer = true; - } - else if (arg.equals("#count") || arg.equals("#sum")) { - hasCount = true; - } - else if (arg.equals("#preview")) { - hasPreview = true; - } - else if ((!arg.contains(":") && !args[i - 1].contains(":") && args.length > (i + 1)) || arg.contains("u:") || arg.contains("user:") || arg.contains("users:") || arg.contains("p:")) { - hasUser = true; - } - else if (arg.contains("page:")) { - hasPage = true; - } - else if (arg.contains("a:") || arg.contains("action:")) { - hasAction = true; - } - else if (arg.contains("i:") || arg.contains("include:") || arg.contains("item:") || arg.contains("items:") || arg.contains("b:") || arg.contains("block:") || arg.contains("blocks:")) { - hasInclude = true; - } - else if (arg.contains("t:") || arg.contains("time:")) { - hasTime = true; - } - else if (arg.contains("e:") || arg.contains("exclude:")) { - hasExclude = true; - } - else if (arg.contains("r:") || arg.contains("radius:")) { - hasRadius = true; - } - } - - if (!hasContainer) { - if (ConfigHandler.lookupType.get(sender.getName()) != null) { - int lookupType = ConfigHandler.lookupType.get(sender.getName()); - if (lookupType == 1) { - validContainer = true; - } - else if (lookupType == 5) { - if (ConfigHandler.lookupUlist.get(sender.getName()).contains("#container")) { - validContainer = true; - } - } - } - } - - if ((lastArg.equals("a:") || lastArg.equals("action:")) && (sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore"))) { - List completions = new ArrayList<>(Arrays.asList(ACTIONS)); - return StringUtil.copyPartialMatches(currentArg, completions, new ArrayList<>(completions.size())); - } - else if ((currentArg.startsWith("a:") || currentArg.startsWith("action:")) && (sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore"))) { - String arg = ""; - String[] split = currentArg.split(":", 2); - String filter = split[0] + ":"; - if (split.length > 1) { - arg = split[1]; - } - - List completions = new ArrayList<>(Arrays.asList(ACTIONS)); - for (int index = 0; index < completions.size(); index++) { - completions.set(index, filter + completions.get(index)); - } - return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); - } - else if ((lastArg.equals("u:") || lastArg.equals("user:") || lastArg.equals("users:") || lastArg.equals("p:")) && (sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore"))) { - return null; - } - else if ((currentArg.startsWith("u:") || currentArg.startsWith("user:") || currentArg.startsWith("users:") || currentArg.startsWith("p:")) && (sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore"))) { - String arg = ""; - String[] split = currentArg.split(":", 2); - String filter = split[0] + ":"; - if (split.length > 1) { - arg = split[1]; - } - - List completions = Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); - for (int index = 0; index < completions.size(); index++) { - completions.set(index, filter + completions.get(index)); - } - - return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); - } - else if ((lastArg.equals("t:") || lastArg.equals("time:") || currentArg.startsWith("t:") || currentArg.startsWith("time:")) && (sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore") || sender.hasPermission("coreprotect.purge"))) { - String filter = lastArg; - String arg = ""; - if (currentArg.contains(":")) { - String[] split = currentArg.split(":", 2); - filter = split[0] + ":"; - if (split.length > 1) { - arg = split[1]; - } - } - else { - filter = ""; - arg = currentArg; - } - - List completions = new ArrayList<>(); - if (arg.chars().allMatch(Character::isDigit)) { - boolean addNumbers = true; - if (currentArg.length() > 0) { - char lastChar = currentArg.charAt(currentArg.length() - 1); - if (Character.isDigit(lastChar)) { - completions.addAll(Arrays.asList(TIMES)); - addNumbers = false; - } - } - if (addNumbers) { - completions.addAll(Arrays.asList(NUMBERS)); - } - - } - - completions = new ArrayList<>(completions); - for (int index = 0; index < completions.size(); index++) { - completions.set(index, filter + arg + completions.get(index)); - } - - return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); - } - else if ((lastArg.equals("page:") || currentArg.startsWith("page:")) && (sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.lookup.near") || sender.hasPermission("coreprotect.inspect"))) { - String filter = lastArg; - String arg = ""; - if (currentArg.contains(":")) { - String[] split = currentArg.split(":", 2); - filter = split[0] + ":"; - if (split.length > 1) { - arg = split[1]; - } - } - else { - filter = ""; - arg = currentArg; - } - - if (arg.chars().allMatch(Character::isDigit)) { - List completions = new ArrayList<>(Arrays.asList(NUMBERS)); - if (arg.length() < 1) { - for (int index = 0; index < completions.size(); index++) { - completions.set(index, filter + arg + completions.get(index)); - } - if (arg.length() == 0) { - completions.remove(0); - } - } - return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); - } - } - else if ((lastArg.equals("r:") || lastArg.equals("radius:") || currentArg.startsWith("r:") || currentArg.startsWith("radius:")) && (sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore") || sender.hasPermission("coreprotect.purge"))) { - String filter = lastArg; - String arg = ""; - if (currentArg.contains(":")) { - String[] split = currentArg.split(":", 2); - filter = split[0] + ":"; - if (split.length > 1) { - arg = split[1]; - } - } - else { - filter = ""; - arg = currentArg; - } - - if (!argument0.equals("purge") && arg.chars().allMatch(Character::isDigit)) { - List completions = new ArrayList<>(Arrays.asList(NUMBERS)); - if (arg.length() < 2) { - for (int index = 0; index < completions.size(); index++) { - completions.set(index, filter + arg + completions.get(index)); - } - } - return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); - } - else if (argument0.equals("purge") || arg.startsWith("#")) { - ArrayList params = new ArrayList<>(); - params.add("#global"); - if (!argument0.equals("purge") && sender.getServer().getPluginManager().getPlugin("WorldEdit") != null) { - params.add("#worldedit"); - } - List worlds = sender.getServer().getWorlds(); - for (World world : worlds) { - params.add("#" + world.getName()); - } - List completions = new ArrayList<>(params); - for (int index = 0; index < completions.size(); index++) { - completions.set(index, filter + completions.get(index)); - } - return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); - } - } - else if ((sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore")) && (lastArg.equals("i:") || lastArg.equals("include:") || lastArg.equals("item:") || lastArg.equals("items:") || lastArg.equals("b:") || lastArg.equals("block:") || lastArg.equals("blocks:") || currentArg.startsWith("i:") || currentArg.startsWith("include:") || currentArg.startsWith("item:") || currentArg.startsWith("items:") || currentArg.startsWith("b:") || currentArg.startsWith("block:") || currentArg.startsWith("blocks:") || lastArg.equals("e:") || lastArg.equals("exclude:") || currentArg.startsWith("e:") || currentArg.startsWith("exclude:"))) { - String filter = lastArg; - String arg = ""; - if (currentArg.contains(":")) { - String[] split = currentArg.split(":", 2); - filter = split[0] + ":"; - if (split.length > 1) { - arg = split[1]; - } - } - else { - filter = ""; - arg = currentArg; - } - - if (materials == null) { - List addList = Arrays.asList(Material.ARMOR_STAND); - List excludeList = Arrays.asList(); - Set materialList = new HashSet<>(); - - Material[] materialValues = Material.values(); - for (Material material : materialValues) { - if (material.isBlock() || material.isItem()) { - materialList.add(material.name().toLowerCase(Locale.ROOT)); - } - } - for (Material exclude : excludeList) { - materialList.remove(exclude.name().toLowerCase(Locale.ROOT)); - } - for (Material add : addList) { - materialList.add(add.name().toLowerCase(Locale.ROOT)); - } - - // add custom tags - for (String tag : CommandParser.getTags().keySet()) { - materialList.add(tag); - } - - materials = new ArrayList<>(materialList); - } - - List completions = new ArrayList<>(materials); - for (int index = 0; index < completions.size(); index++) { - completions.set(index, filter + completions.get(index)); - } - return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); - - } - else if (args.length == 2) { - if (argument0.equals("help") && sender.hasPermission("coreprotect.help")) { - List completions = new ArrayList<>(Arrays.asList(HELP)); - return StringUtil.copyPartialMatches(argument1, completions, new ArrayList<>(completions.size())); - } - else if (argument0.equals("purge") && sender.hasPermission("coreprotect.purge")) { - List completions = new ArrayList<>(Arrays.asList("t:", "r:", "i:")); - return StringUtil.copyPartialMatches(argument1, completions, new ArrayList<>(completions.size())); - } - else if ((sender.hasPermission("coreprotect.lookup") && (argument0.equals("l") || argument0.equals("lookup"))) || (sender.hasPermission("coreprotect.rollback") && (argument0.equals("rollback") || argument0.equals("rb") || argument0.equals("ro"))) || (sender.hasPermission("coreprotect.restore") && (argument0.equals("restore") || argument0.equals("rs") || argument0.equals("re")))) { - List completions = new ArrayList<>(filterParams(true, argument0, argument1, hasUser, hasAction, hasInclude, hasExclude, hasRadius, hasTime, hasContainer, hasCount, hasPreview, pageLookup, validContainer)); - completions.addAll(Bukkit.getOnlinePlayers().stream().filter(player -> player.getName().toLowerCase(Locale.ROOT).startsWith(argument1)).map(Player::getName).collect(Collectors.toList())); - return StringUtil.copyPartialMatches(argument1, completions, new ArrayList<>(completions.size())); - } - } - else if (args.length == 3 && argument0.equals("purge") && sender.hasPermission("coreprotect.purge")) { - if (argument1.startsWith("t:")) { - List completions = new ArrayList<>(Arrays.asList("r:", "i:")); - return StringUtil.copyPartialMatches(args[2].toLowerCase(Locale.ROOT), completions, new ArrayList<>(completions.size())); - } - else if (argument1.startsWith("r:") || argument1.startsWith("i:")) { - List completions = new ArrayList<>(Arrays.asList("t:")); - return StringUtil.copyPartialMatches(args[2].toLowerCase(Locale.ROOT), completions, new ArrayList<>(completions.size())); - } - return Arrays.asList(""); - } - else if ((sender.hasPermission("coreprotect.lookup") && (argument0.equals("l") || argument0.equals("lookup"))) || (sender.hasPermission("coreprotect.rollback") && (argument0.equals("rollback") || argument0.equals("rb") || argument0.equals("ro"))) || (sender.hasPermission("coreprotect.restore") && (argument0.equals("restore") || argument0.equals("rs") || argument0.equals("re")))) { - if ((!argument0.equals("l") && !argument0.equals("lookup")) || !hasPage) { - ArrayList params = filterParams(false, argument0, currentArg, hasUser, hasAction, hasInclude, hasExclude, hasRadius, hasTime, hasContainer, hasCount, hasPreview, pageLookup, validContainer); - List completions = new ArrayList<>(params); - return StringUtil.copyPartialMatches(currentArg, completions, new ArrayList<>(completions.size())); - } - } + // Handle param-specific completions + if (isActionParam(lastArg, currentArg) && hasLookupPermission(sender)) { + return handleActionParamCompletions(currentArg, lastArg); + } + else if (isUserParam(lastArg, currentArg) && hasLookupPermission(sender)) { + return handleUserParamCompletions(currentArg, lastArg); + } + else if (isTimeParam(lastArg, currentArg) && hasTimePermission(sender)) { + return handleTimeParamCompletions(currentArg, lastArg); + } + else if (isPageParam(lastArg, currentArg) && hasPagePermission(sender)) { + return handlePageParamCompletions(currentArg, lastArg); + } + else if (isRadiusParam(lastArg, currentArg) && hasRadiusPermission(sender)) { + return handleRadiusParamCompletions(currentArg, lastArg, argument0); + } + else if (isMaterialParam(lastArg, currentArg) && hasLookupPermission(sender)) { + return handleMaterialParamCompletions(currentArg, lastArg); + } + else if (args.length == 2) { + return handleSecondArgCompletions(sender, argument0, args[1], paramState); + } + else if (args.length == 3 && argument0.equals("purge") && sender.hasPermission("coreprotect.purge")) { + return handlePurgeThirdArgCompletions(args[1], args[2]); + } + else if (hasLookupCommand(argument0, sender) && (!argument0.equals("l") && !argument0.equals("lookup") || !paramState.hasPage)) { + return handleGenericLookupCompletions(argument0, currentArg, paramState); } return Arrays.asList(""); } - private ArrayList filterParams(boolean firstParam, String lastArgument, String argument, boolean hasUser, boolean hasAction, boolean hasInclude, boolean hasExclude, boolean hasRadius, boolean hasTime, boolean hasContainer, boolean hasCount, boolean hasPreview, boolean pageLookup, boolean validContainer) { + private List getFirstLevelCompletions(CommandSender sender, String argument) { + String arg = argument.toLowerCase(Locale.ROOT); + List completions = new ArrayList<>(); + + addCompletionIfPermitted(sender, "coreprotect.help", "help", completions); + addCompletionIfPermitted(sender, "coreprotect.inspect", "inspect", completions); + addCompletionIfPermitted(sender, "coreprotect.rollback", "rollback", completions); + addCompletionIfPermitted(sender, "coreprotect.restore", "restore", completions); + addCompletionIfPermitted(sender, "coreprotect.lookup", "lookup", completions); + addCompletionIfPermitted(sender, "coreprotect.purge", "purge", completions); + addCompletionIfPermitted(sender, "coreprotect.reload", "reload", completions); + addCompletionIfPermitted(sender, "coreprotect.status", "status", completions); + addCompletionIfPermitted(sender, "coreprotect.lookup.near", "near", completions); + addCompletionIfPermitted(sender, "coreprotect.restore", "undo", completions); + + return StringUtil.copyPartialMatches(arg, completions, new ArrayList<>(completions.size())); + } + + private void addCompletionIfPermitted(CommandSender sender, String permission, String completion, List completions) { + if (sender.hasPermission(permission)) { + completions.add(completion); + } + } + + private boolean hasLookupPermission(CommandSender sender) { + return sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.rollback") || sender.hasPermission("coreprotect.restore"); + } + + private boolean hasTimePermission(CommandSender sender) { + return hasLookupPermission(sender) || sender.hasPermission("coreprotect.purge"); + } + + private boolean hasRadiusPermission(CommandSender sender) { + return hasTimePermission(sender); + } + + private boolean hasPagePermission(CommandSender sender) { + return sender.hasPermission("coreprotect.lookup") || sender.hasPermission("coreprotect.lookup.near") || sender.hasPermission("coreprotect.inspect"); + } + + private boolean hasLookupCommand(String cmd, CommandSender sender) { + return (sender.hasPermission("coreprotect.lookup") && (cmd.equals("l") || cmd.equals("lookup"))) || (sender.hasPermission("coreprotect.rollback") && (cmd.equals("rollback") || cmd.equals("rb") || cmd.equals("ro"))) || (sender.hasPermission("coreprotect.restore") && (cmd.equals("restore") || cmd.equals("rs") || cmd.equals("re"))); + } + + private boolean isActionParam(String lastArg, String currentArg) { + return lastArg.equals("a:") || lastArg.equals("action:") || currentArg.startsWith("a:") || currentArg.startsWith("action:"); + } + + private boolean isUserParam(String lastArg, String currentArg) { + return lastArg.equals("u:") || lastArg.equals("user:") || lastArg.equals("users:") || lastArg.equals("p:") || currentArg.startsWith("u:") || currentArg.startsWith("user:") || currentArg.startsWith("users:") || currentArg.startsWith("p:"); + } + + private boolean isTimeParam(String lastArg, String currentArg) { + return lastArg.equals("t:") || lastArg.equals("time:") || currentArg.startsWith("t:") || currentArg.startsWith("time:"); + } + + private boolean isPageParam(String lastArg, String currentArg) { + return lastArg.equals("page:") || currentArg.startsWith("page:"); + } + + private boolean isRadiusParam(String lastArg, String currentArg) { + return lastArg.equals("r:") || lastArg.equals("radius:") || currentArg.startsWith("r:") || currentArg.startsWith("radius:"); + } + + private boolean isMaterialParam(String lastArg, String currentArg) { + return lastArg.equals("i:") || lastArg.equals("include:") || lastArg.equals("item:") || lastArg.equals("items:") || lastArg.equals("b:") || lastArg.equals("block:") || lastArg.equals("blocks:") || currentArg.startsWith("i:") || currentArg.startsWith("include:") || currentArg.startsWith("item:") || currentArg.startsWith("items:") || currentArg.startsWith("b:") || currentArg.startsWith("block:") || currentArg.startsWith("blocks:") || lastArg.equals("e:") || lastArg.equals("exclude:") || currentArg.startsWith("e:") || currentArg.startsWith("exclude:"); + } + + private static class ParamState { + boolean hasUser; + boolean hasAction; + boolean hasInclude; + boolean hasExclude; + boolean hasRadius; + boolean hasTime; + boolean hasContainer; + boolean hasCount; + boolean hasPreview; + boolean hasPage; + boolean validContainer; + boolean pageLookup; + } + + private ParamState getParamState(String[] args) { + ParamState state = new ParamState(); + + if (ConfigHandler.lookupType.get(args[0]) != null && ConfigHandler.lookupPage.get(args[0]) != null) { + state.pageLookup = true; + } + + for (int i = 1; i < args.length; i++) { + String arg = args[i].toLowerCase(Locale.ROOT); + if (arg.equals("#container")) { + state.hasContainer = true; + } + else if (arg.equals("#count") || arg.equals("#sum")) { + state.hasCount = true; + } + else if (arg.equals("#preview")) { + state.hasPreview = true; + } + else if ((!arg.contains(":") && !args[i - 1].contains(":") && args.length > (i + 1)) || arg.contains("u:") || arg.contains("user:") || arg.contains("users:") || arg.contains("p:")) { + state.hasUser = true; + } + else if (arg.contains("page:")) { + state.hasPage = true; + } + else if (arg.contains("a:") || arg.contains("action:")) { + state.hasAction = true; + } + else if (arg.contains("i:") || arg.contains("include:") || arg.contains("item:") || arg.contains("items:") || arg.contains("b:") || arg.contains("block:") || arg.contains("blocks:")) { + state.hasInclude = true; + } + else if (arg.contains("t:") || arg.contains("time:")) { + state.hasTime = true; + } + else if (arg.contains("e:") || arg.contains("exclude:")) { + state.hasExclude = true; + } + else if (arg.contains("r:") || arg.contains("radius:")) { + state.hasRadius = true; + } + } + + if (!state.hasContainer) { + if (ConfigHandler.lookupType.get(args[0]) != null) { + int lookupType = ConfigHandler.lookupType.get(args[0]); + if (lookupType == 1) { + state.validContainer = true; + } + else if (lookupType == 5) { + if (ConfigHandler.lookupUlist.get(args[0]).contains("#container")) { + state.validContainer = true; + } + } + } + } + + return state; + } + + private List handleActionParamCompletions(String currentArg, String lastArg) { + String arg = ""; + String filter = lastArg; + + if (currentArg.contains(":")) { + String[] split = currentArg.split(":", 2); + filter = split[0] + ":"; + if (split.length > 1) { + arg = split[1]; + } + } + + List completions = new ArrayList<>(Arrays.asList(ACTIONS)); + for (int index = 0; index < completions.size(); index++) { + completions.set(index, filter + completions.get(index)); + } + return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); + } + + private List handleUserParamCompletions(String currentArg, String lastArg) { + if (lastArg.equals("u:") || lastArg.equals("user:") || lastArg.equals("users:") || lastArg.equals("p:")) { + return null; + } + + String arg = ""; + String[] split = currentArg.split(":", 2); + String filter = split[0] + ":"; + if (split.length > 1) { + arg = split[1]; + } + + List completions = Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + + for (int index = 0; index < completions.size(); index++) { + completions.set(index, filter + completions.get(index)); + } + + return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); + } + + private List handleTimeParamCompletions(String currentArg, String lastArg) { + String filter = lastArg; + String arg = ""; + if (currentArg.contains(":")) { + String[] split = currentArg.split(":", 2); + filter = split[0] + ":"; + if (split.length > 1) { + arg = split[1]; + } + } + else { + filter = ""; + arg = currentArg; + } + + List completions = new ArrayList<>(); + if (arg.chars().allMatch(Character::isDigit)) { + boolean addNumbers = true; + if (currentArg.length() > 0) { + char lastChar = currentArg.charAt(currentArg.length() - 1); + if (Character.isDigit(lastChar)) { + completions.addAll(Arrays.asList(TIMES)); + addNumbers = false; + } + } + if (addNumbers) { + completions.addAll(Arrays.asList(NUMBERS)); + } + } + + completions = new ArrayList<>(completions); + for (int index = 0; index < completions.size(); index++) { + completions.set(index, filter + arg + completions.get(index)); + } + + return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); + } + + private List handlePageParamCompletions(String currentArg, String lastArg) { + String filter = lastArg; + String arg = ""; + if (currentArg.contains(":")) { + String[] split = currentArg.split(":", 2); + filter = split[0] + ":"; + if (split.length > 1) { + arg = split[1]; + } + } + else { + filter = ""; + arg = currentArg; + } + + if (arg.chars().allMatch(Character::isDigit)) { + List completions = new ArrayList<>(Arrays.asList(NUMBERS)); + if (arg.length() < 1) { + for (int index = 0; index < completions.size(); index++) { + completions.set(index, filter + arg + completions.get(index)); + } + if (arg.length() == 0) { + completions.remove(0); + } + } + return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); + } + + return null; + } + + private List handleRadiusParamCompletions(String currentArg, String lastArg, String baseCommand) { + String filter = lastArg; + String arg = ""; + if (currentArg.contains(":")) { + String[] split = currentArg.split(":", 2); + filter = split[0] + ":"; + if (split.length > 1) { + arg = split[1]; + } + } + else { + filter = ""; + arg = currentArg; + } + + if (!baseCommand.equals("purge") && arg.chars().allMatch(Character::isDigit)) { + List completions = new ArrayList<>(Arrays.asList(NUMBERS)); + if (arg.length() < 2) { + for (int index = 0; index < completions.size(); index++) { + completions.set(index, filter + arg + completions.get(index)); + } + } + return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); + } + else if (baseCommand.equals("purge") || arg.startsWith("#")) { + ArrayList params = new ArrayList<>(); + params.add("#global"); + if (!baseCommand.equals("purge") && Bukkit.getServer().getPluginManager().getPlugin("WorldEdit") != null) { + params.add("#worldedit"); + } + List worlds = Bukkit.getServer().getWorlds(); + for (World world : worlds) { + params.add("#" + world.getName()); + } + List completions = new ArrayList<>(params); + for (int index = 0; index < completions.size(); index++) { + completions.set(index, filter + completions.get(index)); + } + return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); + } + + return null; + } + + private List handleMaterialParamCompletions(String currentArg, String lastArg) { + String filter = lastArg; + String arg = ""; + if (currentArg.contains(":")) { + String[] split = currentArg.split(":", 2); + filter = split[0] + ":"; + if (split.length > 1) { + arg = split[1]; + } + } + else { + filter = ""; + arg = currentArg; + } + + initializeMaterialsIfNeeded(); + + List completions = new ArrayList<>(materials); + for (int index = 0; index < completions.size(); index++) { + completions.set(index, filter + completions.get(index)); + } + return StringUtil.copyPartialMatches(filter + arg, completions, new ArrayList<>(completions.size())); + } + + private void initializeMaterialsIfNeeded() { + if (materials == null) { + List addList = Arrays.asList(Material.ARMOR_STAND); + List excludeList = Arrays.asList(); + Set materialList = new HashSet<>(); + + Material[] materialValues = Material.values(); + for (Material material : materialValues) { + if (material.isBlock() || material.isItem()) { + materialList.add(material.name().toLowerCase(Locale.ROOT)); + } + } + for (Material exclude : excludeList) { + materialList.remove(exclude.name().toLowerCase(Locale.ROOT)); + } + for (Material add : addList) { + materialList.add(add.name().toLowerCase(Locale.ROOT)); + } + + // add custom tags + for (String tag : CommandParser.getTags().keySet()) { + materialList.add(tag); + } + + materials = new ArrayList<>(materialList); + } + } + + private List handleSecondArgCompletions(CommandSender sender, String cmd0, String cmd1, ParamState paramState) { + String argument0 = cmd0.toLowerCase(Locale.ROOT); + String argument1 = cmd1.toLowerCase(Locale.ROOT); + + if (argument0.equals("help") && sender.hasPermission("coreprotect.help")) { + List completions = new ArrayList<>(Arrays.asList(HELP)); + return StringUtil.copyPartialMatches(argument1, completions, new ArrayList<>(completions.size())); + } + else if (argument0.equals("purge") && sender.hasPermission("coreprotect.purge")) { + List completions = new ArrayList<>(Arrays.asList("t:", "r:", "i:")); + return StringUtil.copyPartialMatches(argument1, completions, new ArrayList<>(completions.size())); + } + else if (hasLookupCommand(argument0, sender)) { + List completions = new ArrayList<>(filterParams(true, argument0, argument1, paramState)); + completions.addAll(Bukkit.getOnlinePlayers().stream().filter(player -> player.getName().toLowerCase(Locale.ROOT).startsWith(argument1)).map(Player::getName).collect(Collectors.toList())); + return StringUtil.copyPartialMatches(argument1, completions, new ArrayList<>(completions.size())); + } + + return null; + } + + private List handlePurgeThirdArgCompletions(String arg1, String arg2) { + String argument1 = arg1.toLowerCase(Locale.ROOT); + String argument2 = arg2.toLowerCase(Locale.ROOT); + + if (argument1.startsWith("t:")) { + List completions = new ArrayList<>(Arrays.asList("r:", "i:")); + return StringUtil.copyPartialMatches(argument2, completions, new ArrayList<>(completions.size())); + } + else if (argument1.startsWith("r:") || argument1.startsWith("i:")) { + List completions = new ArrayList<>(Arrays.asList("t:")); + return StringUtil.copyPartialMatches(argument2, completions, new ArrayList<>(completions.size())); + } + return Arrays.asList(""); + } + + private List handleGenericLookupCompletions(String cmd, String currentArg, ParamState paramState) { + ArrayList params = filterParams(false, cmd, currentArg, paramState); + List completions = new ArrayList<>(params); + return StringUtil.copyPartialMatches(currentArg, completions, new ArrayList<>(completions.size())); + } + + private ArrayList filterParams(boolean firstParam, String lastArgument, String argument, ParamState state) { ArrayList params = new ArrayList<>(); for (String param : PARAMS) { - if (param.equals("user:") && !hasUser) { + if (param.equals("user:") && !state.hasUser) { params.add(param); } - else if (param.equals("action:") && !hasAction) { + else if (param.equals("action:") && !state.hasAction) { params.add(param); } - else if (param.equals("include:") && !hasInclude) { + else if (param.equals("include:") && !state.hasInclude) { params.add(param); } - else if (param.equals("exclude:") && !hasExclude) { + else if (param.equals("exclude:") && !state.hasExclude) { params.add(param); } - else if (param.equals("radius:") && !hasRadius) { + else if (param.equals("radius:") && !state.hasRadius) { params.add(param); } - else if (param.equals("time:") && !hasTime) { + else if (param.equals("time:") && !state.hasTime) { params.add(param); } - else if (param.equals("#container") && !hasContainer && !hasRadius && validContainer) { + else if (param.equals("#container") && !state.hasContainer && !state.hasRadius && state.validContainer) { params.add(param); } } - if (firstParam && pageLookup && (lastArgument.equals("l") || lastArgument.equals("lookup"))) { + if (firstParam && state.pageLookup && (lastArgument.equals("l") || lastArgument.equals("lookup"))) { params.add("page:"); } else if (!firstParam && argument.startsWith("#")) { - if (!hasCount) { + if (!state.hasCount) { params.add("#count"); } - if (!hasPreview) { + if (!state.hasPreview) { params.add("#preview"); } } diff --git a/src/main/java/net/coreprotect/database/Database.java b/src/main/java/net/coreprotect/database/Database.java index a694423..dcb3c36 100755 --- a/src/main/java/net/coreprotect/database/Database.java +++ b/src/main/java/net/coreprotect/database/Database.java @@ -8,8 +8,10 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import org.bukkit.Location; import org.bukkit.Material; @@ -44,6 +46,26 @@ public class Database extends Queue { public static final int BLOCKDATA = 12; public static final int ITEM = 13; + private static final Map SQL_QUERIES = new HashMap<>(); + + static { + // Initialize SQL queries for different table types + SQL_QUERIES.put(SIGN, "INSERT INTO %sprefix%sign (time, user, wid, x, y, z, action, color, color_secondary, data, waxed, face, line_1, line_2, line_3, line_4, line_5, line_6, line_7, line_8) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQL_QUERIES.put(BLOCK, "INSERT INTO %sprefix%block (time, user, wid, x, y, z, type, data, meta, blockdata, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQL_QUERIES.put(SKULL, "INSERT INTO %sprefix%skull (time, owner, skin) VALUES (?, ?, ?)"); + SQL_QUERIES.put(CONTAINER, "INSERT INTO %sprefix%container (time, user, wid, x, y, z, type, data, amount, metadata, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQL_QUERIES.put(ITEM, "INSERT INTO %sprefix%item (time, user, wid, x, y, z, type, data, amount, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQL_QUERIES.put(WORLD, "INSERT INTO %sprefix%world (id, world) VALUES (?, ?)"); + SQL_QUERIES.put(CHAT, "INSERT INTO %sprefix%chat (time, user, wid, x, y, z, message) VALUES (?, ?, ?, ?, ?, ?, ?)"); + SQL_QUERIES.put(COMMAND, "INSERT INTO %sprefix%command (time, user, wid, x, y, z, message) VALUES (?, ?, ?, ?, ?, ?, ?)"); + SQL_QUERIES.put(SESSION, "INSERT INTO %sprefix%session (time, user, wid, x, y, z, action) VALUES (?, ?, ?, ?, ?, ?, ?)"); + SQL_QUERIES.put(ENTITY, "INSERT INTO %sprefix%entity (time, data) VALUES (?, ?)"); + SQL_QUERIES.put(MATERIAL, "INSERT INTO %sprefix%material_map (id, material) VALUES (?, ?)"); + SQL_QUERIES.put(ART, "INSERT INTO %sprefix%art_map (id, art) VALUES (?, ?)"); + SQL_QUERIES.put(ENTITY_MAP, "INSERT INTO %sprefix%entity_map (id, entity) VALUES (?, ?)"); + SQL_QUERIES.put(BLOCKDATA, "INSERT INTO %sprefix%blockdata_map (id, data) VALUES (?, ?)"); + } + public static void beginTransaction(Statement statement, boolean isMySQL) { Consumer.transacting = true; @@ -133,8 +155,7 @@ public class Database extends Queue { } public static Connection getConnection(boolean onlyCheckTransacting) { - // Previously 250ms; long consumer commit time may be due to batching - // TODO: Investigate, potentially remove batching for SQLite connections + // Previously 250ms; long consumer commit time may be due to batching (investigate removing batching for SQLite connections) return getConnection(false, false, onlyCheckTransacting, 1000); } @@ -220,64 +241,10 @@ public class Database extends Queue { public static PreparedStatement prepareStatement(Connection connection, int type, boolean keys) { PreparedStatement preparedStatement = null; try { - String signInsert = "INSERT INTO " + ConfigHandler.prefix + "sign (time, user, wid, x, y, z, action, color, color_secondary, data, waxed, face, line_1, line_2, line_3, line_4, line_5, line_6, line_7, line_8) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - String blockInsert = "INSERT INTO " + ConfigHandler.prefix + "block (time, user, wid, x, y, z, type, data, meta, blockdata, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - String skullInsert = "INSERT INTO " + ConfigHandler.prefix + "skull (time, owner, skin) VALUES (?, ?, ?)"; - String containerInsert = "INSERT INTO " + ConfigHandler.prefix + "container (time, user, wid, x, y, z, type, data, amount, metadata, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - String itemInsert = "INSERT INTO " + ConfigHandler.prefix + "item (time, user, wid, x, y, z, type, data, amount, action, rolled_back) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; - String worldInsert = "INSERT INTO " + ConfigHandler.prefix + "world (id, world) VALUES (?, ?)"; - String chatInsert = "INSERT INTO " + ConfigHandler.prefix + "chat (time, user, wid, x, y, z, message) VALUES (?, ?, ?, ?, ?, ?, ?)"; - String commandInsert = "INSERT INTO " + ConfigHandler.prefix + "command (time, user, wid, x, y, z, message) VALUES (?, ?, ?, ?, ?, ?, ?)"; - String sessionInsert = "INSERT INTO " + ConfigHandler.prefix + "session (time, user, wid, x, y, z, action) VALUES (?, ?, ?, ?, ?, ?, ?)"; - String entityInsert = "INSERT INTO " + ConfigHandler.prefix + "entity (time, data) VALUES (?, ?)"; - String materialInsert = "INSERT INTO " + ConfigHandler.prefix + "material_map (id, material) VALUES (?, ?)"; - String artInsert = "INSERT INTO " + ConfigHandler.prefix + "art_map (id, art) VALUES (?, ?)"; - String entityMapInsert = "INSERT INTO " + ConfigHandler.prefix + "entity_map (id, entity) VALUES (?, ?)"; - String blockdataInsert = "INSERT INTO " + ConfigHandler.prefix + "blockdata_map (id, data) VALUES (?, ?)"; - - switch (type) { - case SIGN: - preparedStatement = prepareStatement(connection, signInsert, keys); - break; - case BLOCK: - preparedStatement = prepareStatement(connection, blockInsert, keys); - break; - case SKULL: - preparedStatement = prepareStatement(connection, skullInsert, keys); - break; - case CONTAINER: - preparedStatement = prepareStatement(connection, containerInsert, keys); - break; - case ITEM: - preparedStatement = prepareStatement(connection, itemInsert, keys); - break; - case WORLD: - preparedStatement = prepareStatement(connection, worldInsert, keys); - break; - case CHAT: - preparedStatement = prepareStatement(connection, chatInsert, keys); - break; - case COMMAND: - preparedStatement = prepareStatement(connection, commandInsert, keys); - break; - case SESSION: - preparedStatement = prepareStatement(connection, sessionInsert, keys); - break; - case ENTITY: - preparedStatement = prepareStatement(connection, entityInsert, keys); - break; - case MATERIAL: - preparedStatement = prepareStatement(connection, materialInsert, keys); - break; - case ART: - preparedStatement = prepareStatement(connection, artInsert, keys); - break; - case ENTITY_MAP: - preparedStatement = prepareStatement(connection, entityMapInsert, keys); - break; - case BLOCKDATA: - preparedStatement = prepareStatement(connection, blockdataInsert, keys); - break; + String query = SQL_QUERIES.get(type); + if (query != null) { + query = query.replace("%sprefix%", ConfigHandler.prefix); + preparedStatement = prepareStatement(connection, query, keys); } } catch (Exception e) { @@ -339,251 +306,259 @@ public class Database extends Queue { } } + private static final List DATABASE_TABLES = Arrays.asList("art_map", "block", "chat", "command", "container", "item", "database_lock", "entity", "entity_map", "material_map", "blockdata_map", "session", "sign", "skull", "user", "username_log", "version", "world"); + public static void createDatabaseTables(String prefix, Connection forceConnection, boolean mySQL, boolean purge) { ConfigHandler.databaseTables.clear(); - ConfigHandler.databaseTables.addAll(Arrays.asList("art_map", "block", "chat", "command", "container", "item", "database_lock", "entity", "entity_map", "material_map", "blockdata_map", "session", "sign", "skull", "user", "username_log", "version", "world")); + ConfigHandler.databaseTables.addAll(DATABASE_TABLES); if (mySQL) { - boolean success = false; - try (Connection connection = (forceConnection != null ? forceConnection : Database.getConnection(true, true, true, 0))) { - if (connection != null) { - String index = ""; - Statement statement = connection.createStatement(); - index = ", INDEX(id)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "art_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,art varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "block(rowid bigint NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data int, meta mediumblob, blockdata blob, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(time), INDEX(user,time), INDEX(wid,x,z,time)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "chat(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int (3), z int, message varchar(16000)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(time), INDEX(user,time), INDEX(wid,x,z,time)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "command(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int (3), z int, message varchar(16000)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data int, amount int, metadata blob, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data blob, amount int, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "database_lock(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),status tinyint,time int) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, data blob) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(id)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,entity varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(id)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "material_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,material varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(id)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "blockdata_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,data varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(wid,x,z,time), INDEX(action,time), INDEX(user,time), INDEX(time)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "session(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int (3), z int, action tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(time)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "sign(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int, z int, action tinyint, color int, color_secondary int, data tinyint, waxed tinyint, face tinyint, line_1 varchar(100), line_2 varchar(100), line_3 varchar(100), line_4 varchar(100), line_5 varchar(100), line_6 varchar(100), line_7 varchar(100), line_8 varchar(100)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "skull(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, owner varchar(255), skin varchar(255)) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(user), INDEX(uuid)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "user(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int,user varchar(100),uuid varchar(64)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(uuid,user)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "username_log(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int,uuid varchar(64),user varchar(100)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "version(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int,version varchar(16)) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - index = ", INDEX(id)"; - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "world(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,world varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); - if (!purge && forceConnection == null) { - initializeTables(prefix, statement); - } - statement.close(); - success = true; - } - } - catch (Exception e) { - e.printStackTrace(); - } - if (!success && forceConnection == null) { - Config.getGlobal().MYSQL = false; - } + createMySQLTables(prefix, forceConnection, purge); } - if (!mySQL) { - try (Connection connection = (forceConnection != null ? forceConnection : Database.getConnection(true, 0))) { + else { + createSQLiteTables(prefix, forceConnection, purge); + } + } + + private static void createMySQLTables(String prefix, Connection forceConnection, boolean purge) { + boolean success = false; + try (Connection connection = (forceConnection != null ? forceConnection : Database.getConnection(true, true, true, 0))) { + if (connection != null) { Statement statement = connection.createStatement(); - List tableData = new ArrayList<>(); - List indexData = new ArrayList<>(); - String attachDatabase = ""; - - if (purge && forceConnection == null) { - String query = "ATTACH DATABASE '" + ConfigHandler.path + ConfigHandler.sqlite + ".tmp' AS tmp_db"; - PreparedStatement preparedStmt = connection.prepareStatement(query); - preparedStmt.execute(); - preparedStmt.close(); - attachDatabase = "tmp_db."; - } - - String query = "SELECT type,name FROM " + attachDatabase + "sqlite_master WHERE type='table' OR type='index';"; - ResultSet rs = statement.executeQuery(query); - while (rs.next()) { - String type = rs.getString("type"); - if (type.equalsIgnoreCase("table")) { - tableData.add(rs.getString("name")); - } - else if (type.equalsIgnoreCase("index")) { - indexData.add(rs.getString("name")); - } - } - rs.close(); - - if (!tableData.contains(prefix + "art_map")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "art_map (id INTEGER, art TEXT);"); - } - if (!tableData.contains(prefix + "block")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "block (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data INTEGER, meta BLOB, blockdata BLOB, action INTEGER, rolled_back INTEGER);"); - } - if (!tableData.contains(prefix + "chat")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "chat (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, message TEXT);"); - } - if (!tableData.contains(prefix + "command")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "command (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, message TEXT);"); - } - if (!tableData.contains(prefix + "container")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data INTEGER, amount INTEGER, metadata BLOB, action INTEGER, rolled_back INTEGER);"); - } - if (!tableData.contains(prefix + "item")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data BLOB, amount INTEGER, action INTEGER, rolled_back INTEGER);"); - } - if (!tableData.contains(prefix + "database_lock")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "database_lock (status INTEGER, time INTEGER);"); - } - if (!tableData.contains(prefix + "entity")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity (id INTEGER PRIMARY KEY ASC, time INTEGER, data BLOB);"); - } - if (!tableData.contains(prefix + "entity_map")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity_map (id INTEGER, entity TEXT);"); - } - if (!tableData.contains(prefix + "material_map")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "material_map (id INTEGER, material TEXT);"); - } - if (!tableData.contains(prefix + "blockdata_map")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "blockdata_map (id INTEGER, data TEXT);"); - } - if (!tableData.contains(prefix + "session")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "session (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, action INTEGER);"); - } - if (!tableData.contains(prefix + "sign")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "sign (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, action INTEGER, color INTEGER, color_secondary INTEGER, data INTEGER, waxed INTEGER, face INTEGER, line_1 TEXT, line_2 TEXT, line_3 TEXT, line_4 TEXT, line_5 TEXT, line_6 TEXT, line_7 TEXT, line_8 TEXT);"); - } - if (!tableData.contains(prefix + "skull")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "skull (id INTEGER PRIMARY KEY ASC, time INTEGER, owner TEXT, skin TEXT);"); - } - if (!tableData.contains(prefix + "user")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "user (id INTEGER PRIMARY KEY ASC, time INTEGER, user TEXT, uuid TEXT);"); - } - if (!tableData.contains(prefix + "username_log")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "username_log (id INTEGER PRIMARY KEY ASC, time INTEGER, uuid TEXT, user TEXT);"); - } - if (!tableData.contains(prefix + "version")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "version (time INTEGER, version TEXT);"); - } - if (!tableData.contains(prefix + "world")) { - statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "world (id INTEGER, world TEXT);"); - } - try { - if (!indexData.contains("art_map_id_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "art_map_id_index ON " + ConfigHandler.prefix + "art_map(id);"); - } - if (!indexData.contains("block_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "block_index ON " + ConfigHandler.prefix + "block(wid,x,z,time);"); - } - if (!indexData.contains("block_user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "block_user_index ON " + ConfigHandler.prefix + "block(user,time);"); - } - if (!indexData.contains("block_type_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "block_type_index ON " + ConfigHandler.prefix + "block(type,time);"); - } - if (!indexData.contains("blockdata_map_id_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "blockdata_map_id_index ON " + ConfigHandler.prefix + "blockdata_map(id);"); - } - if (!indexData.contains("chat_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "chat_index ON " + ConfigHandler.prefix + "chat(time);"); - } - if (!indexData.contains("chat_user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "chat_user_index ON " + ConfigHandler.prefix + "chat(user,time);"); - } - if (!indexData.contains("chat_wid_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "chat_wid_index ON " + ConfigHandler.prefix + "chat(wid,x,z,time);"); - } - if (!indexData.contains("command_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "command_index ON " + ConfigHandler.prefix + "command(time);"); - } - if (!indexData.contains("command_user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "command_user_index ON " + ConfigHandler.prefix + "command(user,time);"); - } - if (!indexData.contains("command_wid_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "command_wid_index ON " + ConfigHandler.prefix + "command(wid,x,z,time);"); - } - if (!indexData.contains("container_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "container_index ON " + ConfigHandler.prefix + "container(wid,x,z,time);"); - } - if (!indexData.contains("container_user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "container_user_index ON " + ConfigHandler.prefix + "container(user,time);"); - } - if (!indexData.contains("container_type_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "container_type_index ON " + ConfigHandler.prefix + "container(type,time);"); - } - if (!indexData.contains("item_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "item_index ON " + ConfigHandler.prefix + "item(wid,x,z,time);"); - } - if (!indexData.contains("item_user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "item_user_index ON " + ConfigHandler.prefix + "item(user,time);"); - } - if (!indexData.contains("item_type_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "item_type_index ON " + ConfigHandler.prefix + "item(type,time);"); - } - if (!indexData.contains("entity_map_id_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "entity_map_id_index ON " + ConfigHandler.prefix + "entity_map(id);"); - } - if (!indexData.contains("material_map_id_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "material_map_id_index ON " + ConfigHandler.prefix + "material_map(id);"); - } - if (!indexData.contains("session_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "session_index ON " + ConfigHandler.prefix + "session(wid,x,z,time);"); - } - if (!indexData.contains("session_action_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "session_action_index ON " + ConfigHandler.prefix + "session(action,time);"); - } - if (!indexData.contains("session_user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "session_user_index ON " + ConfigHandler.prefix + "session(user,time);"); - } - if (!indexData.contains("session_time_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "session_time_index ON " + ConfigHandler.prefix + "session(time);"); - } - if (!indexData.contains("sign_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "sign_index ON " + ConfigHandler.prefix + "sign(wid,x,z,time);"); - } - if (!indexData.contains("sign_user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "sign_user_index ON " + ConfigHandler.prefix + "sign(user,time);"); - } - if (!indexData.contains("sign_time_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "sign_time_index ON " + ConfigHandler.prefix + "sign(time);"); - } - if (!indexData.contains("user_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "user_index ON " + ConfigHandler.prefix + "user(user);"); - } - if (!indexData.contains("uuid_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "uuid_index ON " + ConfigHandler.prefix + "user(uuid);"); - } - if (!indexData.contains("username_log_uuid_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "username_log_uuid_index ON " + ConfigHandler.prefix + "username_log(uuid,user);"); - } - if (!indexData.contains("world_id_index")) { - statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + "world_id_index ON " + ConfigHandler.prefix + "world(id);"); - } - } - catch (Exception e) { - Chat.console(Phrase.build(Phrase.DATABASE_INDEX_ERROR)); - if (purge) { - e.printStackTrace(); - } - } + createMySQLTableStructures(prefix, statement); if (!purge && forceConnection == null) { initializeTables(prefix, statement); } statement.close(); + success = true; } - catch (Exception e) { + } + catch (Exception e) { + e.printStackTrace(); + } + if (!success && forceConnection == null) { + Config.getGlobal().MYSQL = false; + } + } + + private static void createMySQLTableStructures(String prefix, Statement statement) throws SQLException { + String index = ""; + + // Art map + index = ", INDEX(id)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "art_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,art varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Block + index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "block(rowid bigint NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data int, meta mediumblob, blockdata blob, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Chat + index = ", INDEX(time), INDEX(user,time), INDEX(wid,x,z,time)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "chat(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int (3), z int, message varchar(16000)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Command + index = ", INDEX(time), INDEX(user,time), INDEX(wid,x,z,time)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "command(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int (3), z int, message varchar(16000)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Container + index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data int, amount int, metadata blob, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Item + index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data blob, amount int, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Database lock + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "database_lock(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),status tinyint,time int) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Entity + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, data blob) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Entity map + index = ", INDEX(id)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,entity varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Material map + index = ", INDEX(id)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "material_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,material varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Blockdata map + index = ", INDEX(id)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "blockdata_map(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,data varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Session + index = ", INDEX(wid,x,z,time), INDEX(action,time), INDEX(user,time), INDEX(time)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "session(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int (3), z int, action tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Sign + index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(time)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "sign(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int, z int, action tinyint, color int, color_secondary int, data tinyint, waxed tinyint, face tinyint, line_1 varchar(100), line_2 varchar(100), line_3 varchar(100), line_4 varchar(100), line_5 varchar(100), line_6 varchar(100), line_7 varchar(100), line_8 varchar(100)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Skull + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "skull(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, owner varchar(255), skin varchar(255)) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // User + index = ", INDEX(user), INDEX(uuid)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "user(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int,user varchar(100),uuid varchar(64)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Username log + index = ", INDEX(uuid,user)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "username_log(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int,uuid varchar(64),user varchar(100)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // Version + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "version(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int,version varchar(16)) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + + // World + index = ", INDEX(id)"; + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "world(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,world varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4"); + } + + private static void createSQLiteTables(String prefix, Connection forceConnection, boolean purge) { + try (Connection connection = (forceConnection != null ? forceConnection : Database.getConnection(true, 0))) { + Statement statement = connection.createStatement(); + List tableData = new ArrayList<>(); + List indexData = new ArrayList<>(); + String attachDatabase = ""; + + if (purge && forceConnection == null) { + String query = "ATTACH DATABASE '" + ConfigHandler.path + ConfigHandler.sqlite + ".tmp' AS tmp_db"; + PreparedStatement preparedStmt = connection.prepareStatement(query); + preparedStmt.execute(); + preparedStmt.close(); + attachDatabase = "tmp_db."; + } + + identifyExistingTablesAndIndexes(statement, attachDatabase, tableData, indexData); + createSQLiteTableStructures(prefix, statement, tableData); + createSQLiteIndexes(prefix, statement, indexData, attachDatabase, purge); + + if (!purge && forceConnection == null) { + initializeTables(prefix, statement); + } + statement.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private static void identifyExistingTablesAndIndexes(Statement statement, String attachDatabase, List tableData, List indexData) throws SQLException { + String query = "SELECT type,name FROM " + attachDatabase + "sqlite_master WHERE type='table' OR type='index';"; + ResultSet rs = statement.executeQuery(query); + while (rs.next()) { + String type = rs.getString("type"); + if (type.equalsIgnoreCase("table")) { + tableData.add(rs.getString("name")); + } + else if (type.equalsIgnoreCase("index")) { + indexData.add(rs.getString("name")); + } + } + rs.close(); + } + + private static void createSQLiteTableStructures(String prefix, Statement statement, List tableData) throws SQLException { + if (!tableData.contains(prefix + "art_map")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "art_map (id INTEGER, art TEXT);"); + } + if (!tableData.contains(prefix + "block")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "block (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data INTEGER, meta BLOB, blockdata BLOB, action INTEGER, rolled_back INTEGER);"); + } + if (!tableData.contains(prefix + "chat")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "chat (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, message TEXT);"); + } + if (!tableData.contains(prefix + "command")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "command (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, message TEXT);"); + } + if (!tableData.contains(prefix + "container")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data INTEGER, amount INTEGER, metadata BLOB, action INTEGER, rolled_back INTEGER);"); + } + if (!tableData.contains(prefix + "item")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, type INTEGER, data BLOB, amount INTEGER, action INTEGER, rolled_back INTEGER);"); + } + if (!tableData.contains(prefix + "database_lock")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "database_lock (status INTEGER, time INTEGER);"); + } + if (!tableData.contains(prefix + "entity")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity (id INTEGER PRIMARY KEY ASC, time INTEGER, data BLOB);"); + } + if (!tableData.contains(prefix + "entity_map")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "entity_map (id INTEGER, entity TEXT);"); + } + if (!tableData.contains(prefix + "material_map")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "material_map (id INTEGER, material TEXT);"); + } + if (!tableData.contains(prefix + "blockdata_map")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "blockdata_map (id INTEGER, data TEXT);"); + } + if (!tableData.contains(prefix + "session")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "session (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, action INTEGER);"); + } + if (!tableData.contains(prefix + "sign")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "sign (time INTEGER, user INTEGER, wid INTEGER, x INTEGER, y INTEGER, z INTEGER, action INTEGER, color INTEGER, color_secondary INTEGER, data INTEGER, waxed INTEGER, face INTEGER, line_1 TEXT, line_2 TEXT, line_3 TEXT, line_4 TEXT, line_5 TEXT, line_6 TEXT, line_7 TEXT, line_8 TEXT);"); + } + if (!tableData.contains(prefix + "skull")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "skull (id INTEGER PRIMARY KEY ASC, time INTEGER, owner TEXT, skin TEXT);"); + } + if (!tableData.contains(prefix + "user")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "user (id INTEGER PRIMARY KEY ASC, time INTEGER, user TEXT, uuid TEXT);"); + } + if (!tableData.contains(prefix + "username_log")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "username_log (id INTEGER PRIMARY KEY ASC, time INTEGER, uuid TEXT, user TEXT);"); + } + if (!tableData.contains(prefix + "version")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "version (time INTEGER, version TEXT);"); + } + if (!tableData.contains(prefix + "world")) { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "world (id INTEGER, world TEXT);"); + } + } + + private static void createSQLiteIndexes(String prefix, Statement statement, List indexData, String attachDatabase, boolean purge) { + try { + createSQLiteIndex(statement, indexData, attachDatabase, "art_map_id_index", prefix + "art_map(id)"); + createSQLiteIndex(statement, indexData, attachDatabase, "block_index", prefix + "block(wid,x,z,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "block_user_index", prefix + "block(user,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "block_type_index", prefix + "block(type,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "blockdata_map_id_index", prefix + "blockdata_map(id)"); + createSQLiteIndex(statement, indexData, attachDatabase, "chat_index", prefix + "chat(time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "chat_user_index", prefix + "chat(user,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "chat_wid_index", prefix + "chat(wid,x,z,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "command_index", prefix + "command(time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "command_user_index", prefix + "command(user,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "command_wid_index", prefix + "command(wid,x,z,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "container_index", prefix + "container(wid,x,z,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "container_user_index", prefix + "container(user,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "container_type_index", prefix + "container(type,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "item_index", prefix + "item(wid,x,z,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "item_user_index", prefix + "item(user,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "item_type_index", prefix + "item(type,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "entity_map_id_index", prefix + "entity_map(id)"); + createSQLiteIndex(statement, indexData, attachDatabase, "material_map_id_index", prefix + "material_map(id)"); + createSQLiteIndex(statement, indexData, attachDatabase, "session_index", prefix + "session(wid,x,z,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "session_action_index", prefix + "session(action,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "session_user_index", prefix + "session(user,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "session_time_index", prefix + "session(time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "sign_index", prefix + "sign(wid,x,z,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "sign_user_index", prefix + "sign(user,time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "sign_time_index", prefix + "sign(time)"); + createSQLiteIndex(statement, indexData, attachDatabase, "user_index", prefix + "user(user)"); + createSQLiteIndex(statement, indexData, attachDatabase, "uuid_index", prefix + "user(uuid)"); + createSQLiteIndex(statement, indexData, attachDatabase, "username_log_uuid_index", prefix + "username_log(uuid,user)"); + createSQLiteIndex(statement, indexData, attachDatabase, "world_id_index", prefix + "world(id)"); + } + catch (Exception e) { + Chat.console(Phrase.build(Phrase.DATABASE_INDEX_ERROR)); + if (purge) { e.printStackTrace(); } } } + private static void createSQLiteIndex(Statement statement, List indexData, String attachDatabase, String indexName, String indexColumns) throws SQLException { + if (!indexData.contains(indexName)) { + statement.executeUpdate("CREATE INDEX IF NOT EXISTS " + attachDatabase + indexName + " ON " + indexColumns + ";"); + } + } + } diff --git a/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java b/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java index 86c1a3d..89007f1 100644 --- a/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java +++ b/src/main/java/net/coreprotect/worldedit/WorldEditBlockState.java @@ -34,37 +34,31 @@ public final class WorldEditBlockState implements BlockState { @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { - // TODO Auto-generated method stub } @Override public List getMetadata(String metadataKey) { - // TODO Auto-generated method stub return null; } @Override public boolean hasMetadata(String metadataKey) { - // TODO Auto-generated method stub return false; } @Override public void removeMetadata(String metadataKey, Plugin owningPlugin) { - // TODO Auto-generated method stub } @Override public Block getBlock() { - // TODO Auto-generated method stub return null; } @Override public MaterialData getData() { - // TODO Auto-generated method stub return null; } @@ -80,7 +74,6 @@ public final class WorldEditBlockState implements BlockState { @Override public byte getLightLevel() { - // TODO Auto-generated method stub return 0; } @@ -125,13 +118,11 @@ public final class WorldEditBlockState implements BlockState { @Override public Chunk getChunk() { - // TODO Auto-generated method stub return null; } @Override public void setData(MaterialData data) { - // TODO Auto-generated method stub } @@ -147,73 +138,61 @@ public final class WorldEditBlockState implements BlockState { @Override public boolean update() { - // TODO Auto-generated method stub return false; } @Override public boolean update(boolean force) { - // TODO Auto-generated method stub return false; } @Override public boolean update(boolean force, boolean applyPhysics) { - // TODO Auto-generated method stub return false; } @Override public byte getRawData() { - // TODO Auto-generated method stub return 0; } @Override public void setRawData(byte data) { - // TODO Auto-generated method stub } @Override public boolean isPlaced() { - // TODO Auto-generated method stub return false; } @Override public boolean isCollidable() { - // TODO Auto-generated method stub return false; } @Override public Collection getDrops() { - // TODO Auto-generated method stub return null; } @Override public Collection getDrops(ItemStack tool) { - // TODO Auto-generated method stub return null; } @Override public Collection getDrops(ItemStack tool, Entity entity) { - // TODO Auto-generated method stub return null; } @Override public BlockState copy() { - // TODO Auto-generated method stub return null; } @Override public BlockState copy(Location location) { - // TODO Auto-generated method stub return null; }