Jump to content
  • Home
  • Files
  • Docs
Topics
  • All Content

  • This Topic
  • This Forum

  • Advanced Search
  • Existing user? Sign In  

    Sign In



    • Not recommended on shared computers


    • Forgot your password?

  • Sign Up
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [SOLVED] [1.16] Custom Sign won't render
Currently Supported: 1.16.X (Latest) and 1.15.X (LTS)
Sign in to follow this  
Followers 0
kiou.23

[SOLVED] [1.16] Custom Sign won't render

By kiou.23, January 16 in Modder Support

  • Reply to this topic
  • Start new topic

Recommended Posts

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16 (edited)

I have registered blocks for both a Standing Sign, and Wall Sign and I have registered an item for the sign.

I did reflection for registering a wood type, and am using this wood type in the signs

I have the texture for the wood type under textures/entity/signs

and I have created the blockstate and model files, copying the vanilla ones (where the blockstates point to a model file that only has a texture for particles)

 

However, the Sign still won't render, and the edit sign screen won't show up.

Sometimes the game crashes when I place a sign, with a NPE, but it isn't consistent.

 

Sign block registration:

EFFETE_SIGN = registerNoItem("effete_sign", () -> new StandingSignBlock(
	AbstractBlock.Properties.create(Material.NETHER_WOOD, MaterialColor.LIME)
		.doesNotBlockMovement().hardnessAndResistance(1.0F).sound(SoundType.WOOD), Main.EFFETE_WOOD_TYPE));
EFFETE_WALL_SIGN = registerNoItem("effete_wall_sign", () -> new WallSignBlock(
	AbstractBlock.Properties.create(Material.NETHER_WOOD, MaterialColor.LIME)
		.doesNotBlockMovement().hardnessAndResistance(1.0F).sound(SoundType.WOOD).lootFrom(EFFETE_SIGN.get()), Main.EFFETE_WOOD_TYPE));

 

Blockstate and model files:

{
  "textures": {
    "particle": "effetewood:block/effete_planks"
  }
}
{
  "variants": {
    "": {
      "model": "effetewood:block/effete_sign"
    }
  }
}

 

Wood Type registration and Reflection code:

private void setup(final FMLCommonSetupEvent event)  {
	reflectionSetup();

  	try {
		EFFETE_WOOD_TYPE = (WoodType) registerWoodTypeMethod.invoke(null, woodTypeConstructor.newInstance("effete"));
	} catch (Exception e) {
		LOGGER.error("Error registering wood type");
		e.printStackTrace();
	}
}

private void reflectionSetup() {
	if (woodTypeConstructor != null) woodTypeConstructor.setAccessible(true);
	if (registerWoodTypeMethod != null) registerWoodTypeMethod.setAccessible(true);
}

private static final Constructor<WoodType> woodTypeConstructor;
private static final Method registerWoodTypeMethod;

private static Constructor<WoodType> getWoodTypeConstructor() {
	try {
		return WoodType.class.getDeclaredConstructor(String.class);
	} catch (Exception e) {
		LOGGER.error("Exception in getWoodTypeConstructor: " + e.getMessage());
		e.printStackTrace();
		return  null;
	}
}

private static Method getRegisterWoodTypeMethod(){
	try {
		return WoodType.class.getDeclaredMethod("register", WoodType.class);
	} catch (Exception e) {
		LOGGER.error("Exception in getRegisterWoodTypeMethod: " + e.getMessage());
		e.printStackTrace();
		return null;
	}
}

static {
	woodTypeConstructor = getWoodTypeConstructor();
	registerWoodTypeMethod = getRegisterWoodTypeMethod();
}

 

Edited January 17 by kiou.23
  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16
  • You do not need to use reflection to invoke the constructor, just make a subclass.
  • That is never how you handle exceptions. Think about what happens if these reflection things fail - you now don't have a WoodType instance. What does your sign do then? Return null? Then it's going to crash - but with some random null pointer exception somewhere, which has no bearing on the actual error (the reflection failed). Make your reflection code throw an exception if it fails! That said - you need to use ObfuscationReflectionHelper and SRG names, or your code will not work outside the development environment.
  • Sign textures are baked in Atlases.collectAllMaterials - which is called from the static initializer of ModelBakery. This class will be initialized very early, way before any mod loading happens probably. That means, Minecraft won't have your wood type when it is stichting textures / baking models. You probably need to hack them in in some way in ModelRegistryEvent.
  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16 (edited)
