Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions multipacks-cli/src/main/java/multipacks/cli/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
import java.util.List;
import java.util.stream.Stream;

import multipacks.bundling.BundleIgnore;
import multipacks.bundling.BundleInclude;
import multipacks.bundling.legacy.BundleIgnore;
import multipacks.bundling.legacy.BundleInclude;
import multipacks.management.legacy.PacksRepository;
import multipacks.packs.legacy.PackIdentifier;
import multipacks.plugins.MultipacksDefaultPlugin;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
import java.util.Map.Entry;
import java.util.Scanner;

import multipacks.bundling.BundleIgnore;
import multipacks.bundling.BundleInclude;
import multipacks.bundling.PackBundler;
import multipacks.bundling.PackagingFailException;
import multipacks.bundling.legacy.BundleIgnore;
import multipacks.bundling.legacy.BundleInclude;
import multipacks.bundling.legacy.PackBundler;
import multipacks.bundling.legacy.PackagingFailException;
import multipacks.management.legacy.LocalRepository;
import multipacks.management.legacy.PacksRepository;
import multipacks.management.legacy.PacksUploadable;
Expand Down
184 changes: 184 additions & 0 deletions multipacks-engine/src/main/java/multipacks/bundling/Bundler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Copyright (c) 2020-2022 MangoPlex
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package multipacks.bundling;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.attribute.FileTime;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.stream.JsonWriter;

import multipacks.packs.Pack;
import multipacks.packs.meta.PackIdentifier;
import multipacks.platform.Platform;
import multipacks.repository.RepositoriesAccess;
import multipacks.repository.Repository;
import multipacks.repository.query.PackQuery;
import multipacks.utils.Messages;
import multipacks.versioning.Version;
import multipacks.vfs.Vfs;

