Use version String for DataFixer
This commit is contained in:
parent
179ada3296
commit
9728dc8dc3
1 changed files with 166 additions and 69 deletions
|
@ -6,7 +6,6 @@ import net.minecraft.nbt.NbtIo;
|
||||||
import net.minecraft.world.level.ChunkPos;
|
import net.minecraft.world.level.ChunkPos;
|
||||||
import net.minecraft.world.level.chunk.storage.RegionFile;
|
import net.minecraft.world.level.chunk.storage.RegionFile;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import ru.bclib.BCLib;
|
|
||||||
import ru.bclib.config.Configs;
|
import ru.bclib.config.Configs;
|
||||||
import ru.bclib.config.PathConfig;
|
import ru.bclib.config.PathConfig;
|
||||||
import ru.bclib.config.SessionConfig;
|
import ru.bclib.config.SessionConfig;
|
||||||
|
@ -19,9 +18,12 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class DataFixerAPI2 {
|
public class DataFixerAPI2 {
|
||||||
|
@ -41,49 +43,52 @@ public class DataFixerAPI2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
List<File> regions = getAllRegions(dir, null);
|
List<File> regions = getAllRegions(dir, null);
|
||||||
regions.parallelStream().forEach((file) -> {
|
regions.parallelStream()
|
||||||
try {
|
.forEach((file) -> {
|
||||||
LOGGER.info("Inspecting " + file);
|
try {
|
||||||
boolean[] changed = new boolean[1];
|
LOGGER.info("Inspecting " + file);
|
||||||
RegionFile region = new RegionFile(file, file.getParentFile(), true);
|
boolean[] changed = new boolean[1];
|
||||||
for (int x = 0; x < 32; x++) {
|
RegionFile region = new RegionFile(file, file.getParentFile(), true);
|
||||||
for (int z = 0; z < 32; z++) {
|
for (int x = 0; x < 32; x++) {
|
||||||
ChunkPos pos = new ChunkPos(x, z);
|
for (int z = 0; z < 32; z++) {
|
||||||
changed[0] = false;
|
ChunkPos pos = new ChunkPos(x, z);
|
||||||
if (region.hasChunk(pos)) {
|
changed[0] = false;
|
||||||
DataInputStream input = region.getChunkDataInputStream(pos);
|
if (region.hasChunk(pos)) {
|
||||||
CompoundTag root = NbtIo.read(input);
|
DataInputStream input = region.getChunkDataInputStream(pos);
|
||||||
// if ((root.toString().contains("betternether") || root.toString().contains("bclib")) && root.toString().contains("chest")) {
|
CompoundTag root = NbtIo.read(input);
|
||||||
// NbtIo.write(root, new File(file.toString() + "-" + x + "-" + z + ".nbt"));
|
// if ((root.toString().contains("betternether") || root.toString().contains("bclib")) && root.toString().contains("chest")) {
|
||||||
// }
|
// NbtIo.write(root, new File(file.toString() + "-" + x + "-" + z + ".nbt"));
|
||||||
input.close();
|
// }
|
||||||
|
input.close();
|
||||||
|
|
||||||
ListTag tileEntities = root.getCompound("Level").getList("TileEntities", 10);
|
ListTag tileEntities = root.getCompound("Level")
|
||||||
fixItemArrayWithID(tileEntities, changed, data, true);
|
.getList("TileEntities", 10);
|
||||||
|
fixItemArrayWithID(tileEntities, changed, data, true);
|
||||||
|
|
||||||
ListTag sections = root.getCompound("Level").getList("Sections", 10);
|
ListTag sections = root.getCompound("Level")
|
||||||
sections.forEach((tag) -> {
|
.getList("Sections", 10);
|
||||||
ListTag palette = ((CompoundTag) tag).getList("Palette", 10);
|
sections.forEach((tag) -> {
|
||||||
palette.forEach((blockTag) -> {
|
ListTag palette = ((CompoundTag) tag).getList("Palette", 10);
|
||||||
CompoundTag blockTagCompound = ((CompoundTag) blockTag);
|
palette.forEach((blockTag) -> {
|
||||||
changed[0] = data.replaceStringFromIDs(blockTagCompound, "Name");
|
CompoundTag blockTagCompound = ((CompoundTag) blockTag);
|
||||||
});
|
changed[0] = data.replaceStringFromIDs(blockTagCompound, "Name");
|
||||||
});
|
});
|
||||||
if (changed[0]) {
|
});
|
||||||
LOGGER.warning("Writing '{}': {}/{}", file, x, z);
|
if (changed[0]) {
|
||||||
DataOutputStream output = region.getChunkDataOutputStream(pos);
|
LOGGER.warning("Writing '{}': {}/{}", file, x, z);
|
||||||
NbtIo.write(root, output);
|
DataOutputStream output = region.getChunkDataOutputStream(pos);
|
||||||
output.close();
|
NbtIo.write(root, output);
|
||||||
}
|
output.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
region.close();
|
}
|
||||||
}
|
region.close();
|
||||||
catch (Exception e) {
|
}
|
||||||
e.printStackTrace();
|
catch (Exception e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
data.markApplied();
|
data.markApplied();
|
||||||
}
|
}
|
||||||
|
@ -110,16 +115,59 @@ public class DataFixerAPI2 {
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
getAllRegions(file, list);
|
getAllRegions(file, list);
|
||||||
}
|
}
|
||||||
else if (file.isFile() && file.getName().endsWith(".mca")) {
|
else if (file.isFile() && file.getName()
|
||||||
|
.endsWith(".mca")) {
|
||||||
list.add(file);
|
list.add(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get mod version from string. String should be in format: %d.%d.%d
|
||||||
|
*
|
||||||
|
* @param version - {@link String} mod version.
|
||||||
|
* @return int mod version.
|
||||||
|
*/
|
||||||
|
public static int getModVersion(String version) {
|
||||||
|
if (version.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
int res = 0;
|
||||||
|
final String semanticVersionPattern = "\\D*(\\d+)\\D*\\.\\D*(\\d+)\\D*\\.\\D*(\\d+)\\D*";
|
||||||
|
final Matcher matcher = Pattern.compile(semanticVersionPattern)
|
||||||
|
.matcher(version);
|
||||||
|
if (matcher.find()) {
|
||||||
|
if (matcher.groupCount() > 0) res = Integer.parseInt(matcher.group(0)) << 20;
|
||||||
|
if (matcher.groupCount() > 1) res |= Integer.parseInt(matcher.group(1)) << 12;
|
||||||
|
if (matcher.groupCount() > 2) res |= Integer.parseInt(matcher.group(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get mod version from integer. String will be in format %d.%d.%d
|
||||||
|
*
|
||||||
|
* @param version - mod version in integer form.
|
||||||
|
* @return {@link String} mod version.
|
||||||
|
*/
|
||||||
|
public static String getModVersion(int version) {
|
||||||
|
int a = (version >> 20) & 0xFF;
|
||||||
|
int b = (version >> 12) & 0xFF;
|
||||||
|
int c = version & 0xFFF;
|
||||||
|
return String.format(Locale.ROOT, "%d.%d.%d", a, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract static class Patch {
|
public abstract static class Patch {
|
||||||
private static List<Patch> ALL = new ArrayList<>(10);
|
private static List<Patch> ALL = new ArrayList<>(10);
|
||||||
private final int level;
|
private final int level;
|
||||||
|
private final String version;
|
||||||
@NotNull
|
@NotNull
|
||||||
private final String modID;
|
private final String modID;
|
||||||
|
|
||||||
|
@ -136,6 +184,22 @@ public class DataFixerAPI2 {
|
||||||
ALL.add(patch.get());
|
ALL.add(patch.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the highest Patch-Version that is available for the given mod. If no patches were
|
||||||
|
* registerd for the mod, this will return 0.0.0
|
||||||
|
*
|
||||||
|
* @param modID The ID of the mod you want to query
|
||||||
|
* @return The highest Patch-Version that was found
|
||||||
|
*/
|
||||||
|
public static String maxPatchVersion(@NotNull String modID) {
|
||||||
|
return ALL.stream()
|
||||||
|
.filter(p -> p.getModID()
|
||||||
|
.equals(modID))
|
||||||
|
.map(p -> p.version)
|
||||||
|
.reduce((p, c) -> c)
|
||||||
|
.orElse("0.0.0");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the highest patch-level that is available for the given mod. If no patches were
|
* Returns the highest patch-level that is available for the given mod. If no patches were
|
||||||
* registerd for the mod, this will return 0
|
* registerd for the mod, this will return 0
|
||||||
|
@ -144,7 +208,12 @@ public class DataFixerAPI2 {
|
||||||
* @return The highest Patch-Level that was found
|
* @return The highest Patch-Level that was found
|
||||||
*/
|
*/
|
||||||
public static int maxPatchLevel(@NotNull String modID) {
|
public static int maxPatchLevel(@NotNull String modID) {
|
||||||
return ALL.stream().filter(p -> p.getModID().equals(modID)).mapToInt(p -> p.level).max().orElse(0);
|
return ALL.stream()
|
||||||
|
.filter(p -> p.getModID()
|
||||||
|
.equals(modID))
|
||||||
|
.mapToInt(p -> p.level)
|
||||||
|
.max()
|
||||||
|
.orElse(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,38 +222,50 @@ public class DataFixerAPI2 {
|
||||||
* Performs some sanity checks on the values and might throw a #RuntimeException if any
|
* Performs some sanity checks on the values and might throw a #RuntimeException if any
|
||||||
* inconsistencies are found.
|
* inconsistencies are found.
|
||||||
*
|
*
|
||||||
* @param modID The ID of the Mod you want to register a patch for. This should be your
|
* @param modID The ID of the Mod you want to register a patch for. This should be your
|
||||||
* ModID only. The ModID can not be {@code null} or an empty String.
|
* ModID only. The ModID can not be {@code null} or an empty String.
|
||||||
* @param level The level of the Patch. This needs to be a non-zero positive value.
|
* @param version The mod-version that introduces the patch. This needs Semantic-Version String
|
||||||
* Developers are responsible for registering their patches in the correct
|
* like x.x.x. Developers are responsible for registering their patches in the correct
|
||||||
* order (with increasing levels). You are not allowed to register a new
|
* order (with increasing versions). You are not allowed to register a new
|
||||||
* Patch with a Patch-level lower or equal than
|
* Patch with a version lower or equal than
|
||||||
* {@link Patch#maxPatchLevel(String)}
|
* {@link Patch#maxPatchVersion(String)}
|
||||||
*/
|
*/
|
||||||
protected Patch(@NotNull String modID, int level) {
|
protected Patch(@NotNull String modID, String version) {
|
||||||
//Patchlevels need to be unique and registered in ascending order
|
//Patchlevels need to be unique and registered in ascending order
|
||||||
if (modID == null || "".equals(modID)) {
|
if (modID == null || "".equals(modID)) {
|
||||||
throw new RuntimeException("[INTERNAL ERROR] Patches need a valid modID!");
|
throw new RuntimeException("[INTERNAL ERROR] Patches need a valid modID!");
|
||||||
}
|
}
|
||||||
if (!ALL.stream().filter(p -> p.getModID().equals(modID)).noneMatch(p -> p.getLevel() >= level) || level <= 0) {
|
|
||||||
|
if (version == null || "".equals(version)) {
|
||||||
|
throw new RuntimeException("Invalid Mod-Version");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.version = version;
|
||||||
|
this.level = getModVersion(version);
|
||||||
|
if (!ALL.stream()
|
||||||
|
.filter(p -> p.getModID()
|
||||||
|
.equals(modID)
|
||||||
|
)
|
||||||
|
.noneMatch(p -> p.getLevel() >= this.level) || this.level <= 0) {
|
||||||
throw new RuntimeException("[INTERNAL ERROR] Patch-levels need to be created in ascending order beginning with 1.");
|
throw new RuntimeException("[INTERNAL ERROR] Patch-levels need to be created in ascending order beginning with 1.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BCLib.LOGGER.info("Creating Patchlevel {} ({}, {})", level, ALL, ALL.stream().noneMatch(p -> p.getLevel() >= level));
|
|
||||||
this.level = level;
|
|
||||||
this.modID = modID;
|
this.modID = modID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Patch{" + "level=" + getModID() + ":" + getLevel() + '}';
|
return "Patch{" + getModID() + ':' + getVersion() + ':' + getLevel() + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
final public int getLevel() {
|
final public int getLevel() {
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Mod-ID that registered this Patch
|
* The Mod-ID that registered this Patch
|
||||||
*
|
*
|
||||||
|
@ -229,19 +310,25 @@ public class DataFixerAPI2 {
|
||||||
private MigrationData(PathConfig config) {
|
private MigrationData(PathConfig config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
this.mods = Collections.unmodifiableSet(Patch.getALL().stream().map(p -> p.modID).collect(Collectors.toSet()));
|
this.mods = Collections.unmodifiableSet(Patch.getALL()
|
||||||
|
.stream()
|
||||||
|
.map(p -> p.modID)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
HashMap<String, String> replacements = new HashMap<String, String>();
|
HashMap<String, String> replacements = new HashMap<String, String>();
|
||||||
for (String modID : mods) {
|
for (String modID : mods) {
|
||||||
Patch.getALL().stream().filter(p -> p.modID.equals(modID)).forEach(patch -> {
|
Patch.getALL()
|
||||||
if (currentPatchLevel(modID) < patch.level) {
|
.stream()
|
||||||
replacements.putAll(patch.getIDReplacements());
|
.filter(p -> p.modID.equals(modID))
|
||||||
LOGGER.info("Applying " + patch);
|
.forEach(patch -> {
|
||||||
}
|
if (currentPatchLevel(modID) < patch.level) {
|
||||||
else {
|
replacements.putAll(patch.getIDReplacements());
|
||||||
LOGGER.info("Ignoring " + patch);
|
LOGGER.info("Applying " + patch);
|
||||||
}
|
}
|
||||||
});
|
else {
|
||||||
|
LOGGER.info("Ignoring " + patch);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.idReplacements = Collections.unmodifiableMap(replacements);
|
this.idReplacements = Collections.unmodifiableMap(replacements);
|
||||||
|
@ -249,14 +336,24 @@ public class DataFixerAPI2 {
|
||||||
|
|
||||||
final public void markApplied() {
|
final public void markApplied() {
|
||||||
for (String modID : mods) {
|
for (String modID : mods) {
|
||||||
LOGGER.info("Updating Patch-Level for '{}' from {} to {} -> {}", modID, currentPatchLevel(modID), Patch.maxPatchLevel(modID), config.setInt(Configs.MAIN_PATCH_CATEGORY, modID, Patch.maxPatchLevel(modID)));
|
LOGGER.info(
|
||||||
|
"Updating Patch-Level for '{}' from {} to {}",
|
||||||
|
modID,
|
||||||
|
currentPatchLevel(modID),
|
||||||
|
Patch.maxPatchLevel(modID)
|
||||||
|
);
|
||||||
|
config.setString(Configs.MAIN_PATCH_CATEGORY, modID, Patch.maxPatchVersion(modID));
|
||||||
}
|
}
|
||||||
|
|
||||||
config.saveChanges();
|
config.saveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String currentPatchVersion(@NotNull String modID) {
|
||||||
|
return config.getString(Configs.MAIN_PATCH_CATEGORY, modID, "0.0.0");
|
||||||
|
}
|
||||||
|
|
||||||
public int currentPatchLevel(@NotNull String modID) {
|
public int currentPatchLevel(@NotNull String modID) {
|
||||||
return config.getInt(Configs.MAIN_PATCH_CATEGORY, modID, 0);
|
return getModVersion(currentPatchVersion(modID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAnyFixes() {
|
public boolean hasAnyFixes() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue