Jump to content

[1.19.4] Adding a custom EntityType to BuiltInRegistries.ENTITY_TYPE fails on validateWrite


LocutusVonBorg

Recommended Posts

I am currently adding a new type of minecart. The eventual goal will be to have it go faster than the vanilla minecart, therefore I named it "Fastcart". I have created my own model that is coloured differently and also created my custom renderer for it. This works as expected. The problem I have comes from the place where I want to set this renderer to go with the Fastcart Entity.

I have this code to do the registration of the renderer, in fact my main mod class.

@Mod(TotallyNotModdedMod.MODID)
public class TotallyNotModdedMod
{
    public static final String MODID = "totallynotmodded";

    public TotallyNotModdedMod()
    {
        IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();

        ItemInitializer.ITEMS.register(modEventBus);
        BlockInitializer.BLOCKS.register(modEventBus);

        MinecraftForge.EVENT_BUS.register(CreativeTabCreator.class);

        registerFastcartRenderer();
    }

    private void registerFastcartRenderer() {
        EntityRenderers.register(EntityType.MINECART, (p_174070_) -> new FastcartRenderer<>(p_174070_, ModelLayers.MINECART));
    }
}

Observe the last two lines. My renderer is registered with the EntityRenderers and is attached to the EntityType.MINECART . This allowed me to test my renderer, as this would render the vanilla minecarts with my own renderer, and this works fine. The minecarts are now rendered using my own texture and renderer and stuff. Yay for me!

However, I now have to switch this to use my own EntityType so only my Fastcart Entity gets the FastcartRenderer and I don't overwrite the Renderer for the default Minecart. I thought I could do this by simply adding my own EntityType but turns out, everything in the EntityType class is private. I copied the contents of its register method and tried to create my own:

public class FastcartEntityTypeProvider {

    //This seems to be the problem.
    //The write in the register takes place too later after the registries are already locked.
    //Might have to properly setup the Mixins to circumvent this.
    public static final EntityType<Fastcart> FASTCART = register("fastcart", EntityType.Builder.<Fastcart>of(Fastcart::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8));

    private static <T extends Entity> EntityType<T> register(String p_20635_, EntityType.Builder<T> p_20636_) {
        return Registry.register(BuiltInRegistries.ENTITY_TYPE, p_20635_, p_20636_.build(p_20635_));
    }
}

If I switch "EntityType.MINECART" for "FastcartEntityTypeProvider.FASTCART", I get an error that complains about the invalidity of my write, because the registries seem to already been frozen: https://haste.locutusvonborg.de/ejoquraqoz.yaml

How can I register my EntityType early enough? Do I really have to use Mixin to insert my register in the static block of the EntityType class? To be honest, I'd rather like to avoid this, but I would do it if I have no other choice.

All my code is available on https://github.com/LocutusV0nB0rg/TotallyNotModded

Link to comment
Share on other sites

Like all registered objects, use a DeferredRegister/RegistryObject and don't create things at classloading time like your FASTCART object.

The registry you want is https://github.com/MinecraftForge/MinecraftForge/blob/42115d37d6a46856e3dc914b54a1ce6d33b9872a/src/main/java/net/minecraftforge/registries/ForgeRegistries.java#L75

 

And entity renderers should not be registered like that.

Besides crashing game on a server where those classes don't exist, it is the wrong time to do it.

https://github.com/MinecraftForge/MinecraftForge/blob/42115d37d6a46856e3dc914b54a1ce6d33b9872a/src/main/java/net/minecraftforge/client/event/EntityRenderersEvent.java#L103

 

I suggest you familiarise yourself with the wiki: https://forge.gemwire.uk/wiki/Main_Page

if you want to avoid all the common mistakes.

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

This wiki is helpful, and to be honest it's the first time I've ever heard of it, so thank you for that.

I have switched to registering by the event as you suggested and tested it by registering the renderer on the EntityType.MINECART . It works fine, so that seems good. Now, I switch to my brand new EntityInitializer:

@Mod.EventBusSubscriber(modid = TotallyNotModdedMod.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class EntityRendererRegisterListener {

    @SubscribeEvent
    public static void addEntityRenderers(EntityRenderersEvent.RegisterRenderers event) {
        event.registerEntityRenderer(FASTCART_ENTITY_TYPE, (p_174070_) -> new FastcartRenderer<>(p_174070_, ModelLayers.MINECART));
    }


    @SubscribeEvent
    public void register(RegisterEvent event) {
        event.register(ForgeRegistries.Keys.ENTITY_TYPES, helper -> helper.register(
                "fastcart",
                FASTCART_ENTITY_TYPE));
    }


}

This is my other class.

public class EntityInitializer {
    public static final DeferredRegister<EntityType<?>> ENTITY_TYPES =
            DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, TotallyNotModdedMod.MODID);

    public static final EntityType<? extends AbstractMinecart> FASTCART_ENTITY_TYPE =
            EntityType.Builder.<Fastcart>of(Fastcart::new, MobCategory.MISC).sized(0.98F, 0.7F).clientTrackingRange(8).build("fastcart");

}

