Jump to content

[1.16.4] Change Texture onBlockActivated


BentiGorlich

Recommended Posts

Hallo Modders,

 

I want to have my Block change the texture to the texture of the block it is right clicked with. I honestly have no idea how this would be done other than override the `onBlockActivated` method.

Any idea how this could be done? It would be helpful if you could name a mod on 1.16 that does this in some regard, too.

 

Thanks in advance :)

 

Link to comment
Share on other sites

It would be ok if there was the limitation that it could only look like other cubes and not like a torch for example. Thats why I thought, that shouldn't be that hard, just replace the texture from it with the texture from the right clicked block.

Override getModelData in your tile entity and return a data that contains the current block state.

how do I get an IModelData object from a BlockState? BlockRendererDispatcher#getModelForState is not static, how would I get an instance of that?

Link to comment
Share on other sites

43 minutes ago, diesieben07 said:

Minecraft#getBlockRendererDispatcher. Please try to use your IDE

Yeah you were right, I could have found that by mysqlf, sorry.
 

 

43 minutes ago, diesieben07 said:

Implement IModelData and add a field to your class that can store the BlockState

Done

 

2 hours ago, diesieben07 said:

Ensure this data is synced to the client.

I don't know how to do that. The only time i really synced something to a client was through a open gui call, how would i send something to sync that up in the `onBlockActivated` method?

 

2 hours ago, diesieben07 said:

Make a custom model loader, which creates a special model that will mimic whatever blockstate your tile entity currently contains - it knows which block state it is based on the model data from step 3.

Can you give me a class to refer to? I really don't know which class I would have to extend for that, nor where to register it

 

I really appreciate your help :)

Link to comment
Share on other sites

So I started looking into it. Sadly forge only has examples with the bucket item that are helpful, so I could not get the gist of it.

 

I have these 2 classes now:

public class GatePlacerModelLoader implements IModelLoader<GatePlacerModelConfiguration> {

	public static GatePlacerModelLoader INSTANCE = new GatePlacerModelLoader();
	
	@Override
	public void onResourceManagerReload(IResourceManager resourceManager) {
		// TODO Auto-generated method stub
	}

	@Override
	public GatePlacerModelConfiguration read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
		// TODO Auto-generated method stub
		return null;
	}
}
public class GatePlacerModelConfiguration implements IModelGeometry<GatePlacerModelConfiguration> {

	@Override
	public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
		
		return null;
	}

	@Override
	public Collection getTextures(IModelConfiguration owner, Function modelGetter, Set missingTextureErrors) {
		// TODO Auto-generated method stub
		return null;
	}
}

And I register the loader like so:

public void init(FMLServerStartingEvent event) {
	ModelLoaderRegistry.registerLoader(new ResourceLocation(MODID, "gate_placer"), GatePlacerModelLoader.INSTANCE);
}

My problem is, that I couldn't find a reference to how these are called for rendering

- how to tell them which block they should render through my render model

- how do I get the blockstate of the mimiced block (I can't get the normal block state eigher...)

Link to comment
Share on other sites

6 minutes ago, diesieben07 said:

Use ModelRegistryEvent instead.

Done

6 minutes ago, diesieben07 said:
43 minutes ago, BentiGorlich said:

how to tell them which block they should render through my render model

In your model you need to delegate the methods (the most important one is probably just getQuads) to the other model. Which "other model" you use depends on the model data (it has the mimiced block state in it). By delegating to the other model here, your block will appear as if it had that other model.

Which class do you mean with "model"? I do not have a method called `getQuads()` in the GatePlacerModelLoader class, the GatePlacerModelConfiguration class, the GatePlacerBlock class, or the GatePlacerTileEntity class. So do I have to make another class class GatePlacerModel? and where would I register it, so it renders my block?

 

9 minutes ago, diesieben07 said:
47 minutes ago, BentiGorlich said:

how do I get the blockstate of the mimiced block (I can't get the normal block state eigher...)

Its given to you as the IModelData in your IBakedModel. This is the same model data you returned from your tile entity.

In the GatePlacerModelConfiguration class I have to return a `IBakedModel` in the bake method. How do I build it?
And where would I have a method for using the baked model?

Link to comment
Share on other sites

I have the problem, that nothing is happening. I have the loader and the model in the blockstate.json:
(if I remove the model property it just renders as the default black/pink block)

{
    "variants": {
        "": { 
            "loader": "gates:gate_placer_loader",
            "model": "gates:block/gate_placer"
        }
    }
}

But my GatePlacerModel class is never called.

ModelLoader:

public class GatePlacerModelLoader implements IModelLoader<GatePlacerModelConfiguration> {

	public static GatePlacerModelLoader INSTANCE = new GatePlacerModelLoader();
	
	@Override
	public void onResourceManagerReload(IResourceManager resourceManager) {
		// TODO Auto-generated method stub
	}

	@Override
	public GatePlacerModelConfiguration read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
		return new GatePlacerModelConfiguration();
	}
}

ModelConfiguration:

public class GatePlacerModelConfiguration implements IModelGeometry<GatePlacerModelConfiguration> {

	@Override
	public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
		return new GatePlacerModel(overrides);
	}

	@Override
	public Collection getTextures(IModelConfiguration owner, Function modelGetter, Set missingTextureErrors) {
		Set<RenderMaterial> texs = Sets.newHashSet();

        if (owner.isTexturePresent("base")) texs.add(owner.resolveTexture("base"));
        if (owner.isTexturePresent("all")) texs.add(owner.resolveTexture("all"));

        return texs;
	}
}

Model:

public class GatePlacerModel extends BakedModel {

	public GatePlacerModel(ItemOverrideList overrides) {
		super(false, false, false, null, overrides, null, null);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData extraData) {
		if(extraData.hasProperty(GatePlacerTileEntity.MIMICED_BLOCKSTATE_PROPERTY)) {
			BlockState mimiced = extraData.getData(GatePlacerTileEntity.MIMICED_BLOCKSTATE_PROPERTY);
			IBakedModel mimicedModel = Minecraft.getInstance().getBlockRendererDispatcher().getModelForState(mimiced);
			return mimicedModel.getQuads(mimiced, side, rand, extraData);
		} else {
			return super.getQuads(state, side, rand, extraData);
		}
	}
}

Inside of my block i have this method:

	@Override
	public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) {
		ItemStack activeStack = player.getHeldItem(handIn);
		if(activeStack.getItem() instanceof BlockItem) {
			Block block = ((BlockItem)activeStack.getItem()).getBlock();
			((GatePlacerTileEntity)worldIn.getTileEntity(pos)).setMimicedBlockState(block.getDefaultState());
			// notify for block update, so the new mimiced block is synced in the tileentity class
			worldIn.notifyBlockUpdate(pos, state, state.with(MIMICED, Boolean.valueOf(true)), 2);
			return ActionResultType.SUCCESS;
		}
		return ActionResultType.FAIL;
	}

Am I doing something wrong?

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.

Announcements



×
×
  • Create New...

Important Information

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