fabric-registry-sync: lots of fixes and debug functionality

This commit is contained in:
asie 2019-06-09 14:27:39 +02:00
parent 229941196c
commit baba33ba30
13 changed files with 262 additions and 104 deletions

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-registry-sync-v0"
version = getSubprojectVersion(project, "0.2.1")
version = getSubprojectVersion(project, "0.2.2")
dependencies {
compile project(path: ':fabric-api-base', configuration: 'dev')

View file

@ -31,7 +31,7 @@ public class FabricRegistryClientInit implements ClientModInitializer {
public void onInitializeClient() {
ClientSidePacketRegistry.INSTANCE.register(RegistrySyncManager.ID, (ctx, buf) -> {
// if not hosting server, apply packet
RegistrySyncManager.receivePacket(ctx, buf, !MinecraftClient.getInstance().isInSingleplayer(), (e) -> {
RegistrySyncManager.receivePacket(ctx, buf, RegistrySyncManager.DEBUG || !MinecraftClient.getInstance().isInSingleplayer(), (e) -> {
LOGGER.error("Registry remapping failed!", e);
MinecraftClient.getInstance().execute(() -> {
((ClientPlayerEntity) ctx.getPlayer()).networkHandler.getClientConnection().disconnect(

View file

@ -16,8 +16,12 @@
package net.fabricmc.fabric.impl.registry;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.fabricmc.fabric.api.network.PacketContext;
@ -29,7 +33,13 @@ import net.minecraft.util.PacketByteBuf;
import net.minecraft.util.registry.MutableRegistry;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.SimpleRegistry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@ -37,7 +47,10 @@ import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
public final class RegistrySyncManager {
public static final Identifier ID = new Identifier("fabric", "registry/sync");
static final boolean DEBUG = System.getProperty("fabric.registry.debug", "false").equalsIgnoreCase("true");
static final Identifier ID = new Identifier("fabric", "registry/sync");
private static final Logger LOGGER = LogManager.getLogger();
private static final boolean DEBUG_WRITE_REGISTRY_DATA = System.getProperty("fabric.registry.debug.writeContentsAsCsv", "false").equalsIgnoreCase("true");
private static final Set<Identifier> REGISTRY_BLACKLIST = ImmutableSet.of();
private static final Set<Identifier> REGISTRY_BLACKLIST_NETWORK = ImmutableSet.of();
@ -80,6 +93,39 @@ public final class RegistrySyncManager {
CompoundTag mainTag = new CompoundTag();
for (Identifier registryId : Registry.REGISTRIES.getIds()) {
if (DEBUG_WRITE_REGISTRY_DATA) {
File location = new File(".fabric" + File.separatorChar + "debug" + File.separatorChar + "registry");
boolean c = true;
if (!location.exists()) {
if (!location.mkdirs()) {
LOGGER.warn("[fabric-registry-sync debug] Could not create " + location.getAbsolutePath() + " directory!");
c = false;
}
}
MutableRegistry registry = Registry.REGISTRIES.get(registryId);
if (c && registry != null) {
File file = new File(location, registryId.toString().replace(':', '.').replace('/', '.') + ".csv");
try (FileOutputStream stream = new FileOutputStream(file)) {
StringBuilder builder = new StringBuilder("Raw ID,String ID,Class Type\n");
for (Object o : registry) {
String classType = (o == null) ? "null" : o.getClass().getName();
//noinspection unchecked
Identifier id = registry.getId(o);
if (id == null) continue;
//noinspection unchecked
int rawId = registry.getRawId(o);
String stringId = id.toString();
builder.append("\"").append(rawId).append("\",\"").append(stringId).append("\",\"").append(classType).append("\"\n");
}
stream.write(builder.toString().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
LOGGER.warn("[fabric-registry-sync debug] Could not write to " + file.getAbsolutePath() + "!", e);
}
}
}
if (REGISTRY_BLACKLIST.contains(registryId)) {
continue;
} else if (isClientSync && REGISTRY_BLACKLIST_NETWORK.contains(registryId)) {
@ -87,12 +133,35 @@ public final class RegistrySyncManager {
}
MutableRegistry registry = Registry.REGISTRIES.get(registryId);
if (registry instanceof SimpleRegistry && registry instanceof RemappableRegistry) {
if (registry instanceof RemappableRegistry) {
CompoundTag registryTag = new CompoundTag();
//noinspection unchecked
for (Identifier identifier : (Set<Identifier>) registry.getIds()) {
registryTag.putInt(identifier.toString(), registry.getRawId(registry.get(identifier)));
IntSet rawIdsFound = DEBUG ? new IntOpenHashSet() : null;
for (Object o : registry) {
//noinspection unchecked
Identifier id = registry.getId(o);
if (id == null) continue;
//noinspection unchecked
int rawId = registry.getRawId(o);
if (DEBUG) {
if (registry.get(id) != o) {
LOGGER.error("[fabric-registry-sync] Inconsistency detected in " + registryId + ": object " + o + " -> string ID " + id + " -> object " + registry.get(id) + "!");
}
if (registry.get(rawId) != o) {
LOGGER.error("[fabric-registry-sync] Inconsistency detected in " + registryId + ": object " + o + " -> integer ID " + rawId + " -> object " + registry.get(rawId) + "!");
}
if (!rawIdsFound.add(rawId)) {
LOGGER.error("[fabric-registry-sync] Inconsistency detected in " + registryId + ": multiple objects hold the raw ID " + rawId + " (this one is " + id + ")");
}
}
registryTag.putInt(id.toString(), rawId);
}
mainTag.put(registryId.toString(), registryTag);
}
}
@ -106,22 +175,29 @@ public final class RegistrySyncManager {
public static void apply(CompoundTag tag, RemappableRegistry.RemapMode mode) throws RemapException {
CompoundTag mainTag = tag.getCompound("registries");
Set<String> containedRegistries = Sets.newHashSet(mainTag.getKeys());
for (Identifier registryId : Registry.REGISTRIES.getIds()) {
if (!mainTag.containsKey(registryId.toString())) {
if (!containedRegistries.remove(registryId.toString())) {
continue;
}
CompoundTag registryTag = mainTag.getCompound(registryId.toString());
MutableRegistry registry = Registry.REGISTRIES.get(registryId);
if (registry instanceof SimpleRegistry && registry instanceof RemappableRegistry) {
if (registry instanceof RemappableRegistry) {
Object2IntMap<Identifier> idMap = new Object2IntOpenHashMap<>();
for (String key : registryTag.getKeys()) {
idMap.put(new Identifier(key), registryTag.getInt(key));
}
((RemappableRegistry) registry).remap(registryId.toString(), idMap, mode);
}
}
if (!containedRegistries.isEmpty()) {
LOGGER.warn("[fabric-registry-sync] Could not find the following registries: " + Joiner.on(", ").join(containedRegistries));
}
}
public static void unmap() throws RemapException {

View file

@ -25,10 +25,12 @@ import net.minecraft.util.registry.Registry;
public class RemapStateImpl<T> implements RegistryIdRemapCallback.RemapState<T> {
private final Int2IntMap rawIdChangeMap;
private final Int2ObjectMap<Identifier> oldIdMap;
private final Int2ObjectMap<Identifier> newIdMap;
public RemapStateImpl(Registry<T> registry, Int2IntMap rawIdChangeMap) {
public RemapStateImpl(Registry<T> registry, Int2ObjectMap<Identifier> oldIdMap, Int2IntMap rawIdChangeMap) {
this.rawIdChangeMap = rawIdChangeMap;
this.oldIdMap = oldIdMap;
this.newIdMap = new Int2ObjectOpenHashMap<>();
for (Int2IntMap.Entry entry : rawIdChangeMap.int2IntEntrySet()) {
@ -44,7 +46,7 @@ public class RemapStateImpl<T> implements RegistryIdRemapCallback.RemapState<T>
@Override
public Identifier getIdFromOld(int oldRawId) {
return newIdMap.get(rawIdChangeMap.getOrDefault(oldRawId, -1));
return oldIdMap.get(oldRawId);
}
@Override

View file

@ -28,15 +28,17 @@ import java.util.HashMap;
import java.util.Map;
public class IdListTracker<V, OV> implements RegistryEntryAddedCallback<V>, RegistryIdRemapCallback<V>, RegistryEntryRemovedCallback<V> {
private final String name;
private final IdList<OV> mappers;
private Map<Identifier, OV> removedMapperCache = new HashMap<>();
private IdListTracker(IdList<OV> mappers) {
private IdListTracker(String name, IdList<OV> mappers) {
this.name = name;
this.mappers = mappers;
}
public static <V, OV> void register(Registry<V> registry, IdList<OV> mappers) {
IdListTracker<V, OV> updater = new IdListTracker<>(mappers);
public static <V, OV> void register(Registry<V> registry, String name, IdList<OV> mappers) {
IdListTracker<V, OV> updater = new IdListTracker<>(name, mappers);
RegistryEntryAddedCallback.event(registry).register(updater);
RegistryIdRemapCallback.event(registry).register(updater);
RegistryEntryRemovedCallback.event(registry).register(updater);

View file

@ -16,6 +16,8 @@
package net.fabricmc.fabric.impl.registry.trackers;
import com.google.common.base.Joiner;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
@ -23,20 +25,27 @@ import net.fabricmc.fabric.api.event.registry.RegistryIdRemapCallback;
import net.fabricmc.fabric.api.event.registry.RegistryEntryRemovedCallback;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Int2ObjectMapTracker<V, OV> implements RegistryEntryAddedCallback<V>, RegistryIdRemapCallback<V>, RegistryEntryRemovedCallback<V> {
private static final Logger LOGGER = LogManager.getLogger();
private final String name;
private final Int2ObjectMap<OV> mappers;
private Map<Identifier, OV> removedMapperCache = new HashMap<>();
private Int2ObjectMapTracker(Int2ObjectMap<OV> mappers) {
private Int2ObjectMapTracker(String name, Int2ObjectMap<OV> mappers) {
this.name = name;
this.mappers = mappers;
}
public static <V, OV> void register(Registry<V> registry, Int2ObjectMap<OV> mappers) {
Int2ObjectMapTracker<V, OV> updater = new Int2ObjectMapTracker<>(mappers);
public static <V, OV> void register(Registry<V> registry, String name, Int2ObjectMap<OV> mappers) {
Int2ObjectMapTracker<V, OV> updater = new Int2ObjectMapTracker<>(name, mappers);
RegistryEntryAddedCallback.event(registry).register(updater);
RegistryIdRemapCallback.event(registry).register(updater);
RegistryEntryRemovedCallback.event(registry).register(updater);
@ -52,22 +61,38 @@ public class Int2ObjectMapTracker<V, OV> implements RegistryEntryAddedCallback<V
@Override
public void onRemap(RemapState<V> state) {
Int2ObjectMap<OV> oldMappers = new Int2ObjectOpenHashMap<>(mappers);
Int2IntMap remapMap = state.getRawIdChangeMap();
List<String> errors = null;
mappers.clear();
for (int i : oldMappers.keySet()) {
int newI = state.getRawIdChangeMap().getOrDefault(i, i);
if (mappers.containsKey(newI)) {
throw new RuntimeException("Int2ObjectMap contained two equal IDs " + newI + " (" + state.getIdFromOld(i) + "/" + i + " -> " + state.getIdFromNew(newI) + "/" + newI + ")!");
}
int newI = remapMap.getOrDefault(i, Integer.MIN_VALUE);
if (newI >= 0) {
if (mappers.containsKey(newI)) {
if (errors == null) {
errors = new ArrayList<>();
}
mappers.put(newI, oldMappers.get(i));
errors.add(" - Map contained two equal IDs " + newI + " (" + state.getIdFromOld(i) + "/" + i + " -> " + state.getIdFromNew(newI) + "/" + newI + ")!");
} else {
mappers.put(newI, oldMappers.get(i));
}
} else {
LOGGER.warn("[fabric-registry-sync] Int2ObjectMap " + name + " is dropping mapping for integer ID " + i + " (" + state.getIdFromOld(i) + ") - should not happen!");
removedMapperCache.put(state.getIdFromOld(i), oldMappers.get(i));
}
}
if (errors != null) {
throw new RuntimeException("Errors while remapping Int2ObjectMap " + name + " found:\n" + Joiner.on('\n').join(errors));
}
}
@Override
public void onEntryRemoved(int rawId, Identifier id, V object) {
if (mappers.containsKey(rawId)) {
removedMapperCache.put(id, mappers.remove(rawId));
OV mapper = mappers.remove(rawId);
if (mapper != null) {
removedMapperCache.put(id, mapper);
}
}
}

View file

@ -57,7 +57,7 @@ public final class StateIdTracker<T, S> implements RegistryIdRemapCallback<T>, R
stateGetter.apply(object).forEach(stateList::add);
currentHighestId = rawId;
} else {
logger.debug("[fabric-registry-sync] Non-sequential RegistryEntryAddedCallback for state ID tracker (at " + id + "), forcing state map recalculation...");
logger.debug("[fabric-registry-sync] Non-sequential RegistryEntryAddedCallback for " + object.getClass().getSimpleName() + " ID tracker (at " + id + "), forcing state map recalculation...");
recalcStateMap();
}
}

View file

@ -18,8 +18,7 @@ package net.fabricmc.fabric.mixin.registry;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.fabricmc.fabric.api.event.Event;
@ -116,12 +115,21 @@ public abstract class MixinIdRegistry<T> implements RemappableRegistry, Listenab
@SuppressWarnings({"unchecked", "ConstantConditions"})
@Inject(method = "set", at = @At("HEAD"))
public void setPre(int id, Identifier identifier, Object object, CallbackInfoReturnable info) {
int indexedEntriesId = indexedEntries.getId((T) object);
if (indexedEntriesId >= 0) {
throw new RuntimeException("Attempted to register object " + object + " twice! (at raw IDs " + indexedEntriesId + " and " + id + " )");
}
if (!entries.containsKey(identifier)) {
fabric_isObjectNew = true;
} else {
T oldObject = entries.get(identifier);
int oldId = indexedEntries.getId(oldObject);
if (oldObject != object || oldId != id) {
if (oldObject != null && oldObject != object) {
int oldId = indexedEntries.getId(oldObject);
if (oldId != id) {
throw new RuntimeException("Attempted to register ID " + identifier + " at different raw IDs (" + oldId + ", " + id + ")! If you're trying to override an item, use .set(), not .register()!");
}
fabric_removeObjectEvent.invoker().onEntryRemoved(oldId, identifier, oldObject);
fabric_isObjectNew = true;
} else {
@ -148,14 +156,18 @@ public abstract class MixinIdRegistry<T> implements RemappableRegistry, Listenab
case AUTHORITATIVE:
break;
case REMOTE: {
List<String> strings = new ArrayList<>();
List<String> strings = null;
for (Identifier remoteId : remoteIndexedEntries.keySet()) {
if (!registry.getIds().contains(remoteId)) {
if (!entries.keySet().contains(remoteId)) {
if (strings == null) {
strings = new ArrayList<>();
}
strings.add(" - " + remoteId);
}
}
if (!strings.isEmpty()) {
if (strings != null) {
StringBuilder builder = new StringBuilder("Received ID map for " + name + " contains IDs unknown to the receiver!");
for (String s : strings) {
builder.append('\n').append(s);
@ -164,10 +176,10 @@ public abstract class MixinIdRegistry<T> implements RemappableRegistry, Listenab
}
} break;
case EXACT: {
if (!registry.getIds().equals(remoteIndexedEntries.keySet())) {
if (!entries.keySet().equals(remoteIndexedEntries.keySet())) {
List<String> strings = new ArrayList<>();
for (Identifier remoteId : remoteIndexedEntries.keySet()) {
if (!registry.getIds().contains(remoteId)) {
if (!entries.keySet().contains(remoteId)) {
strings.add(" - " + remoteId + " (missing on local)");
}
}
@ -196,53 +208,68 @@ public abstract class MixinIdRegistry<T> implements RemappableRegistry, Listenab
if (fabric_prevIndexedEntries == null) {
fabric_prevIndexedEntries = new Object2IntOpenHashMap<>();
fabric_prevEntries = HashBiMap.create(entries);
for (Identifier id : registry.getIds()) {
//noinspection unchecked
fabric_prevIndexedEntries.put(id, registry.getRawId(registry.get(id)));
for (Object o : registry) {
fabric_prevIndexedEntries.put(registry.getId(o), registry.getRawId(o));
}
}
Int2ObjectMap<Identifier> oldIdMap = new Int2ObjectOpenHashMap<>();
for (Object o : registry) {
oldIdMap.put(registry.getRawId(o), registry.getId(o));
}
// If we're AUTHORITATIVE, we append entries which only exist on the
// local side to the new entry list. For REMOTE, we instead drop them.
if (mode == RemapMode.AUTHORITATIVE) {
int maxValue = 0;
switch (mode) {
case AUTHORITATIVE: {
int maxValue = 0;
Object2IntMap<Identifier> oldRemoteIndexedEntries = remoteIndexedEntries;
remoteIndexedEntries = new Object2IntOpenHashMap<>();
for (Identifier id : oldRemoteIndexedEntries.keySet()) {
int v = oldRemoteIndexedEntries.getInt(id);
remoteIndexedEntries.put(id, v);
if (v > maxValue) maxValue = v;
}
for (Identifier id : registry.getIds()) {
if (!remoteIndexedEntries.containsKey(id)) {
FABRIC_LOGGER.warn("Adding " + id + " to saved/remote registry.");
remoteIndexedEntries.put(id, ++maxValue);
Object2IntMap<Identifier> oldRemoteIndexedEntries = remoteIndexedEntries;
remoteIndexedEntries = new Object2IntOpenHashMap<>();
for (Identifier id : oldRemoteIndexedEntries.keySet()) {
int v = oldRemoteIndexedEntries.getInt(id);
remoteIndexedEntries.put(id, v);
if (v > maxValue) maxValue = v;
}
}
} else if (mode == RemapMode.REMOTE) {
// TODO: Is this what mods really want?
Set<Identifier> droppedIds = new HashSet<>();
for (Identifier id : registry.getIds()) {
if (!remoteIndexedEntries.containsKey(id)) {
droppedIds.add(id);
Object object = registry.get(id);
// Emit RemoveObject events for removed objects.
//noinspection unchecked
fabric_getRemoveObjectEvent().invoker().onEntryRemoved(registry.getRawId(object), id, (T) object);
for (Identifier id : registry.getIds()) {
if (!remoteIndexedEntries.containsKey(id)) {
FABRIC_LOGGER.warn("Adding " + id + " to saved/remote registry.");
remoteIndexedEntries.put(id, ++maxValue);
}
}
}
} break;
case REMOTE: {
// TODO: Is this what mods really want?
Set<Identifier> droppedIds = new HashSet<>();
entries.keySet().removeAll(droppedIds);
for (Identifier id : registry.getIds()) {
if (!remoteIndexedEntries.containsKey(id)) {
Object object = registry.get(id);
int rid = registry.getRawId(object);
droppedIds.add(id);
// Emit RemoveObject events for removed objects.
//noinspection unchecked
fabric_getRemoveObjectEvent().invoker().onEntryRemoved(rid, id, (T) object);
}
}
// note: indexedEntries cannot be safely remove()d from
entries.keySet().removeAll(droppedIds);
} break;
}
Int2IntMap idMap = new Int2IntOpenHashMap();
for (Object o : indexedEntries) {
Identifier id = registry.getId(o);
idMap.put(registry.getRawId(o), remoteIndexedEntries.getInt(id));
int rid = registry.getRawId(o);
// see above note
if (remoteIndexedEntries.containsKey(id)) {
idMap.put(rid, remoteIndexedEntries.getInt(id));
}
}
// entries was handled above, if it was necessary.
@ -276,7 +303,7 @@ public abstract class MixinIdRegistry<T> implements RemappableRegistry, Listenab
}
//noinspection unchecked
fabric_getRemapEvent().invoker().onRemap(new RemapStateImpl(registry, idMap));
fabric_getRemapEvent().invoker().onRemap(new RemapStateImpl(registry, oldIdMap, idMap));
}
@Override

View file

@ -30,12 +30,10 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.*;
@Mixin(WorldSaveHandler.class)
public class MixinWorldSaveHandler {
@ -49,6 +47,7 @@ public class MixinWorldSaveHandler {
@Unique
private CompoundTag fabric_lastSavedIdMap = null;
@Unique
private boolean fabric_readIdMapFile(File file) throws IOException, RemapException {
if (file.exists()) {
FileInputStream fileInputStream = new FileInputStream(file);
@ -63,20 +62,69 @@ public class MixinWorldSaveHandler {
return false;
}
private File getWorldIdMapFile(int i) {
@Unique
private File fabric_getWorldIdMapFile(int i) {
return new File(new File(worldDir, "data"), "fabricRegistry" + ".dat" + (i == 0 ? "" : ("." + i)));
}
@Unique
private void fabric_saveRegistryData() {
CompoundTag newIdMap = RegistrySyncManager.toTag(false);
if (!newIdMap.equals(fabric_lastSavedIdMap)) {
for (int i = FABRIC_ID_REGISTRY_BACKUPS - 1; i >= 0; i--) {
File file = fabric_getWorldIdMapFile(i);
if (file.exists()) {
if (i == FABRIC_ID_REGISTRY_BACKUPS - 1) {
file.delete();
} else {
File target = fabric_getWorldIdMapFile(i + 1);
file.renameTo(target);
}
}
}
try {
File file = fabric_getWorldIdMapFile(0);
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
if (!parentFile.mkdirs()) {
FABRIC_LOGGER.warn("[fabric-registry-sync] Could not create directory " + parentFile + "!");
}
}
FileOutputStream fileOutputStream = new FileOutputStream(file);
NbtIo.writeCompressed(newIdMap, fileOutputStream);
fileOutputStream.close();
} catch (IOException e) {
FABRIC_LOGGER.warn("[fabric-registry-sync] Failed to save registry file!", e);
}
fabric_lastSavedIdMap = newIdMap;
}
}
@Inject(method = "saveWorld", at = @At("HEAD"))
public void saveWorld(LevelProperties levelProperties, CompoundTag compoundTag, CallbackInfo info) {
if (!worldDir.exists()) {
return;
}
fabric_saveRegistryData();
}
// TODO: stop double save on client?
@Inject(method = "readProperties", at = @At("HEAD"))
public void readWorldProperties(CallbackInfoReturnable<LevelProperties> callbackInfo) {
// Load
for (int i = 0; i < FABRIC_ID_REGISTRY_BACKUPS; i++) {
FABRIC_LOGGER.info("Loading Fabric registry [file " + (i + 1) + "/" + (FABRIC_ID_REGISTRY_BACKUPS + 1) + "]");
FABRIC_LOGGER.trace("[fabric-registry-sync] Loading Fabric registry [file " + (i + 1) + "/" + (FABRIC_ID_REGISTRY_BACKUPS + 1) + "]");
try {
if (fabric_readIdMapFile(getWorldIdMapFile(i))) {
break;
if (fabric_readIdMapFile(fabric_getWorldIdMapFile(i))) {
FABRIC_LOGGER.info("[fabric-registry-sync] Loaded registry data [file " + (i + 1) + "/" + (FABRIC_ID_REGISTRY_BACKUPS + 1) + "]");
return;
}
} catch (FileNotFoundException e) {
// pass
} catch (IOException e) {
if (i >= FABRIC_ID_REGISTRY_BACKUPS - 1) {
throw new RuntimeException(e);
@ -88,29 +136,7 @@ public class MixinWorldSaveHandler {
}
}
CompoundTag newIdMap = RegistrySyncManager.toTag(false);
if (!newIdMap.equals(fabric_lastSavedIdMap)) {
for (int i = FABRIC_ID_REGISTRY_BACKUPS - 1; i >= 0; i--) {
File file = getWorldIdMapFile(i);
if (file.exists()) {
if (i == FABRIC_ID_REGISTRY_BACKUPS - 1) {
file.delete();
} else {
File target = getWorldIdMapFile(i + 1);
file.renameTo(target);
}
}
}
try {
FileOutputStream fileOutputStream = new FileOutputStream(getWorldIdMapFile(0));
NbtIo.writeCompressed(newIdMap, fileOutputStream);
fileOutputStream.close();
} catch (IOException e) {
FABRIC_LOGGER.warn("Failed to save registry file!", e);
}
fabric_lastSavedIdMap = newIdMap;
}
// If not returned (not present), try saving the registry data
fabric_saveRegistryData();
}
}

View file

@ -34,6 +34,6 @@ public class MixinBlockColorMap {
@Inject(method = "<init>", at = @At("RETURN"))
private void create(CallbackInfo info) {
IdListTracker.register(Registry.BLOCK, providers);
IdListTracker.register(Registry.BLOCK, "BlockColors.providers", providers);
}
}

View file

@ -34,6 +34,6 @@ public class MixinItemColorMap {
@Inject(method = "<init>", at = @At("RETURN"))
private void create(CallbackInfo info) {
IdListTracker.register(Registry.ITEM, providers);
IdListTracker.register(Registry.ITEM, "ItemColors.providers", providers);
}
}

View file

@ -38,7 +38,7 @@ public class MixinItemModelMap {
@Inject(method = "<init>", at = @At("RETURN"))
public void onInit(BakedModelManager bakedModelManager, CallbackInfo info) {
Int2ObjectMapTracker.register(Registry.ITEM, modelIds);
Int2ObjectMapTracker.register(Registry.ITEM, models);
Int2ObjectMapTracker.register(Registry.ITEM, "ItemModels.modelIds", modelIds);
Int2ObjectMapTracker.register(Registry.ITEM, "ItemModels.models", models);
}
}

View file

@ -36,6 +36,6 @@ public class MixinParticleManager {
@Inject(method = "<init>", at = @At("RETURN"))
public void onInit(World world, TextureManager textureManager, CallbackInfo info) {
Int2ObjectMapTracker.register(Registry.PARTICLE_TYPE, factories);
Int2ObjectMapTracker.register(Registry.PARTICLE_TYPE, "ParticleManager.factories", factories);
}
}