use of net.minecraftforge.registries.ForgeRegistry.REGISTRIES in project MinecraftForge by MinecraftForge.
the class GameData method injectSnapshot.
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Multimap<ResourceLocation, ResourceLocation> injectSnapshot(Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot, boolean injectFrozenData, boolean isLocalWorld) {
LOGGER.info(REGISTRIES, "Injecting existing registry data into this {} instance", EffectiveSide.get());
RegistryManager.ACTIVE.registries.forEach((name, reg) -> reg.validateContent(name));
RegistryManager.ACTIVE.registries.forEach((name, reg) -> reg.dump(name));
RegistryManager.ACTIVE.registries.forEach((name, reg) -> reg.resetDelegates());
// Update legacy names
snapshot = snapshot.entrySet().stream().sorted(// FIXME Registries need dependency ordering, this makes sure blocks are done before items (for ItemCallbacks) but it's lazy as hell
Map.Entry.comparingByKey()).collect(Collectors.toMap(e -> RegistryManager.ACTIVE.updateLegacyName(e.getKey()), Map.Entry::getValue, (k1, k2) -> k1, LinkedHashMap::new));
if (isLocalWorld) {
List<ResourceLocation> missingRegs = snapshot.keySet().stream().filter(name -> !RegistryManager.ACTIVE.registries.containsKey(name)).collect(Collectors.toList());
if (missingRegs.size() > 0) {
String header = "Forge Mod Loader detected missing/unknown registrie(s).\n\n" + "There are " + missingRegs.size() + " missing registries in this save.\n" + "If you continue the missing registries will get removed.\n" + "This may cause issues, it is advised that you create a world backup before continuing.\n\n";
StringBuilder text = new StringBuilder("Missing Registries:\n");
for (ResourceLocation s : missingRegs) text.append(s).append("\n");
LOGGER.warn(REGISTRIES, header);
LOGGER.warn(REGISTRIES, text.toString());
}
}
RegistryManager STAGING = new RegistryManager("STAGING");
final Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps = Maps.newHashMap();
final LinkedHashMap<ResourceLocation, Map<ResourceLocation, Integer>> missing = Maps.newLinkedHashMap();
// Load the snapshot into the "STAGING" registry
snapshot.forEach((key, value) -> {
final Class<? extends IForgeRegistryEntry> clazz = RegistryManager.ACTIVE.getSuperType(key);
remaps.put(key, Maps.newLinkedHashMap());
missing.put(key, Maps.newLinkedHashMap());
loadPersistentDataToStagingRegistry(RegistryManager.ACTIVE, STAGING, remaps.get(key), missing.get(key), key, value, clazz);
});
snapshot.forEach((key, value) -> {
value.dummied.forEach(dummy -> {
Map<ResourceLocation, Integer> m = missing.get(key);
ForgeRegistry<?> reg = STAGING.getRegistry(key);
// Currently missing locally, we just inject and carry on
if (m.containsKey(dummy)) {
if (reg.markDummy(dummy, m.get(dummy)))
m.remove(dummy);
} else if (isLocalWorld) {
LOGGER.debug(REGISTRIES, "Registry {}: Resuscitating dummy entry {}", key, dummy);
} else {
// The server believes this is a dummy block identity, but we seem to have one locally. This is likely a conflict
// in mod setup - Mark this entry as a dummy
int id = reg.getID(dummy);
LOGGER.warn(REGISTRIES, "Registry {}: The ID {} @ {} is currently locally mapped - it will be replaced with a dummy for this session", dummy, key, id);
reg.markDummy(dummy, id);
}
});
});
int count = missing.values().stream().mapToInt(Map::size).sum();
if (count > 0) {
LOGGER.debug(REGISTRIES, "There are {} mappings missing - attempting a mod remap", count);
Multimap<ResourceLocation, ResourceLocation> defaulted = ArrayListMultimap.create();
Multimap<ResourceLocation, ResourceLocation> failed = ArrayListMultimap.create();
missing.entrySet().stream().filter(e -> e.getValue().size() > 0).forEach(m -> {
ResourceLocation name = m.getKey();
ForgeRegistry<?> reg = STAGING.getRegistry(name);
RegistryEvent.MissingMappings<?> event = reg.getMissingEvent(name, m.getValue());
MinecraftForge.EVENT_BUS.post(event);
List<MissingMappings.Mapping<?>> lst = event.getAllMappings().stream().filter(e -> e.getAction() == MissingMappings.Action.DEFAULT).sorted((a, b) -> a.toString().compareTo(b.toString())).collect(Collectors.toList());
if (!lst.isEmpty()) {
LOGGER.error(REGISTRIES, () -> LogMessageAdapter.adapt(sb -> {
sb.append("Unidentified mapping from registry ").append(name).append('\n');
lst.stream().sorted().forEach(map -> sb.append('\t').append(map.key).append(": ").append(map.id).append('\n'));
}));
}
event.getAllMappings().stream().filter(e -> e.getAction() == MissingMappings.Action.FAIL).forEach(fail -> failed.put(name, fail.key));
final Class<? extends IForgeRegistryEntry> clazz = RegistryManager.ACTIVE.getSuperType(name);
processMissing(clazz, name, STAGING, event, m.getValue(), remaps.get(name), defaulted.get(name), failed.get(name), !isLocalWorld);
});
if (!defaulted.isEmpty() && !isLocalWorld)
return defaulted;
if (!defaulted.isEmpty()) {
String header = "Forge Mod Loader detected missing registry entries.\n\n" + "There are " + defaulted.size() + " missing entries in this save.\n" + "If you continue the missing entries will get removed.\n" + "A world backup will be automatically created in your saves directory.\n\n";
StringBuilder buf = new StringBuilder();
defaulted.asMap().forEach((name, entries) -> {
buf.append("Missing ").append(name).append(":\n");
entries.stream().sorted((o1, o2) -> o1.compareNamespaced(o2)).forEach(rl -> buf.append(" ").append(rl).append("\n"));
buf.append("\n");
});
LOGGER.warn(REGISTRIES, header);
LOGGER.warn(REGISTRIES, buf.toString());
}
if (!defaulted.isEmpty()) {
if (isLocalWorld)
LOGGER.error(REGISTRIES, "There are unidentified mappings in this world - we are going to attempt to process anyway");
}
}
if (injectFrozenData) {
// If we're loading from disk, we can actually substitute air in the block map for anything that is otherwise "missing". This keeps the reference in the map, in case
// the block comes back later
missing.forEach((name, m) -> {
if (m.isEmpty())
return;
ForgeRegistry<?> reg = STAGING.getRegistry(name);
m.forEach((rl, id) -> reg.markDummy(rl, id));
});
// If we're loading up the world from disk, we want to add in the new data that might have been provisioned by mods
// So we load it from the frozen persistent registry
RegistryManager.ACTIVE.registries.forEach((name, reg) -> {
final Class<? extends IForgeRegistryEntry> clazz = RegistryManager.ACTIVE.getSuperType(name);
loadFrozenDataToStagingRegistry(STAGING, name, remaps.get(name), clazz);
});
}
// Validate that all the STAGING data is good
STAGING.registries.forEach((name, reg) -> reg.validateContent(name));
// Load the STAGING registry into the ACTIVE registry
// for (Map.Entry<ResourceLocation, IForgeRegistry<? extends IForgeRegistryEntry<?>>> r : RegistryManager.ACTIVE.registries.entrySet())
RegistryManager.ACTIVE.registries.forEach((key, value) -> {
final Class<? extends IForgeRegistryEntry> registrySuperType = RegistryManager.ACTIVE.getSuperType(key);
loadRegistry(key, STAGING, RegistryManager.ACTIVE, registrySuperType, true);
});
RegistryManager.ACTIVE.registries.forEach((name, reg) -> {
reg.bake();
// Dump the active registry
reg.dump(name);
});
// Tell mods that the ids have changed
fireRemapEvent(remaps, false);
// The id map changed, ensure we apply object holders
ObjectHolderRegistry.applyObjectHolders();
// Return an empty list, because we're good
return ArrayListMultimap.create();
}
use of net.minecraftforge.registries.ForgeRegistry.REGISTRIES in project MinecraftForge by MinecraftForge.
the class HandshakeHandler method handleRegistryLoading.
private boolean handleRegistryLoading(final Supplier<NetworkEvent.Context> contextSupplier) {
// We use a countdown latch to suspend the impl thread pending the client thread processing the registry data
AtomicBoolean successfulConnection = new AtomicBoolean(false);
CountDownLatch block = new CountDownLatch(1);
contextSupplier.get().enqueueWork(() -> {
LOGGER.debug(FMLHSMARKER, "Injecting registry snapshot from server.");
final Multimap<ResourceLocation, ResourceLocation> missingData = GameData.injectSnapshot(registrySnapshots, false, false);
LOGGER.debug(FMLHSMARKER, "Snapshot injected.");
if (!missingData.isEmpty()) {
LOGGER.error(FMLHSMARKER, "Missing registry data for impl connection:\n{}", LogMessageAdapter.adapt(sb -> missingData.forEach((reg, entry) -> sb.append("\t").append(reg).append(": ").append(entry).append('\n'))));
}
successfulConnection.set(missingData.isEmpty());
block.countDown();
});
LOGGER.debug(FMLHSMARKER, "Waiting for registries to load.");
try {
block.await();
} catch (InterruptedException e) {
Thread.interrupted();
}
if (successfulConnection.get()) {
LOGGER.debug(FMLHSMARKER, "Registry load complete, continuing handshake.");
} else {
LOGGER.error(FMLHSMARKER, "Failed to load registry, closing connection.");
this.manager.disconnect(new TextComponent("Failed to synchronize registry data from server, closing connection"));
}
return successfulConnection.get();
}
Aggregations