From 7310506ed48db68a61ac50b3edbf92c67b853192 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sun, 22 Mar 2020 19:23:35 +0000 Subject: [PATCH] Add option to have road regeneration be persistent across restarts. (#2715) * Add option to have road regeneration be persistent across restarts. * Use int[] not Integer[]. There's the possibility of large arrays given the size of some worlds. * Correctly close Input/Output streams with try-with-resource. Also don't try to ObjectOutputStream if an existing file hasn't actually been deleted. --- .../plotsquared/plot/PlotSquared.java | 134 +++++++++++------- .../plotsquared/plot/commands/DebugExec.java | 8 +- .../plotsquared/plot/config/Settings.java | 2 + .../plot/generator/HybridUtils.java | 12 +- 4 files changed, 96 insertions(+), 60 deletions(-) diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java index a66f6edaa..21d9e1c8f 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/PlotSquared.java @@ -22,74 +22,32 @@ import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils; import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator; import com.github.intellectualsites.plotsquared.plot.listener.WESubscriber; import com.github.intellectualsites.plotsquared.plot.logger.ILogger; -import com.github.intellectualsites.plotsquared.plot.object.BlockBucket; -import com.github.intellectualsites.plotsquared.plot.object.ConsolePlayer; -import com.github.intellectualsites.plotsquared.plot.object.Location; -import com.github.intellectualsites.plotsquared.plot.object.Plot; -import com.github.intellectualsites.plotsquared.plot.object.PlotArea; -import com.github.intellectualsites.plotsquared.plot.object.PlotCluster; -import com.github.intellectualsites.plotsquared.plot.object.PlotFilter; -import com.github.intellectualsites.plotsquared.plot.object.PlotId; -import com.github.intellectualsites.plotsquared.plot.object.PlotManager; -import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; -import com.github.intellectualsites.plotsquared.plot.object.StringWrapper; +import com.github.intellectualsites.plotsquared.plot.object.*; import com.github.intellectualsites.plotsquared.plot.object.worlds.DefaultPlotAreaManager; import com.github.intellectualsites.plotsquared.plot.object.worlds.PlotAreaManager; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager; -import com.github.intellectualsites.plotsquared.plot.util.ChatManager; -import com.github.intellectualsites.plotsquared.plot.util.ChunkManager; -import com.github.intellectualsites.plotsquared.plot.util.CommentManager; -import com.github.intellectualsites.plotsquared.plot.util.EconHandler; -import com.github.intellectualsites.plotsquared.plot.util.EventDispatcher; -import com.github.intellectualsites.plotsquared.plot.util.InventoryUtil; -import com.github.intellectualsites.plotsquared.plot.util.LegacyConverter; -import com.github.intellectualsites.plotsquared.plot.util.MainUtil; -import com.github.intellectualsites.plotsquared.plot.util.MathMan; -import com.github.intellectualsites.plotsquared.plot.util.ReflectionUtils; -import com.github.intellectualsites.plotsquared.plot.util.SchematicHandler; -import com.github.intellectualsites.plotsquared.plot.util.SetupUtils; -import com.github.intellectualsites.plotsquared.plot.util.StringMan; -import com.github.intellectualsites.plotsquared.plot.util.TaskManager; -import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler; -import com.github.intellectualsites.plotsquared.plot.util.WorldUtil; +import com.github.intellectualsites.plotsquared.plot.util.*; import com.github.intellectualsites.plotsquared.plot.util.block.GlobalBlockQueue; import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpireManager; import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpiryTask; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; import lombok.Getter; import lombok.NonNull; import lombok.Setter; import org.jetbrains.annotations.Nullable; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; import java.sql.SQLException; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; import java.util.function.Consumer; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -506,6 +464,43 @@ import java.util.zip.ZipInputStream; } plotAreaManager.addPlotArea(plotArea); plotArea.setupBorder(); + if (!Settings.Enabled_Components.PERSISTENT_ROAD_REGEN) { + return; + } + File file = new File( + this.IMP.getDirectory() + File.separator + "persistent_regen_data_" + plotArea.id + "_" + + plotArea.worldname); + if (!file.exists()) { + return; + } + TaskManager.runTask(() -> { + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { + List list = (List) ois.readObject(); + ArrayList regionInts = (ArrayList) list.get(0); + ArrayList chunkInts = (ArrayList) list.get(1); + HashSet regions = new HashSet<>(); + Set chunks = new HashSet<>(); + regionInts.forEach(l -> regions.add(BlockVector2.at(l[0], l[1]))); + chunkInts.forEach(l -> chunks.add(BlockVector2.at(l[0], l[1]))); + int height = (int) list.get(2); + PlotSquared.log( + Captions.PREFIX + "Incomplete road regeneration found. Restarting in world " + + plotArea.worldname + " with height " + height + "."); + PlotSquared.debug(" Regions: " + regions.size()); + PlotSquared.debug(" Chunks: " + chunks.size()); + HybridUtils.UPDATE = true; + HybridUtils.manager.scheduleRoadUpdate(plotArea, regions, height, chunks); + } catch (IOException | ClassNotFoundException e) { + PlotSquared.log(Captions.PREFIX + "Error restarting road regeneration."); + e.printStackTrace(); + } finally { + if (!file.delete()) { + PlotSquared.log( + Captions.PREFIX + "Error deleting persistent_regen_data_" + plotArea.id + + ". Please manually delete this file."); + } + } + }); } /** @@ -1525,6 +1520,7 @@ import java.util.zip.ZipInputStream; public void disable() { try { eventDispatcher.unregisterAll(); + checkRoadRegenPersistence(); // Validate that all data in the db is correct final HashSet plots = new HashSet<>(); try { @@ -1542,6 +1538,46 @@ import java.util.zip.ZipInputStream; } } + /** + * Handle road regen persistence + */ + private void checkRoadRegenPersistence() { + if (!HybridUtils.UPDATE || !Settings.Enabled_Components.PERSISTENT_ROAD_REGEN || ( + HybridUtils.regions.isEmpty() && HybridUtils.chunks.isEmpty())) { + return; + } + PlotSquared.log( + Captions.PREFIX + "Road regeneration incomplete. Saving incomplete regions to disk."); + PlotSquared.debug(" Regions: " + HybridUtils.regions.size()); + PlotSquared.debug(" Chunks: " + HybridUtils.chunks.size()); + ArrayList regions = new ArrayList<>(); + ArrayList chunks = new ArrayList<>(); + for (BlockVector2 r : HybridUtils.regions) { + regions.add(new int[] {r.getBlockX(), r.getBlockZ()}); + } + for (BlockVector2 c : HybridUtils.chunks) { + chunks.add(new int[] {c.getBlockX(), c.getBlockZ()}); + } + List list = new ArrayList<>(); + list.add(regions); + list.add(chunks); + list.add(HybridUtils.height); + File file = new File(this.IMP.getDirectory() + File.separator + "persistent_regen_data_" + + HybridUtils.area.id + "_" + HybridUtils.area.worldname); + if (file.exists() && !file.delete()) { + PlotSquared.log(Captions.PREFIX + + "persistent_regen_data file already exists and could not be deleted."); + return; + } + try (ObjectOutputStream oos = new ObjectOutputStream( + Files.newOutputStream(file.toPath(), StandardOpenOption.CREATE_NEW))) { + oos.writeObject(list); + } catch (IOException e) { + PlotSquared.log(Captions.PREFIX + "Error create persistent_regen_data file."); + e.printStackTrace(); + } + } + /** * Setup the database connection. */ diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugExec.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugExec.java index fdd4c2f8d..37a8b16e7 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugExec.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/commands/DebugExec.java @@ -49,11 +49,7 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.sql.Timestamp; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.concurrent.CompletableFuture; @CommandDeclaration(command = "debugexec", @@ -249,7 +245,7 @@ public class DebugExec extends SubCommand { boolean result; if (HybridUtils.regions != null) { result = - HybridUtils.manager.scheduleRoadUpdate(area, HybridUtils.regions, 0); + HybridUtils.manager.scheduleRoadUpdate(area, HybridUtils.regions, 0, new HashSet<>()); } else { result = HybridUtils.manager.scheduleRoadUpdate(area, 0); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java index e1b7c6727..50701b098 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/Settings.java @@ -350,5 +350,7 @@ public class Settings extends Config { @Comment("Delete plots when a player is banned") public static boolean BAN_DELETER = false; @Comment("Allows PlaceholderAPI placeholders to be used in captions, flags, etc") public static boolean EXTERNAL_PLACEHOLDERS = true; + @Comment("Make road regeneration persistent across restarts") public static boolean + PERSISTENT_ROAD_REGEN = false; } } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java index 70b1245c7..754bd6f24 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/generator/HybridUtils.java @@ -50,6 +50,7 @@ public abstract class HybridUtils { public static HybridUtils manager; public static Set regions; + public static int height; public static Set chunks = new HashSet<>(); public static PlotArea area; public static boolean UPDATE = false; @@ -351,7 +352,7 @@ public abstract class HybridUtils { } HybridUtils.UPDATE = true; Set regions = ChunkManager.manager.getChunkChunks(area.worldname); - return scheduleRoadUpdate(area, regions, extend); + return scheduleRoadUpdate(area, regions, extend, new HashSet<>()); } public boolean scheduleSingleRegionRoadUpdate(Plot plot, int extend) { @@ -361,14 +362,15 @@ public abstract class HybridUtils { HybridUtils.UPDATE = true; Set regions = new HashSet<>(); regions.add(ChunkManager.getRegion(plot.getCenter())); - return scheduleRoadUpdate(plot.getArea(), regions, extend); + return scheduleRoadUpdate(plot.getArea(), regions, extend, new HashSet<>()); } public boolean scheduleRoadUpdate(final PlotArea area, Set regions, - final int extend) { + final int extend, Set chunks) { HybridUtils.regions = regions; HybridUtils.area = area; - chunks = new HashSet<>(); + HybridUtils.height = extend; + HybridUtils.chunks = chunks; final AtomicInteger count = new AtomicInteger(0); TaskManager.runTask(new Runnable() { @Override public void run() { @@ -621,7 +623,7 @@ public abstract class HybridUtils { return false; } - public boolean regeneratePlotWalls(final PlotArea area) { + public static boolean regeneratePlotWalls(final PlotArea area) { PlotManager plotManager = area.getPlotManager(); return plotManager.regenerateAllPlotWalls(); }