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.
This commit is contained in:
dordsor21 2020-03-22 19:23:35 +00:00 committed by GitHub
parent 26b5ee7482
commit 7310506ed4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 60 deletions

View File

@ -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.generator.IndependentPlotGenerator;
import com.github.intellectualsites.plotsquared.plot.listener.WESubscriber; import com.github.intellectualsites.plotsquared.plot.listener.WESubscriber;
import com.github.intellectualsites.plotsquared.plot.logger.ILogger; import com.github.intellectualsites.plotsquared.plot.logger.ILogger;
import com.github.intellectualsites.plotsquared.plot.object.BlockBucket; import com.github.intellectualsites.plotsquared.plot.object.*;
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.worlds.DefaultPlotAreaManager; 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.PlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotArea;
import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager; import com.github.intellectualsites.plotsquared.plot.object.worlds.SinglePlotAreaManager;
import com.github.intellectualsites.plotsquared.plot.util.ChatManager; import com.github.intellectualsites.plotsquared.plot.util.*;
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.block.GlobalBlockQueue; 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.ExpireManager;
import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpiryTask; import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpiryTask;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.Setter; import lombok.Setter;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.BufferedReader; import java.io.*;
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.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayDeque; import java.util.*;
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.Map.Entry; 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.function.Consumer;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -506,6 +464,43 @@ import java.util.zip.ZipInputStream;
} }
plotAreaManager.addPlotArea(plotArea); plotAreaManager.addPlotArea(plotArea);
plotArea.setupBorder(); 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<Object> list = (List<Object>) ois.readObject();
ArrayList<int[]> regionInts = (ArrayList<int[]>) list.get(0);
ArrayList<int[]> chunkInts = (ArrayList<int[]>) list.get(1);
HashSet<BlockVector2> regions = new HashSet<>();
Set<BlockVector2> 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() { public void disable() {
try { try {
eventDispatcher.unregisterAll(); eventDispatcher.unregisterAll();
checkRoadRegenPersistence();
// Validate that all data in the db is correct // Validate that all data in the db is correct
final HashSet<Plot> plots = new HashSet<>(); final HashSet<Plot> plots = new HashSet<>();
try { 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<int[]> regions = new ArrayList<>();
ArrayList<int[]> 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<Object> 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. * Setup the database connection.
*/ */

View File

@ -49,11 +49,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Arrays; import java.util.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@CommandDeclaration(command = "debugexec", @CommandDeclaration(command = "debugexec",
@ -249,7 +245,7 @@ public class DebugExec extends SubCommand {
boolean result; boolean result;
if (HybridUtils.regions != null) { if (HybridUtils.regions != null) {
result = result =
HybridUtils.manager.scheduleRoadUpdate(area, HybridUtils.regions, 0); HybridUtils.manager.scheduleRoadUpdate(area, HybridUtils.regions, 0, new HashSet<>());
} else { } else {
result = HybridUtils.manager.scheduleRoadUpdate(area, 0); result = HybridUtils.manager.scheduleRoadUpdate(area, 0);
} }

View File

@ -350,5 +350,7 @@ public class Settings extends Config {
@Comment("Delete plots when a player is banned") public static boolean BAN_DELETER = false; @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") @Comment("Allows PlaceholderAPI placeholders to be used in captions, flags, etc")
public static boolean EXTERNAL_PLACEHOLDERS = true; public static boolean EXTERNAL_PLACEHOLDERS = true;
@Comment("Make road regeneration persistent across restarts") public static boolean
PERSISTENT_ROAD_REGEN = false;
} }
} }

View File

@ -50,6 +50,7 @@ public abstract class HybridUtils {
public static HybridUtils manager; public static HybridUtils manager;
public static Set<BlockVector2> regions; public static Set<BlockVector2> regions;
public static int height;
public static Set<BlockVector2> chunks = new HashSet<>(); public static Set<BlockVector2> chunks = new HashSet<>();
public static PlotArea area; public static PlotArea area;
public static boolean UPDATE = false; public static boolean UPDATE = false;
@ -351,7 +352,7 @@ public abstract class HybridUtils {
} }
HybridUtils.UPDATE = true; HybridUtils.UPDATE = true;
Set<BlockVector2> regions = ChunkManager.manager.getChunkChunks(area.worldname); Set<BlockVector2> 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) { public boolean scheduleSingleRegionRoadUpdate(Plot plot, int extend) {
@ -361,14 +362,15 @@ public abstract class HybridUtils {
HybridUtils.UPDATE = true; HybridUtils.UPDATE = true;
Set<BlockVector2> regions = new HashSet<>(); Set<BlockVector2> regions = new HashSet<>();
regions.add(ChunkManager.getRegion(plot.getCenter())); 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<BlockVector2> regions, public boolean scheduleRoadUpdate(final PlotArea area, Set<BlockVector2> regions,
final int extend) { final int extend, Set<BlockVector2> chunks) {
HybridUtils.regions = regions; HybridUtils.regions = regions;
HybridUtils.area = area; HybridUtils.area = area;
chunks = new HashSet<>(); HybridUtils.height = extend;
HybridUtils.chunks = chunks;
final AtomicInteger count = new AtomicInteger(0); final AtomicInteger count = new AtomicInteger(0);
TaskManager.runTask(new Runnable() { TaskManager.runTask(new Runnable() {
@Override public void run() { @Override public void run() {
@ -621,7 +623,7 @@ public abstract class HybridUtils {
return false; return false;
} }
public boolean regeneratePlotWalls(final PlotArea area) { public static boolean regeneratePlotWalls(final PlotArea area) {
PlotManager plotManager = area.getPlotManager(); PlotManager plotManager = area.getPlotManager();
return plotManager.regenerateAllPlotWalls(); return plotManager.regenerateAllPlotWalls();
} }