Skip to content

Commit

Permalink
Rework GameRegistry system to be more registry-like
Browse files Browse the repository at this point in the history
Signed-off-by: TheSilkMiner <thesilkminer@outlook.com>
  • Loading branch information
TheSilkMiner committed Jun 21, 2022
1 parent 0c3b08f commit c2ce273
Show file tree
Hide file tree
Showing 15 changed files with 269 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ public ResourceManager resourceManager() {
public <T> RegistryResolver<T> findResolver(final ObjectType<T> type) {
return ContentTweakerCore.core().metaRegistry().registryResolvers().findResolverFor(type);
}

@Override
public <T> GameRegistry<T> findRegistryFromKey(final ObjectType<T> type, final ResourceKey<? extends Registry<T>> key) {
return ServiceManager.platform().findRegistryFromKey(type, key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ public interface ApiBridge {
ResourceManager resourceManager();

<T> RegistryResolver<T> findResolver(final ObjectType<T> type);
<T> GameRegistry<T> findRegistryFromKey(final ObjectType<T> type, final ResourceKey<? extends Registry<T>> key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.blamejared.contenttweaker.core.api.registry;

import com.blamejared.contenttweaker.core.api.ContentTweakerApi;
import com.blamejared.contenttweaker.core.api.object.ObjectHolder;
import com.blamejared.contenttweaker.core.api.object.ObjectType;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;

import java.util.Collection;
import java.util.function.Supplier;
import java.util.stream.Stream;

public interface GameRegistry<T> {
static <T> GameRegistry<T> findFromKey(final ObjectType<T> type, final ResourceKey<? extends Registry<T>> key) {
return ContentTweakerApi.get().findRegistryFromKey(type, key);
}

ObjectType<T> type();
T get(final ResourceLocation name);
ResourceLocation nameOf(final T object);
Collection<T> all();
void enqueueRegistration(final ResourceLocation name, final Supplier<T> objectCreator);

default void enqueueRegistration(final ObjectHolder<T> holder) {
this.enqueueRegistration(holder.id(), holder);
}

default Stream<T> stream() {
return this.all().stream();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
package com.blamejared.contenttweaker.core.registry;

import com.blamejared.contenttweaker.core.ContentTweakerCore;
import com.blamejared.contenttweaker.core.api.object.ObjectHolder;
import com.blamejared.contenttweaker.core.api.object.ObjectType;
import com.blamejared.contenttweaker.core.api.registry.RegistryButler;
import com.blamejared.crafttweaker.api.util.GenericUtil;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;

import java.util.Collection;
import java.util.Objects;

// Handles registration of the various objects
public final class Winston implements RegistryButler {
private final Multimap<ObjectType<?>, ObjectHolder<?>> commands;

private Winston() {
this.commands = LinkedHashMultimap.create();
}
private Winston() {}

public static Winston of() {
return new Winston();
}

@Override
public <T> void register(final ObjectHolder<T> holder) {
this.commands.put(holder.type(), holder);
}

public <T> void executeForRegistry(final GameRegistry<T> registry) {
this.commandsFor(registry.type()).forEach(registry::register);
}

private <T> Collection<ObjectHolder<T>> commandsFor(final ObjectType<T> type) {
return this.commands.get(type)
.stream()
.map(GenericUtil::<ObjectHolder<T>>uncheck)
.toList();
ContentTweakerCore.core()
.metaRegistry()
.registryResolvers()
.findResolverFor(Objects.requireNonNull(holder).type())
.enqueueRegistration(holder);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.blamejared.contenttweaker.core.service;

import com.blamejared.contenttweaker.core.api.object.ObjectType;
import com.blamejared.contenttweaker.core.api.registry.GameRegistry;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;

import java.nio.file.Path;

public interface PlatformService {
Path gameDirectory();
Path locateResource(final String... components);
<T> GameRegistry<T> findRegistryFromKey(final ObjectType<T> type, final ResourceKey<? extends Registry<T>> key);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public abstract class RegistryMixin {
}
ContentTweakerCore.LOGGER.info("Registering objects for type '{}'", type);
try {
ContentTweakerCore.core().registryButler().executeForRegistry(FabricGameRegistry.of(registry, type));
FabricGameRegistry.of(registry, type).doRegistration();
} catch (final Throwable e) {
CraftTweakerAPI.LOGGER.error("A critical internal ContentTweaker error occurred", e);
ContentTweakerCore.LOGGER.error("A critical internal ContentTweaker error occurred", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
package com.blamejared.contenttweaker.fabric.registry;

import com.blamejared.contenttweaker.core.api.object.ObjectType;
import com.blamejared.contenttweaker.core.registry.GameRegistry;
import com.blamejared.contenttweaker.core.api.registry.GameRegistry;
import com.blamejared.crafttweaker.api.util.GenericUtil;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Stream;

public final class FabricGameRegistry<T> implements GameRegistry<T> {
private static final Map<ObjectType<?>, FabricGameRegistry<?>> INSTANCES = new HashMap<>();

private final Registry<T> registry;
private final ObjectType<T> type;
private final List<Runnable> commands;

private FabricGameRegistry(final Registry<T> registry, final ObjectType<T> type) {
this.registry = registry;
this.type = type;
this.commands = new ArrayList<>();
}

public static <T> FabricGameRegistry<T> of(final Registry<T> registry, final ObjectType<T> type) {
Objects.requireNonNull(registry, "registry");
Objects.requireNonNull(type, "type");
return new FabricGameRegistry<>(registry, type);
return GenericUtil.uncheck(INSTANCES.computeIfAbsent(type, it -> new FabricGameRegistry<>(registry, type)));
}

@Override
Expand All @@ -29,14 +41,34 @@ public ObjectType<T> type() {

@Override
public T get(final ResourceLocation name) {
return this.registry.get(name);
return this.registry.get(Objects.requireNonNull(name));
}

@Override
public ResourceLocation nameOf(final T object) {
return this.registry.getKey(Objects.requireNonNull(object));
}

@Override
public Collection<T> all() {
return this.stream().toList();
}

@Override
public void register(final ResourceLocation name, final T object) {
public void enqueueRegistration(final ResourceLocation name, final Supplier<T> object) {
Objects.requireNonNull(name, "name");
Objects.requireNonNull(object, "object");
Registry.register(this.registry, name, object);
this.commands.add(() -> Registry.register(this.registry, name, Objects.requireNonNull(object.get(), "get")));
}

@Override
public Stream<T> stream() {
return this.registry.stream();
}

public void doRegistration() {
this.commands.forEach(Runnable::run);
this.commands.clear();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.blamejared.contenttweaker.fabric.service;

import com.blamejared.contenttweaker.core.api.ContentTweakerConstants;
import com.blamejared.contenttweaker.core.api.object.ObjectType;
import com.blamejared.contenttweaker.core.api.registry.GameRegistry;
import com.blamejared.contenttweaker.core.service.PlatformService;
import com.blamejared.contenttweaker.fabric.registry.FabricGameRegistry;
import com.blamejared.crafttweaker.api.util.GenericUtil;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;

import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -33,4 +39,9 @@ public Path locateResource(final String... components) {
.findFirst()
.orElse(possiblePaths.get(0)); // Guaranteed at least one possible root path
}

@Override
public <T> GameRegistry<T> findRegistryFromKey(final ObjectType<T> type, final ResourceKey<? extends Registry<T>> key) {
return FabricGameRegistry.of(GenericUtil.uncheck(Objects.requireNonNull(Registry.REGISTRY.get(Objects.requireNonNull(key).location()))), Objects.requireNonNull(type));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

import com.blamejared.contenttweaker.core.ContentTweakerCore;
import com.blamejared.contenttweaker.core.api.object.ObjectType;
import com.blamejared.contenttweaker.core.registry.GameRegistry;
import com.blamejared.contenttweaker.forge.registry.ForgeGameRegistry;
import com.blamejared.contenttweaker.forge.registry.VanillaGameRegistry;
import com.blamejared.contenttweaker.forge.registry.GameRegistryFactory;
import com.blamejared.crafttweaker.api.CraftTweakerAPI;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
Expand All @@ -21,8 +19,6 @@
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import java.util.function.BiFunction;

@Mixin(GameData.class)
public abstract class GameDataMixin {

Expand Down Expand Up @@ -61,28 +57,24 @@ public abstract class GameDataMixin {

@Unique
private static <T extends IForgeRegistryEntry<T>> void contenttweaker$postRegistryEventDispatch$registerCotObjects0(final ForgeRegistry<T> registry) {
contenttweaker$registerCotObjects0(registry, registry.getRegistryKey(), ForgeGameRegistry::of);
contenttweaker$registerCotObjects0(registry.getRegistryKey());
}

@Unique
private static <T> void contenttweaker$postVanillaRegisterEvent$registerCotObjects0(final Registry<T> registry) {
contenttweaker$registerCotObjects0(registry, registry.key(), VanillaGameRegistry::of);
contenttweaker$registerCotObjects0(registry.key());
}

@Unique
private static <T, U> void contenttweaker$registerCotObjects0(
final U registry,
final ResourceKey<? extends Registry<T>> key,
final BiFunction<ObjectType<T>, U, GameRegistry<T>> creator
) {
private static <T> void contenttweaker$registerCotObjects0(final ResourceKey<? extends Registry<T>> key) {
final ObjectType<T> type = ContentTweakerCore.core().metaRegistry().objectTypes().get(key);
if (type == null) {
ContentTweakerCore.LOGGER.info("Unknown registry '{}': are you missing an object type for it?", key);
return;
}
ContentTweakerCore.LOGGER.info("Registering objects for type '{}'", type);
try {
ContentTweakerCore.core().registryButler().executeForRegistry(creator.apply(type, registry));
GameRegistryFactory.findRegistryFromTypeAlone(type).doRegistration();
} catch (final Throwable e) {
CraftTweakerAPI.LOGGER.error("A critical internal ContentTweaker error occurred", e);
ContentTweakerCore.LOGGER.error("A critical internal ContentTweaker error occurred", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.blamejared.contenttweaker.forge.registry;

import com.blamejared.contenttweaker.core.api.registry.GameRegistry;
import net.minecraft.Util;

import java.util.List;

public interface BulletGameRegistry<T> extends GameRegistry<T> {
List<Runnable> commands();

default void doRegistration() {
Util.make(this.commands(), commands -> {
commands.forEach(Runnable::run);
commands.clear();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.blamejared.contenttweaker.core.api.ContentTweakerConstants;
import com.blamejared.contenttweaker.core.api.object.ObjectType;
import com.blamejared.contenttweaker.core.registry.GameRegistry;
import com.blamejared.crafttweaker.api.util.GenericUtil;
import com.google.common.base.Suppliers;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.ModContainer;
Expand All @@ -11,27 +11,35 @@
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

public final class ForgeGameRegistry<T extends IForgeRegistryEntry<T>> implements GameRegistry<T> {
public final class ForgeGameRegistry<T extends IForgeRegistryEntry<T>> implements BulletGameRegistry<T> {
private static final Map<ObjectType<?>, ForgeGameRegistry<?>> INSTANCES = new HashMap<>();
private static final Supplier<ModContainer> COT_CONTAINER = Suppliers.memoize(() -> ModList.get().getModContainerById(ContentTweakerConstants.MOD_ID).orElseThrow());

private final ObjectType<T> type;
private final ForgeRegistry<T> forgeRegistry;
private final List<Runnable> commands;

private ForgeGameRegistry(final ObjectType<T> type, final ForgeRegistry<T> registry) {
this.type = type;
this.forgeRegistry = registry;
this.commands = new ArrayList<>();
}

public static <T extends IForgeRegistryEntry<T>> ForgeGameRegistry<T> of(final ObjectType<T> type, final ForgeRegistry<T> registry) {
static <T extends IForgeRegistryEntry<T>> ForgeGameRegistry<T> of(final ObjectType<T> type, final ForgeRegistry<T> registry) {
Objects.requireNonNull(type, "type");
Objects.requireNonNull(registry, "registry");
if (registry.getRegistrySuperType() != type.type()) {
throw new IllegalArgumentException("Mismatched types between registry (" + registry.getRegistrySuperType().getName() + ") and type (" + type.type().getName() + ")");
}
return new ForgeGameRegistry<>(type, registry);
return GenericUtil.uncheck(INSTANCES.computeIfAbsent(type, it -> new ForgeGameRegistry<>(type, registry)));
}

@Override
Expand All @@ -41,14 +49,34 @@ public ObjectType<T> type() {

@Override
public T get(final ResourceLocation name) {
return this.forgeRegistry.getValue(name);
return this.forgeRegistry.getValue(Objects.requireNonNull(name));
}

@Override
public void register(final ResourceLocation name, final T object) {
public ResourceLocation nameOf(final T object) {
return Objects.requireNonNull(object).getRegistryName();
}

@Override
public void enqueueRegistration(final ResourceLocation name, final Supplier<T> object) {
Objects.requireNonNull(name, "name");
Objects.requireNonNull(object, "object");
this.withContainer(() -> this.forgeRegistry.register(object.setRegistryName(name)));
this.commands.add(() -> this.forgeRegistry.register(Objects.requireNonNull(object.get(), "get").setRegistryName(name)));
}

@Override
public Collection<T> all() {
return this.forgeRegistry.getValues();
}

@Override
public List<Runnable> commands() {
return this.commands;
}

@Override
public void doRegistration() {
this.withContainer(BulletGameRegistry.super::doRegistration);
}

private void withContainer(final Runnable runnable) {
Expand Down

0 comments on commit c2ce273

Please sign in to comment.