1 hour ago, diesieben07 said:
  • You do not need to use reflection to invoke the constructor, just make a subclass.

I had asked on discord and someone suggested using reflection. but yeah, a subclass is way better

This is correct?

public class ModWoodType extends WoodType {

    public static final WoodType EFFETE = new ModWoodType("effete");

    protected ModWoodType(String name) {
        super(name);
    }
}
1 hour ago, diesieben07 said:
  • That is never how you handle exceptions. Think about what happens if these reflection things fail - you now don't have a WoodType instance. What does your sign do then? Return null? Then it's going to crash - but with some random null pointer exception somewhere, which has no bearing on the actual error (the reflection failed). Make your reflection code throw an exception if it fails! That said - you need to use ObfuscationReflectionHelper and SRG names, or your code will not work outside the development environment.

Yeah, you told me that in another thread. But since I don't need to use reflection, I'm going to postpone studying error handling to another week

1 hour ago, diesieben07 said:
  • Sign textures are baked in Atlases.collectAllMaterials - which is called from the static initializer of ModelBakery. This class will be initialized very early, way before any mod loading happens probably. That means, Minecraft won't have your wood type when it is stichting textures / baking models. You probably need to hack them in in some way in ModelRegistryEvent.

And how should I go about doing that?

I tried:

@SubscribeEvent
public static void modelRegistryEvent(ModelRegistryEvent e) {
	Atlases.SIGN_MATERIALS.put(ModWoodType.EFFETE, new RenderMaterial(Atlases.SIGN_ATLAS, new ResourceLocation("effetewood:entity/signs/effete")));
}

It still doesn't work (The edit screen pops up for less than a second, and appear to have the missing pink/black texture), and the actual block just is invisible

