Iris/src/main/java/com/volmit/iris/manager/ProjectManager.java
2021-07-14 02:34:13 -04:00

420 lines
14 KiB
Java

package com.volmit.iris.manager;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.scaffold.cache.AtomicCache;
import com.volmit.iris.util.*;
import lombok.Data;
import org.zeroturnaround.zip.ZipUtil;
import org.zeroturnaround.zip.commons.FileUtils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.UUID;
@Data
public class ProjectManager {
public static final String LISTING = "https://raw.githubusercontent.com/IrisDimensions/_listing/main/listing-v2.json";
public static final String WORKSPACE_NAME = "packs";
private KMap<String, String> cacheListing = null;
private IrisProject activeProject;
private static final AtomicCache<Integer> counter = new AtomicCache<>();
public ProjectManager() {
if (IrisSettings.get().isStudio()) {
J.a(() ->
{
File ignore = getWorkspaceFile(".gitignore");
if (!ignore.exists()) {
File m = Iris.getCached("Pack Ignore (.gitignore)", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/packignore.ignore");
if (m != null) {
try {
IO.copyFile(m, ignore);
} catch (IOException e) {
}
}
}
});
}
}
public static int countUniqueDimensions() {
int vv = counter.aquire(() -> {
int v = 0;
try {
for (File i : Iris.instance.getDataFolder(WORKSPACE_NAME).listFiles()) {
try {
if (i.isDirectory() && i.list().length > 0 && !Iris.proj.getListing(true).containsKey(i.getName())) {
v++;
}
} catch (Throwable ignored) {
}
}
} catch (Throwable ignored) {
}
return v;
});
return vv;
}
public IrisDimension installIntoWorld(MortarSender sender, String type, File folder) {
sender.sendMessage("Looking for Package: " + type);
File iris = new File(folder, "iris");
File irispack = new File(folder, "iris/pack");
IrisDimension dim = IrisDataManager.loadAnyDimension(type);
if (dim == null) {
for (File i : Iris.proj.getWorkspaceFolder().listFiles()) {
if (i.isFile() && i.getName().equals(type + ".iris")) {
sender.sendMessage("Found " + type + ".iris in " + ProjectManager.WORKSPACE_NAME + " folder");
ZipUtil.unpack(i, irispack);
break;
}
}
} else {
sender.sendMessage("Found " + type + " dimension in " + ProjectManager.WORKSPACE_NAME + " folder. Repackaging");
File f = new IrisProject(new File(getWorkspaceFolder(), type)).getPath();
try {
FileUtils.copyDirectory(f, irispack);
} catch (IOException e) {
}
}
File dimf = new File(irispack, "dimensions/" + type + ".json");
if (!dimf.exists() || !dimf.isFile()) {
Iris.proj.downloadSearch(sender, type, false);
File downloaded = Iris.proj.getWorkspaceFolder(type);
for (File i : downloaded.listFiles()) {
if (i.isFile()) {
try {
FileUtils.copyFile(i, new File(irispack, i.getName()));
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
FileUtils.copyDirectory(i, new File(irispack, i.getName()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
IO.delete(downloaded);
}
if (!dimf.exists() || !dimf.isFile()) {
sender.sendMessage("Can't find the " + dimf.getName() + " in the dimensions folder of this pack! Failed!");
return null;
}
IrisDataManager dm = new IrisDataManager(irispack);
dim = dm.getDimensionLoader().load(type);
if (dim == null) {
sender.sendMessage("Can't load the dimension! Failed!");
return null;
}
sender.sendMessage(folder.getName() + " type installed. ");
return dim;
}
public void downloadSearch(MortarSender sender, String key, boolean trim) {
downloadSearch(sender, key, trim, false);
}
public void downloadSearch(MortarSender sender, String key, boolean trim, boolean forceOverwrite) {
String url = "?";
try {
url = getListing(false).get(key);
url = url == null ? key : url;
Iris.info("Assuming URL " + url);
String branch = "master";
String[] nodes = url.split("\\Q/\\E");
String repo = nodes[0] + "/" + nodes[1];
branch = nodes.length > 2 ? nodes[2] : branch;
download(sender, repo, branch, trim, forceOverwrite);
} catch (Throwable e) {
e.printStackTrace();
sender.sendMessage("Failed to download '" + key + "' from " + url + ".");
}
}
public void download(MortarSender sender, String repo, String branch, boolean trim) throws JsonSyntaxException, IOException {
download(sender, repo, branch, trim, false);
}
public void download(MortarSender sender, String repo, String branch, boolean trim, boolean forceOverwrite) throws JsonSyntaxException, IOException {
String url = "https://codeload.github.com/" + repo + "/zip/refs/heads/" + branch;
sender.sendMessage("Downloading " + url);
File zip = Iris.getNonCachedFile("pack-" + trim + "-" + repo, url);
File temp = Iris.getTemp();
File work = new File(temp, "dl-" + UUID.randomUUID());
File packs = getWorkspaceFolder();
sender.sendMessage("Unpacking " + repo);
try {
ZipUtil.unpack(zip, work);
} catch (Throwable e) {
e.printStackTrace();
sender.sendMessage(
"Issue when unpacking. Please check/do the following:" +
"\n1. Do you have a functioning internet connection?" +
"\n2. Did the download corrupt?" +
"\n3. Try deleting the */plugins/iris/packs folder and re-download." +
"\n4. Download the pack from the GitHub repo: https://github.com/IrisDimensions/overworld" +
"\n5. Contact support (if all other options do not help)"
);
}
File dir = null;
File[] zipFiles = work.listFiles();
if (zipFiles == null) {
sender.sendMessage("No files were extracted from the zip file.");
return;
}
try {
dir = zipFiles.length == 1 && zipFiles[0].isDirectory() ? zipFiles[0] : null;
} catch (NullPointerException e) {
sender.sendMessage("Error when finding home directory. Are there any non-text characters in the file name?");
return;
}
if (dir == null) {
sender.sendMessage("Invalid Format. Missing root folder or too many folders!");
return;
}
File dimensions = new File(dir, "dimensions");
if (!(dimensions.exists() && dimensions.isDirectory())) {
sender.sendMessage("Invalid Format. Missing dimensions folder");
return;
}
if (dimensions.listFiles() == null) {
sender.sendMessage("No dimension file found in the extracted zip file.");
sender.sendMessage("Check it is there on GitHub and report this to staff!");
} else if (dimensions.listFiles().length != 1) {
sender.sendMessage("Dimensions folder must have 1 file in it");
return;
}
File dim = dimensions.listFiles()[0];
if (!dim.isFile()) {
sender.sendMessage("Invalid dimension (folder) in dimensions folder");
return;
}
String key = dim.getName().split("\\Q.\\E")[0];
IrisDimension d = new Gson().fromJson(IO.readAll(dim), IrisDimension.class);
sender.sendMessage("Importing " + d.getName() + " (" + key + ")");
File packEntry = new File(packs, key);
if (forceOverwrite) {
IO.delete(packEntry);
}
if (IrisDataManager.loadAnyDimension(key) != null) {
sender.sendMessage("Another dimension in the packs folder is already using the key " + key + " IMPORT FAILED!");
return;
}
if (packEntry.exists() && packEntry.listFiles().length > 0) {
sender.sendMessage("Another pack is using the key " + key + ". IMPORT FAILED!");
return;
}
FileUtils.copyDirectory(dir, packEntry);
if (trim) {
sender.sendMessage("Trimming " + key);
File cp = compilePackage(sender, key, false, false);
IO.delete(packEntry);
packEntry.mkdirs();
ZipUtil.unpack(cp, packEntry);
}
sender.sendMessage("Successfully Aquired " + d.getName());
}
public KMap<String, String> getListing(boolean cached) {
if (cached && cacheListing != null) {
return cacheListing;
}
JSONObject a;
if (cached) {
a = new JSONObject(Iris.getCached("cachedlisting", LISTING));
} else {
a = new JSONObject(Iris.getNonCached(true + "listing", LISTING));
}
KMap<String, String> l = new KMap<>();
for (String i : a.keySet()) {
l.put(i, a.getString(i));
}
return l;
}
public boolean isProjectOpen() {
return activeProject != null && activeProject.isOpen();
}
public void open(MortarSender sender, String dimm) {
try {
open(sender, dimm, () ->
{
if (sender.isPlayer()) {
}
});
} catch (Exception e) {
sender.sendMessage("Error when creating studio world:");
e.printStackTrace();
}
}
public void open(MortarSender sender, String dimm, Runnable onDone) {
if (isProjectOpen()) {
close();
}
IrisProject project = new IrisProject(new File(getWorkspaceFolder(), dimm));
activeProject = project;
project.open(sender, onDone);
}
public File getWorkspaceFolder(String... sub) {
return Iris.instance.getDataFolderList(WORKSPACE_NAME, sub);
}
public File getWorkspaceFile(String... sub) {
return Iris.instance.getDataFileList(WORKSPACE_NAME, sub);
}
public void close() {
if (isProjectOpen()) {
activeProject.close();
activeProject = null;
}
}
public File compilePackage(MortarSender sender, String d, boolean obfuscate, boolean minify) {
return new IrisProject(new File(getWorkspaceFolder(), d)).compilePackage(sender, obfuscate, minify);
}
public void createFrom(String existingPack, String newName) {
File importPack = getWorkspaceFolder(existingPack);
File newPack = getWorkspaceFolder(newName);
if (importPack.listFiles().length == 0) {
Iris.warn("Couldn't find the pack to create a new dimension from.");
return;
}
try {
FileUtils.copyDirectory(importPack, newPack, new FileFilter() {
@Override
public boolean accept(File pathname) {
return !pathname.getAbsolutePath().contains(".git");
}
}, false);
} catch (IOException e) {
e.printStackTrace();
}
new File(importPack, existingPack + ".code-workspace").delete();
File dimFile = new File(importPack, "dimensions/" + existingPack + ".json");
File newDimFile = new File(newPack, "dimensions/" + newName + ".json");
try {
FileUtils.copyFile(dimFile, newDimFile);
} catch (IOException e) {
e.printStackTrace();
}
new File(newPack, "dimensions/" + existingPack + ".json").delete();
try {
JSONObject json = new JSONObject(IO.readAll(newDimFile));
if (json.has("name")) {
json.put("name", Form.capitalizeWords(newName.replaceAll("\\Q-\\E", " ")));
IO.writeAll(newDimFile, json.toString(4));
}
} catch (JSONException | IOException e) {
e.printStackTrace();
}
try {
IrisProject p = new IrisProject(getWorkspaceFolder(newName));
JSONObject ws = p.createCodeWorkspaceConfig();
IO.writeAll(getWorkspaceFile(newName, newName + ".code-workspace"), ws.toString(0));
} catch (JSONException | IOException e) {
e.printStackTrace();
}
}
public void create(MortarSender sender, String s, String downloadable) {
boolean shouldDelete = false;
File importPack = getWorkspaceFolder(downloadable);
if (importPack.listFiles().length == 0) {
downloadSearch(sender, downloadable, false);
if (importPack.listFiles().length > 0) {
shouldDelete = true;
}
}
if (importPack.listFiles().length == 0) {
sender.sendMessage("Couldn't find the pack to create a new dimension from.");
return;
}
File importDimensionFile = new File(importPack, "dimensions/" + downloadable + ".json");
if (!importDimensionFile.exists()) {
sender.sendMessage("Missing Imported Dimension File");
return;
}
sender.sendMessage("Importing " + downloadable + " into new Project " + s);
createFrom(downloadable, s);
if (shouldDelete) {
importPack.delete();
}
open(sender, s);
}
public void create(MortarSender sender, String s) {
create(sender, s, "example");
}
public void updateWorkspace() {
if (isProjectOpen()) {
activeProject.updateWorkspace();
}
}
}