diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000..e824a5e --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,21 @@ +name: Java CI with Gradle + +on: [push, pull_request] + +jobs: + build: + if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Validate Gradle Wrapper + uses: gradle/wrapper-validation-action@v1 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + check-latest: true + - name: Build and test with Gradle + run: ./gradlew test diff --git a/build.gradle.kts b/build.gradle.kts index f4a3707..a50e216 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,10 +12,13 @@ dependencies { api("com.google.code.gson:gson:2.10.1") api("com.viaversion:nbt:3.0.0") api("it.unimi.dsi:fastutil:8.5.12") - api("ch.qos.logback:logback-classic:1.4.6") + api("ch.qos.logback:logback-classic:1.4.14") compileOnly("org.jetbrains:annotations:24.0.1") // Uncomment to manually run mappings gen in ide // compileOnly(files("server.jar")) + + testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") } group = "com.viaversion" @@ -70,4 +73,8 @@ tasks { build { dependsOn(shadowJar) } + + test { + useJUnitPlatform() + } } diff --git a/mappings/diff/mapping-1.14to1.15.json b/mappings/diff/mapping-1.14to1.15.json index 59ed5f1..033049a 100644 --- a/mappings/diff/mapping-1.14to1.15.json +++ b/mappings/diff/mapping-1.14to1.15.json @@ -16,5 +16,12 @@ "11211": "bell[attachment=double_wall,facing=south,powered=false]", "11212": "bell[attachment=double_wall,facing=west,powered=false]", "11213": "bell[attachment=double_wall,facing=east,powered=false]" + }, + "sounds": { + "entity.parrot.imitate.enderman": "", + "entity.parrot.imitate.panda": "", + "entity.parrot.imitate.polar_bear": "", + "entity.parrot.imitate.wolf": "", + "entity.parrot.imitate.zombie_pigman": "" } } \ No newline at end of file diff --git a/output/backwards/mappings-1.13to1.12.nbt b/output/backwards/mappings-1.13to1.12.nbt index 6b5d115..e246587 100644 Binary files a/output/backwards/mappings-1.13to1.12.nbt and b/output/backwards/mappings-1.13to1.12.nbt differ diff --git a/output/mappings-1.12to1.13.nbt b/output/mappings-1.12to1.13.nbt index 848c5a6..050e321 100644 Binary files a/output/mappings-1.12to1.13.nbt and b/output/mappings-1.12to1.13.nbt differ diff --git a/src/main/java/com/viaversion/mappingsgenerator/CursedMappings.java b/src/main/java/com/viaversion/mappingsgenerator/CursedMappings.java index 49d174e..fbf189c 100644 --- a/src/main/java/com/viaversion/mappingsgenerator/CursedMappings.java +++ b/src/main/java/com/viaversion/mappingsgenerator/CursedMappings.java @@ -23,27 +23,29 @@ import java.io.IOException; public final class CursedMappings { public static void optimizeAndSaveOhSoSpecial1_12AsNBT() throws IOException { - final MappingsOptimizer optimizer = new MappingsOptimizer("1.12", "1.13"); - optimizer.keepUnknownFields(); - optimizer.handleUnknownFields(); + final MappingsOptimizer optimizer = create("1.12", "1.13"); optimizer.cursedMappings("blocks", "blockstates", "blockstates", 4084); - optimizer.cursedMappings("items", "items", "items"); optimizer.cursedMappings("legacy_enchantments", "enchantments", "enchantments", 72); - optimizer.mappings(false, "sounds"); optimizer.write(MappingsOptimizer.OUTPUT_DIR); } public static void optimizeAndSaveOhSoSpecial1_12AsNBTBackwards() throws IOException { - final MappingsOptimizer optimizer = new MappingsOptimizer("1.13", "1.12"); - optimizer.keepUnknownFields(); - optimizer.handleUnknownFields(); + final MappingsOptimizer optimizer = create("1.13", "1.12"); optimizer.cursedMappings("blockstates", "blocks", "blockstates", 8582); - optimizer.cursedMappings("items", "items", "items"); optimizer.cursedMappings("enchantments", "legacy_enchantments", "enchantments"); optimizer.names("items", "itemnames"); optimizer.fullNames("entitynames", "entitynames"); optimizer.fullNames("sounds", "soundnames"); - optimizer.mappings(false, "sounds"); optimizer.write(MappingsOptimizer.OUTPUT_BACKWARDS_DIR); } + + private static MappingsOptimizer create(final String from, final String to) throws IOException { + final MappingsOptimizer optimizer = new MappingsOptimizer(from, to); + optimizer.setErrorStrategy(ErrorStrategy.IGNORE); + optimizer.keepUnknownFields(); + optimizer.handleUnknownFields(); + optimizer.cursedMappings("items", "items", "items"); + optimizer.mappings(false, "sounds"); + return optimizer; + } } diff --git a/src/main/java/com/viaversion/mappingsgenerator/ErrorStrategy.java b/src/main/java/com/viaversion/mappingsgenerator/ErrorStrategy.java new file mode 100644 index 0000000..8fe04f2 --- /dev/null +++ b/src/main/java/com/viaversion/mappingsgenerator/ErrorStrategy.java @@ -0,0 +1,40 @@ +/* + * This file is part of ViaVersion Mappings - https://github.com/ViaVersion/Mappings + * Copyright (C) 2023 Nassim Jahnke + * Copyright (C) 2023 ViaVersion and contributors + * + * 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 . + */ +package com.viaversion.mappingsgenerator; + +import java.util.function.Consumer; + +public enum ErrorStrategy { + IGNORE(message -> { + }), + WARN(MappingsLoader.LOGGER::warn), + ERROR(message -> { + throw new RuntimeException(message); + }); + + private final Consumer action; + + ErrorStrategy(final Consumer action) { + this.action = action; + } + + public void apply(final String message) { + action.accept(message); + } +} \ No newline at end of file diff --git a/src/main/java/com/viaversion/mappingsgenerator/ManualRunner.java b/src/main/java/com/viaversion/mappingsgenerator/ManualRunner.java index dca5b29..4a3fdbb 100644 --- a/src/main/java/com/viaversion/mappingsgenerator/ManualRunner.java +++ b/src/main/java/com/viaversion/mappingsgenerator/ManualRunner.java @@ -25,18 +25,15 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public final class ManualRunner { - private static final Logger LOGGER = LoggerFactory.getLogger(ManualRunner.class.getSimpleName()); private static final Set SPECIAL_BACKWARDS_ONLY = Set.of("1.9.4", "1.10", "1.11"); private static final boolean ALL = true; public static void main(final String[] args) throws IOException { if (ALL) { - runAll(); + runAll(ErrorStrategy.WARN); return; } @@ -52,9 +49,9 @@ public final class ManualRunner { } /** - * Runs the optimizer for all mapping files present in the mappings/ directory. + * Runs the optimizer for all mapping files present in the 'mappings' directory. */ - public static void runAll() throws IOException { + public static void runAll(final ErrorStrategy errorStrategy) throws IOException { final List versions = new ArrayList<>(); for (final File file : MappingsOptimizer.MAPPINGS_DIR.toFile().listFiles()) { final String name = file.getName(); @@ -69,7 +66,6 @@ public final class ManualRunner { for (int i = 0; i < versions.size() - 1; i++) { final String from = versions.get(i); final String to = versions.get(i + 1); - LOGGER.info("============================="); if (from.equals("1.12") && to.equals("1.13")) { CursedMappings.optimizeAndSaveOhSoSpecial1_12AsNBT(); CursedMappings.optimizeAndSaveOhSoSpecial1_12AsNBTBackwards(); @@ -78,17 +74,18 @@ public final class ManualRunner { final boolean special = SPECIAL_BACKWARDS_ONLY.contains(from); if (!special) { - new MappingsOptimizer(from, to).optimizeAndWrite(); - LOGGER.info("-----------------------------"); + final MappingsOptimizer mappingsOptimizer = new MappingsOptimizer(from, to); + mappingsOptimizer.setErrorStrategy(errorStrategy); + mappingsOptimizer.optimizeAndWrite(); } final MappingsOptimizer backwardsOptimizer = new MappingsOptimizer(to, from); + backwardsOptimizer.setErrorStrategy(errorStrategy); if (special) { backwardsOptimizer.ignoreMissingMappingsFor("sounds"); } backwardsOptimizer.optimizeAndWrite(); - LOGGER.info(""); } } diff --git a/src/main/java/com/viaversion/mappingsgenerator/MappingsLoader.java b/src/main/java/com/viaversion/mappingsgenerator/MappingsLoader.java index 6657a78..be8f918 100644 --- a/src/main/java/com/viaversion/mappingsgenerator/MappingsLoader.java +++ b/src/main/java/com/viaversion/mappingsgenerator/MappingsLoader.java @@ -38,8 +38,8 @@ import org.slf4j.LoggerFactory; public final class MappingsLoader { + public static final Logger LOGGER = LoggerFactory.getLogger(MappingsLoader.class.getSimpleName()); private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create(); - private static final Logger LOGGER = LoggerFactory.getLogger(MappingsLoader.class.getSimpleName()); /** * Loads and return the json mappings file. @@ -63,10 +63,10 @@ public final class MappingsLoader { * @param unmappedIdentifiers array of unmapped identifiers * @param mappedIdentifiers array of mapped identifiers * @param diffIdentifiers diff identifiers - * @param warnOnMissing whether to warn on missing mappings + * @param errorStrategy whether to warn on missing mappings * @return mappings result with int to int array mappings */ - public static MappingsResult map(final JsonArray unmappedIdentifiers, final JsonArray mappedIdentifiers, @Nullable final JsonObject diffIdentifiers, final boolean warnOnMissing) { + public static MappingsResult map(final JsonArray unmappedIdentifiers, final JsonArray mappedIdentifiers, @Nullable final JsonObject diffIdentifiers, final ErrorStrategy errorStrategy) { final int[] output = new int[unmappedIdentifiers.size()]; final Object2IntMap mappedIdentifierMap = MappingsLoader.arrayToMap(mappedIdentifiers); int emptyMappings = 0; @@ -74,7 +74,7 @@ public final class MappingsLoader { int shiftChanges = 0; for (int id = 0; id < unmappedIdentifiers.size(); id++) { final JsonElement unmappedIdentifier = unmappedIdentifiers.get(id); - final int mappedId = mapEntry(id, unmappedIdentifier.getAsString(), mappedIdentifierMap, diffIdentifiers, warnOnMissing); + final int mappedId = mapEntry(id, unmappedIdentifier.getAsString(), mappedIdentifierMap, diffIdentifiers, errorStrategy); output[id] = mappedId; if (mappedId == -1) { @@ -98,16 +98,16 @@ public final class MappingsLoader { * @param unmappedIdentifiers object of unmapped identifiers, keyed by their int id * @param mappedIdentifiers object of mapped identifiers, keyed by their int id * @param diffIdentifiers diff identifiers - * @param warnOnMissing whether to warn on missing mappings + * @param errorStrategy whether to warn on missing mappings * @return mappings result */ - public static Int2IntMap map(final JsonObject unmappedIdentifiers, final JsonObject mappedIdentifiers, @Nullable final JsonObject diffIdentifiers, final boolean warnOnMissing) { + public static Int2IntMap map(final JsonObject unmappedIdentifiers, final JsonObject mappedIdentifiers, @Nullable final JsonObject diffIdentifiers, final ErrorStrategy errorStrategy) { final Int2IntMap output = new Int2IntLinkedOpenHashMap(); output.defaultReturnValue(-1); final Object2IntMap mappedIdentifierMap = MappingsLoader.indexedObjectToMap(mappedIdentifiers); for (final Map.Entry entry : unmappedIdentifiers.entrySet()) { final int id = Integer.parseInt(entry.getKey()); - final int mappedId = mapEntry(id, entry.getValue().getAsString(), mappedIdentifierMap, diffIdentifiers, warnOnMissing); + final int mappedId = mapEntry(id, entry.getValue().getAsString(), mappedIdentifierMap, diffIdentifiers, errorStrategy); output.put(id, mappedId); } return output; @@ -120,10 +120,10 @@ public final class MappingsLoader { * @param value value of the entry * @param mappedIdentifiers mapped identifiers * @param diffIdentifiers diff identifiers - * @param warnOnMissing whether to warn on missing mappings + * @param errorStrategy whether to warn on missing mappings * @return mapped id, or -1 if it was not found */ - private static int mapEntry(final int id, final String value, final Object2IntMap mappedIdentifiers, @Nullable final JsonObject diffIdentifiers, final boolean warnOnMissing) { + private static int mapEntry(final int id, final String value, final Object2IntMap mappedIdentifiers, @Nullable final JsonObject diffIdentifiers, final ErrorStrategy errorStrategy) { int mappedId = mappedIdentifiers.getInt(value); if (mappedId != -1) { return mappedId; @@ -131,9 +131,7 @@ public final class MappingsLoader { final int dataIndex; if (diffIdentifiers == null) { - if (warnOnMissing) { - LOGGER.warn("No direct mapping or diff file for {} :( ", value); - } + errorStrategy.apply("No direct mapping or diff file for " + value + " :( "); return -1; } @@ -167,8 +165,8 @@ public final class MappingsLoader { mappedId = mappedIdentifiers.getInt(mappedName); } - if (mappedId == -1 && warnOnMissing) { - LOGGER.warn("No diff entry for {} :( ", value); + if (mappedId == -1) { + errorStrategy.apply("No mapping for " + value + " :( "); } return mappedId; } @@ -202,7 +200,7 @@ public final class MappingsLoader { final JsonObject existingDiffIdentifiers = existingDiffObject != null && existingDiffObject.has(key) ? existingDiffObject.getAsJsonObject(key) : null; for (int id = 0; id < unmappedIdentifiers.size(); id++) { final String unmappedIdentifier = unmappedIdentifiers.get(id).getAsString(); - final int mappedId = mapEntry(id, unmappedIdentifier, mappedIdentifierMap, existingDiffIdentifiers, false); + final int mappedId = mapEntry(id, unmappedIdentifier, mappedIdentifierMap, existingDiffIdentifiers, ErrorStrategy.IGNORE); if (mappedId != -1) { continue; } @@ -281,6 +279,6 @@ public final class MappingsLoader { * @param identityMappings number of identity mappings * @param shiftChanges number of shift changes where a mapped id is not the last mapped id + 1 */ - record MappingsResult(int[] mappings, int mappedSize, int emptyMappings, int identityMappings, int shiftChanges) { + public record MappingsResult(int[] mappings, int mappedSize, int emptyMappings, int identityMappings, int shiftChanges) { } } diff --git a/src/main/java/com/viaversion/mappingsgenerator/MappingsOptimizer.java b/src/main/java/com/viaversion/mappingsgenerator/MappingsOptimizer.java index 43c7ef6..9a57338 100644 --- a/src/main/java/com/viaversion/mappingsgenerator/MappingsOptimizer.java +++ b/src/main/java/com/viaversion/mappingsgenerator/MappingsOptimizer.java @@ -87,6 +87,7 @@ public final class MappingsOptimizer { private final String toVersion; private final JsonObject unmappedObject; private final JsonObject mappedObject; + private ErrorStrategy errorStrategy = ErrorStrategy.WARN; private JsonObject diffObject; private boolean keepUnknownFields; @@ -143,7 +144,7 @@ public final class MappingsOptimizer { * Optimizes mapping files as nbt files with only the necessary data (int to int mappings in form of int arrays). */ public void optimizeAndWrite() throws IOException { - LOGGER.info("Compacting json mapping files for versions {} → {}...", fromVersion, toVersion); + LOGGER.info("=== Compacting json mapping files for versions {} → {}...", fromVersion, toVersion); if (keepUnknownFields) { handleUnknownFields(); @@ -244,7 +245,8 @@ public final class MappingsOptimizer { continue; } - LOGGER.warn("NON-STANDARD FIELD: {} - writing it to the file without changes", key); + errorStrategy.apply("NON-STANDARD FIELD: " + key + " - writing it to the file without changes"); + final Tag asTag = JsonConverter.toTag(unmappedObject.get(key)); output.put(key, asTag); } @@ -275,8 +277,8 @@ public final class MappingsOptimizer { serialize(result, output, key, alwaysWriteIdentity); } - private boolean shouldWarn(final String key) { - return !ignoreMissing.contains(key); + private ErrorStrategy shouldWarn(final String key) { + return ignoreMissing.contains(key) ? ErrorStrategy.IGNORE : errorStrategy; } public void cursedMappings(final String unmappedKey, final String mappedKey, final String outputKey) { @@ -295,7 +297,7 @@ public final class MappingsOptimizer { JsonConverter.toJsonObject(unmappedObject.get(unmappedKey)), mappedIdentifiers, diffObject != null ? diffObject.getAsJsonObject(unmappedKey) : null, - true + errorStrategy ); final CompoundTag changedTag = new CompoundTag(); @@ -560,4 +562,8 @@ public final class MappingsOptimizer { // One entry in two arrays each time the id is not shifted by 1 from the last id + more approximate length for extra tags return result.shiftChanges() * 2 + 10; } + + public void setErrorStrategy(final ErrorStrategy errorStrategy) { + this.errorStrategy = errorStrategy; + } } diff --git a/src/test/java/com/viaversion/mappingsgenerator/MappingsTest.java b/src/test/java/com/viaversion/mappingsgenerator/MappingsTest.java new file mode 100644 index 0000000..fd27705 --- /dev/null +++ b/src/test/java/com/viaversion/mappingsgenerator/MappingsTest.java @@ -0,0 +1,12 @@ +package com.viaversion.mappingsgenerator; + +import java.io.IOException; +import org.junit.jupiter.api.Test; + +public class MappingsTest { + + @Test + void testFilledStatus() throws IOException { + ManualRunner.runAll(ErrorStrategy.ERROR); + } +}