mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-06 15:56:14 +00:00
implement namespaced registries
This commit is contained in:
@@ -10,6 +10,8 @@ import com.dfsek.terra.api.registry.Registry;
|
||||
|
||||
import com.dfsek.terra.api.registry.exception.NoSuchEntryException;
|
||||
|
||||
import com.dfsek.terra.api.registry.key.RegistryKey;
|
||||
|
||||
import io.leangen.geantyref.TypeToken;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
@@ -92,12 +94,12 @@ public class RegistryArgument<T, R> extends CommandArgument<T, R> {
|
||||
public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext,
|
||||
@NonNull Queue<@NonNull String> inputQueue) {
|
||||
String input = inputQueue.remove();
|
||||
return registry.get(input).map(ArgumentParseResult::success).orElse(ArgumentParseResult.failure(new NoSuchEntryException("No such entry: " + input)));
|
||||
return registry.get(RegistryKey.parse(input)).map(ArgumentParseResult::success).orElse(ArgumentParseResult.failure(new NoSuchEntryException("No such entry: " + input)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull List<@NonNull String> suggestions(@NonNull CommandContext<T> commandContext, @NonNull String input) {
|
||||
return registry.keys().stream().sorted().collect(Collectors.toList());
|
||||
return registry.keys().stream().map(RegistryKey::toString).sorted().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@ import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.registry.key.Keyed;
|
||||
import com.dfsek.terra.api.registry.key.Namespaced;
|
||||
import com.dfsek.terra.api.registry.key.RegistryKey;
|
||||
import com.dfsek.terra.api.registry.meta.RegistryHolder;
|
||||
import com.dfsek.terra.api.tectonic.ConfigLoadingDelegate;
|
||||
import com.dfsek.terra.api.tectonic.LoaderRegistrar;
|
||||
@@ -27,9 +29,9 @@ import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider;
|
||||
|
||||
|
||||
public interface ConfigPack extends LoaderRegistrar, ConfigLoadingDelegate, RegistryHolder, StringIdentifiable, Namespaced {
|
||||
public interface ConfigPack extends LoaderRegistrar, ConfigLoadingDelegate, RegistryHolder, Keyed {
|
||||
|
||||
ConfigPack registerConfigType(ConfigType<?, ?> type, String id, int priority);
|
||||
ConfigPack registerConfigType(ConfigType<?, ?> type, RegistryKey id, int priority);
|
||||
|
||||
Map<BaseAddon, VersionRange> addons();
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.dfsek.terra.api.registry;
|
||||
|
||||
import com.dfsek.terra.api.registry.key.RegistryKey;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
|
||||
@@ -21,5 +23,5 @@ public interface CheckedRegistry<T> extends Registry<T> {
|
||||
*
|
||||
* @throws DuplicateEntryException If an entry with the same identifier is already present.
|
||||
*/
|
||||
void register(@NotNull String identifier, @NotNull T value) throws DuplicateEntryException;
|
||||
void register(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
package com.dfsek.terra.api.registry;
|
||||
|
||||
import com.dfsek.terra.api.registry.key.RegistryKey;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
|
||||
@@ -19,7 +21,7 @@ public interface OpenRegistry<T> extends Registry<T> {
|
||||
* @param identifier Identifier to assign value.
|
||||
* @param value Value to register.
|
||||
*/
|
||||
boolean register(@NotNull String identifier, @NotNull T value);
|
||||
boolean register(@NotNull RegistryKey identifier, @NotNull T value);
|
||||
|
||||
/**
|
||||
* Add a value to this registry, checking whether it is present first.
|
||||
@@ -29,7 +31,7 @@ public interface OpenRegistry<T> extends Registry<T> {
|
||||
*
|
||||
* @throws DuplicateEntryException If an entry with the same identifier is already present.
|
||||
*/
|
||||
void registerChecked(@NotNull String identifier, @NotNull T value) throws DuplicateEntryException;
|
||||
void registerChecked(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException;
|
||||
|
||||
/**
|
||||
* Clears all entries from the registry.
|
||||
|
||||
@@ -9,39 +9,41 @@ package com.dfsek.terra.api.registry;
|
||||
|
||||
import com.dfsek.tectonic.api.loader.type.TypeLoader;
|
||||
|
||||
import com.dfsek.terra.api.registry.key.RegistryKey;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
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;
|
||||
|
||||
|
||||
public interface Registry<T> extends TypeLoader<T> {
|
||||
/**
|
||||
* Get a value from the registry.
|
||||
*
|
||||
* @param identifier Identifier of value.
|
||||
* @param key Identifier of value.
|
||||
*
|
||||
* @return Value matching the identifier, {@code null} if no value is present.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
Optional<T> get(@NotNull String identifier);
|
||||
Optional<T> get(@NotNull RegistryKey key);
|
||||
|
||||
/**
|
||||
* Check if the registry contains a value.
|
||||
*
|
||||
* @param identifier Identifier of value.
|
||||
* @param key Identifier of value.
|
||||
*
|
||||
* @return Whether the registry contains the value.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
boolean contains(@NotNull String identifier);
|
||||
boolean contains(@NotNull RegistryKey key);
|
||||
|
||||
/**
|
||||
* Perform the given action for every value in the registry.
|
||||
@@ -55,7 +57,7 @@ public interface Registry<T> extends TypeLoader<T> {
|
||||
*
|
||||
* @param consumer Action to perform on pair.
|
||||
*/
|
||||
void forEach(@NotNull BiConsumer<String, T> consumer);
|
||||
void forEach(@NotNull BiConsumer<RegistryKey, T> consumer);
|
||||
|
||||
/**
|
||||
* Get the entries of this registry as a {@link Set}.
|
||||
@@ -73,7 +75,30 @@ public interface Registry<T> extends TypeLoader<T> {
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
Set<String> keys();
|
||||
Set<RegistryKey> keys();
|
||||
|
||||
TypeKey<T> getType();
|
||||
|
||||
default Optional<T> tryGet(String attempt) {
|
||||
return get(attempt, map -> {
|
||||
if(map.isEmpty()) return Optional.empty();
|
||||
if(map.size() == 1) {
|
||||
return map.values().stream().findFirst(); // only one value.
|
||||
}
|
||||
throw new IllegalArgumentException("ID \"" + attempt + "\" is ambiguous; matches: " + map
|
||||
.keySet()
|
||||
.stream()
|
||||
.map(RegistryKey::toString)
|
||||
.reduce("", (a, b) -> a + "\n - " + b));
|
||||
});
|
||||
}
|
||||
|
||||
Map<RegistryKey, T> get(String id);
|
||||
|
||||
default Optional<T> get(String attempt, Function<Map<RegistryKey, T>, Optional<T>> reduction) {
|
||||
if(attempt.contains(":")) {
|
||||
return get(RegistryKey.parse(attempt));
|
||||
}
|
||||
return reduction.apply(get(attempt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.dfsek.terra.api.registry.key;
|
||||
|
||||
public interface Keyed extends Namespaced, StringIdentifiable {
|
||||
RegistryKey getRegistryKey();
|
||||
|
||||
@Override
|
||||
default String getNamespace() {
|
||||
return getRegistryKey().getNamespace();
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getID() {
|
||||
return getRegistryKey().getID();
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,7 @@ package com.dfsek.terra.api.registry.key;
|
||||
public interface Namespaced {
|
||||
String getNamespace();
|
||||
|
||||
default RegistryKey getKey(String key) {
|
||||
return new RegistryKey() {
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return Namespaced.this.getNamespace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return key;
|
||||
}
|
||||
};
|
||||
default RegistryKey getKey(String id) {
|
||||
return RegistryKey.of(getNamespace(), id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,70 @@
|
||||
package com.dfsek.terra.api.registry.key;
|
||||
|
||||
public interface RegistryKey extends StringIdentifiable, Namespaced {
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public final class RegistryKey implements StringIdentifiable, Namespaced {
|
||||
private static final Pattern ID_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]*$");
|
||||
private final String namespace;
|
||||
private final String id;
|
||||
|
||||
private RegistryKey(String namespace, String id) {
|
||||
if(!ID_PATTERN.matcher(namespace).matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Namespace must only contain alphanumeric characters, hyphens, and underscores. \"" + namespace +
|
||||
"\" is not a valid namespace.");
|
||||
}
|
||||
|
||||
if(!ID_PATTERN.matcher(id).matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"ID must only contain alphanumeric characters, hyphens, and underscores. \"" + id +
|
||||
"\" is not a valid ID.");
|
||||
}
|
||||
|
||||
this.namespace = namespace;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static RegistryKey parse(String key) {
|
||||
if(key.chars().filter(c -> c == ':').count() != 1) {
|
||||
throw new IllegalArgumentException("Malformed RegistryKey: " + key);
|
||||
}
|
||||
String namespace = key.substring(0, key.indexOf(":"));
|
||||
String id = key.substring(key.indexOf(":") + 1);
|
||||
|
||||
return new RegistryKey(namespace, id);
|
||||
}
|
||||
|
||||
public static RegistryKey of(String namespace, String id) {
|
||||
return new RegistryKey(namespace, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(namespace, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof RegistryKey that) {
|
||||
return this.id.equals(that.id) && this.namespace.equals(that.namespace);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return namespace + ":" + id;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user