/**
* @author nahkd
*
*/
public class Bundler {
public RepositoriesAccess repositoriesAccess;
public boolean includeLicenses = true;
public String[] licenseFileNames = new String[] {
"license", "licence", "license.txt", "licence.txt", "license.md", "licence.md"
};

public Bundler() {
}

public Bundler setRepositoriesAccess(RepositoriesAccess access) {
this.repositoriesAccess = access;
return this;
}

public Bundler setIncludeLicenses(boolean includeLicenses) {
this.includeLicenses = includeLicenses;
return this;
}

public Bundler fromPlatform(Platform platform) {
return this
.setRepositoriesAccess(platform);
}

private Vfs bundleWithoutFinish(Pack pack, Vfs licensesStore, Vfs packFinalOutput) {
// TODO: Return CompletableFuture instead
Vfs content = Vfs.createVirtualRoot();

if (pack.getIndex().dependencies.size() > 0) {
if (repositoriesAccess == null) throw new IllegalStateException("Repositories accessor is missing for this Bundler");

for (PackQuery depQuery : pack.getIndex().dependencies) {
for (Repository repo : repositoriesAccess.getRepositories()) {
try {
// TODO: improve dependencies resolution algorithm
// caching is needed.
Collection<PackIdentifier> ids = repo.search(depQuery).get();
if (ids.size() == 0) throw new RuntimeException(Messages.cantResolveDependency(depQuery)); // TODO

PackIdentifier latest = null;
for (PackIdentifier id : ids) {
if (latest == null || latest.packVersion.compareTo(id.packVersion) < 0) {
latest = id;
}
}

Pack dep = repo.obtain(latest).get();
Vfs.copyRecursive(bundleWithoutFinish(dep, licensesStore, null), content);
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}

Vfs thisPack = pack.createVfs(true);
List<Vfs> contentTypeDirs = Stream.of(thisPack.listFiles()).filter(v -> v.isDir()).toList();

for (Vfs contentTypeDir : contentTypeDirs) {
Vfs contentTypeDirOut = content.get(contentTypeDir.getName());
if (contentTypeDirOut == null) contentTypeDirOut = content.mkdir(contentTypeDir.getName());
Vfs.copyRecursive(contentTypeDir, contentTypeDirOut);
}

if (includeLicenses && licensesStore != null) {
for (String licenseFileName : licenseFileNames) {
Vfs f = thisPack.get(licenseFileName);
if (f != null) {
Vfs to = licensesStore.touch("license-" + pack.getIndex().name);
try (OutputStream streamOut = to.getOutputStream(); InputStream streamIn = f.getInputStream()) {
streamIn.transferTo(streamOut);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}

if (packFinalOutput != null) {
Vfs packPng = thisPack.get("pack.png");
if (packPng != null) {
Vfs packPngTo = content.touch("pack.png");
try (OutputStream streamOut = packPngTo.getOutputStream(); InputStream streamIn = packPng.getInputStream()) {
streamIn.transferTo(streamOut);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

return content;
}

public Vfs bundle(Pack pack, Version targetGameVersion) {
Vfs licenses = Vfs.createVirtualRoot();
Vfs finalOutput = Vfs.createVirtualRoot();
Vfs content = bundleWithoutFinish(pack, licenses, finalOutput);

Vfs.copyRecursive(licenses, content);
Vfs.copyRecursive(finalOutput, content);

Vfs packMcmeta = content.touch("pack.mcmeta");
try (OutputStream stream = packMcmeta.getOutputStream()) {
JsonObject json = pack.getIndex().buildPackMcmeta(targetGameVersion);
JsonWriter writer = new JsonWriter(new OutputStreamWriter(stream, StandardCharsets.UTF_8));
new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create().toJson(json, writer);
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}

return content;
}

public void bundleToStream(Pack pack, Version targetGameVersion, OutputStream stream) throws IOException {
ZipOutputStream zip = new ZipOutputStream(stream, StandardCharsets.UTF_8);
FileTime bundleTime = FileTime.fromMillis(System.currentTimeMillis());
Vfs content = bundle(pack, targetGameVersion);
vfsAddZipEntry(content, bundleTime, zip);
zip.finish();
}

private void vfsAddZipEntry(Vfs file, FileTime bundleTime, ZipOutputStream zip) throws IOException {
if (file.isDir()) {
for (Vfs child : file.listFiles()) vfsAddZipEntry(child, bundleTime, zip);
} else {
ZipEntry entry = new ZipEntry(file.getPathFromRoot().toString())
.setCreationTime(bundleTime)
.setLastModifiedTime(bundleTime);
zip.putNextEntry(entry);
zip.write(file.getContent());
zip.closeEntry();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package multipacks.bundling;
package multipacks.bundling.legacy;

public enum BundleIgnore {
LICENSES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package multipacks.bundling;
package multipacks.bundling.legacy;

public enum BundleInclude {
NONE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package multipacks.bundling;
package multipacks.bundling.legacy;

import java.util.HashMap;
import java.util.function.Supplier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package multipacks.bundling;
package multipacks.bundling.legacy;

import java.io.File;
import java.io.IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package multipacks.bundling;
package multipacks.bundling.legacy;

public class PackagingFailException extends RuntimeException {
private static final long serialVersionUID = 2251765351034996381L;
Expand Down
18 changes: 0 additions & 18 deletions multipacks-engine/src/main/java/multipacks/packs/Pack.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
*/
package multipacks.packs;

import java.util.List;
import java.util.stream.Stream;

import multipacks.packs.meta.PackIndex;
import multipacks.vfs.Vfs;

Expand All @@ -41,19 +38,4 @@ default Vfs createVfs(boolean applyModifiers) {
// TODO: implement modifiers here
return vfs;
}

/**
* Apply contents from this pack (with modifiers) to output VFS.
* @param outputVfs VFS that will be applied to.
*/
default void applyAsDependency(Vfs outputVfs) {
Vfs thisPack = createVfs(true);
List<Vfs> contentTypeDirs = Stream.of(thisPack.listFiles()).filter(v -> v.isDir()).toList();

for (Vfs contentTypeDir : contentTypeDirs) {
Vfs contentTypeDirOut = outputVfs.get(contentTypeDir.getName());
if (contentTypeDirOut == null) contentTypeDirOut = outputVfs.mkdir(contentTypeDir.getName());
Vfs.copyRecursive(contentTypeDir, contentTypeDirOut, true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import java.io.IOException;

import multipacks.bundling.BundleResult;
import multipacks.bundling.legacy.BundleResult;
import multipacks.vfs.legacy.VirtualFs;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import multipacks.bundling.BundleInclude;
import multipacks.bundling.legacy.BundleInclude;
import multipacks.utils.Selects;
import multipacks.versioning.GameVersions;
import multipacks.versioning.Version;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import multipacks.repository.query.PackQuery;
import multipacks.utils.Selects;
import multipacks.versioning.GameVersions;
import multipacks.versioning.Version;

/**
Expand All @@ -32,16 +33,21 @@
*
*/
public class PackIndex extends PackInfo {
public static final String FIELD_DESCRIPTION = "description";
public static final String FIELD_DEPENDENCIES = "dependencies";

public String description;
public final List<PackQuery> dependencies = new ArrayList<>();

public PackIndex(String name, Version packVersion, String author, Version sourceGameVersion) {
public PackIndex(String name, Version packVersion, String author, Version sourceGameVersion, String description) {
super(name, packVersion, author, sourceGameVersion);
this.description = description;
}

public PackIndex(JsonObject json) {
super(json);

description = Selects.getChain(json.get(FIELD_DESCRIPTION), j -> j.getAsString(), null);
Selects.getChain(json.get(FIELD_DEPENDENCIES), j -> {
j.getAsJsonArray().forEach(e -> dependencies.add(PackQuery.parse(e.getAsString())));
return null;
Expand All @@ -51,6 +57,7 @@ public PackIndex(JsonObject json) {
@Override
public JsonObject toJson() {
JsonObject json = super.toJson();
if (description != null && description.trim().length() > 0) json.addProperty(FIELD_DESCRIPTION, description);
if (dependencies.size() > 0) json.add(FIELD_DEPENDENCIES, queriesToJson());
return json;
}
Expand All @@ -60,4 +67,15 @@ private JsonArray queriesToJson() {
for (PackQuery query : dependencies) json.add(query.toString());
return json;
}

public JsonObject buildPackMcmeta(Version targetGameVersion) {
JsonObject root = new JsonObject();

JsonObject pack = new JsonObject();
pack.addProperty("pack_format", GameVersions.getPackFormat(targetGameVersion));
if (description != null && description.trim().length() > 0) pack.addProperty("description", description);
root.add("pack", pack);

return root;
}
}
28 changes: 28 additions & 0 deletions multipacks-engine/src/main/java/multipacks/platform/Platform.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2020-2022 MangoPlex
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package multipacks.platform;

import multipacks.repository.RepositoriesAccess;

/**
* Multipacks platform interface (some people may call this "Multipacks environment"). If you are creating your
* own platform, you have to implement this interface. Take a look at "Multipacks for Spigot" if you need an
* example.
* @author nahkd
*
*/
public interface Platform extends RepositoriesAccess {
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import multipacks.bundling.PackBundler;
import multipacks.bundling.legacy.PackBundler;
import multipacks.management.legacy.PacksRepository;
import multipacks.packs.legacy.DynamicPack;
import multipacks.packs.legacy.Pack;
Expand Down
Loading