mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-11 19:14:11 +00:00
[VERY VERY VERY BAD IDEA]
This commit is contained in:
@@ -32,7 +32,6 @@ dependencies {
|
||||
implementation(gradleApi())
|
||||
implementation('org.ow2.asm:asm:9.10.1')
|
||||
implementation('org.apache.commons:commons-compress:1.28.0')
|
||||
implementation('com.github.VolmitSoftware:NMSTools:c88961416f')
|
||||
implementation('io.papermc.paperweight:paperweight-userdev:2.0.0-beta.21')
|
||||
testImplementation('junit:junit:4.13.2')
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
public class Config {
|
||||
public int jvm = 25;
|
||||
public NMSBinding.Type type = NMSBinding.Type.DIRECT;
|
||||
public String version;
|
||||
}
|
||||
@@ -1,285 +0,0 @@
|
||||
import com.volmit.nmstools.NMSToolsExtension;
|
||||
import com.volmit.nmstools.NMSToolsPlugin;
|
||||
import io.papermc.paperweight.userdev.PaperweightUser;
|
||||
import io.papermc.paperweight.userdev.PaperweightUserDependenciesExtension;
|
||||
import io.papermc.paperweight.userdev.PaperweightUserExtension;
|
||||
import io.papermc.paperweight.userdev.attribute.Obfuscation;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Named;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.attributes.Bundling;
|
||||
import org.gradle.api.attributes.Category;
|
||||
import org.gradle.api.attributes.LibraryElements;
|
||||
import org.gradle.api.attributes.Usage;
|
||||
import org.gradle.api.file.FileTree;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.plugins.ExtraPropertiesExtension;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion;
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService;
|
||||
import org.gradle.work.DisableCachingByDefault;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static io.papermc.paperweight.util.constants.ConstantsKt.REOBF_CONFIG;
|
||||
|
||||
public class NMSBinding implements Plugin<Project> {
|
||||
private static final String NEW_LINE = System.lineSeparator();
|
||||
private static final byte[] NEW_LINE_BYTES = NEW_LINE.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
@Override
|
||||
public void apply(Project target) {
|
||||
ExtraPropertiesExtension extra = target.getExtensions().getExtraProperties();
|
||||
Object configValue = extra.has("nms") ? extra.get("nms") : null;
|
||||
if (!(configValue instanceof Config)) {
|
||||
throw new GradleException("No NMS binding configuration found");
|
||||
}
|
||||
|
||||
Config config = (Config) configValue;
|
||||
int jvm = config.jvm;
|
||||
Type type = config.type;
|
||||
|
||||
if (type == Type.USER_DEV) {
|
||||
target.getPlugins().apply(PaperweightUser.class);
|
||||
|
||||
PaperweightUserDependenciesExtension dependenciesExtension =
|
||||
target.getDependencies().getExtensions().findByType(PaperweightUserDependenciesExtension.class);
|
||||
if (dependenciesExtension != null) {
|
||||
dependenciesExtension.paperDevBundle(config.version);
|
||||
}
|
||||
|
||||
JavaPluginExtension java = target.getExtensions().findByType(JavaPluginExtension.class);
|
||||
if (java == null) {
|
||||
throw new GradleException("Java plugin not found");
|
||||
}
|
||||
|
||||
java.getToolchain().getLanguageVersion().set(JavaLanguageVersion.of(jvm));
|
||||
JavaToolchainService javaToolchains = target.getExtensions().getByType(JavaToolchainService.class);
|
||||
target.getExtensions().configure(PaperweightUserExtension.class,
|
||||
extension -> extension.getJavaLauncher().set(javaToolchains.launcherFor(java.getToolchain())));
|
||||
} else {
|
||||
extra.set("nmsTools.useBuildTools", type == Type.BUILD_TOOLS);
|
||||
target.getPlugins().apply(NMSToolsPlugin.class);
|
||||
target.getExtensions().configure(NMSToolsExtension.class, extension -> {
|
||||
extension.getJvm().set(jvm);
|
||||
extension.getVersion().set(config.version);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
String outgoingArtifactTask = type == Type.USER_DEV ? "jar" : "remap";
|
||||
ObjectFactory objects = target.getObjects();
|
||||
Configuration reobfConfiguration = target.getConfigurations().findByName(REOBF_CONFIG);
|
||||
if (reobfConfiguration == null) {
|
||||
reobfConfiguration = target.getConfigurations().create(REOBF_CONFIG);
|
||||
}
|
||||
|
||||
target.getConfigurations().named(REOBF_CONFIG).configure(configuration -> {
|
||||
configuration.setCanBeConsumed(true);
|
||||
configuration.setCanBeResolved(false);
|
||||
configuration.getAttributes().attribute(Usage.USAGE_ATTRIBUTE, named(objects, Usage.class, Usage.JAVA_RUNTIME));
|
||||
configuration.getAttributes().attribute(Category.CATEGORY_ATTRIBUTE, named(objects, Category.class, Category.LIBRARY));
|
||||
configuration.getAttributes().attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, named(objects, LibraryElements.class, LibraryElements.JAR));
|
||||
configuration.getAttributes().attribute(Bundling.BUNDLING_ATTRIBUTE, named(objects, Bundling.class, Bundling.EXTERNAL));
|
||||
configuration.getAttributes().attribute(Obfuscation.Companion.getOBFUSCATION_ATTRIBUTE(), named(objects, Obfuscation.class, Obfuscation.OBFUSCATED));
|
||||
configuration.getOutgoing().artifact(target.getTasks().named(outgoingArtifactTask));
|
||||
});
|
||||
|
||||
int[] version = parseVersion(config.version);
|
||||
int major = version[0];
|
||||
int minor = version[1];
|
||||
if (major <= 20 && minor <= 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
target.getTasks().register("convert", ConversionTask.class, type);
|
||||
target.getTasks().named("compileJava").configure(task -> task.dependsOn("convert"));
|
||||
target.getRootProject().getTasks()
|
||||
.matching(task -> task.getName().equals("prepareKotlinBuildScriptModel"))
|
||||
.configureEach(task -> task.dependsOn(target.getPath() + ":convert"));
|
||||
}
|
||||
|
||||
public static void nmsBinding(Project project, Action<Config> action) {
|
||||
Config config = new Config();
|
||||
action.execute(config);
|
||||
project.getExtensions().getExtraProperties().set("nms", config);
|
||||
project.getPlugins().apply(NMSBinding.class);
|
||||
}
|
||||
|
||||
private static int[] parseVersion(String version) {
|
||||
String trimmed = version;
|
||||
int suffix = trimmed.indexOf('-');
|
||||
if (suffix >= 0) {
|
||||
trimmed = trimmed.substring(0, suffix);
|
||||
}
|
||||
|
||||
String[] parts = trimmed.split("\\.");
|
||||
if ("1".equals(parts[0])) {
|
||||
return new int[]{Integer.parseInt(parts[1]), Integer.parseInt(parts[2])};
|
||||
}
|
||||
return new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[1])};
|
||||
}
|
||||
|
||||
private static <T extends Named> T named(ObjectFactory objects, Class<T> type, String name) {
|
||||
return objects.named(type, name);
|
||||
}
|
||||
|
||||
@DisableCachingByDefault
|
||||
public abstract static class ConversionTask extends DefaultTask {
|
||||
private final Pattern pattern;
|
||||
private final String replacement;
|
||||
|
||||
@Inject
|
||||
public ConversionTask(Type type) {
|
||||
setGroup("nms");
|
||||
getInputs().property("type", type);
|
||||
|
||||
JavaPluginExtension java = getProject().getExtensions().findByType(JavaPluginExtension.class);
|
||||
if (java == null) {
|
||||
throw new GradleException("Java plugin not found");
|
||||
}
|
||||
|
||||
Provider<FileTree> source = java.getSourceSets().named(SourceSet.MAIN_SOURCE_SET_NAME).map(SourceSet::getAllJava);
|
||||
getInputs().files(source);
|
||||
getOutputs().files(source);
|
||||
|
||||
if (type == Type.USER_DEV) {
|
||||
this.pattern = Pattern.compile("org\\.bukkit\\.craftbukkit\\." + getProject().getName());
|
||||
this.replacement = "org.bukkit.craftbukkit";
|
||||
} else {
|
||||
this.pattern = Pattern.compile("org\\.bukkit\\.craftbukkit\\.(?!" + getProject().getName() + ")");
|
||||
this.replacement = "org.bukkit.craftbukkit." + getProject().getName() + ".";
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void process() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(16);
|
||||
try {
|
||||
Set<File> files = getInputs().getFiles().getFiles();
|
||||
List<Future<?>> futures = new ArrayList<>(files.size());
|
||||
for (File file : files) {
|
||||
if (!file.getName().endsWith(".java")) {
|
||||
continue;
|
||||
}
|
||||
futures.add(executor.submit(() -> processFile(file)));
|
||||
}
|
||||
|
||||
for (Future<?> future : futures) {
|
||||
future.get();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException(e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e.getCause());
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void processFile(File file) {
|
||||
List<String> output = new ArrayList<>();
|
||||
boolean changed = false;
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.startsWith("package") || line.isBlank()) {
|
||||
output.add(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!line.startsWith("import")) {
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
output.add(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (!matcher.find()) {
|
||||
output.add(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
output.add(matcher.replaceAll(replacement));
|
||||
changed = true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (hasTrailingNewLine(file)) {
|
||||
output.add("");
|
||||
}
|
||||
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
|
||||
for (int i = 0; i < output.size(); i++) {
|
||||
writer.append(output.get(i));
|
||||
if (i + 1 < output.size()) {
|
||||
writer.append(NEW_LINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasTrailingNewLine(File file) throws IOException {
|
||||
if (NEW_LINE_BYTES.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
|
||||
if (raf.length() < NEW_LINE_BYTES.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[NEW_LINE_BYTES.length];
|
||||
raf.seek(raf.length() - bytes.length);
|
||||
raf.readFully(bytes);
|
||||
return Arrays.equals(bytes, NEW_LINE_BYTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
USER_DEV,
|
||||
BUILD_TOOLS,
|
||||
DIRECT
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import org.gradle.api.GradleException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public final class NativeRuntimeArtifacts {
|
||||
public static final String MANIFEST = "META-INF/iris/native-runtime.properties";
|
||||
private static final String GROUP = "com.github.VolmitSoftware.VolmLib";
|
||||
private static final String NATIVE = "art/arcane/volmlib/nativelib/";
|
||||
|
||||
private NativeRuntimeArtifacts() {
|
||||
}
|
||||
|
||||
public static void generate(Map<String, File> artifacts, String version, File output, File rules) throws IOException {
|
||||
List<String> manifest = new ArrayList<>();
|
||||
manifest.add("modules=" + String.join(",", artifacts.keySet()));
|
||||
manifest.add("repository=https://jitpack.io/");
|
||||
Set<String> retained = new TreeSet<>();
|
||||
for (Map.Entry<String, File> artifact : artifacts.entrySet()) {
|
||||
String module = artifact.getKey();
|
||||
manifest.add(module + ".coordinate=" + GROUP + ":" + module + ":" + version);
|
||||
manifest.add(module + ".sha256=" + digest(artifact.getValue()));
|
||||
try (JarFile jar = new JarFile(artifact.getValue())) {
|
||||
Enumeration<JarEntry> entries = jar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (!entry.getName().endsWith(".class")) {
|
||||
continue;
|
||||
}
|
||||
try (InputStream input = jar.getInputStream(entry)) {
|
||||
for (String reference : ClassReferences.read(input.readAllBytes())) {
|
||||
if (reference.startsWith("art/arcane/volmlib/") && !implementation(reference)) {
|
||||
retained.add(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File manifestFile = new File(output, MANIFEST);
|
||||
Files.createDirectories(manifestFile.toPath().getParent());
|
||||
Files.write(manifestFile.toPath(), manifest, StandardCharsets.UTF_8);
|
||||
Path runtimeRoots = output.toPath().resolve("META-INF/volmit/runtime-roots.list");
|
||||
Files.createDirectories(runtimeRoots.getParent());
|
||||
Files.write(runtimeRoots, retained, StandardCharsets.UTF_8);
|
||||
List<String> keep = new ArrayList<>();
|
||||
keep.add("-keep class art.arcane.volmlib.nativelib.** { *; }");
|
||||
for (String reference : retained) {
|
||||
keep.add("-keep class " + reference.replace('/', '.') + " { *; }");
|
||||
}
|
||||
Files.createDirectories(rules.toPath().getParent());
|
||||
Files.write(rules.toPath(), keep, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static void verify(File artifact, List<String> adapters, String version) throws IOException {
|
||||
try (JarFile jar = new JarFile(artifact)) {
|
||||
JarEntry entry = jar.getJarEntry(MANIFEST);
|
||||
if (entry == null) {
|
||||
throw new GradleException("Missing native runtime dependency manifest");
|
||||
}
|
||||
Properties manifest = new Properties();
|
||||
try (InputStream input = jar.getInputStream(entry)) {
|
||||
manifest.load(input);
|
||||
}
|
||||
Set<String> expected = new TreeSet<>();
|
||||
expected.add("native-common");
|
||||
for (String adapter : adapters) {
|
||||
expected.add("native-" + adapter);
|
||||
}
|
||||
Set<String> actual = new TreeSet<>(List.of(manifest.getProperty("modules", "").split(",")));
|
||||
if (!expected.equals(actual)) {
|
||||
throw new GradleException("Native dependency modules differ: " + actual + "; expected " + expected);
|
||||
}
|
||||
for (String module : expected) {
|
||||
String coordinate = GROUP + ":" + module + ":" + version;
|
||||
if (!coordinate.equals(manifest.getProperty(module + ".coordinate"))
|
||||
|| !manifest.getProperty(module + ".sha256", "").matches("[0-9a-f]{64}")) {
|
||||
throw new GradleException("Invalid native runtime dependency: " + module);
|
||||
}
|
||||
}
|
||||
Enumeration<JarEntry> entries = jar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
String name = entries.nextElement().getName();
|
||||
if (name.endsWith(".class") && implementation(name)) {
|
||||
throw new GradleException("Native runtime implementation is bundled: " + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean implementation(String name) {
|
||||
if (!name.startsWith(NATIVE)) {
|
||||
return false;
|
||||
}
|
||||
String relative = name.substring(NATIVE.length());
|
||||
return relative.startsWith("common/") || relative.startsWith("minecraft")
|
||||
|| relative.matches("v[0-9_]+R[0-9]+/.*");
|
||||
}
|
||||
|
||||
private static String digest(File file) throws IOException {
|
||||
try {
|
||||
return HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(Files.readAllBytes(file.toPath())));
|
||||
} catch (NoSuchAlgorithmException exception) {
|
||||
throw new IllegalStateException(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,6 @@ public final class GenerationRevisionScope {
|
||||
"core/src/main/java",
|
||||
"spi/src/main/java",
|
||||
"adapters/bukkit/plugin/src/main/java",
|
||||
"adapters/bukkit/nms/v26_2_R1/src/main/java",
|
||||
"adapters/bukkit/nms/v26_3_R1/src/main/java",
|
||||
"adapters/minecraft-common/src/main/java",
|
||||
"adapters/modded-common/src/main/java",
|
||||
"adapters/client-common/src/main/java",
|
||||
@@ -31,8 +29,6 @@ public final class GenerationRevisionScope {
|
||||
"core/src/main/java/art/arcane/iris/world/safeguard/Diagnostic.java",
|
||||
"core/src/main/java/art/arcane/iris/world/safeguard/ValueWithDiagnostics.java",
|
||||
"core/src/main/java/art/arcane/iris/diagnostics/splash/IrisSplashRenderer.java",
|
||||
"adapters/bukkit/nms/v26_2_R1/src/main/java/art/arcane/iris/platform/bukkit/nms/v26_2_R1/NmsWorldLifecycle.java",
|
||||
"adapters/bukkit/nms/v26_3_R1/src/main/java/art/arcane/iris/platform/bukkit/nms/v26_3_R1/NmsWorldLifecycle.java",
|
||||
"adapters/bukkit/plugin/src/main/java/art/arcane/iris/command/CommandDeveloper.java",
|
||||
"adapters/bukkit/plugin/src/main/java/art/arcane/iris/command/CommandPregen.java",
|
||||
"adapters/bukkit/plugin/src/main/java/art/arcane/iris/command/CommandIris.java",
|
||||
|
||||
@@ -20,7 +20,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class GenerationRevisionScopeTest {
|
||||
private static final String ENGINE_ROOT = "core/src/main/java/art/arcane/iris/generation/runtime/";
|
||||
private static final String NMS_ROOT = "adapters/bukkit/nms/v26_2_R1/src/main/java/art/arcane/iris/platform/bukkit/nms/v26_2_R1/";
|
||||
private static final String BUKKIT_POLICY_ROOT = "core/src/main/java/art/arcane/iris/platform/bukkit/nms/";
|
||||
private static final String COMMAND_ROOT = "adapters/bukkit/plugin/src/main/java/art/arcane/iris/command/";
|
||||
|
||||
@Rule
|
||||
@@ -70,7 +70,7 @@ public class GenerationRevisionScopeTest {
|
||||
assertNewSourceChangesRevision(fixture, root + "/NewSource.java");
|
||||
}
|
||||
assertNewSourceChangesRevision(fixture, ENGINE_ROOT + "NewDiagnostics.java");
|
||||
assertNewSourceChangesRevision(fixture, NMS_ROOT + "NmsWorldLifecycleHelper.java");
|
||||
assertNewSourceChangesRevision(fixture, BUKKIT_POLICY_ROOT + "NewGenerationPolicy.java");
|
||||
assertNewSourceChangesRevision(fixture, COMMAND_ROOT + "NewCommand.java");
|
||||
assertNewSourceChangesRevision(fixture, "core/src/main/java/art/arcane/iris/world/safeguard/NewTask.java");
|
||||
}
|
||||
@@ -87,10 +87,31 @@ public class GenerationRevisionScopeTest {
|
||||
assertTrue(relative, manifest.sources().containsKey(relative));
|
||||
}
|
||||
assertFalse(manifest.sources().containsKey(ENGINE_ROOT + "EngineDiagnostics.java"));
|
||||
assertFalse(manifest.sources().containsKey(NMS_ROOT + "NmsWorldLifecycle.java"));
|
||||
assertFalse(manifest.sources().containsKey(COMMAND_ROOT + "CommandIris.java"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publishedNativeSourcesChangeTheGenerationFingerprint() throws Exception {
|
||||
Fixture fixture = fixture();
|
||||
Path nativeSources = fixture.root().resolve("native-sources.jar");
|
||||
writeNativeSources(nativeSources, "class NativeGenerator { int height = 1; }");
|
||||
Map<String, Path> dependencies = Map.of("volmlib", fixture.dependencies().get("volmlib"),
|
||||
"com.github.VolmitSoftware.VolmLib:native-minecraft26_2-sources", nativeSources);
|
||||
String original = GenerationBuildRevision.fingerprint(
|
||||
GenerationBuildRevision.capture(fixture.options(), dependencies));
|
||||
writeNativeSources(nativeSources, "class NativeGenerator { int height = 2; }");
|
||||
assertNotEquals(original, GenerationBuildRevision.fingerprint(
|
||||
GenerationBuildRevision.capture(fixture.options(), dependencies)));
|
||||
}
|
||||
|
||||
private static void writeNativeSources(Path archive, String content) throws IOException {
|
||||
try (ZipOutputStream output = new ZipOutputStream(Files.newOutputStream(archive))) {
|
||||
output.putNextEntry(new ZipEntry("modded/art/arcane/volmlib/nativelib/NativeGenerator.java"));
|
||||
output.write(content.getBytes(StandardCharsets.UTF_8));
|
||||
output.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertNewSourceChangesRevision(Fixture fixture, String relative) throws IOException {
|
||||
Path source = fixture.root().resolve(relative);
|
||||
write(source, "class NewSource {}");
|
||||
@@ -144,9 +165,9 @@ public class GenerationRevisionScopeTest {
|
||||
"core/src/main/java/art/arcane/iris/pack/loading/IrisData.java",
|
||||
"core/src/main/java/art/arcane/iris/configuration/IrisSettings.java",
|
||||
"core/agent/src/main/java/GenerationTransformer.java",
|
||||
NMS_ROOT + "NmsGenerationHooks.java",
|
||||
NMS_ROOT + "NmsGenerationRegistry.java",
|
||||
NMS_ROOT + "NMSBinding.java",
|
||||
BUKKIT_POLICY_ROOT + "BukkitGeneratorContext.java",
|
||||
BUKKIT_POLICY_ROOT + "BukkitBiomePolicy.java",
|
||||
BUKKIT_POLICY_ROOT + "BukkitBinding.java",
|
||||
"spi/src/main/java/art/arcane/iris/spi/PlatformGenerationRegistry.java",
|
||||
"adapters/modded-common/src/main/java/art/arcane/iris/modded/IrisModdedChunkGenerator.java"
|
||||
);
|
||||
|
||||
@@ -25,8 +25,8 @@ public class ModdedArtifactVerifierTest {
|
||||
private static final String METADATA = "fabric.mod.json";
|
||||
private static final String CODEC_CLASS = "art/arcane/volmlib/util/mantle/io/Lz4IOWorkerCodecSupport.class";
|
||||
private static final String HARDWARE_CLASS = "art/arcane/iris/platform/bootstrap/getHardware.class";
|
||||
private static final String MIXIN_CONFIG = "irisworldgen.entity.mixins.json";
|
||||
private static final String CLIENT_MIXIN_CONFIG = "irisworldgen.client.mixins.json";
|
||||
private static final String MIXIN_CONFIG = "volmlib.entity.mixins.json";
|
||||
private static final String CLIENT_MIXIN_CONFIG = "volmlib.client.mixins.json";
|
||||
private static final String NEOFORGE_METADATA = "META-INF/neoforge.mods.toml";
|
||||
private static final List<String> REQUIRED_ENTRIES = List.of(METADATA, CODEC_CLASS, HARDWARE_CLASS);
|
||||
private static final byte[] INTERNAL_CODEC = (
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import org.gradle.api.GradleException;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class NativeRuntimeArtifactsTest {
|
||||
@Test
|
||||
public void recordsExactDependenciesAndRetainsSharedProviderReferences() throws Exception {
|
||||
Path directory = Files.createTempDirectory("native-artifacts");
|
||||
File provider = directory.resolve("provider.jar").toFile();
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
writer.visit(Opcodes.V17, Opcodes.ACC_PUBLIC, "art/arcane/volmlib/nativelib/v26_2_R1/terrain/Provider", null,
|
||||
"art/arcane/volmlib/util/collection/KList", null);
|
||||
writer.visitEnd();
|
||||
try (JarOutputStream jar = new JarOutputStream(Files.newOutputStream(provider.toPath()))) {
|
||||
jar.putNextEntry(new JarEntry("art/arcane/volmlib/nativelib/v26_2_R1/terrain/Provider.class"));
|
||||
jar.write(writer.toByteArray());
|
||||
jar.closeEntry();
|
||||
}
|
||||
File rules = directory.resolve("keep.pro").toFile();
|
||||
NativeRuntimeArtifacts.generate(Map.of("native-common", provider, "native-v26_2_R1", provider),
|
||||
"revision", directory.toFile(), rules);
|
||||
assertTrue(Files.readString(rules.toPath()).contains("-keep class art.arcane.volmlib.util.collection.KList { *; }"));
|
||||
File plugin = directory.resolve("plugin.jar").toFile();
|
||||
try (JarOutputStream jar = new JarOutputStream(Files.newOutputStream(plugin.toPath()))) {
|
||||
jar.putNextEntry(new JarEntry(NativeRuntimeArtifacts.MANIFEST));
|
||||
Files.copy(directory.resolve(NativeRuntimeArtifacts.MANIFEST), jar);
|
||||
jar.closeEntry();
|
||||
}
|
||||
NativeRuntimeArtifacts.verify(plugin, List.of("v26_2_R1"), "revision");
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verify(plugin, List.of("v26_3_R1"), "revision"));
|
||||
assertThrows(GradleException.class, () -> NativeRuntimeArtifacts.verify(plugin, List.of("v26_2_R1"), "other"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user