Jump to content

[Solved] Help with Custom registry using dispatch() and dataPackRegistry()


Recommended Posts

Posted (edited)

I know I'm almost there, but I'm just not grasping something in the way custom registries work.  I'm following the steps outlined in the gemwire wiki:

Quote

 

To create a dispatch codec for a Thing class, the following steps can be performed:

1. Create a Thing abstract class class and ThingType interface. The ThingType interface should have a method that supplies a Codec<Thing>, while Thing subclasses must define a method that supplies a ThingType.

2. Create a map or registry of ThingTypes, and register a ThingType for each sub-codec we want to have.

3. Create a Codec<ThingType>, or have the ThingType registry implement Codec.

4. Create our Codec<Thing> master codec by invoking Codec#dispatch on our ThingType codec. This method's arguments are:

A field name for the ID of the sub-codec (the example json below is using "type")

A function to retrieve a ThingType from a Thing

A function to retrieve a Codec<Thing> from a ThingType

 

I have a collection of classes that implement "GeneType" that can be instantiated multiple times as instances that extend the class "Gene".  I've created the DeferredRegister of GeneTypes, I need the datapack directory of gene configurations read in and an entry placed in the Gene registry for each file in the directory.  The end goal is to create my own GeneType and Genes and allow other modders to create GeneTypes and datapack designers to create their own Genes.

I'm stuck on #3 in the wiki instructions.  I've looked at the Forge BiomeModifiers registry, and the RecipeManger (both similar in concept to what I'm trying to do) but they don't implement exactly what I need. 

Here's what I have so far, Registry definitions:

	public static final DeferredRegister<GeneType> GENE_TYPES = DeferredRegister.create(GeneticsRebirthAPI.GENE_TYPE_REGISTRY_NAME, GeneticsRebirth.MODID);
	public static final Supplier<IForgeRegistry<GeneType>> GENE_TYPE_REGISTRY = GENE_TYPES.makeRegistry(RegistryBuilder::new);

	public static final RegistryObject<GeneType> DROP =  GENE_TYPES.register("drop", DropGeneType::new);


	public static final DeferredRegister<Gene> GENES = DeferredRegister.create(GeneticsRebirthAPI.GENE_REGISTRY_NAME, GeneticsRebirth.MODID);
	public static final Supplier<IForgeRegistry<Gene>> GENE_REGISTRY = GENES.makeRegistry(() -> new RegistryBuilder<Gene>().disableSaving().dataPackRegistry(/*something needs to go here*/));

First GeneType:

public class DropGeneType implements GeneType {
	public static final Codec<DropGene> CODEC = RecordCodecBuilder.create((in) -> in.group(
			BlockState.CODEC.fieldOf("source").forGetter(DropGene::source)
		).apply(in, DropGene::new));


	@Override
	public List<GeneEvents> needsEvents() {
		return List.of(GeneEvents.LOOT_DROP);
	}

	@Override
	public Codec<? extends Gene> codec() {
		return CODEC;
	}


	public record DropGeneLevel() implements GeneLevel {

	}

	public record DropGene(BlockState source) implements Gene {

		@Override
		public Supplier<GeneType> type() {
			return GeneRegistry.DROP;
		}
	}
}

 

Can someone guide me on coding steps 3 and 4? Specifically:

  1. How do I have the GeneType registry implement Codec?
  2. What codec do I pass to dataPackRegistry() 
  3. Since DataPacks can be reloaded do I need to do anything special? or does the forge registry system handle all the reloading?

I found two examples of using dispatch().. and they are vastly different, and I'm not sure when I need the "Lazy protections" and when I don't.

public static final Codec<ParticleOptions> CODEC = Registry.PARTICLE_TYPE.byNameCodec().dispatch("type", ParticleOptions::getType, ParticleType::codec);

Codec<BiomeModifier> DIRECT_CODEC = ExtraCodecs.lazyInitializedCodec(() -> ForgeRegistries.BIOME_MODIFIER_SERIALIZERS.get().getCodec())
  .dispatch(BiomeModifier::codec, Function.identity());

Thanks for your help.

-pete

Edited by ClubPT
solved
Posted
11 hours ago, ClubPT said:

How do I have the GeneType registry implement Codec?

Forge registries already have an attached codec which you can get via IForgeRegistry#getCodec. You should have the codec be lazily initialized as the forge registry won't exist until after the gather phase, and you shouldn't need the codec until then. This can be done using ExtraCodecs#lazyInitializedCodec if you don't want to make the codec field itself lazy.

11 hours ago, ClubPT said:

What codec do I pass to dataPackRegistry() 

The codec that creates the gene. First, you get the codec for the GeneType using the method above. Then you create the dispatch codec. The first parameter would be how to get the GeneType from the Gene. The second parameter would be how to get the codec for the GeneType itself.

11 hours ago, ClubPT said:

Since DataPacks can be reloaded do I need to do anything special? or does the forge registry system handle all the reloading?

Forge handles this itself. You don't need to do anything special.

11 hours ago, ClubPT said:

I found two examples of using dispatch().. and they are vastly different

Not really, they are doing the same thing. The major difference is that one has the type as a generic class while the other makes the type a direct codec. The advantage of the direct codec allows the identity function to be passed in as the second parameter as the type is literally the codec rather than a field stored in the type. The first parameter in the particle options simply specifies the name of the key used to differentiate how to deserialize the data:

{

  "type": "<type_registry_name>"

  // Deserialize Data here

}

 

11 hours ago, ClubPT said:

and I'm not sure when I need the "Lazy protections" and when I don't.

You'll always need to use lazy protections if the codec itself is not lazy as registries, as mentioned above, are created during the gather phase. That is why the IForgeRegistry when made is in a supplier since it hasn't been created yet.

Posted

Thank you, that clears it up for me.  I ended up with this setup:

	public static final DeferredRegister<GeneType> GENE_TYPES = DeferredRegister.create(GeneticsRebirthAPI.GENE_TYPE_REGISTRY_NAME, GeneticsRebirth.MODID);
	public static final Supplier<IForgeRegistry<GeneType>> GENE_TYPE_REGISTRY = GENE_TYPES.makeRegistry(RegistryBuilder::new);

	public static final RegistryObject<GeneType> DROP =  GENE_TYPES.register("drop", DropGeneType::new);

	public static final Supplier<Codec<Gene>> GENE_CODEC = () -> GENE_TYPE_REGISTRY.get().getCodec().dispatch("gene", Gene::type, GeneType::codec);

	public static final DeferredRegister<Gene> GENES = DeferredRegister.create(GeneticsRebirthAPI.GENE_REGISTRY_NAME, GeneticsRebirth.MODID);
	public static final Supplier<IForgeRegistry<Gene>> GENE_REGISTRY = GENES.makeRegistry(() -> new RegistryBuilder<Gene>().disableSaving().dataPackRegistry(GENE_CODEC.get()));

 

  • ClubPT changed the title to [Solved] Help with Custom registry using dispatch() and dataPackRegistry()

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.