mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-22 16:17:44 +00:00
O-o .o-o. o-O
This commit is contained in:
1 parent
cd05fd1bca
commit
4dea984d77
30 files changed
+2363
-176
No files matched your search
@@ -0,0 +1,110 @@
|
||||
package art.arcane.iris.core;
|
||||
|
||||
import art.arcane.iris.core.nms.datapack.v1217.DataFixerV1217;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.Assume;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisDatapackCompilerTest {
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void compilesInstalledAndWorldLocalPacksIntoOneDatapack() throws Exception {
|
||||
Path dataDirectory = temporaryFolder.newFolder("data").toPath();
|
||||
Path serverRoot = temporaryFolder.newFolder("server").toPath();
|
||||
createPack(dataDirectory.resolve("packs/alpha"), "alpha", "alpha_custom");
|
||||
createPack(dataDirectory.resolve("packs/beta"), "beta", "beta_custom");
|
||||
createPack(serverRoot.resolve("dimensions/example/world/iris/pack"), "world_local", "world_custom");
|
||||
|
||||
List<File> packRoots = IrisDatapackCompiler.collectPackRoots(dataDirectory, serverRoot);
|
||||
Path datapackRoot = temporaryFolder.newFolder("datapack").toPath();
|
||||
IrisDatapackCompiler.CompilationResult result = IrisDatapackCompiler.compile(
|
||||
packRoots,
|
||||
new KList<File>().qadd(datapackRoot.toFile()),
|
||||
new DataFixerV1217(),
|
||||
107,
|
||||
false
|
||||
);
|
||||
|
||||
assertEquals(3, result.packCount());
|
||||
assertEquals(3, result.dimensionCount());
|
||||
assertEquals(3, result.biomeCount());
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("pack.mcmeta")));
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("data/iris/dimension_type/alpha.json")));
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("data/iris/dimension_type/beta.json")));
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("data/iris/dimension_type/world_local.json")));
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("data/alpha/worldgen/biome/alpha_custom.json")));
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("data/beta/worldgen/biome/beta_custom.json")));
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("data/world_local/worldgen/biome/world_custom.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilesExternalPackFixtureWhenConfigured() throws Exception {
|
||||
String configuredPack = System.getenv("IRIS_TEST_PACK");
|
||||
Assume.assumeTrue(configuredPack != null && !configuredPack.isBlank());
|
||||
Path packRoot = Path.of(configuredPack).toAbsolutePath().normalize();
|
||||
Assume.assumeTrue(Files.isDirectory(packRoot.resolve("dimensions")));
|
||||
Path datapackRoot = temporaryFolder.newFolder("external-datapack").toPath();
|
||||
|
||||
IrisDatapackCompiler.CompilationResult result = IrisDatapackCompiler.compile(
|
||||
List.of(packRoot.toFile()),
|
||||
new KList<File>().qadd(datapackRoot.toFile()),
|
||||
new DataFixerV1217(),
|
||||
107,
|
||||
false
|
||||
);
|
||||
|
||||
assertTrue(result.packCount() > 0);
|
||||
assertTrue(result.dimensionCount() > 0);
|
||||
assertTrue(result.biomeCount() > 0);
|
||||
assertTrue(Files.isRegularFile(datapackRoot.resolve("pack.mcmeta")));
|
||||
}
|
||||
|
||||
private static void createPack(Path root, String dimensionKey, String biomeId) throws Exception {
|
||||
Files.createDirectories(root.resolve("dimensions"));
|
||||
Files.createDirectories(root.resolve("biomes"));
|
||||
Files.writeString(
|
||||
root.resolve("dimensions").resolve(dimensionKey + ".json"),
|
||||
"""
|
||||
{
|
||||
"name": "Test Dimension",
|
||||
"environment": "NORMAL",
|
||||
"logicalHeight": 256,
|
||||
"dimensionHeight": {
|
||||
"min": -64,
|
||||
"max": 320
|
||||
}
|
||||
}
|
||||
""",
|
||||
StandardCharsets.UTF_8
|
||||
);
|
||||
Files.writeString(
|
||||
root.resolve("biomes/test.json"),
|
||||
"""
|
||||
{
|
||||
"name": "Test Biome",
|
||||
"derivative": "minecraft:plains",
|
||||
"vanillaDerivative": "minecraft:plains",
|
||||
"customDerivitives": [
|
||||
{
|
||||
"id": "%s"
|
||||
}
|
||||
]
|
||||
}
|
||||
""".formatted(biomeId),
|
||||
StandardCharsets.UTF_8
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package art.arcane.iris.core.loader;
|
||||
|
||||
import art.arcane.iris.engine.framework.MeteredCache;
|
||||
import art.arcane.iris.engine.framework.PreservationRegistry;
|
||||
import art.arcane.iris.spi.IrisServices;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
public class IrisDataDatapackCompilerCacheTest {
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private IrisData runtimeData;
|
||||
private IrisData compilerData;
|
||||
|
||||
@Before
|
||||
public void registerPreservationService() {
|
||||
IrisServices.register(PreservationRegistry.class, new NoOpPreservationRegistry());
|
||||
}
|
||||
|
||||
@After
|
||||
public void closeDataAndServices() {
|
||||
if (compilerData != null) {
|
||||
compilerData.close();
|
||||
}
|
||||
if (runtimeData != null) {
|
||||
runtimeData.close();
|
||||
}
|
||||
IrisServices.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closingCompilerDoesNotEvictRuntimeDataForSameDirectory() throws Exception {
|
||||
File packDirectory = temporaryFolder.newFolder("pack");
|
||||
runtimeData = IrisData.get(packDirectory);
|
||||
compilerData = IrisData.openDatapackCompiler(packDirectory);
|
||||
|
||||
compilerData.close();
|
||||
compilerData = null;
|
||||
|
||||
assertSame(runtimeData, IrisData.getLoaded(packDirectory).orElseThrow());
|
||||
}
|
||||
|
||||
private static final class NoOpPreservationRegistry implements PreservationRegistry {
|
||||
@Override
|
||||
public void register(Thread thread) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(ExecutorService service) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCache(MeteredCache cache) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dereference() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+389
@@ -0,0 +1,389 @@
|
||||
package art.arcane.iris.core.pack;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DefaultPackBootstrapProvisionerTest {
|
||||
@Test
|
||||
public void coldInstallUsesFreshCacheWithoutSecondRequest() throws Exception {
|
||||
byte[] archive = packArchive("overworld", "bootstrap_biome");
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(archive, requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-cold");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions options = options(server, root, Duration.ofHours(1));
|
||||
DefaultPackBootstrapProvisioner.ProvisionResult installed = DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
);
|
||||
DefaultPackBootstrapProvisioner.ProvisionResult unchanged = DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
);
|
||||
|
||||
assertEquals(DefaultPackBootstrapProvisioner.ProvisionStatus.INSTALLED, installed.status());
|
||||
assertEquals(DefaultPackBootstrapProvisioner.ProvisionStatus.UNCHANGED, unchanged.status());
|
||||
assertEquals(1, requests.get());
|
||||
assertTrue(Files.isRegularFile(installed.packRoot().resolve("dimensions/overworld.json")));
|
||||
assertTrue(Files.isRegularFile(installed.datapackRoot().resolve("pack.mcmeta")));
|
||||
assertTrue(Files.isRegularFile(installed.datapackRoot().resolve("data/overworld/worldgen/biome/bootstrap_biome.json")));
|
||||
assertTrue(DefaultPackBootstrapProvisioner.isProvisioned(dataDirectory));
|
||||
assertTrue(DefaultPackBootstrapProvisioner.wasProvisionedThisStartup());
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void corruptCacheRedownloadsAndRepairsArchive() throws Exception {
|
||||
byte[] archive = packArchive("overworld", "bootstrap_biome");
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(archive, requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-corrupt-cache");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions options = options(server, root, Duration.ofHours(1));
|
||||
DefaultPackBootstrapProvisioner.provision(dataDirectory, ignored -> {
|
||||
}, options);
|
||||
Path cache = dataDirectory.resolve("cache/bootstrap/default-overworld.zip");
|
||||
Files.writeString(cache, "corrupt", StandardCharsets.UTF_8);
|
||||
|
||||
DefaultPackBootstrapProvisioner.provision(dataDirectory, ignored -> {
|
||||
}, options);
|
||||
|
||||
assertEquals(2, requests.get());
|
||||
try (ZipInputStream zip = new ZipInputStream(Files.newInputStream(cache))) {
|
||||
assertTrue(zip.getNextEntry() != null);
|
||||
}
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void traversalArchiveFailsWithoutMarkerOrEscape() throws Exception {
|
||||
LinkedHashMap<String, String> files = new LinkedHashMap<>();
|
||||
files.put("dimensions/overworld.json", dimensionJson("overworld"));
|
||||
files.put("../escape.txt", "unsafe");
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(zip(files), requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-traversal");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions options = options(server, root, Duration.ZERO);
|
||||
|
||||
assertThrows(IOException.class, () -> DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
));
|
||||
assertFalse(Files.exists(dataDirectory.resolve("bootstrap/provisioned.properties")));
|
||||
assertFalse(Files.exists(root.resolve("escape.txt")));
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingDimensionLayoutFailsWithoutInstallingPack() throws Exception {
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(zip(Map.of("README.md", "not an Iris pack")), requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-layout");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions options = options(server, root, Duration.ZERO);
|
||||
|
||||
assertThrows(IOException.class, () -> DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
));
|
||||
assertFalse(Files.exists(dataDirectory.resolve("packs/overworld")));
|
||||
assertFalse(Files.exists(dataDirectory.resolve("bootstrap/provisioned.properties")));
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existingSymlinkedPackIsCompiledWithoutDownloadOrReplacement() throws Exception {
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(packArchive("remote", "remote_biome"), requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-symlink");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
Path target = root.resolve("custom-overworld");
|
||||
writePack(target, "overworld", "local_biome");
|
||||
Files.createDirectories(dataDirectory.resolve("packs"));
|
||||
Path link = dataDirectory.resolve("packs/overworld");
|
||||
Files.createSymbolicLink(link, target);
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions options = options(server, root, Duration.ZERO);
|
||||
|
||||
DefaultPackBootstrapProvisioner.ProvisionResult result = DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
);
|
||||
|
||||
assertEquals(0, requests.get());
|
||||
assertTrue(Files.isSymbolicLink(link));
|
||||
assertEquals(target.toRealPath(), link.toRealPath());
|
||||
assertTrue(Files.isRegularFile(result.datapackRoot().resolve("data/overworld/worldgen/biome/local_biome.json")));
|
||||
|
||||
Files.writeString(target.resolve("biomes/local.json"), biomeJson("changed_biome"), StandardCharsets.UTF_8);
|
||||
assertFalse(DefaultPackBootstrapProvisioner.isProvisioned(dataDirectory));
|
||||
DefaultPackBootstrapProvisioner.ProvisionResult updated = DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
);
|
||||
assertEquals(DefaultPackBootstrapProvisioner.ProvisionStatus.UPDATED, updated.status());
|
||||
assertEquals(0, requests.get());
|
||||
assertTrue(Files.isSymbolicLink(link));
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalPackRebuildsAggregateWithoutNetwork() throws Exception {
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(packArchive("overworld", "first_biome"), requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-aggregate");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions options = options(server, root, Duration.ofHours(1));
|
||||
DefaultPackBootstrapProvisioner.provision(dataDirectory, ignored -> {
|
||||
}, options);
|
||||
writePack(dataDirectory.resolve("packs/second"), "second", "second_biome");
|
||||
writePack(root.resolve("dimensions/example/world/iris/pack"), "world_local", "world_local_biome");
|
||||
|
||||
assertFalse(DefaultPackBootstrapProvisioner.isProvisioned(dataDirectory));
|
||||
DefaultPackBootstrapProvisioner.ProvisionResult updated = DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
);
|
||||
|
||||
assertEquals(DefaultPackBootstrapProvisioner.ProvisionStatus.UPDATED, updated.status());
|
||||
assertEquals(1, requests.get());
|
||||
assertTrue(Files.isRegularFile(updated.datapackRoot().resolve("data/second/worldgen/biome/second_biome.json")));
|
||||
assertTrue(Files.isRegularFile(updated.datapackRoot().resolve("data/world_local/worldgen/biome/world_local_biome.json")));
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void localEditRelinquishesManagedOwnershipWithoutRemoteReplacement() throws Exception {
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(packArchive("overworld", "managed_biome"), requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-managed-edit");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions initialOptions = options(server, root, Duration.ofHours(1));
|
||||
DefaultPackBootstrapProvisioner.provision(dataDirectory, ignored -> {
|
||||
}, initialOptions);
|
||||
Path editedBiome = dataDirectory.resolve("packs/overworld/biomes/local.json");
|
||||
Files.writeString(editedBiome, biomeJson("locally_edited_biome"), StandardCharsets.UTF_8);
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions refreshOptions = options(server, root, Duration.ZERO);
|
||||
|
||||
DefaultPackBootstrapProvisioner.ProvisionResult updated = DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
refreshOptions
|
||||
);
|
||||
|
||||
assertEquals(1, requests.get());
|
||||
assertTrue(Files.readString(editedBiome).contains("locally_edited_biome"));
|
||||
assertTrue(Files.isRegularFile(updated.datapackRoot().resolve("data/overworld/worldgen/biome/locally_edited_biome.json")));
|
||||
Properties marker = new Properties();
|
||||
try (java.io.InputStream input = Files.newInputStream(dataDirectory.resolve("bootstrap/provisioned.properties"))) {
|
||||
marker.load(input);
|
||||
}
|
||||
assertEquals("false", marker.getProperty("managedDefault"));
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failedAggregateCompilationPreservesPreviousOutputAndMarker() throws Exception {
|
||||
AtomicInteger requests = new AtomicInteger();
|
||||
HttpServer server = server(packArchive("overworld", "first_biome"), requests);
|
||||
Path root = Files.createTempDirectory("iris-bootstrap-rollback");
|
||||
try {
|
||||
Path dataDirectory = root.resolve("plugins/Iris");
|
||||
DefaultPackBootstrapProvisioner.ProvisionOptions options = options(server, root, Duration.ofHours(1));
|
||||
DefaultPackBootstrapProvisioner.ProvisionResult first = DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
);
|
||||
byte[] marker = Files.readAllBytes(dataDirectory.resolve("bootstrap/provisioned.properties"));
|
||||
byte[] metadata = Files.readAllBytes(first.datapackRoot().resolve("pack.mcmeta"));
|
||||
Path invalidPack = dataDirectory.resolve("packs/invalid");
|
||||
Files.createDirectories(invalidPack.resolve("dimensions"));
|
||||
Files.writeString(invalidPack.resolve("dimensions/broken.json"), "{", StandardCharsets.UTF_8);
|
||||
|
||||
assertThrows(IOException.class, () -> DefaultPackBootstrapProvisioner.provision(
|
||||
dataDirectory,
|
||||
ignored -> {
|
||||
},
|
||||
options
|
||||
));
|
||||
assertTrue(java.util.Arrays.equals(marker, Files.readAllBytes(dataDirectory.resolve("bootstrap/provisioned.properties"))));
|
||||
assertTrue(java.util.Arrays.equals(metadata, Files.readAllBytes(first.datapackRoot().resolve("pack.mcmeta"))));
|
||||
} finally {
|
||||
server.stop(0);
|
||||
delete(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvesConfiguredLevelRootFromServerProperties() throws Exception {
|
||||
Path serverRoot = Files.createTempDirectory("iris-bootstrap-level-root");
|
||||
try {
|
||||
Files.writeString(
|
||||
serverRoot.resolve("server.properties"),
|
||||
"level-name=levels/primary\n",
|
||||
StandardCharsets.UTF_8
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
serverRoot.resolve("levels/primary").normalize(),
|
||||
DefaultPackBootstrapProvisioner.resolveLevelRoot(serverRoot)
|
||||
);
|
||||
} finally {
|
||||
delete(serverRoot);
|
||||
}
|
||||
}
|
||||
|
||||
private static DefaultPackBootstrapProvisioner.ProvisionOptions options(
|
||||
HttpServer server,
|
||||
Path serverRoot,
|
||||
Duration refreshInterval
|
||||
) {
|
||||
URI source = URI.create("http://127.0.0.1:" + server.getAddress().getPort() + "/overworld.zip");
|
||||
return new DefaultPackBootstrapProvisioner.ProvisionOptions(
|
||||
source,
|
||||
HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(2)).build(),
|
||||
Clock.fixed(Instant.parse("2026-07-12T12:00:00Z"), ZoneOffset.UTC),
|
||||
refreshInterval,
|
||||
Duration.ofSeconds(2),
|
||||
1,
|
||||
Duration.ZERO,
|
||||
8L * 1024L * 1024L,
|
||||
serverRoot
|
||||
);
|
||||
}
|
||||
|
||||
private static HttpServer server(byte[] response, AtomicInteger requests) throws IOException {
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
|
||||
server.createContext("/overworld.zip", exchange -> respond(exchange, response, requests));
|
||||
server.start();
|
||||
return server;
|
||||
}
|
||||
|
||||
private static void respond(HttpExchange exchange, byte[] response, AtomicInteger requests) throws IOException {
|
||||
requests.incrementAndGet();
|
||||
exchange.getResponseHeaders().add("Content-Type", "application/zip");
|
||||
exchange.sendResponseHeaders(200, response.length);
|
||||
exchange.getResponseBody().write(response);
|
||||
exchange.close();
|
||||
}
|
||||
|
||||
private static byte[] packArchive(String dimensionKey, String biomeId) throws IOException {
|
||||
LinkedHashMap<String, String> files = new LinkedHashMap<>();
|
||||
files.put("dimensions/" + dimensionKey + ".json", dimensionJson(dimensionKey));
|
||||
files.put("regions/local.json", "{\"name\":\"Local\",\"landBiomes\":[\"local\"]}");
|
||||
files.put("biomes/local.json", biomeJson(biomeId));
|
||||
return zip(files);
|
||||
}
|
||||
|
||||
private static void writePack(Path root, String dimensionKey, String biomeId) throws IOException {
|
||||
Files.createDirectories(root.resolve("dimensions"));
|
||||
Files.createDirectories(root.resolve("regions"));
|
||||
Files.createDirectories(root.resolve("biomes"));
|
||||
Files.writeString(root.resolve("dimensions/" + dimensionKey + ".json"), dimensionJson(dimensionKey), StandardCharsets.UTF_8);
|
||||
Files.writeString(root.resolve("regions/local.json"), "{\"name\":\"Local\",\"landBiomes\":[\"local\"]}", StandardCharsets.UTF_8);
|
||||
Files.writeString(root.resolve("biomes/local.json"), biomeJson(biomeId), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static String dimensionJson(String name) {
|
||||
return "{\"name\":\"" + name + "\",\"regions\":[\"local\"],\"logicalHeight\":256,\"dimensionHeight\":{\"min\":-64,\"max\":320}}";
|
||||
}
|
||||
|
||||
private static String biomeJson(String biomeId) {
|
||||
return "{\"name\":\"Local\",\"derivative\":\"minecraft:plains\",\"customDerivitives\":[{\"id\":\""
|
||||
+ biomeId + "\",\"category\":\"plains\"}]}";
|
||||
}
|
||||
|
||||
private static byte[] zip(Map<String, String> files) throws IOException {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zip = new ZipOutputStream(bytes)) {
|
||||
for (Map.Entry<String, String> entry : files.entrySet()) {
|
||||
zip.putNextEntry(new ZipEntry(entry.getKey()));
|
||||
zip.write(entry.getValue().getBytes(StandardCharsets.UTF_8));
|
||||
zip.closeEntry();
|
||||
}
|
||||
}
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
|
||||
private static void delete(Path root) throws IOException {
|
||||
if (!Files.exists(root)) {
|
||||
return;
|
||||
}
|
||||
try (java.util.stream.Stream<Path> stream = Files.walk(root)) {
|
||||
for (Path path : stream.sorted(java.util.Comparator.reverseOrder()).toList()) {
|
||||
Files.deleteIfExists(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,27 @@ package art.arcane.iris.core.pack;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PackDownloaderTest {
|
||||
@Test
|
||||
public void resolvesDefaultOverworldBetaRelease() {
|
||||
assertEquals(
|
||||
"https://github.com/IrisDimensions/overworld/releases/download/beta/overworld.zip",
|
||||
PackDownloader.defaultOverworldReleaseUrl()
|
||||
);
|
||||
assertTrue(PackDownloader.isDefaultOverworld("overworld"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsOtherPacksAsDefaultOverworld() {
|
||||
assertFalse(PackDownloader.isDefaultOverworld("theend"));
|
||||
assertFalse(PackDownloader.isDefaultOverworld(""));
|
||||
assertFalse(PackDownloader.isDefaultOverworld(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvesBranchReference() {
|
||||
assertEquals(
|
||||
|
||||
@@ -41,7 +41,7 @@ public class IrisDimensionBiomeTagTest {
|
||||
IrisDimension.installBiomeTags(temporaryFolder.getRoot(), "overworld:swamp", tags);
|
||||
|
||||
Path output = temporaryFolder.getRoot().toPath()
|
||||
.resolve("iris/data/minecraft/tags/worldgen/biome/allows_surface_slime_spawns.json");
|
||||
.resolve("data/minecraft/tags/worldgen/biome/allows_surface_slime_spawns.json");
|
||||
JSONObject tag = new JSONObject(Files.readString(output, StandardCharsets.UTF_8));
|
||||
|
||||
assertEquals("overworld:swamp", tag.getJSONArray("values").getString(0));
|
||||
|
||||
Reference in new issue
Block a user