Cleanup command merged

This commit is contained in:
cyberpwn 2021-08-14 10:00:43 -04:00
parent 52ba831b1c
commit 3c9608efbd
9 changed files with 615 additions and 21 deletions

View File

@ -19,13 +19,31 @@
package com.volmit.iris.core.decrees; package com.volmit.iris.core.decrees;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.project.IrisProject;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.object.dimensional.IrisDimension; import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.object.objects.IrisObject;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeExecutor; import com.volmit.iris.util.decree.DecreeExecutor;
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.format.C; import com.volmit.iris.util.format.C;
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 com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.jobs.Job;
import com.volmit.iris.util.scheduling.jobs.JobCollection;
import com.volmit.iris.util.scheduling.jobs.QueueJob;
import com.volmit.iris.util.scheduling.jobs.SingleJob;
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true) import java.io.File;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@Decree(name = "studio", aliases = "std", description = "Studio Commands", studio = true)
public class CMDIrisStudio implements DecreeExecutor public class CMDIrisStudio implements DecreeExecutor
{ {
@Decree(description = "Open a new studio world", aliases = "o", sync = true) @Decree(description = "Open a new studio world", aliases = "o", sync = true)
@ -50,4 +68,184 @@ public class CMDIrisStudio implements DecreeExecutor
Iris.proj.close(); Iris.proj.close();
sender().sendMessage(C.YELLOW + "Project Closed"); sender().sendMessage(C.YELLOW + "Project Closed");
} }
@Decree(description = "Clean an Iris Project, optionally beautifying JSON & fixing block ids with missing keys. Also rebuilds the vscode schemas. ")
public void clean(
@Param(name = "project", required = true, description = "The project to update")
IrisDimension project,
@Param(name = "beautify", defaultValue = "false", description = "Filters all valid JSON files with a beautifier (indentation: 4)")
boolean beautify,
@Param(name = "fix-ids", defaultValue = "false", description = "Fixes any block ids used such as \"dirt\" will be converted to \"minecraft:dirt\"")
boolean fixIds,
@Param(name = "rewriteObjects", defaultValue = "false", description = "Imports all objects and re-writes them cleaning up positions & block data in the process.")
boolean rewriteObjects
) {
KList<Job> jobs = new KList<>();
KList<File> files = new KList<File>();
files(Iris.instance.getDataFolder("packs", project.getLoadKey()), files);
MultiBurst burst = new MultiBurst("Cleaner", Thread.MIN_PRIORITY, Runtime.getRuntime().availableProcessors() * 2);
jobs.add(new SingleJob("Updating Workspace", () -> {
if (!new IrisProject(Iris.proj.getWorkspaceFolder(project.getLoadKey())).updateWorkspace()) {
sender().sendMessage(C.GOLD + "Invalid project: " + project.getLoadKey() + ". Try deleting the code-workspace file and try again.");
}
J.sleep(250);
}));
sender().sendMessage("Files: " + files.size());
if(fixIds)
{
QueueJob<File> r = new QueueJob<>() {
@Override
public void execute(File f) {
try {
JSONObject p = new JSONObject(IO.readAll(f));
fixBlocks(p);
J.sleep(1);
IO.writeAll(f, p.toString(4));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getName() {
return "Fixing IDs";
}
};
r.queue(files);
jobs.add(r);
}
if(beautify)
{
QueueJob<File> r = new QueueJob<>() {
@Override
public void execute(File f) {
try {
JSONObject p = new JSONObject(IO.readAll(f));
IO.writeAll(f, p.toString(4));
J.sleep(1);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getName() {
return "Beautify";
}
};
r.queue(files);
jobs.add(r);
}
if(rewriteObjects)
{
QueueJob<Runnable> q = new QueueJob<Runnable>() {
@Override
public void execute(Runnable runnable) {
runnable.run();
J.sleep(50);
}
@Override
public String getName() {
return "Rewriting Objects";
}
};
IrisData data = new IrisData(Iris.proj.getWorkspaceFolder(project.getLoadKey()));
for (String f : data.getObjectLoader().getPossibleKeys()) {
CompletableFuture<?> gg = burst.complete(() ->{
File ff = data.getObjectLoader().findFile(f);
IrisObject oo = new IrisObject(0, 0, 0);
try {
oo.read(ff);
} catch (Throwable e) {
Iris.error("FAILER TO READ: " + f);
return;
}
if (oo == null) {
Iris.error("FAILER TO READ: " + f);
return;
}
try {
oo.write(ff);
} catch (IOException e) {
Iris.error("FAILURE TO WRITE: " + oo.getLoadFile());
}
});
q.queue(() -> {
try {
gg.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
}
jobs.add(q);
}
jobs.add(new SingleJob("Finishing Up", burst::shutdownNow));
new JobCollection("Cleaning", jobs).execute(sender());
}
public void files(File clean, KList<File> files)
{
if (clean.isDirectory()) {
for (File i : clean.listFiles()) {
files(i, files);
}
} else if (clean.getName().endsWith(".json")) {
try {
files.add(clean);
} catch (Throwable e) {
Iris.reportError(e);
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
}
}
}
private void fixBlocks(JSONObject obj) {
for (String i : obj.keySet()) {
Object o = obj.get(i);
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
obj.put(i, "minecraft:" + o);
}
if (o instanceof JSONObject) {
fixBlocks((JSONObject) o);
} else if (o instanceof JSONArray) {
fixBlocks((JSONArray) o);
}
}
}
private void fixBlocks(JSONArray obj) {
for (int i = 0; i < obj.length(); i++) {
Object o = obj.get(i);
if (o instanceof JSONObject) {
fixBlocks((JSONObject) o);
} else if (o instanceof JSONArray) {
fixBlocks((JSONArray) o);
}
}
}
} }

View File

@ -446,4 +446,62 @@ public class IrisProject {
sender.sendMessage("Failed!"); sender.sendMessage("Failed!");
return null; return null;
} }
public static int clean(VolmitSender s, File clean) {
int c = 0;
if (clean.isDirectory()) {
for (File i : clean.listFiles()) {
c += clean(s, i);
}
} else if (clean.getName().endsWith(".json")) {
try {
clean(clean);
} catch (Throwable e) {
Iris.reportError(e);
Iris.error("Failed to beautify " + clean.getAbsolutePath() + " You may have errors in your json!");
}
c++;
}
return c;
}
public static void clean(File clean) throws IOException {
JSONObject obj = new JSONObject(IO.readAll(clean));
fixBlocks(obj, clean);
IO.writeAll(clean, obj.toString(4));
}
public static void fixBlocks(JSONObject obj, File f) {
for (String i : obj.keySet()) {
Object o = obj.get(i);
if (i.equals("block") && o instanceof String && !o.toString().trim().isEmpty() && !o.toString().contains(":")) {
obj.put(i, "minecraft:" + o);
Iris.debug("Updated Block Key: " + o + " to " + obj.getString(i) + " in " + f.getPath());
}
if (o instanceof JSONObject) {
fixBlocks((JSONObject) o, f);
} else if (o instanceof JSONArray) {
fixBlocks((JSONArray) o, f);
}
}
}
public static void fixBlocks(JSONArray obj, File f) {
for (int i = 0; i < obj.length(); i++) {
Object o = obj.get(i);
if (o instanceof JSONObject) {
fixBlocks((JSONObject) o, f);
} else if (o instanceof JSONArray) {
fixBlocks((JSONArray) o, f);
}
}
}
} }

View File

@ -47,10 +47,8 @@ public interface DecreeSystem extends CommandExecutor, TabCompleter {
@Nullable @Nullable
@Override @Override
default List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { default List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
Iris.debug("TAB COMPLETE ======================================================");
KList<String> enhanced = new KList<>(args); KList<String> enhanced = new KList<>(args);
KList<String> v = getRoot().tabComplete(enhanced, enhanced.toString(" ")); KList<String> v = getRoot().tabComplete(enhanced, enhanced.toString(" "));
Iris.debug("input: '" + enhanced.toString(" ") + "'");
v.removeDuplicates(); v.removeDuplicates();
return v; return v;
} }

View File

@ -0,0 +1,61 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.decree.handlers;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeParameterHandler;
import com.volmit.iris.util.decree.exceptions.DecreeParsingException;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
public class BooleanHandler implements DecreeParameterHandler<Boolean> {
@Override
public KList<Boolean> getPossibilities() {
return null;
}
@Override
public String toString(Boolean aByte) {
return aByte.toString();
}
@Override
public Boolean parse(String in) throws DecreeParsingException {
try
{
return Boolean.parseBoolean(in);
}
catch(Throwable e)
{
throw new DecreeParsingException("Unable to parse boolean \"" + in + "\"");
}
}
@Override
public boolean supports(Class<?> type) {
return type.equals(Boolean.class) || type.equals(boolean.class);
}
@Override
public String getRandomDefault()
{
return M.r(0.5) + "";
}
}

View File

@ -367,14 +367,14 @@ public class VolmitSender implements CommandSender {
{ {
m.add((i.isNode() m.add((i.isNode()
? (i.getNode().getParameters().isNotEmpty()) ? (i.getNode().getParameters().isNotEmpty())
? "<gradient:#aebef2:#aef0f2>✦ <gradient:#5ef288:#99f25e>" ? "<#aebef2>✦ <#5ef288>"
+ i.getParentPath() + i.getParentPath()
+ " <gradient:#42ecf5:#428df5>" + " <#42ecf5>"
+ i.getName() + " " + i.getName() + " "
+ i.getNode().getParameters().shuffleCopy(RNG.r).convert((f) + i.getNode().getParameters().shuffleCopy(RNG.r).convert((f)
-> (f.isRequired() || RNG.r.b(0.5) -> (f.isRequired() || RNG.r.b(0.5)
? "<gradient:#f2e15e:#c4d45b>" + f.getNames().getRandom() + "=" ? "<#f2e15e>" + f.getNames().getRandom() + "="
+ "<gradient:#d665f0:#a37feb>" + f.example() + "<#d665f0>" + f.example()
: "")) : ""))
.toString(" ") .toString(" ")
: "" : ""
@ -419,7 +419,7 @@ public class VolmitSender implements CommandSender {
sendHeader(Form.capitalize(v.getName()) + " Help"); sendHeader(Form.capitalize(v.getName()) + " Help");
if(isPlayer() && v.getParent() != null) if(isPlayer() && v.getParent() != null)
{ {
sendMessageRaw("<hover:show_text:'"+"<gradient:#b54b38:#b5a038>Click to go back to <gradient:#3299bf:#323bbf>" + Form.capitalize(v.getParent().getName()) + " Help" +"'><click:run_command:" + v.getParent().getPath() + "><font:minecraft:uniform><gradient:#f58571:#f5cd71>〈 Back</click></hover>"); sendMessageRaw("<hover:show_text:'"+"<#b54b38>Click to go back to <#3299bf>" + Form.capitalize(v.getParent().getName()) + " Help" +"'><click:run_command:" + v.getParent().getPath() + "><font:minecraft:uniform><#f58571>〈 Back</click></hover>");
} }
for(VirtualDecreeCommand i : v.getNodes()) for(VirtualDecreeCommand i : v.getNodes())
@ -427,23 +427,23 @@ public class VolmitSender implements CommandSender {
if(isPlayer()) if(isPlayer())
{ {
//@builder //@builder
sendMessageRaw( String s = (
"<hover:show_text:'"+ "<hover:show_text:'"+
i.getNames().copy().reverse().convert((f) -> "<gradient:#42ecf5:#428df5>" + f).toString(", ") + "\n" i.getNames().copy().reverse().convert((f) -> "<#42ecf5>" + f).toString(", ") + "\n"
+ "<#3fe05a>✎ <gradient:#6ad97d:#6ad9d5><font:minecraft:uniform>" + i.getDescription() + "<reset>\n" + "<#3fe05a>✎ <#6ad97d><font:minecraft:uniform>" + i.getDescription() + "<reset>\n"
+ "<#bbe03f>✒ <gradient:#a8e0a2:#aef2cd>" + (i.isNode() + "<#bbe03f>✒ <#a8e0a2>" + (i.isNode()
? ((i.getNode().getParameters().isEmpty() ? ((i.getNode().getParameters().isEmpty()
? "<font:minecraft:uniform>There are no parameters.<reset>" ? "<font:minecraft:uniform>There are no parameters.<reset>"
: "<font:minecraft:uniform>Hover over all of the parameters to learn more.<reset>") + "\n") : "<font:minecraft:uniform>Hover over all of the parameters to learn more.<reset>") + "\n")
: "<font:minecraft:uniform>This is a command category. Run <reset><gradient:#98eda5:#ccf0bd>" + i.getPath()) : "<font:minecraft:uniform>This is a command category. Run <reset><#98eda5>" + i.getPath())
+ (i.isNode() + (i.isNode()
? (i.getNode().getParameters().isNotEmpty()) ? (i.getNode().getParameters().isNotEmpty())
? "<gradient:#aebef2:#aef0f2>✦ <gradient:#5ef288:#99f25e><font:minecraft:uniform>" ? "<#aebef2>✦ <#5ef288><font:minecraft:uniform>"
+ i.getParentPath() + i.getParentPath()
+ " <gradient:#42ecf5:#428df5>" + " <#42ecf5>"
+ i.getName() + " " + i.getName() + " "
+ i.getNode().getParameters().convert((f) + i.getNode().getParameters().convert((f)
-> "<gradient:#d665f0:#a37feb>" + f.example()) -> "<#d665f0>" + f.example())
.toString(" ") + "\n" .toString(" ") + "\n"
: "" : ""
: "") : "")
@ -453,13 +453,13 @@ public class VolmitSender implements CommandSender {
+ (i.isNode() ? + (i.isNode() ?
" " + i.getNode().getParameters().convert((f) " " + i.getNode().getParameters().convert((f)
-> "<hover:show_text:'" -> "<hover:show_text:'"
+ f.getNames().convert((ff) -> "<gradient:#d665f0:#a37feb>" + ff).toString(", ") + "\n" + f.getNames().convert((ff) -> "<#d665f0>" + ff).toString(", ") + "\n"
+ "<#3fe05a>✎ <gradient:#6ad97d:#6ad9d5><font:minecraft:uniform>" + f.getDescription() + "<reset>\n" + "<#3fe05a>✎ <#6ad97d><font:minecraft:uniform>" + f.getDescription() + "<reset>\n"
+ (f.isRequired() + (f.isRequired()
? "<#db4321>⚠ <gradient:#faa796:#f0ba78><font:minecraft:uniform>This parameter is required." ? "<#db4321>⚠ <#faa796><font:minecraft:uniform>This parameter is required."
: (f.hasDefault() : (f.hasDefault()
? "<#2181db>✔ <gradient:#78dcf0:#baf7e5><font:minecraft:uniform>Defaults to \""+f.getParam().defaultValue()+"\" if undefined." ? "<#2181db>✔ <#78dcf0><font:minecraft:uniform>Defaults to \""+f.getParam().defaultValue()+"\" if undefined."
: "<#a73abd>✔ <gradient:#78dcf0:#baf7e5><font:minecraft:uniform>This parameter is optional.")) : "<#a73abd>✔ <#78dcf0><font:minecraft:uniform>This parameter is optional."))
+ "'>" + "'>"
+ (f.isRequired() ? "<red>[" : "") + (f.isRequired() ? "<red>[" : "")
+ "<gradient:#d665f0:#a37feb>" + f.getName() + "<gradient:#d665f0:#a37feb>" + f.getName()
@ -469,6 +469,8 @@ public class VolmitSender implements CommandSender {
) )
); );
//@done //@done
sendMessageRaw(s);
System.out.println(s);
} }
else else

View File

@ -0,0 +1,76 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.scheduling.jobs;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import java.util.concurrent.CompletableFuture;
public interface Job
{
String getName();
void execute();
void completeWork();
int getTotalWork();
default int getWorkRemaining()
{
return getTotalWork() - getWorkCompleted();
}
int getWorkCompleted();
default String getProgressString()
{
return Form.pc(getProgress(), 0);
}
default double getProgress()
{
return (double)getWorkCompleted() / (double)getTotalWork();
}
default void execute(VolmitSender sender)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
CompletableFuture<?> f = J.afut(this::execute);
int c = J.ar(() -> {
if(sender.isPlayer())
{
sender.sendProgress(getProgress(), getName());
}
else
{
sender.sendMessage(getName() + ": " + getProgressString());
}
}, sender.isPlayer() ? 0 : 20);
f.whenComplete((fs, ff) -> {
J.car(c);
sender.sendMessage("Completed " + getName() + " in " + Form.duration(p.getMilliseconds(), 1));
});
}
}

View File

@ -0,0 +1,70 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.scheduling.jobs;
import com.volmit.iris.util.collection.KList;
public class JobCollection implements Job {
private final String name;
private String status;
private final KList<Job> jobs;
public JobCollection(String name, Job... jobs)
{
this(name, new KList<>(jobs));
}
public JobCollection(String name, KList<Job> jobs)
{
this.name = name;
status = null;
this.jobs = new KList<>(jobs);
}
@Override
public String getName() {
return status == null ? name : (name + "" + status);
}
@Override
public void execute() {
for(Job i : jobs)
{
status = i.getName();
i.execute();
}
status = null;
}
@Override
public void completeWork() {
}
@Override
public int getTotalWork() {
return jobs.stream().mapToInt(Job::getTotalWork).sum();
}
@Override
public int getWorkCompleted() {
return jobs.stream().mapToInt(Job::getWorkCompleted).sum();
}
}

View File

@ -0,0 +1,73 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.scheduling.jobs;
import com.volmit.iris.util.collection.KList;
public abstract class QueueJob<T> implements Job {
private final KList<T> queue;
private int totalWork;
private int completed;
public QueueJob()
{
totalWork = 0;
completed = 0;
queue = new KList<>();
}
public void queue(T t)
{
queue.add(t);
totalWork++;
}
public void queue(KList<T> f)
{
queue.addAll(f);
totalWork += f.size();
}
public abstract void execute(T t);
@Override
public void execute() {
totalWork = queue.size();
while(queue.isNotEmpty())
{
execute(queue.pop());
completeWork();
}
}
@Override
public void completeWork() {
completed++;
}
@Override
public int getTotalWork() {
return totalWork;
}
@Override
public int getWorkCompleted() {
return completed;
}
}

View File

@ -0,0 +1,58 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.scheduling.jobs;
public class SingleJob implements Job{
private boolean done;
private final String name;
private final Runnable runnable;
public SingleJob(String name, Runnable runnable)
{
this.name = name;
done = false;
this.runnable = runnable;
}
@Override
public String getName() {
return name;
}
@Override
public void execute() {
runnable.run();
completeWork();
}
@Override
public void completeWork() {
done = true;
}
@Override
public int getTotalWork() {
return 1;
}
@Override
public int getWorkCompleted() {
return done ? 1 : 0;
}
}