mirror of
https://github.com/ViaVersion/Mappings.git
synced 2024-12-12 15:16:52 +01:00
Add some update helper utilities
This commit is contained in:
parent
0a9ae7dc73
commit
fd0a16aaf5
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,6 +2,8 @@ libraries/
|
|||||||
logs/
|
logs/
|
||||||
generated/
|
generated/
|
||||||
output/
|
output/
|
||||||
|
states.txt
|
||||||
|
states_output.txt
|
||||||
|
|
||||||
### Java files ###
|
### Java files ###
|
||||||
*.class
|
*.class
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
package com.viaversion.mappingsgenerator.helper;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.viaversion.mappingsgenerator.util.GsonUtil;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static com.viaversion.mappingsgenerator.MappingsOptimizer.MAPPINGS_DIR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link BlockStateMapper} in use, except for the array of wood/stone-based building blocks.
|
||||||
|
* <p>
|
||||||
|
* Directly edits the diff file.
|
||||||
|
*/
|
||||||
|
final class AnnoyingBlockStateMapper {
|
||||||
|
|
||||||
|
private static final List<Function<String, String>> MAPPERS = new ArrayList<>();
|
||||||
|
private static final List<String> WONDERFUL_STATES = List.of(
|
||||||
|
"_wood", "_log", "_sapling", "_wall", "_slab", "_stairs",
|
||||||
|
"_trapdoor", "_door", "_button", "_hanging_sign", "_wall_sign", "_sign",
|
||||||
|
"_leaves", "_fence_gate", "_fence", "_pressure_plate"
|
||||||
|
);
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws IOException {
|
||||||
|
// Input examples
|
||||||
|
final String from = "1.21.4";
|
||||||
|
final String to = "1.21.2";
|
||||||
|
replace("resin_brick", "brick");
|
||||||
|
replace("tuff", "andesite");
|
||||||
|
contains("copper", "brick");
|
||||||
|
|
||||||
|
final Path path = MAPPINGS_DIR.resolve("diff").resolve(String.format("mapping-%sto%s.json", from, to));
|
||||||
|
final JsonObject object = GsonUtil.GSON.fromJson(Files.readString(path), JsonObject.class);
|
||||||
|
final JsonObject blockStates = object.getAsJsonObject("blockstates");
|
||||||
|
final JsonObject outputStates = new JsonObject();
|
||||||
|
final Set<String> handled = new HashSet<>();
|
||||||
|
for (final Map.Entry<String, JsonElement> entry : blockStates.entrySet()) {
|
||||||
|
final String value = entry.getValue().getAsString();
|
||||||
|
final String key = entry.getKey();
|
||||||
|
if (!value.isEmpty()) {
|
||||||
|
outputStates.add(key, entry.getValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String keyPart = key.split("\\[")[0];
|
||||||
|
if (handled.contains(keyPart)) {
|
||||||
|
outputStates.add(key, entry.getValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String wonderfulState = WONDERFUL_STATES.stream().filter(keyPart::endsWith).findAny().orElse(null);
|
||||||
|
if (wonderfulState == null) {
|
||||||
|
outputStates.add(key, entry.getValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
handled.add(key);
|
||||||
|
String outputKey = keyPart.replace(wonderfulState, "");
|
||||||
|
for (final Function<String, String> mapper : MAPPERS) {
|
||||||
|
outputKey = mapper.apply(outputKey);
|
||||||
|
}
|
||||||
|
outputStates.addProperty(keyPart, outputKey + wonderfulState + "[");
|
||||||
|
}
|
||||||
|
|
||||||
|
object.add("blockstates", outputStates);
|
||||||
|
Files.writeString(path, GsonUtil.GSON.toJson(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void equals(final String from, final String to) {
|
||||||
|
MAPPERS.add(s -> s.equals(from) ? to : s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void contains(final String from, final String to) {
|
||||||
|
MAPPERS.add(s -> s.contains(from) ? to : s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void replace(final String from, final String to) {
|
||||||
|
MAPPERS.add(s -> s.replace(from, to));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,227 @@
|
|||||||
|
package com.viaversion.mappingsgenerator.helper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility to more easily map blockstates.
|
||||||
|
* <p>
|
||||||
|
* Copy the stubbed lines from diff mappings into a file called states.txt and update the CONSUMER contents.
|
||||||
|
* Different methods will do different things, the result will be printed to the console.
|
||||||
|
*/
|
||||||
|
final class BlockStateMapper {
|
||||||
|
|
||||||
|
private static final Function<BlockState, BlockState> CONSUMER = state -> {
|
||||||
|
state.addProperty(5, "waterlogged", "false");
|
||||||
|
state.setState("glow_lichen");
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws IOException {
|
||||||
|
applyFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyFunction() throws IOException {
|
||||||
|
final String content = Files.readString(Path.of("states.txt"));
|
||||||
|
for (final String line : content.split("\n")) {
|
||||||
|
String trimmedLine = line.replace("\"", "").trim();
|
||||||
|
if (trimmedLine.endsWith(": ,")) {
|
||||||
|
trimmedLine = trimmedLine.substring(0, trimmedLine.length() - 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
final BlockState state = new BlockState(trimmedLine);
|
||||||
|
System.out.println("\"" + trimmedLine + "\": \"" + CONSUMER.apply(state) + "\",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void replace(final String... replacements) throws IOException {
|
||||||
|
final String content = Files.readString(Path.of("states.txt"));
|
||||||
|
for (final String line : content.split("\n")) {
|
||||||
|
boolean found = false;
|
||||||
|
for (int i = 0; i < replacements.length; i += 2) {
|
||||||
|
final String from = replacements[i];
|
||||||
|
if (!line.contains(from)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String to = replacements[i + 1];
|
||||||
|
final String[] split = line.split("\": \"", 2);
|
||||||
|
System.out.println(split[0] + "\": \"" + split[1].replace(from, to));
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
System.out.println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void editKey() throws IOException {
|
||||||
|
final String newName = "dark_oak_slab";
|
||||||
|
final String content = Files.readString(Path.of("states.txt"));
|
||||||
|
for (String line : content.split("\"\",")) {
|
||||||
|
if (line.trim().equals("}")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String firstPart = line;
|
||||||
|
line = line.replace("\"", "").replace(": ", "").trim();
|
||||||
|
final String[] split = line.split("\\[", 2);
|
||||||
|
System.out.println(firstPart + "\"minecraft:" + newName + "[" + split[1] + "\",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class BlockState {
|
||||||
|
|
||||||
|
private final List<Property> properties = new ArrayList<>();
|
||||||
|
private String state;
|
||||||
|
|
||||||
|
public BlockState(final String state) {
|
||||||
|
final int start = state.indexOf('[');
|
||||||
|
if (start == -1) {
|
||||||
|
this.state = state;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.endsWith("]")) {
|
||||||
|
throw new IllegalArgumentException("Invalid block state: " + state);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = state.substring(0, start);
|
||||||
|
|
||||||
|
int lastCommaIndex = start;
|
||||||
|
int commaIndex;
|
||||||
|
while ((commaIndex = state.indexOf(',', lastCommaIndex + 1)) != -1) {
|
||||||
|
final String part = state.substring(lastCommaIndex + 1, commaIndex);
|
||||||
|
final String[] split = part.split("=", 2);
|
||||||
|
properties.add(new Property(split[0], split[1]));
|
||||||
|
|
||||||
|
lastCommaIndex = commaIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String part = state.substring(lastCommaIndex + 1, state.length() - 1);
|
||||||
|
final String[] split = part.split("=", 2);
|
||||||
|
properties.add(new Property(split[0], split[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable Property getProperty(final String key) {
|
||||||
|
for (final Property property : properties) {
|
||||||
|
if (property.key.equals(key)) {
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addProperty(final String key, final String value) {
|
||||||
|
properties.add(new Property(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addProperty(final int index, final String key, final String value) {
|
||||||
|
properties.add(index, new Property(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable Property removeProperty(final String key) {
|
||||||
|
for (int i = 0; i < properties.size(); i++) {
|
||||||
|
final Property property = properties.get(i);
|
||||||
|
if (property.key.equals(key)) {
|
||||||
|
properties.remove(i);
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Property> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(final String state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final StringBuilder builder = new StringBuilder(state).append('[');
|
||||||
|
for (final Property property : properties) {
|
||||||
|
builder.append(property.getKey()).append('=').append(property.getValue()).append(',');
|
||||||
|
}
|
||||||
|
return builder.substring(0, builder.length() - 1) + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
final BlockState that = (BlockState) o;
|
||||||
|
if (!properties.equals(that.properties)) return false;
|
||||||
|
return state.equals(that.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = properties.hashCode();
|
||||||
|
result = 31 * result + state.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockState copy() {
|
||||||
|
return new BlockState(toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Property {
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public Property(final String key, final String value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(final String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(final String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
final Property property = (Property) o;
|
||||||
|
if (!key.equals(property.key)) return false;
|
||||||
|
return value.equals(property.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = key.hashCode();
|
||||||
|
result = 31 * result + value.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
package com.viaversion.mappingsgenerator.helper;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.viaversion.mappingsgenerator.util.PathUtil;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility to compare generate a diff of translations between two Minecraft versions.
|
||||||
|
* Copy the output into VB's translations file.
|
||||||
|
*/
|
||||||
|
final class TranslationMapper {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(TranslationMapper.class.getSimpleName());
|
||||||
|
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
|
||||||
|
|
||||||
|
public static void main(final String[] args) throws IOException {
|
||||||
|
final String oldVer = "1.21.2";
|
||||||
|
final String newVer = "1.21.4-rc3";
|
||||||
|
|
||||||
|
final Map<String, String> oldTranslations = load(oldVer);
|
||||||
|
final Set<String> oldValues = new HashSet<>(oldTranslations.values());
|
||||||
|
final Map<String, String> newTranslations = load(newVer);
|
||||||
|
|
||||||
|
final JsonObject diff = new JsonObject();
|
||||||
|
for (final Map.Entry<String, String> entry : newTranslations.entrySet()) {
|
||||||
|
if (oldTranslations.containsKey(entry.getKey())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldValues.contains(entry.getValue())) {
|
||||||
|
LOGGER.warn("Changed value: {}", entry.getValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff.addProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for removed translations
|
||||||
|
for (final Map.Entry<String, String> entry : oldTranslations.entrySet()) {
|
||||||
|
if (!newTranslations.containsKey(entry.getKey())) {
|
||||||
|
//LOGGER.warn("mappings.put(\"" + entry.getKey() + "\", \"" + entry.getValue() + "\");");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info(diff.toString());
|
||||||
|
LOGGER.info("Mappings size: {}", diff.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> load(final String version) throws IOException {
|
||||||
|
final File jarFile = PathUtil.minecraftDir().resolve("versions").resolve(version).resolve(version + ".jar").toFile();
|
||||||
|
if (!jarFile.exists()) {
|
||||||
|
throw new IllegalArgumentException("File " + jarFile + " does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String contents;
|
||||||
|
try (final ZipFile file = new ZipFile(jarFile)) {
|
||||||
|
ZipEntry langEntry = file.getEntry("assets/minecraft/lang/en_us.json");
|
||||||
|
if (langEntry == null) {
|
||||||
|
// Pre 1.13 translations
|
||||||
|
langEntry = file.getEntry("assets/minecraft/lang/en_us.lang");
|
||||||
|
if (langEntry != null) {
|
||||||
|
try (final InputStream inputStream = file.getInputStream(langEntry)) {
|
||||||
|
contents = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
return loadLegacyTranslations(contents);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("File " + jarFile + " does not contain en_us.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (final InputStream inputStream = file.getInputStream(langEntry)) {
|
||||||
|
contents = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final JsonObject object = GSON.fromJson(contents, JsonObject.class);
|
||||||
|
final Map<String, String> translations = new LinkedHashMap<>();
|
||||||
|
for (final Map.Entry<String, JsonElement> entry : object.entrySet()) {
|
||||||
|
translations.put(entry.getKey(), entry.getValue().getAsString());
|
||||||
|
}
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> loadLegacyTranslations(final String contents) {
|
||||||
|
final Map<String, String> translations = new LinkedHashMap<>();
|
||||||
|
contents.lines().forEach(line -> {
|
||||||
|
final int index = line.indexOf('=');
|
||||||
|
if (index != -1) {
|
||||||
|
translations.put(line.substring(0, index), line.substring(index + 1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.viaversion.mappingsgenerator.util;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
public final class GsonUtil {
|
||||||
|
|
||||||
|
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.viaversion.mappingsgenerator.util;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public final class PathUtil {
|
||||||
|
|
||||||
|
public static Path minecraftDir() {
|
||||||
|
// Windows path
|
||||||
|
Path minecraftDir = Paths.get(home(), "AppData", "Roaming", ".minecraft");
|
||||||
|
if (!Files.isDirectory(minecraftDir)) {
|
||||||
|
// MacOS path
|
||||||
|
minecraftDir = Paths.get(home(), "Library", "Application Support", "minecraft");
|
||||||
|
}
|
||||||
|
return minecraftDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String home() {
|
||||||
|
return System.getProperty("user.home");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user