mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 18:23:06 +00:00
Added studio trim command
- Added studio trim command. Allows you to analyze/delete unused files in a project/pack
This commit is contained in:
parent
13532a1f0a
commit
ae9b8326a4
@ -18,12 +18,16 @@
|
|||||||
|
|
||||||
package com.volmit.iris.core.commands;
|
package com.volmit.iris.core.commands;
|
||||||
|
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.IrisSettings;
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.gui.NoiseExplorerGUI;
|
import com.volmit.iris.core.gui.NoiseExplorerGUI;
|
||||||
import com.volmit.iris.core.gui.VisionGUI;
|
import com.volmit.iris.core.gui.VisionGUI;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||||
import com.volmit.iris.core.project.IrisProject;
|
import com.volmit.iris.core.project.IrisProject;
|
||||||
|
import com.volmit.iris.core.project.ProjectTrimmer;
|
||||||
|
import com.volmit.iris.core.service.CommandSVC;
|
||||||
import com.volmit.iris.core.service.ConversionSVC;
|
import com.volmit.iris.core.service.ConversionSVC;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
@ -49,6 +53,7 @@ import com.volmit.iris.util.decree.DecreeExecutor;
|
|||||||
import com.volmit.iris.util.decree.DecreeOrigin;
|
import com.volmit.iris.util.decree.DecreeOrigin;
|
||||||
import com.volmit.iris.util.decree.annotations.Decree;
|
import com.volmit.iris.util.decree.annotations.Decree;
|
||||||
import com.volmit.iris.util.decree.annotations.Param;
|
import com.volmit.iris.util.decree.annotations.Param;
|
||||||
|
import com.volmit.iris.util.decree.virtual.VirtualDecreeCommand;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.function.Function2;
|
import com.volmit.iris.util.function.Function2;
|
||||||
@ -62,6 +67,7 @@ import com.volmit.iris.util.math.RNG;
|
|||||||
import com.volmit.iris.util.math.Spiraler;
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
import com.volmit.iris.util.noise.CNG;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.O;
|
import com.volmit.iris.util.scheduling.O;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
@ -70,6 +76,7 @@ import com.volmit.iris.util.scheduling.jobs.JobCollection;
|
|||||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||||
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
import com.volmit.iris.util.scheduling.jobs.SingleJob;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
|
import org.apache.logging.log4j.core.util.JsonUtils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.FluidCollisionMode;
|
import org.bukkit.FluidCollisionMode;
|
||||||
@ -84,17 +91,28 @@ import org.bukkit.util.Vector;
|
|||||||
import java.awt.Desktop;
|
import java.awt.Desktop;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.attribute.FileTime;
|
import java.nio.file.attribute.FileTime;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||||
public class CommandStudio implements DecreeExecutor {
|
public class CommandStudio implements DecreeExecutor {
|
||||||
@ -283,6 +301,128 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
new JobCollection("Cleaning", jobs).execute(sender());
|
new JobCollection("Cleaning", jobs).execute(sender());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Trim the pack of all unused files")
|
||||||
|
public void trim(
|
||||||
|
@Param(defaultValue = "overworld", description = "The pack to trim")
|
||||||
|
IrisDimension project
|
||||||
|
) {
|
||||||
|
sender().sendMessage("Analyzing the " + project.getName() + " pack...");
|
||||||
|
|
||||||
|
ProjectTrimmer trimmer = new ProjectTrimmer(project);
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
trimmer.analyze();
|
||||||
|
time = System.currentTimeMillis() - time;
|
||||||
|
sender().sendMessage("Done! Took " + time + "ms!");
|
||||||
|
|
||||||
|
Map<Class<? extends IrisRegistrant>, KList<String>> result = trimmer.getResult();
|
||||||
|
List<Class<? extends IrisRegistrant>> sorted = result.keySet().stream().filter(key -> result.get(key).size() > 0)
|
||||||
|
.sorted(Comparator.comparingInt(key -> result.get(key).size())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
List<String> realFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
int total = result.values().stream().mapToInt(ArrayList::size).sum();
|
||||||
|
if (sorted.size() > 0) {
|
||||||
|
sender().sendMessage("Found total of " + total + " unused files of " + sorted.size() + " different types");
|
||||||
|
|
||||||
|
for (Class<? extends IrisRegistrant> clazz : sorted) {
|
||||||
|
try {
|
||||||
|
KList<String> files = result.get(clazz);
|
||||||
|
|
||||||
|
IrisRegistrant dummy = clazz.getConstructor().newInstance();
|
||||||
|
String filesString1 = String.join(", ", files);
|
||||||
|
String filesString2 = filesString1.replaceAll(", ", "\n");
|
||||||
|
String type = dummy.getTypeName();
|
||||||
|
String chatString = "- " + files.size() + "x " + type + "s (" + filesString1;
|
||||||
|
chatString = chatString.substring(0, Math.min(chatString.length(), 56)) + "...)";
|
||||||
|
|
||||||
|
//Add the raw files to a list so we can delete them later
|
||||||
|
realFiles.addAll(files.stream().map(s -> dummy.getFolderName() + "/" + s + (clazz.equals(IrisObject.class) ? ".iob" : ".json")).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
sender().sendMessage("<hover:show_text:" + filesString2 + ">" + chatString + "</hover>");
|
||||||
|
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
String password = UUID.randomUUID().toString().replaceAll("\\Q-\\E", "");
|
||||||
|
final VolmitSender sender = sender();
|
||||||
|
|
||||||
|
Consumer<String> confirm = (string) -> {
|
||||||
|
if (string.equalsIgnoreCase("delete") || string.equalsIgnoreCase("both")) {
|
||||||
|
sender.sendMessage(C.RED + "Deleting files...");
|
||||||
|
|
||||||
|
long time2 = System.currentTimeMillis();
|
||||||
|
realFiles.forEach(s -> {
|
||||||
|
File file = new File(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey()), s);
|
||||||
|
if (!file.exists()) Iris.warn("<NOMINI>Couldn't find file " + file.getPath() + " to delete");
|
||||||
|
else IO.delete(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
sender.sendMessage(C.GREEN + "Files deleted! Took " + (System.currentTimeMillis() - time2) + "ms!");
|
||||||
|
if (!string.equalsIgnoreCase("both")) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(string.equalsIgnoreCase("file") || string.equalsIgnoreCase("both"))) {
|
||||||
|
sender.sendMessage(C.RED +"Unknown option \"" + string + "\". Writing to file anyway...");
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey()) + File.separator + "unused-files.txt");
|
||||||
|
try {
|
||||||
|
List<String> lines = new ArrayList<>(realFiles);
|
||||||
|
lines.add(0, "# Unused files in " + project.getLoadKey() + " project");
|
||||||
|
lines.add(1, "");
|
||||||
|
|
||||||
|
if (file.exists()) file.delete();
|
||||||
|
Files.write(file.toPath(), lines);
|
||||||
|
|
||||||
|
String openFilePassword = UUID.randomUUID().toString().replaceAll("\\Q-\\E", "");
|
||||||
|
Consumer<String> openFile = (s) -> {
|
||||||
|
try {
|
||||||
|
Desktop.getDesktop().open(file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
sender.sendMessage(C.RED + "Failed to open file: " + e.getLocalizedMessage());
|
||||||
|
sender.sendMessage(C.RED + "See the console for details");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sender.sendMessage("<hover:show_text:" + C.YELLOW + "Click to open the file!><click:run_command:/irisdecree " + openFilePassword + " open>" + C.DARK_GREEN + "Done! File written to " + file.getAbsolutePath() + "</click></hover>");
|
||||||
|
|
||||||
|
CompletableFuture<String> onReturn2 = new CompletableFuture<>();
|
||||||
|
onReturn2.thenAccept(openFile);
|
||||||
|
|
||||||
|
Iris.service(CommandSVC.class).post(openFilePassword, onReturn2);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CompletableFuture<String> onReturn = new CompletableFuture<>();
|
||||||
|
onReturn.thenAccept(confirm);
|
||||||
|
|
||||||
|
if (sender().isPlayer()) {
|
||||||
|
sender().sendMessage(C.GREEN + "<click:run_command:/irisdecree " + password + " delete>Click <bold>" + C.RED + "HERE" + C.GREEN + "</bold> to</click> automatically delete these files.");
|
||||||
|
sender().sendMessage(C.GREEN + "Or instead, <click:run_command:/irisdecree " + password + " file>click <bold>" + C.BLUE + "HERE" + C.GREEN + "</bold> to</click> create a file with a list of all the files.");
|
||||||
|
sender().sendMessage(C.GREEN + "Or, you can <click:run_command:/irisdecree " + password + " both>click <bold>" + C.YELLOW + "HERE" + C.GREEN + "</bold> to</click> do both of these");
|
||||||
|
|
||||||
|
Iris.service(CommandSVC.class).post(password, onReturn);
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "Enter an option bellow to continue:");
|
||||||
|
sender().sendMessage(C.GREEN + "DELETE - Delete all the files that are unused");
|
||||||
|
sender().sendMessage(C.GREEN + "FILE - Write the list of all the unused files to a file");
|
||||||
|
sender().sendMessage(C.GREEN + "BOTH - Do both of the above options");
|
||||||
|
|
||||||
|
Iris.service(CommandSVC.class).postConsole(onReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.DARK_GREEN + "Analyzed entire project and found no unused files! Congrats!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "Get the version of a pack")
|
@Decree(description = "Get the version of a pack")
|
||||||
public void version(
|
public void version(
|
||||||
@Param(defaultValue = "overworld", description = "The dimension get the version of", aliases = "dim", contextual = true)
|
@Param(defaultValue = "overworld", description = "The dimension get the version of", aliases = "dim", contextual = true)
|
||||||
|
533
src/main/java/com/volmit/iris/core/project/ProjectTrimmer.java
Normal file
533
src/main/java/com/volmit/iris/core/project/ProjectTrimmer.java
Normal file
@ -0,0 +1,533 @@
|
|||||||
|
package com.volmit.iris.core.project;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||||
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
|
import com.volmit.iris.engine.object.IrisCave;
|
||||||
|
import com.volmit.iris.engine.object.IrisDimension;
|
||||||
|
import com.volmit.iris.engine.object.IrisEntity;
|
||||||
|
import com.volmit.iris.engine.object.IrisExpression;
|
||||||
|
import com.volmit.iris.engine.object.IrisGenerator;
|
||||||
|
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||||
|
import com.volmit.iris.engine.object.IrisJigsawPool;
|
||||||
|
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||||
|
import com.volmit.iris.engine.object.IrisLoot;
|
||||||
|
import com.volmit.iris.engine.object.IrisLootTable;
|
||||||
|
import com.volmit.iris.engine.object.IrisMarker;
|
||||||
|
import com.volmit.iris.engine.object.IrisObject;
|
||||||
|
import com.volmit.iris.engine.object.IrisRavine;
|
||||||
|
import com.volmit.iris.engine.object.IrisRegion;
|
||||||
|
import com.volmit.iris.engine.object.IrisScript;
|
||||||
|
import com.volmit.iris.engine.object.IrisSpawner;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.json.JSONArray;
|
||||||
|
import com.volmit.iris.util.json.JSONObject;
|
||||||
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ProjectTrimmer {
|
||||||
|
|
||||||
|
private IrisDimension dimension;
|
||||||
|
|
||||||
|
private KList<String> biomes;
|
||||||
|
private KList<String> regions;
|
||||||
|
private KList<String> caves;
|
||||||
|
private KList<String> entities;
|
||||||
|
private KList<String> objects;
|
||||||
|
private KList<String> generators;
|
||||||
|
private KList<String> expressions;
|
||||||
|
private KList<String> loot;
|
||||||
|
private KList<String> spawners;
|
||||||
|
private KList<String> jigsawPieces;
|
||||||
|
private KList<String> jigsawPools;
|
||||||
|
private KList<String> jigsawStructures;
|
||||||
|
private KList<String> scripts;
|
||||||
|
private KList<String> markers;
|
||||||
|
private KList<String> ravines;
|
||||||
|
|
||||||
|
private IrisData data;
|
||||||
|
|
||||||
|
private KList<Runnable> futureTasks = new KList<>();
|
||||||
|
|
||||||
|
public ProjectTrimmer(IrisDimension dimension) {
|
||||||
|
this.dimension = dimension;
|
||||||
|
|
||||||
|
data = IrisData.get(Iris.service(StudioSVC.class).getWorkspaceFolder(dimension.getLoadKey()));
|
||||||
|
|
||||||
|
biomes = new KList<>(data.getBiomeLoader().getPossibleKeys());
|
||||||
|
regions = new KList<>(data.getRegionLoader().getPossibleKeys());
|
||||||
|
caves = new KList<>(data.getCaveLoader().getPossibleKeys());
|
||||||
|
entities = new KList<>(data.getEntityLoader().getPossibleKeys());
|
||||||
|
objects = new KList<>(data.getObjectLoader().getPossibleKeys());
|
||||||
|
generators = new KList<>(data.getGeneratorLoader().getPossibleKeys());
|
||||||
|
expressions = new KList<>(data.getExpressionLoader().getPossibleKeys());
|
||||||
|
loot = new KList<>(data.getLootLoader().getPossibleKeys());
|
||||||
|
spawners = new KList<>(data.getSpawnerLoader().getPossibleKeys());
|
||||||
|
jigsawPieces = new KList<>(data.getJigsawPieceLoader().getPossibleKeys());
|
||||||
|
jigsawPools = new KList<>(data.getJigsawPoolLoader().getPossibleKeys());
|
||||||
|
jigsawStructures = new KList<>(data.getJigsawStructureLoader().getPossibleKeys());
|
||||||
|
scripts = new KList<>(data.getScriptLoader().getPossibleKeys());
|
||||||
|
markers = new KList<>(data.getMarkerLoader().getPossibleKeys());
|
||||||
|
ravines = new KList<>(data.getRavineLoader().getPossibleKeys());
|
||||||
|
|
||||||
|
if (objects.contains("null") || objects.contains(null))
|
||||||
|
Iris.warn("Warning! Some objects are null! This means you have encountered the AtomicCache bug! If you delete the files, it may break something!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyze the dimension pack. Do NOT run this on the main thread!
|
||||||
|
*/
|
||||||
|
public void analyze() {
|
||||||
|
|
||||||
|
for (String dimension : data.getDimensionLoader().getPossibleKeys()) {
|
||||||
|
File file = data.getDimensionLoader().findFile(dimension);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
if (json.keySet().contains("regions")) {
|
||||||
|
regions.removeAll(convertStringArray(json.getJSONArray("regions")));
|
||||||
|
}
|
||||||
|
if (json.keySet().contains("stronghold")) {
|
||||||
|
jigsawStructures.remove(json.getString("stronghold"));
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzeCommonDRB(json); //Objects, structures
|
||||||
|
trimExpressions(json);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KList<String> usedRegions = new KList<>(Arrays.stream(data.getRegionLoader().getPossibleKeys())
|
||||||
|
.filter(reg -> !this.regions.contains(reg)).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
//Regions
|
||||||
|
for (String region : usedRegions) {
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
File file = data.getRegionLoader().findFile(region);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
if (json.keySet().contains("landBiomes")) {
|
||||||
|
analyzeBiomeArray(json.getJSONArray("landBiomes"));
|
||||||
|
}
|
||||||
|
if (json.keySet().contains("seaBiomes")) {
|
||||||
|
analyzeBiomeArray(json.getJSONArray("seaBiomes"));
|
||||||
|
}
|
||||||
|
if (json.keySet().contains("shoreBiomes")) {
|
||||||
|
analyzeBiomeArray(json.getJSONArray("shoreBiomes"));
|
||||||
|
}
|
||||||
|
if (json.keySet().contains("caveBiomes")) {
|
||||||
|
analyzeBiomeArray(json.getJSONArray("caveBiomes"));
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzeCommonDRB(json); //Objects, structures
|
||||||
|
trimExpressions(json);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Burst tasks for all biomes and regions
|
||||||
|
burstTasks();
|
||||||
|
|
||||||
|
|
||||||
|
KList<String> usedBiomes = new KList<>(Arrays.stream(data.getBiomeLoader().getPossibleKeys())
|
||||||
|
.filter(biome -> !this.biomes.contains(biome)).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
//Biomes
|
||||||
|
for (String biome : usedBiomes) {
|
||||||
|
analyzeBiome(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
burstTasks();
|
||||||
|
|
||||||
|
KList<String> usedJigsaws = new KList<>(Arrays.stream(data.getJigsawStructureLoader().getPossibleKeys())
|
||||||
|
.filter(jig -> !this.jigsawStructures.contains(jig)).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (String jigsaw : usedJigsaws) {
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
File file = data.getJigsawStructureLoader().findFile(jigsaw);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
if (json.keySet().contains("pieces")) {
|
||||||
|
JSONArray pieces = json.getJSONArray("pieces");
|
||||||
|
for (int i = 0; i < pieces.length(); i++) {
|
||||||
|
String pieceString = pieces.getString(i);
|
||||||
|
File pieceFile = data.getJigsawPieceLoader().findFile(pieceString);
|
||||||
|
this.jigsawPieces.remove(pieceString);
|
||||||
|
analyzeJigsawObject(new JSONObject(IO.readAll(pieceFile)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (IOException e) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
burstTasks();
|
||||||
|
|
||||||
|
KList<String> usedEntities = new KList<>(Arrays.stream(data.getEntityLoader().getPossibleKeys())
|
||||||
|
.filter(jig -> !this.entities.contains(jig)).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
for (String entity : usedEntities) {
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
File file = data.getEntityLoader().findFile(entity);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
if (json.keySet().contains("postSpawnScripts")) {
|
||||||
|
scripts.removeAll(convertStringArray(json.getJSONArray("postSpawnScripts")));
|
||||||
|
}
|
||||||
|
if (json.keySet().contains("spawnerScripts")) {
|
||||||
|
scripts.remove(json.getString("spawnerScripts"));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
burstTasks();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the unused files in the project after calling {@link #analyze()}
|
||||||
|
* @return A map of all the unused files by type
|
||||||
|
*/
|
||||||
|
public Map<Class<? extends IrisRegistrant>, KList<String>> getResult() {
|
||||||
|
Map<Class<? extends IrisRegistrant>, KList<String>> map = new HashMap<>();
|
||||||
|
map.put(IrisBiome.class, biomes);
|
||||||
|
map.put(IrisRegion.class, regions);
|
||||||
|
map.put(IrisCave.class, caves);
|
||||||
|
map.put(IrisRavine.class, ravines);
|
||||||
|
map.put(IrisObject.class, objects);
|
||||||
|
map.put(IrisEntity.class, entities);
|
||||||
|
map.put(IrisGenerator.class, generators);
|
||||||
|
map.put(IrisSpawner.class, spawners);
|
||||||
|
map.put(IrisLootTable.class, loot);
|
||||||
|
map.put(IrisExpression.class, expressions);
|
||||||
|
map.put(IrisScript.class, scripts);
|
||||||
|
map.put(IrisJigsawPiece.class, jigsawPieces);
|
||||||
|
map.put(IrisJigsawPool.class, jigsawPools);
|
||||||
|
map.put(IrisJigsawStructure.class, jigsawStructures);
|
||||||
|
map.put(IrisMarker.class, markers);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do all queued tasks in a burst
|
||||||
|
*/
|
||||||
|
private void burstTasks() {
|
||||||
|
while (futureTasks.size() > 0) {
|
||||||
|
KList<Runnable> clonedTasks = new KList<>(futureTasks);
|
||||||
|
futureTasks.clear();
|
||||||
|
|
||||||
|
MultiBurst burster = new MultiBurst();
|
||||||
|
burster.burst(clonedTasks); //The tasks themselves can add more tasks to futureTasks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyze common things within dimensions, regions and objects
|
||||||
|
* @param object The parent json object
|
||||||
|
*/
|
||||||
|
private void analyzeCommonDRB(JSONObject object) {
|
||||||
|
//Jigsaws
|
||||||
|
if (object.keySet().contains("jigsawStructures")) {
|
||||||
|
JSONArray jigsaws = object.getJSONArray("jigsawStructures");
|
||||||
|
for (int i = 0; i < jigsaws.length(); i++) {
|
||||||
|
JSONObject jigobject = jigsaws.getJSONObject(i);
|
||||||
|
jigsawStructures.remove(jigobject.getString("structure"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Objects
|
||||||
|
if (object.keySet().contains("objects")) {
|
||||||
|
JSONArray objectsArray = object.getJSONArray("objects");
|
||||||
|
for (int i = 0; i < objectsArray.length(); i++) {
|
||||||
|
JSONObject innerObject = objectsArray.getJSONObject(i); //The actual object within the objects
|
||||||
|
|
||||||
|
analyzeObject(innerObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Loot
|
||||||
|
if (object.keySet().contains("loot")) {
|
||||||
|
JSONObject lootObject = object.getJSONObject("loot");
|
||||||
|
this.loot.removeAll(convertStringArray(lootObject.getJSONArray("tables")));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Spawners
|
||||||
|
if (object.keySet().contains("entitySpawners")) {
|
||||||
|
JSONArray entitySpawners = object.getJSONArray("entitySpawners");
|
||||||
|
analyzeSpawnerArray(entitySpawners);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Caves and stuff
|
||||||
|
if (object.keySet().contains("carvings")) {
|
||||||
|
JSONObject carvings = object.getJSONObject("carvings");
|
||||||
|
|
||||||
|
if (carvings.keySet().contains("caves")) {
|
||||||
|
JSONArray array = carvings.getJSONArray("caves");
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
JSONObject cave = array.getJSONObject(i);
|
||||||
|
this.caves.remove(cave.getString("cave"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (carvings.keySet().contains("ravines")) {
|
||||||
|
JSONArray array = carvings.getJSONArray("ravines");
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
JSONObject cave = array.getJSONObject(i);
|
||||||
|
this.ravines.remove(cave.getString("ravine"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeObject(JSONObject object) {
|
||||||
|
JSONArray placeArray = object.getJSONArray("place");
|
||||||
|
objects.removeAll(convertStringArray(placeArray));
|
||||||
|
|
||||||
|
if (object.keySet().contains("loot")) {
|
||||||
|
JSONArray loot = object.getJSONArray("loot");
|
||||||
|
for (int j = 0; j < loot.length(); j++) {
|
||||||
|
JSONObject lootObject = loot.getJSONObject(j);
|
||||||
|
this.loot.remove(lootObject.getString("name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object.keySet().contains("markers")) {
|
||||||
|
JSONArray markers = object.getJSONArray("markers");
|
||||||
|
for (int j = 0; j < markers.length(); j++) {
|
||||||
|
JSONObject marker = markers.getJSONObject(j);
|
||||||
|
String markerName = marker.getString("marker");
|
||||||
|
analyzeMarker(markerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeJigsawObject(JSONObject object) {
|
||||||
|
objects.remove(object.getString("object"));
|
||||||
|
|
||||||
|
JSONObject placement = object.getJSONObject("placementOptions");
|
||||||
|
if (placement.keySet().contains("loot")) {
|
||||||
|
JSONArray loot = placement.getJSONArray("loot");
|
||||||
|
for (int j = 0; j < loot.length(); j++) {
|
||||||
|
JSONObject lootObject = loot.getJSONObject(j);
|
||||||
|
this.loot.remove(lootObject.getString("name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (placement.keySet().contains("markers")) {
|
||||||
|
JSONArray markers = placement.getJSONArray("markers");
|
||||||
|
for (int j = 0; j < markers.length(); j++) {
|
||||||
|
JSONObject marker = markers.getJSONObject(j);
|
||||||
|
String markerName = marker.getString("marker");
|
||||||
|
analyzeMarker(markerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object.keySet().contains("connectors")) {
|
||||||
|
JSONArray connectors = object.getJSONArray("connectors");
|
||||||
|
for (int j = 0; j < connectors.length(); j++) {
|
||||||
|
JSONObject connector = connectors.getJSONObject(j);
|
||||||
|
|
||||||
|
if (connector.keySet().contains("pools")) {
|
||||||
|
JSONArray pools = connector.getJSONArray("pools");
|
||||||
|
analyzePoolArray(pools);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeMarker(String name) {
|
||||||
|
if (markers.contains(name)) {
|
||||||
|
markers.remove(name);
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
File file = data.getMarkerLoader().findFile(name);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
if (json.keySet().contains("spawners")) {
|
||||||
|
analyzeSpawnerArray(json.getJSONArray("spawners"));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeSpawnerArray(JSONArray spawners) {
|
||||||
|
for (int i = 0; i < spawners.length(); i++) {
|
||||||
|
String spawner = spawners.getString(i);
|
||||||
|
|
||||||
|
if (this.spawners.contains(spawner)) {
|
||||||
|
this.spawners.remove(spawner);
|
||||||
|
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
File file = data.getSpawnerLoader().findFile(spawner);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
if (json.keySet().contains("spawns")) {
|
||||||
|
JSONArray spawnArray = json.getJSONArray("spawns");
|
||||||
|
for (int j = 0; j < spawnArray.length(); j++) {
|
||||||
|
JSONObject spawnObject = spawnArray.getJSONObject(j);
|
||||||
|
entities.remove(spawnObject.getString("entity"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (json.keySet().contains("initialSpawns")) {
|
||||||
|
JSONArray spawnArray = json.getJSONArray("initialSpawns");
|
||||||
|
for (int j = 0; j < spawnArray.length(); j++) {
|
||||||
|
JSONObject spawnObject = spawnArray.getJSONObject(j);
|
||||||
|
entities.remove(spawnObject.getString("entity"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeBiome(String biome) {
|
||||||
|
if (biomes.contains(biome)) {
|
||||||
|
biomes.remove(biome);
|
||||||
|
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
File file = data.getBiomeLoader().findFile(biome);
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
if (json.keySet().contains("children")) {
|
||||||
|
analyzeBiomeArray(json.getJSONArray("children"));
|
||||||
|
}
|
||||||
|
if (json.keySet().contains("generators")) {
|
||||||
|
JSONArray ogenerators = json.getJSONArray("generators");
|
||||||
|
for (int j = 0; j < ogenerators.length(); j++) {
|
||||||
|
JSONObject genobject = ogenerators.getJSONObject(j);
|
||||||
|
generators.remove(genobject.getString("generator"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
analyzeCommonDRB(json); //Objects, structures
|
||||||
|
trimExpressions(json);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzeBiomeArray(JSONArray array) {
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
String biome = array.getString(i);
|
||||||
|
|
||||||
|
analyzeBiome(biome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void analyzePoolArray(JSONArray array) {
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
String pool = array.getString(i);
|
||||||
|
|
||||||
|
if (this.jigsawPools.contains(pool)) {
|
||||||
|
this.jigsawPools.remove(pool);
|
||||||
|
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
File file = data.getJigsawPoolLoader().findFile(pool);
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(IO.readAll(file));
|
||||||
|
|
||||||
|
if (json.keySet().contains("pieces")) {
|
||||||
|
JSONArray pieces = json.getJSONArray("pieces");
|
||||||
|
|
||||||
|
for (String piece : convertStringArray(pieces)) {
|
||||||
|
if (this.jigsawPieces.contains(piece)) {
|
||||||
|
futureTasks.add(() -> {
|
||||||
|
|
||||||
|
File pieceFile = data.getJigsawPoolLoader().findFile(pool);
|
||||||
|
try {
|
||||||
|
JSONObject pieceJSON = new JSONObject(IO.readAll(pieceFile));
|
||||||
|
analyzeJigsawObject(pieceJSON);
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a JSON string array to a java list
|
||||||
|
* @param array The JSON string array
|
||||||
|
* @return The list
|
||||||
|
*/
|
||||||
|
private List<String> convertStringArray(JSONArray array) {
|
||||||
|
List<String> newList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
String s = array.getString(i);
|
||||||
|
if (s != null) newList.add(s);
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans for styles with expressions in them and removes all used expressions
|
||||||
|
* @param object The parent json
|
||||||
|
*/
|
||||||
|
private void trimExpressions(JSONObject object) {
|
||||||
|
for (String key : object.keySet()) {
|
||||||
|
Object o = object.get(key);
|
||||||
|
|
||||||
|
if (key.equalsIgnoreCase("style")) {
|
||||||
|
if (o instanceof JSONObject && ((JSONObject) o).keySet().contains("expression")) {
|
||||||
|
this.expressions.remove(((JSONObject) o).getString("expression"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o instanceof JSONObject) {
|
||||||
|
trimExpressions((JSONObject)o);
|
||||||
|
} else if (o instanceof JSONArray) {
|
||||||
|
JSONArray array = (JSONArray)o;
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
Object o2 = array.get(i);
|
||||||
|
|
||||||
|
if (o2 instanceof JSONObject) {
|
||||||
|
trimExpressions((JSONObject) o2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user