Files
MinecraftForge/src/main/java/net/minecraftforge/registries/RegistryManager.java
T

192 lines
7.0 KiB
Java
Raw Normal View History

/*
* Minecraft Forge - Forge Development LLC
* SPDX-License-Identifier: LGPL-2.1-only
*/
2017-06-19 15:02:18 -07:00
package net.minecraftforge.registries;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
2017-06-19 15:02:18 -07:00
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
2017-06-19 15:02:18 -07:00
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
2021-07-17 00:08:49 -05:00
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.Registry;
2021-11-26 18:57:41 +00:00
import net.minecraftforge.network.HandshakeMessages;
2017-06-19 15:02:18 -07:00
import net.minecraftforge.registries.ForgeRegistry.Snapshot;
import org.apache.commons.lang3.tuple.Pair;
2018-08-29 21:30:15 -04:00
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
2017-06-19 15:02:18 -07:00
public class RegistryManager
{
2018-08-29 21:30:15 -04:00
private static final Logger LOGGER = LogManager.getLogger();
2017-06-19 15:02:18 -07:00
public static final RegistryManager ACTIVE = new RegistryManager("ACTIVE");
public static final RegistryManager VANILLA = new RegistryManager("VANILLA");
public static final RegistryManager FROZEN = new RegistryManager("FROZEN");
BiMap<ResourceLocation, ForgeRegistry<? extends IForgeRegistryEntry<?>>> registries = HashBiMap.create();
private BiMap<Class<? extends IForgeRegistryEntry<?>>, ResourceLocation> superTypes = HashBiMap.create();
2017-06-19 15:02:18 -07:00
private Set<ResourceLocation> persisted = Sets.newHashSet();
2019-06-09 00:55:42 -04:00
private Set<ResourceLocation> synced = Sets.newHashSet();
private Map<ResourceLocation, ResourceLocation> legacyNames = new HashMap<>();
2017-06-19 15:02:18 -07:00
private final String name;
public RegistryManager(String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
@SuppressWarnings("unchecked")
public <V extends IForgeRegistryEntry<V>> Class<V> getSuperType(ResourceLocation key)
{
return (Class<V>)superTypes.inverse().get(key);
}
@SuppressWarnings("unchecked")
public <V extends IForgeRegistryEntry<V>> ForgeRegistry<V> getRegistry(ResourceLocation key)
{
return (ForgeRegistry<V>)this.registries.get(key);
}
2021-07-17 00:08:49 -05:00
public <V extends IForgeRegistryEntry<V>> ForgeRegistry<V> getRegistry(ResourceKey<? extends Registry<V>> key)
2020-08-13 00:13:48 -07:00
{
return getRegistry(key.location());
2020-08-13 00:13:48 -07:00
}
public <V extends IForgeRegistryEntry<V>> IForgeRegistry<V> getRegistry(Class<? super V> cls)
2017-06-19 15:02:18 -07:00
{
return getRegistry(superTypes.get(cls));
}
public <V extends IForgeRegistryEntry<V>> ResourceLocation getName(IForgeRegistry<V> reg)
{
return this.registries.inverse().get(reg);
}
public <V extends IForgeRegistryEntry<V>> ResourceLocation updateLegacyName(ResourceLocation legacyName)
{
ResourceLocation originalName = legacyName;
while (getRegistry(legacyName) == null)
{
legacyName = legacyNames.get(legacyName);
if (legacyName == null)
{
return originalName;
}
}
return legacyName;
}
2017-06-19 15:02:18 -07:00
public <V extends IForgeRegistryEntry<V>> ForgeRegistry<V> getRegistry(ResourceLocation key, RegistryManager other)
{
if (!this.registries.containsKey(key))
{
ForgeRegistry<V> ot = other.getRegistry(key);
if (ot == null)
return null;
this.registries.put(key, ot.copy(this));
this.superTypes.put(ot.getRegistrySuperType(), key);
if (other.persisted.contains(key))
this.persisted.add(key);
2019-06-09 00:55:42 -04:00
if (other.synced.contains(key))
this.synced.add(key);
other.legacyNames.entrySet().stream()
.filter(e -> e.getValue().equals(key))
.forEach(e -> addLegacyName(e.getKey(), e.getValue()));
2017-06-19 15:02:18 -07:00
}
return getRegistry(key);
}
2019-01-11 23:52:30 +01:00
<V extends IForgeRegistryEntry<V>> ForgeRegistry<V> createRegistry(ResourceLocation name, RegistryBuilder<V> builder)
2017-06-19 15:02:18 -07:00
{
Set<Class<?>> parents = Sets.newHashSet();
2019-01-11 23:52:30 +01:00
findSuperTypes(builder.getType(), parents);
2017-06-19 15:02:18 -07:00
SetView<Class<?>> overlappedTypes = Sets.intersection(parents, superTypes.keySet());
if (!overlappedTypes.isEmpty())
{
Class<?> foundType = overlappedTypes.iterator().next();
2019-01-11 23:52:30 +01:00
LOGGER.error("Found existing registry of type {} named {}, you cannot create a new registry ({}) with type {}, as {} has a parent of that type",
foundType, superTypes.get(foundType), name, builder.getType(), builder.getType());
2017-06-19 15:02:18 -07:00
throw new IllegalArgumentException("Duplicate registry parent type found - you can only have one registry for a particular super type");
}
ForgeRegistry<V> reg = new ForgeRegistry<V>(this, name, builder);
2017-06-19 15:02:18 -07:00
registries.put(name, reg);
2019-01-11 23:52:30 +01:00
superTypes.put(builder.getType(), name);
if (builder.getSaveToDisc())
2017-06-19 15:02:18 -07:00
this.persisted.add(name);
2019-06-09 00:55:42 -04:00
if (builder.getSync())
this.synced.add(name);
for (ResourceLocation legacyName : builder.getLegacyNames())
addLegacyName(legacyName, name);
2017-06-19 15:02:18 -07:00
return getRegistry(name);
}
private void addLegacyName(ResourceLocation legacyName, ResourceLocation name)
{
if (this.legacyNames.containsKey(legacyName))
{
throw new IllegalArgumentException("Legacy name conflict for registry " + name + ", upgrade path must be linear: " + legacyName);
}
this.legacyNames.put(legacyName, name);
}
2017-06-19 15:02:18 -07:00
private void findSuperTypes(Class<?> type, Set<Class<?>> types)
{
if (type == null || type == Object.class)
{
return;
}
types.add(type);
for (Class<?> interfac : type.getInterfaces())
{
findSuperTypes(interfac, types);
}
findSuperTypes(type.getSuperclass(), types);
}
public Map<ResourceLocation, Snapshot> takeSnapshot(boolean savingToDisc)
{
Map<ResourceLocation, Snapshot> ret = Maps.newHashMap();
2019-06-09 00:55:42 -04:00
Set<ResourceLocation> keys = savingToDisc ? this.persisted : this.synced;
2017-06-19 15:02:18 -07:00
keys.forEach(name -> ret.put(name, getRegistry(name).makeSnapshot()));
return ret;
}
//Public for testing only
public void clean()
{
this.persisted.clear();
2019-06-09 00:55:42 -04:00
this.synced.clear();
2017-06-19 15:02:18 -07:00
this.registries.clear();
this.superTypes.clear();
}
2021-11-26 18:57:41 +00:00
public static List<Pair<String, HandshakeMessages.S2CRegistry>> generateRegistryPackets(boolean isLocal)
{
return !isLocal ? ACTIVE.takeSnapshot(false).entrySet().stream().
2021-11-26 18:57:41 +00:00
map(e->Pair.of("Registry " + e.getKey(), new HandshakeMessages.S2CRegistry(e.getKey(), e.getValue()))).
collect(Collectors.toList()) : Collections.emptyList();
}
public static List<ResourceLocation> getRegistryNamesForSyncToClient()
{
return ACTIVE.registries.keySet().stream().
filter(resloc -> ACTIVE.synced.contains(resloc)).
collect(Collectors.toList());
}
2017-06-19 15:02:18 -07:00
}