make Registry immutable, remove other registry implementations

This commit is contained in:
dfsek
2022-08-21 00:51:26 -07:00
parent b04a4850da
commit 620ae7d1ff
39 changed files with 275 additions and 819 deletions

View File

@@ -7,6 +7,9 @@
package com.dfsek.terra.api;
import com.dfsek.terra.api.registry.meta.RegistryHolder;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
@@ -19,7 +22,6 @@ import com.dfsek.terra.api.event.EventManager;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.profiler.Profiler;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.tectonic.LoaderRegistrar;
@@ -27,24 +29,13 @@ import com.dfsek.terra.api.tectonic.LoaderRegistrar;
/**
* Represents a Terra mod/plugin instance.
*/
public interface Platform extends LoaderRegistrar {
public interface Platform extends LoaderRegistrar, RegistryHolder {
boolean reload();
@NotNull
@Contract(pure = true)
String platformName();
/**
* Runs a task that may or may not be thread safe, depending on platform.
* <p>
* Allows platforms to define what code is safe to be run asynchronously.
*
* @param task Task to be run.
*/
default void runPossiblyUnsafeTask(@NotNull Runnable task) {
task.run();
}
@NotNull
@Contract(pure = true)
WorldHandle getWorldHandle();
@@ -59,11 +50,7 @@ public interface Platform extends LoaderRegistrar {
@NotNull
@Contract(pure = true)
CheckedRegistry<ConfigPack> getConfigRegistry();
@NotNull
@Contract(pure = true)
Registry<BaseAddon> getAddons();
Registry<BaseAddon> addons();
@NotNull
@Contract(pure = true)

View File

@@ -17,7 +17,7 @@ import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.properties.PropertyHolder;
import com.dfsek.terra.api.registry.key.Keyed;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.registry.meta.CheckedRegistryHolder;
import com.dfsek.terra.api.registry.meta.RegistryHolder;
import com.dfsek.terra.api.registry.meta.RegistryProvider;
import com.dfsek.terra.api.tectonic.ConfigLoadingDelegate;
import com.dfsek.terra.api.tectonic.LoaderRegistrar;
@@ -30,7 +30,7 @@ import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorPr
public interface ConfigPack extends LoaderRegistrar,
ConfigLoadingDelegate,
CheckedRegistryHolder,
RegistryHolder,
RegistryProvider,
Keyed<ConfigPack>,
PropertyHolder {

View File

@@ -11,17 +11,17 @@ import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.ConfigType;
import com.dfsek.terra.api.event.events.FailThroughEvent;
import com.dfsek.terra.api.event.events.PackEvent;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
public abstract class ConfigTypeLoadEvent implements PackEvent, FailThroughEvent {
private final ConfigType<?, ?> type;
private final CheckedRegistry<?> registry;
private final Registry<?> registry;
private final ConfigPack pack;
public ConfigTypeLoadEvent(ConfigType<?, ?> type, CheckedRegistry<?> registry, ConfigPack pack) {
public ConfigTypeLoadEvent(ConfigType<?, ?> type, Registry<?> registry, ConfigPack pack) {
this.type = type;
this.registry = registry;
this.pack = pack;
@@ -37,11 +37,11 @@ public abstract class ConfigTypeLoadEvent implements PackEvent, FailThroughEvent
}
@SuppressWarnings("unchecked")
public <T> CheckedRegistry<T> getRegistry(Class<T> clazz) {
public <T> Registry<T> getRegistry(Class<T> clazz) {
if(!clazz.isAssignableFrom(type.getTypeKey().getRawType()))
throw new ClassCastException(
"Cannot assign object from loader of type " + ReflectionUtil.typeToString(type.getTypeKey().getType()) + " to class " +
clazz.getCanonicalName());
return (CheckedRegistry<T>) registry;
return (Registry<T>) registry;
}
}

View File

@@ -9,11 +9,11 @@ package com.dfsek.terra.api.event.events.config.type;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.ConfigType;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.Registry;
public class ConfigTypePostLoadEvent extends ConfigTypeLoadEvent {
public ConfigTypePostLoadEvent(ConfigType<?, ?> type, CheckedRegistry<?> registry, ConfigPack pack) {
public ConfigTypePostLoadEvent(ConfigType<?, ?> type, Registry<?> registry, ConfigPack pack) {
super(type, registry, pack);
}
}

View File

@@ -9,11 +9,11 @@ package com.dfsek.terra.api.event.events.config.type;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.ConfigType;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.Registry;
public class ConfigTypePreLoadEvent extends ConfigTypeLoadEvent {
public ConfigTypePreLoadEvent(ConfigType<?, ?> type, CheckedRegistry<?> registry, ConfigPack pack) {
public ConfigTypePreLoadEvent(ConfigType<?, ?> type, Registry<?> registry, ConfigPack pack) {
super(type, registry, pack);
}
}

View File

@@ -1,32 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the common/api directory.
*/
package com.dfsek.terra.api.registry;
import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import com.dfsek.terra.api.registry.key.Keyed;
import com.dfsek.terra.api.registry.key.RegistryKey;
public interface CheckedRegistry<T> extends Registry<T> {
/**
* Add a value to this registry, checking whether it is present first.
*
* @param identifier Identifier to assign value.
* @param value Value to register.
*
* @throws DuplicateEntryException If an entry with the same identifier is already present.
*/
void register(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException;
@SuppressWarnings("unchecked")
default void register(@NotNull Keyed<? extends T> value) throws DuplicateEntryException {
register(value.getRegistryKey(), (T) value);
}
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the common/api directory.
*/
package com.dfsek.terra.api.registry;
import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import com.dfsek.terra.api.registry.key.Keyed;
import com.dfsek.terra.api.registry.key.RegistryKey;
public interface OpenRegistry<T> extends Registry<T> {
/**
* Add a value to this registry.
*
* @param identifier Identifier to assign value.
* @param value Value to register.
*/
boolean register(@NotNull RegistryKey identifier, @NotNull T value);
@SuppressWarnings("unchecked")
default boolean register(@NotNull Keyed<? extends T> value) {
return register(value.getRegistryKey(), (T) value);
}
/**
* Add a value to this registry, checking whether it is present first.
*
* @param identifier Identifier to assign value.
* @param value Value to register.
*
* @throws DuplicateEntryException If an entry with the same identifier is already present.
*/
void registerChecked(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException;
@SuppressWarnings("unchecked")
default void registerChecked(@NotNull Keyed<? extends T> value) {
registerChecked(value.getRegistryKey(), (T) value);
}
/**
* Clears all entries from the registry.
*/
void clear();
}

View File

@@ -8,16 +8,17 @@
package com.dfsek.terra.api.registry;
import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.terra.api.registry.key.Keyed;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.reflection.TypeKey;
@@ -65,7 +66,22 @@ public interface Registry<T> extends TypeLoader<T> {
*/
@NotNull
@Contract(pure = true)
Collection<T> entries();
Set<T> entries();
/**
* Add a value to this registry.
*
* @param identifier Identifier to assign value.
* @param value Value to register.
*/
@Contract(pure = true, value = "_,_->new")
Registry<T> register(@NotNull RegistryKey identifier, @NotNull T value);
@SuppressWarnings("unchecked")
@Contract(pure = true, value = "_->new")
default Registry<T> register(@NotNull Keyed<? extends T> value) {
return register(value.getRegistryKey(), (T) value);
}
/**
* Get all the keys in this registry.
@@ -82,31 +98,7 @@ public interface Registry<T> extends TypeLoader<T> {
return getType().getRawType();
}
@Deprecated
default Optional<T> getByID(String id) {
return getByID(id, map -> {
if(map.isEmpty()) return Optional.empty();
if(map.size() == 1) {
return map.values().stream().findFirst(); // only one value.
}
throw new IllegalArgumentException("ID \"" + id + "\" is ambiguous; matches: " + map
.keySet()
.stream()
.map(RegistryKey::toString)
.reduce("", (a, b) -> a + "\n - " + b));
});
}
Map<RegistryKey, T> getID(String id);
default Collection<T> getAllWithID(String id) {
return getMatches(id).values();
}
Map<RegistryKey, T> getMatches(String id);
default Optional<T> getByID(String attempt, Function<Map<RegistryKey, T>, Optional<T>> reduction) {
if(attempt.contains(":")) {
return get(RegistryKey.parse(attempt));
}
return reduction.apply(getMatches(attempt));
}
Map<RegistryKey, T> getNamespace(String namespace);
}

View File

@@ -13,4 +13,9 @@ public interface Keyed<T extends Keyed<T>> extends Namespaced, StringIdentifiabl
default String getID() {
return getRegistryKey().getID();
}
@SuppressWarnings("unchecked")
default T coerce() {
return (T) this;
}
}

View File

@@ -1,19 +0,0 @@
package com.dfsek.terra.api.registry.meta;
import java.lang.reflect.Type;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.util.reflection.TypeKey;
public interface CheckedRegistryHolder extends RegistryHolder {
default <T> CheckedRegistry<T> getCheckedRegistry(Class<T> clazz) throws IllegalStateException {
return getCheckedRegistry((Type) clazz);
}
default <T> CheckedRegistry<T> getCheckedRegistry(TypeKey<T> type) throws IllegalStateException {
return getCheckedRegistry(type.getType());
}
<T> CheckedRegistry<T> getCheckedRegistry(Type type);
}

View File

@@ -1,13 +1,13 @@
package com.dfsek.terra.api.registry.meta;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.util.reflection.TypeKey;
public interface RegistryProvider {
default <T> CheckedRegistry<T> getOrCreateRegistry(Class<T> clazz) {
return getOrCreateRegistry(TypeKey.of(clazz));
default <T> Registry<T> createRegistry(Class<T> clazz) {
return createRegistry(TypeKey.of(clazz));
}
<T> CheckedRegistry<T> getOrCreateRegistry(TypeKey<T> type);
<T> Registry<T> createRegistry(TypeKey<T> type);
}