diff --git a/src/main/java/net/knarcraft/stargate/Stargate.java b/src/main/java/net/knarcraft/stargate/Stargate.java index b8f9dd9..2bc73e3 100644 --- a/src/main/java/net/knarcraft/stargate/Stargate.java +++ b/src/main/java/net/knarcraft/stargate/Stargate.java @@ -22,6 +22,7 @@ import net.knarcraft.stargate.thread.ChunkUnloadThread; import net.knarcraft.stargate.thread.StarGateThread; import net.knarcraft.stargate.utility.EconomyHandler; import net.knarcraft.stargate.utility.FileHelper; +import net.knarcraft.stargate.utility.PortalFileHelper; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Server; @@ -532,7 +533,7 @@ public class Stargate extends JavaPlugin { public void loadAllPortals() { for (World world : getServer().getWorlds()) { if (!managedWorlds.contains(world.getName())) { - PortalHandler.loadAllPortals(world); + PortalFileHelper.loadAllPortals(world); managedWorlds.add(world.getName()); } } diff --git a/src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java b/src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java index 0fa3ed9..6ee5ba8 100644 --- a/src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/WorldEventListener.java @@ -1,8 +1,8 @@ package net.knarcraft.stargate.listener; import net.knarcraft.stargate.Stargate; -import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.portal.PortalRegistry; +import net.knarcraft.stargate.utility.PortalFileHelper; import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -23,7 +23,7 @@ public class WorldEventListener implements Listener { @EventHandler public void onWorldLoad(WorldLoadEvent event) { if (!Stargate.managedWorlds.contains(event.getWorld().getName()) && - PortalHandler.loadAllPortals(event.getWorld())) { + PortalFileHelper.loadAllPortals(event.getWorld())) { Stargate.managedWorlds.add(event.getWorld().getName()); } } diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java b/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java index 8f90732..b044a37 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalCreator.java @@ -8,6 +8,7 @@ import net.knarcraft.stargate.utility.DirectionHelper; import net.knarcraft.stargate.utility.EconomyHandler; import net.knarcraft.stargate.utility.EconomyHelper; import net.knarcraft.stargate.utility.PermissionHelper; +import net.knarcraft.stargate.utility.PortalFileHelper; import org.bukkit.Bukkit; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -209,7 +210,7 @@ public class PortalCreator { PortalHandler.updatePortalsPointingAtNewPortal(portal); } - PortalHandler.saveAllPortals(portal.getWorld()); + PortalFileHelper.saveAllPortals(portal.getWorld()); return portal; } diff --git a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java index f4a9708..80cb5f4 100644 --- a/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java +++ b/src/main/java/net/knarcraft/stargate/portal/PortalHandler.java @@ -5,25 +5,15 @@ import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.container.RelativeBlockVector; import net.knarcraft.stargate.container.TwoTuple; import net.knarcraft.stargate.utility.PermissionHelper; -import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.OfflinePlayer; -import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.block.Sign; import org.bukkit.entity.Player; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Scanner; -import java.util.UUID; -import java.util.logging.Level; /** * Keeps track of all loaded portals, and handles portal creation @@ -126,7 +116,7 @@ public class PortalHandler { * * @param portal
The portal to register
*/ - static void registerPortal(Portal portal) { + public static void registerPortal(Portal portal) { PortalRegistry.registerPortal(portal); } @@ -391,198 +381,13 @@ public class PortalHandler { return PortalRegistry.getBungeePortals().get(name.toLowerCase()); } - /** - * Saves all portals for the given world - * - * @param worldThe world to save portals for
- */ - public static void saveAllPortals(World world) { - Stargate.managedWorlds.add(world.getName()); - String loc = Stargate.getSaveLocation() + "/" + world.getName() + ".db"; - - try { - BufferedWriter bw = new BufferedWriter(new FileWriter(loc, false)); - - for (Portal portal : PortalRegistry.getAllPortals()) { - String wName = portal.getWorld().getName(); - if (!wName.equalsIgnoreCase(world.getName())) continue; - StringBuilder builder = new StringBuilder(); - BlockLocation button = portal.getStructure().getButton(); - - builder.append(portal.getName()).append(':'); - builder.append(portal.getSignLocation().toString()).append(':'); - builder.append((button != null) ? button.toString() : "").append(':'); - builder.append(0).append(':'); - builder.append(0).append(':'); - builder.append(portal.getYaw()).append(':'); - builder.append(portal.getTopLeft().toString()).append(':'); - builder.append(portal.getGate().getFilename()).append(':'); - builder.append(portal.getOptions().isFixed() ? portal.getDestinationName() : "").append(':'); - builder.append(portal.getNetwork()).append(':'); - UUID owner = portal.getOwnerUUID(); - if (owner != null) { - builder.append(portal.getOwnerUUID().toString()); - } else { - builder.append(portal.getOwnerName()); - } - builder.append(':'); - builder.append(portal.getOptions().isHidden()).append(':'); - builder.append(portal.getOptions().isAlwaysOn()).append(':'); - builder.append(portal.getOptions().isPrivate()).append(':'); - builder.append(portal.getWorld().getName()).append(':'); - builder.append(portal.getOptions().isFree()).append(':'); - builder.append(portal.getOptions().isBackwards()).append(':'); - builder.append(portal.getOptions().isShown()).append(':'); - builder.append(portal.getOptions().isNoNetwork()).append(':'); - builder.append(portal.getOptions().isRandom()).append(':'); - builder.append(portal.getOptions().isBungee()); - - bw.append(builder.toString()); - bw.newLine(); - } - - bw.close(); - } catch (Exception e) { - Stargate.logger.log(Level.SEVERE, "Exception while writing stargates to " + loc + ": " + e); - } - } - - /** - * Loads all portals for the given world - * - * @param worldThe world to load portals for
- * @returnTrue if portals could be loaded
- */ - public static boolean loadAllPortals(World world) { - String location = Stargate.getSaveLocation(); - - File database = new File(location, world.getName() + ".db"); - - if (database.exists()) { - return loadPortals(world, database); - } else { - Stargate.logger.info(Stargate.getString("prefix") + "{" + world.getName() + "} No stargates for world "); - } - return false; - } - - /** - * Loads all the given portals - * - * @param worldThe world to load portals for
- * @param databaseThe database file containing the portals
- * @returnTrue if the portals were loaded successfully
- */ - private static boolean loadPortals(World world, File database) { - int lineIndex = 0; - try { - Scanner scanner = new Scanner(database); - while (scanner.hasNextLine()) { - lineIndex++; - String line = scanner.nextLine().trim(); - - //Ignore empty and comment lines - if (line.startsWith("#") || line.isEmpty()) { - continue; - } - - //Check if the min. required portal data is present - String[] portalData = line.split(":"); - if (portalData.length < 8) { - Stargate.logger.info(Stargate.getString("prefix") + "Invalid line - " + lineIndex); - continue; - } - - loadPortal(portalData, world, lineIndex); - } - scanner.close(); - - // Open any always-on gates. Do this here as it should be more efficient than in the loop. - TwoTupleThe array describing the portal
- * @param worldThe world to create the portal in
- * @param lineIndexThe line index to report in case the user needs to fix an error
- */ - private static void loadPortal(String[] portalData, World world, int lineIndex) { - //Load min. required portal data - String name = portalData[0]; - PortalLocation portalLocation = new PortalLocation(); - portalLocation.setSignLocation(new BlockLocation(world, portalData[1])); - BlockLocation button = (portalData[2].length() > 0) ? new BlockLocation(world, portalData[2]) : null; - portalLocation.setYaw(Float.parseFloat(portalData[5])); - portalLocation.setTopLeft(new BlockLocation(world, portalData[6])); - Gate gate = GateHandler.getGateByName(portalData[7]); - if (gate == null) { - //Mark the sign as invalid to reduce some player confusion - Sign sign = (Sign) portalLocation.getSignLocation().getBlock().getState(); - Stargate.setLine(sign, 3, Stargate.getString("signInvalidGate")); - sign.update(); - - Stargate.logger.info(Stargate.getString("prefix") + "Gate layout on line " + lineIndex + - " does not exist [" + portalData[7] + "]"); - return; - } - - //Load extra portal data - String destination = (portalData.length > 8) ? portalData[8] : ""; - String network = (portalData.length > 9) ? portalData[9] : Stargate.getDefaultNetwork(); - if (network.isEmpty()) { - network = Stargate.getDefaultNetwork(); - } - String ownerString = (portalData.length > 10) ? portalData[10] : ""; - - // Attempt to get owner as UUID - UUID ownerUUID = null; - String ownerName; - if (ownerString.length() > 16) { - try { - ownerUUID = UUID.fromString(ownerString); - OfflinePlayer offlineOwner = Bukkit.getServer().getOfflinePlayer(ownerUUID); - ownerName = offlineOwner.getName(); - } catch (IllegalArgumentException ex) { - // neither name nor UUID, so keep it as-is - ownerName = ownerString; - Stargate.debug("loadAllPortals", "Invalid stargate owner string: " + ownerString); - } - } else { - ownerName = ownerString; - } - - //Creates the new portal - Portal portal = new Portal(portalLocation, button, destination, name, - network, gate, ownerUUID, ownerName, getPortalOptions(portalData)); - - registerPortal(portal); - portal.getPortalOpener().closePortal(true); - } - /** * Gets all portal options stored in the portal data * * @param portalDataThe string list containing all information about a portal
* @returnA map between portal options and booleans
*/ - private static MapA TwoTuple where the first value is the number of always open portals and the second value is the total number of portals
*/ - private static TwoTupleThe world to save portals for
+ */ + public static void saveAllPortals(World world) { + Stargate.managedWorlds.add(world.getName()); + String saveFileLocation = Stargate.getSaveLocation() + "/" + world.getName() + ".db"; + + try { + BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(saveFileLocation, false)); + + for (Portal portal : PortalRegistry.getAllPortals()) { + //Skip portals in other worlds + String worldName = portal.getWorld().getName(); + if (!worldName.equalsIgnoreCase(world.getName())) { + continue; + } + //Save the portal + savePortal(bufferedWriter, portal); + } + + bufferedWriter.close(); + } catch (Exception e) { + Stargate.logger.log(Level.SEVERE, "Exception while writing stargates to " + saveFileLocation + ": " + e); + } + } + + /** + * Saves one portal + * + * @param bufferedWriterThe buffered writer to write to
+ * @param portalThe portal to save
+ * @throws IOExceptionIf unable to write to the buffered writer
+ */ + private static void savePortal(BufferedWriter bufferedWriter, Portal portal) throws IOException { + StringBuilder builder = new StringBuilder(); + BlockLocation button = portal.getStructure().getButton(); + + //WARNING: Because of the primitive save format, any change in order will break everything! + builder.append(portal.getName()).append(':'); + builder.append(portal.getSignLocation().toString()).append(':'); + builder.append((button != null) ? button.toString() : "").append(':'); + + //Add removes config values to keep indices consistent + builder.append(0).append(':'); + builder.append(0).append(':'); + + builder.append(portal.getYaw()).append(':'); + builder.append(portal.getTopLeft().toString()).append(':'); + builder.append(portal.getGate().getFilename()).append(':'); + + //Only save the destination name if the gate is fixed as it doesn't matter otherwise + builder.append(portal.getOptions().isFixed() ? portal.getDestinationName() : "").append(':'); + + builder.append(portal.getNetwork()).append(':'); + + //Name is saved as a fallback if the UUID is unavailable + UUID owner = portal.getOwnerUUID(); + if (owner != null) { + builder.append(portal.getOwnerUUID().toString()); + } else { + builder.append(portal.getOwnerName()); + } + + //Save all the portal options + savePortalOptions(portal, builder); + + bufferedWriter.append(builder.toString()); + bufferedWriter.newLine(); + } + + /** + * Saves all portal options for the given portal + * + * @param portalThe portal to save
+ * @param builderThe string builder to append to
+ */ + private static void savePortalOptions(Portal portal, StringBuilder builder) { + PortalOptions options = portal.getOptions(); + builder.append(':'); + builder.append(options.isHidden()).append(':'); + builder.append(options.isAlwaysOn()).append(':'); + builder.append(options.isPrivate()).append(':'); + builder.append(portal.getWorld().getName()).append(':'); + builder.append(options.isFree()).append(':'); + builder.append(options.isBackwards()).append(':'); + builder.append(options.isShown()).append(':'); + builder.append(options.isNoNetwork()).append(':'); + builder.append(options.isRandom()).append(':'); + builder.append(options.isBungee()); + } + + /** + * Loads all portals for the given world + * + * @param worldThe world to load portals for
+ * @returnTrue if portals could be loaded
+ */ + public static boolean loadAllPortals(World world) { + String location = Stargate.getSaveLocation(); + + File database = new File(location, world.getName() + ".db"); + + if (database.exists()) { + return loadPortals(world, database); + } else { + Stargate.logger.info(Stargate.getString("prefix") + "{" + world.getName() + + "} No stargates for world "); + } + return false; + } + + /** + * Loads all the given portals + * + * @param worldThe world to load portals for
+ * @param databaseThe database file containing the portals
+ * @returnTrue if the portals were loaded successfully
+ */ + private static boolean loadPortals(World world, File database) { + int lineIndex = 0; + try { + Scanner scanner = new Scanner(database); + while (scanner.hasNextLine()) { + //Read the line and do whatever needs to be done + readPortalLine(scanner, ++lineIndex, world); + } + scanner.close(); + + //Do necessary tasks after all portals have loaded + doPostLoadTasks(world); + return true; + } catch (Exception e) { + Stargate.logger.log(Level.SEVERE, "Exception while reading stargates from " + database.getName() + + ": " + lineIndex); + e.printStackTrace(); + } + return false; + } + + /** + * Reads one file line containing information about one portal + * + * @param scannerThe scanner to read
+ * @param lineIndexThe index of the read line
+ * @param worldThe world for which portals are currently being read
+ */ + private static void readPortalLine(Scanner scanner, int lineIndex, World world) { + String line = scanner.nextLine().trim(); + + //Ignore empty and comment lines + if (line.startsWith("#") || line.isEmpty()) { + return; + } + + //Check if the min. required portal data is present + String[] portalData = line.split(":"); + if (portalData.length < 8) { + Stargate.logger.info(Stargate.getString("prefix") + "Invalid line - " + lineIndex); + return; + } + + //Load the portal defined in the current line + loadPortal(portalData, world, lineIndex); + } + + /** + * Performs tasks which must be run after portals have loaded + * + *This will open always on portals, print info about loaded stargates and re-draw portal signs for loaded + * portals.
+ * + * @param worldThe world portals have been loaded for
+ */ + private static void doPostLoadTasks(World world) { + //Open any always-on portals. Do this here as it should be more efficient than in the loop. + TwoTupleThe array describing the portal
+ * @param worldThe world to create the portal in
+ * @param lineIndexThe line index to report in case the user needs to fix an error
+ */ + private static void loadPortal(String[] portalData, World world, int lineIndex) { + //Load min. required portal data + String name = portalData[0]; + BlockLocation button = (portalData[2].length() > 0) ? new BlockLocation(world, portalData[2]) : null; + + //Load the portal's location + PortalLocation portalLocation = new PortalLocation(); + portalLocation.setSignLocation(new BlockLocation(world, portalData[1])); + portalLocation.setYaw(Float.parseFloat(portalData[5])); + portalLocation.setTopLeft(new BlockLocation(world, portalData[6])); + + //Check if the portal's gate type exists and is loaded + Gate gate = GateHandler.getGateByName(portalData[7]); + if (gate == null) { + //Mark the sign as invalid to reduce some player confusion + markPortalWithInvalidGate(portalLocation, portalData[7], lineIndex); + return; + } + + //Load extra portal data + String destination = (portalData.length > 8) ? portalData[8] : ""; + String network = (portalData.length > 9 && !portalData[9].isEmpty()) ? portalData[9] : Stargate.getDefaultNetwork(); + String ownerString = (portalData.length > 10) ? portalData[10] : ""; + + //Try to get owner as UUID + TwoTupleThe saved owner string. Should be a UUID, or a player name if legacy
+ * @returnA two-tuple containing the UUID and owner name. The UUID might be null if the ownerString was not a UUID
+ */ + private static TwoTupleThe location of the portal with an invalid gate
+ * @param gateNameThe name of the invalid gate type
+ * @param lineIndexThe index of the line the invalid portal was found at
+ */ + private static void markPortalWithInvalidGate(PortalLocation portalLocation, String gateName, int lineIndex) { + Sign sign = (Sign) portalLocation.getSignLocation().getBlock().getState(); + Stargate.setLine(sign, 3, Stargate.getString("signInvalidGate")); + sign.update(); + + Stargate.logger.info(Stargate.getString("prefix") + "Gate layout on line " + lineIndex + + " does not exist [" + gateName + "]"); + } + +}