This should do the registration not at class load time, but now I get https://haste.locutusvonborg.de/sumewaridu.sql as an error, something seems to be wrong with my registration?

Link to comment
Share on other sites

39 minutes ago, warjort said:

 and don't create things at classloading time like your FASTCART object.

 

I have no idea why you are creating a DeferredRegister then using the RegisterEvent instead of a RegistryObject?

Either way, static initialisation of an object that goes in a registry will usually fail because the registries are frozen. The exact time of classloading is almost completely random.
You need to use a Supplier/RegistryObject to defer object construction until the correct time, or create the object during the RegisterEvent callback.

 

But, this forum is a support forum for people with real problems. It is not a mod learning forum.

You need to read the documentation, search the forum and look at other mods or vanilla code if you want to learn.

 

You also need to stop posting snippets of code in the forum. You should put all the relevant code on github that reproduces your problem.

If the issue is not obvious from what little information you post, you will likely just end up with your question getting ignored.

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

1 hour ago, warjort said:

You also need to stop posting snippets of code in the forum. You should put all the relevant code on github that reproduces your problem.

If the issue is not obvious from what little information you post, you will likely just end up with your question getting ignored.

I am a stackoverflow user, where it's greatly appreciated to demonstrate the code that seems to be the problem. However, if it is considered bad practice here, I will refrain from doing so in the future. All my code I have mentioned is live, on github, in the repository I linked in my original post.

I have a background of Paper server plugins for vanilla minecraft. I have some experience with how learning to develop code for minecraft applications works and I do read any documentation I can get my hands on. No need to get offensive. Also, I'd be glad to be shown the door where noobs can ask questions that seem to be unworthy of the people here.

1 hour ago, warjort said:

I have no idea why you are creating a DeferredRegister then using the RegisterEvent instead of a RegistryObject?

Because I do not know better. Is that a crime? If I knew the answer to all those questions, I would probably not be here asking for help.

I tried to copy the basic structure of the registry of the kaupenjoe tutorials, thats why I tried it like him. He does static initialisation https://github.com/Tutorials-By-Kaupenjoe/Forge-Tutorial-1.19/blob/3-blocks/src/main/java/net/kaupenjoe/tutorialmod/block/ModBlocks.java

Anyways:

I switched to a event based approach and got this:

https://github.com/LocutusV0nB0rg/TotallyNotModded/blob/master/src/main/java/borg/locutus/totallynotmodded/EntityRendererRegisterListener.java

This also seems to be wrong, I seem to register a lot of nonsense entries... https://haste.locutusvonborg.de/wixisokelo.yaml

 

 

Link to comment
Share on other sites

Honestly I give up on this forum.

I can't remember the last time I answered a question that wasn't somebody posting a stupid question 10 minutes after being given a link to the documentation.

i.e. they didn't read it or didn't spend anytime trying to understand it or work out the problem for themselves.

And  most are the just same questions over and over again, like this one, that I have already answered multiple times just this month. People never use search.

 

I didn't say don't post code, I said the opposite. i.e. post all the relevant code in a format that reproduces your problem.

 

To  (partly) answer your question:

minecraft:pig means your entity type is not registered. It is the fallback name minecraft uses when it can't find things in the entity type registry.

I don't feel like trying to debug your code after your response.

 

And this code will still crash the server:

https://github.com/LocutusV0nB0rg/TotallyNotModded/blob/3bc197514eab7fcc54982ccbdd5bc63442d3e781/src/main/java/borg/locutus/totallynotmodded/EntityRendererRegisterListener.java#L21

You cannot mix client classes into code that will run on the server.

 

Anyway, goodbye forum. It's been fun, or at least some of it has.

 

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

Making a clean cut about all the OT...

---

3 hours ago, warjort said:

Either way, static initialisation of an object that goes in a registry will usually fail because the registries are frozen. The exact time of classloading is almost completely random.
You need to use a Supplier/RegistryObject to defer object construction until the correct time, or create the object during the RegisterEvent callback.

It seems I'm misunderstanding the documentation on this point. https://forge.gemwire.uk/wiki/Registration#DeferredRegister

It clearly suggests to just call the register method with static initialisation. I understand this might be suboptimal, but it is suggested there nevertheless.

 

I am unsure on which code will run on the server and which one will run on the client. I undestand all rendering is done on the client (obviously, duh...), but what are the concrete consequences I have to draw? Just split my code up in two strictly separated sections with a "commons" area?

Link to comment
Share on other sites

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.



×
×
  • Create New...

Important Information

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