(dumb question: I don't need to specify "textures/entity/..." in the resouce location, right?)

Edited January 16 by kiou.23
  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16
6 minutes ago, kiou.23 said:

But since I don't need to use reflection, I'm going to postpone studying error handling to another week

You still need reflection to register it.

 

6 minutes ago, kiou.23 said:

And how should I go about doing that?

I don't know. It might be better to just make your own renderer and not use this vanilla stuff.

  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16
9 minutes ago, diesieben07 said:

You still need reflection to register it.

Alright, where can I learn about the ObsfuscationReflectionHelper and SRG names? (and by register, you mean registering to the VALUES field from the WoodType class?)

10 minutes ago, diesieben07 said:

I don't know. It might be better to just make your own renderer and not use this vanilla stuff.

doesn't this do it?

Atlases.SIGN_MATERIALS.put(ModWoodType.EFFETE, new RenderMaterial(Atlases.SIGN_ATLAS, new ResourceLocation("effetewood:entity/signs/effete")));

if it doesn't, can you point me towards how I would write my own renderer?

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16
15 minutes ago, kiou.23 said:

Alright, where can I learn about the ObsfuscationReflectionHelper and SRG names?

ObfuscationReflectionHelper has javadocs. SRG names can be obtained from forge-bot on the Forge discord.

 

17 minutes ago, kiou.23 said:

doesn't this do it?


Atlases.SIGN_MATERIALS.put(ModWoodType.EFFETE, new RenderMaterial(Atlases.SIGN_ATLAS, new ResourceLocation("effetewood:entity/signs/effete")));

if it doesn't, can you point me towards how I would write my own renderer?

No, because SIGN_MATERIALS is copied into ModelBakery.LOCATIONS_BUILTIN_TEXTURES in Atlases.collectAllMaterials which is called from ModelBakery static init, which happens way before this event. Any changes to SIGN_MATERIALS later will be ignored.

You'd have to also add it to LOCATIONS_BUILTIN_TEXTURES, but I don't know if that would even be enough - worth a try though.

 

  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16 (edited)
14 minutes ago, diesieben07 said:

No, because SIGN_MATERIALS is copied into ModelBakery.LOCATIONS_BUILTIN_TEXTURES in Atlases.collectAllMaterials which is called from ModelBakery static init, which happens way before this event. Any changes to SIGN_MATERIALS later will be ignored.

You'd have to also add it to LOCATIONS_BUILTIN_TEXTURES, but I don't know if that would even be enough - worth a try though.

I'll try it (Edit: nvm, no idea how to try it, and it may not even work)

there seems to be another problem tho: I changed the wood type of the sign to OAK, just to see if it rendered with a vanilla wood type, and nope. it's still invisible. however, the edit screen has the oak sign texture (it still only stays up for milliseconds)

this has to be related to something else, right?

Edited January 16 by kiou.23
  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16

Probably. Vanilla loves hardcoding things.

Would be best to see a Git repo of your mod so I can use the debugger.

  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16
19 minutes ago, diesieben07 said:

Probably. Vanilla loves hardcoding things.

Would be best to see a Git repo of your mod so I can use the debugger.

git repo: https://github.com/jvcmarcenes/effetewood

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16

You cannot use the vanilla sign blocks, because they use SignTileEntity, which is only marked valid for the vanilla signs. You need to make your own TileEntityType and use that.

  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16
3 minutes ago, diesieben07 said:

You cannot use the vanilla sign blocks, because they use SignTileEntity, which is only marked valid for the vanilla signs. You need to make your own TileEntityType and use that.

so I also need to write my own Sign blocks? and can I just make them a subclass of the vanilla classes?

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16
Just now, kiou.23 said:

so I also need to write my own Sign blocks? and can I just make them a subclass of the vanilla classes?

Yes and yes.

  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16

Okay, so my Custom Sign Tile Entity has to extend SignTileEntity, because PlayerEntity#openSignEditor() expects a SignTileEntity.

but from there I can't call super() and pass in my custom Tile Entity Type, because the TileEntityType for SignTileEntity is hardcoded in the constructor.

How to proceed?

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16
6 minutes ago, kiou.23 said:

Okay, so my Custom Sign Tile Entity has to extend SignTileEntity, because PlayerEntity#openSignEditor() expects a SignTileEntity.

but from there I can't call super() and pass in my custom Tile Entity Type, because the TileEntityType for SignTileEntity is hardcoded in the constructor.

How to proceed?

Override getType.

  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16

Did the classes, now the edit screen shows up, and if I use a vanilla WoodType for the sign, the texture shows up in the edit screen (not in the actual block tho, it still won't render)

the changes are on github.

How should I go about rendering the Sign again? I'll need to write my own TileEntityRenderer?

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16

There are several problems which all contribute to the things you are seeing (or rather not seeing):

  • Your event handler for ModelRegistryEvent is not called, because you registered it to the wrong event bus. ModelRegistryEvent is fired on FMLJavaModLoadingContext.get().getModEventBus(), but you used MinecraftForge.EVENT_BUS.
  • You create the RenderMaterial wrongly. Minecraft will use Atlases.getSignMaterial to create the material - which does not match up with what you are doing here. You need to also use that method. This means that the "minecraft" namespace will be used, there is no way around that. Because of this you should prefix the name of your WoodType with your ModID, so "effetewood_effete", to avoid collisions not only with the texture but also the WoodType registry. Then your texture also needs to be in minecraft/textures/entity/signs/effetewood_effete.png naturally.
  • In ModelRegistryEvent you also need to add the RenderMaterial to the set of built-in textures (ModelBakery.LOCATIONS_BUILTIN_TEXTURES) so that Minecraft will actually load the texture and stitch it onto the atlas. Because the field is protected, you can use a little hack to avoid having to use reflection:
    static class FakeBakery extends ModelBakery {
        private FakeBakery(IResourceManager resourceManagerIn, BlockColors blockColorsIn, IProfiler profilerIn, int maxMipmapLevel)
        {
            super(resourceManagerIn, blockColorsIn, profilerIn, maxMipmapLevel);
        }
    
        static Set<RenderMaterial> getBuiltinTextures() {
            return ModelBakery.LOCATIONS_BUILTIN_TEXTURES;
        }
    }

    Now you can just call FakeBakery.getBuiltinTextures to get the field and add your RenderMaterial to it.

  • Because you now have your own tile entity type, you need to tell Minecraft to use the SignTileEntityRenderer for it. Use ClientRegistry.bindTileEntityRenderer in FMLClientSetupEvent for that.
  • Registering the wood type in ModelRegistryEvent means it won't be registered on the server. However FMLCommonSetupEvent is too late, so you have to do it in the mod constructor. Unfortunately in this case, mod construction (like many startup events, e.g. FMLCommonSetupEvent) runs in parallel on a threadpool, which means you cannot just register your WoodType there (the underlying data structure ObjectArraySet is not threadsafe). With normal event handlers (like FMLCommonSetupEvent) you can just use enqueueWork on the event to run something synchronously on the main thread. However in this case we are in the mod constructor, which doesn't receive an event instance. There is still a DeferredWorkQueue for us to use though (i.e. call enqueueWork to run something on the main thread): DeferredWorkQueue.lookup(Optional.of(FMLConstructModEvent.class)).get().enqueueWork with a Runnable lambda will do the trick. In there you can then safely register your WoodType.

With these fixes the custom sign now works:

image.png.d5f6a2183145fd9e7d8ad1bda27f05e7.png

  • Thanks 1
  • Quote

Share this post


Link to post
Share on other sites

kiou.23    10

kiou.23

kiou.23    10

  • Creeper Killer
  • kiou.23
  • Members
  • 10
  • 190 posts
Posted January 16

Wow that's alot, I was trying to do the brute force way of simply reimplementing all the classes over, but it didn't quite work.

I'll take a look at your solution and try doing that. Thank you a lot for taking the time to help me with this!

(is it fine for me to dm you on discord if I face a roadblock again? relevant to adding this signs of course)

  • Quote

Share this post


Link to post
Share on other sites

diesieben07    7695

diesieben07

diesieben07    7695

  • Reality Controller
  • diesieben07
  • Forum Team
  • 7695
  • 56361 posts
Posted January 16
6 minutes ago, kiou.23 said:

is it fine for me to dm you on discord if I face a roadblock again? relevant to adding this signs of course

probably better just to ask in the modder support channels - your chances of getting a quick response are better. I am not the only person who can help :D If I'm online on discord and see it, I'll reply - otherwise someone else will.

  • Like 1
  • Quote

Share this post


Link to post
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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  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.

    • Insert image from URL
×
  • Desktop
  • Tablet
  • Phone
Sign in to follow this  
Followers 0
Go To Topic Listing



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • cadbane86140
      Minecraft: Cereal UHC Season 2 Episode 5- THE FINALE!

      By cadbane86140 · Posted 3 hours ago

      Hello There! A bit of a late upload due to technical issues but ITS UP! So after a week of Cereal UHC we have finally reached the end of it! I am so thankful to be apart of this series and I can't wait for the next season! There are so many hilarious moments especially during the final battle! I hope you all enjoyed this series and if you did don't forget to like and sub for more!  
    • samjviana
      [1.16.5] How to make EnchantedBook go to Custom ItemGroup

      By samjviana · Posted 3 hours ago

      But how can i do that for an enchantment book, for normal items i was able to do that by calling the function "group" as you said, but with the enchantment seems to be different.
    • poopoodice
      [1.16.5] How to make EnchantedBook go to Custom ItemGroup

      By poopoodice · Posted 4 hours ago

      Just create an instance of ItemGroup, and set the group of the item in the item property builder.
    • poopoodice
      Trying to make a crop have an "X" shape model

      By poopoodice · Posted 4 hours ago

      Check the parent of their block model.
    • LexManos
      Forge says this file does not have an app associated with it.

      By LexManos · Posted 4 hours ago

      Some zip managers like to take control of the .jar file extension away from Java. Make sure you have Java installed and try running Jarfix once, then try the installer again.
  • Topics

    • cadbane86140
      0
      Minecraft: Cereal UHC Season 2 Episode 5- THE FINALE!

      By cadbane86140
      Started 3 hours ago

    • samjviana
      2
      [1.16.5] How to make EnchantedBook go to Custom ItemGroup

      By samjviana
      Started 7 hours ago

    • TheMajorN
      1
      Trying to make a crop have an "X" shape model

      By TheMajorN
      Started 6 hours ago

    • ESCCarp
      3
      Forge says this file does not have an app associated with it.

      By ESCCarp
      Started 8 hours ago

    • hammy3502
      0
      [1.16.4] Fluid Flowing Very Oddly

      By hammy3502
      Started 5 hours ago

  • Who's Online (See full list)

    • NEXUS5709
    • ASTRO_D3RP
    • hammy3502
    • Lucipro71
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [SOLVED] [1.16] Custom Sign won't render
  • Theme

Copyright © 2019 ForgeDevelopment LLC · Ads by Longitude Ads LLC Powered by Invision Community