Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.8] [SOLVED] Manipulating model in ISmartBlockModel.handleBlockState()


SnowyEgret
 Share

Recommended Posts

Hi,

 

I have implemented ISmartModel as instructed in TheGreyGhost's MBE04 tutorial. Things are working fine. In handleBlockState() I am looking up a model from an IBlockState I get from an unlisted property of the incoming IExtendedBlockState.

 

Before returning the model, can I manipulate it? I am attempting to find a way to modify the color of it's texture (I posted a couple of days ago on this).  There is a method returning the model's texture (of class TextureAtlasSprite), and a method to get the texture's texture data which is also setable. My printlns seem to indicate the texture data is changed, but I am not seeing any difference to the texture in game.

 

Here is my implentation of ISmartModel:

 

package ds.plato.block;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.IFlexibleBakedModel;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;

public class BlockSelectedModel implements ISmartBlockModel {

public static ModelResourceLocation modelResourceLocation = new ModelResourceLocation("plato:blockSelected");
private IBakedModel defaultModel;
private IUnlistedProperty prevBlockProperty;

public BlockSelectedModel(IBakedModel defaultModel, PropertyPreviousBlock prevBlockProperty) {
	super();
	this.defaultModel = defaultModel;
	this.prevBlockProperty = prevBlockProperty;
}

@Override
public IBakedModel handleBlockState(IBlockState state) {
	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
	IBlockState s = ((IExtendedBlockState) state).getValue(prevBlockProperty);
	IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes()
			.getModelForState(s);

	IFlexibleBakedModel m = (IFlexibleBakedModel)model;

	TextureAtlasSprite t = m.getTexture();
	int[][] td = t.getFrameTextureData(0);
	System.out.println(Arrays.deepToString(td));

	td = modifyTextureData(td);
	List l = new ArrayList();
	l.add(td);
	t.setFramesTextureData(l);

	t = m.getTexture();
	td = t.getFrameTextureData(0);
	System.out.println(Arrays.deepToString(td));

	return m;
}

@Override
public List getFaceQuads(EnumFacing p_177551_1_) {
	// TODO Auto-generated method stub
	return null;
}

@Override
public List getGeneralQuads() {
	// TODO Auto-generated method stub
	return null;
}

@Override
public boolean isAmbientOcclusion() {
	// TODO Auto-generated method stub
	return false;
}

@Override
public boolean isGui3d() {
	// TODO Auto-generated method stub
	return false;
}

@Override
public boolean isBuiltInRenderer() {
	// TODO Auto-generated method stub
	return false;
}

@Override
public TextureAtlasSprite getTexture() {
	return defaultModel.getTexture();
}

@Override
public ItemCameraTransforms getItemCameraTransforms() {
	// TODO Auto-generated method stub
	return null;
}

// Private-------------------------------------------------------------

private int[][] modifyTextureData(int[][] data) {
	for (int i = 0; i < data.length; i++) {
		for (int j = 0; j < data[i].length; j++) {
			data[i][j] = 0;
		}
	}
	return data;
}

}

 

For testing purposes I am just setting the texture data to 0. Seems I can cast the IBakedModel to an IFlexibleBakedModel, for whatever that's worth.

Link to comment
Share on other sites

Hi

 

the getTexture method is not generally used for rendering the block  - it is used (for example) for the 'exploding shards' that you get when you destroy a block by digging it.

 

In order to change the texture, you will need to change the BakedQuad data (each BakedQuad in your BlockModel is made up of four corners (vertices) - and at each vertex, it records the [x,y,z] position as well as a texture coordinate [u,v]. 

 

All of the textures for blocks and item models are "stitched together" into a large texture sheet, see the "Texture Coordinates" diagram on this page halfway down

http://greyminecraftcoder.blogspot.co.at/2014/12/the-tessellator-and-worldrenderer-18.html

 

You will need to create your BakedQuads with the correct texture coordinates of the new texture

An example of how you can do this is in MBE15, this class works for the faces of the cube

https://github.com/TheGreyGhost/MinecraftByExample/blob/master/src/main/java/minecraftbyexample/mbe15_item_smartitemmodel/ChessboardSmartItemModel.java

see createBakedQuadForFace().

FaceBakery.makeBakedQuad() can be useful for generating quads

 

If you want to change a model with arbitrary quads (not just the NEWSUD faces of the cube) then you can probably read the quads from the base model one by one, convert the int arrays to vertex data, replace the [u,v] with the new [u,v], and create a new list of BakedQuads from it.  Haven't tried it, but it should work.

 

-TGG

Link to comment
Share on other sites

Thanks TGG for the response.

 

I think the last, more generic, method you proposed is the way I need to go. Just a few questions to begin. Here is a start for new handleBlockState():

 

	@Override
public IBakedModel handleBlockState(IBlockState state) {
	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
	IBlockState s = ((IExtendedBlockState) state).getValue(prevBlockProperty);
	IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes()
			.getModelForState(s);

	IFlexibleBakedModel m = (IFlexibleBakedModel) model;

	VertexFormat format = m.getFormat();
	System.out.println("format=" + format);

	List<BakedQuad> generalQuads = m.getGeneralQuads();
	System.out.println(Arrays.toString(generalQuads.toArray()));
	for (BakedQuad q : generalQuads) {
		int[] vd = q.getVertexData();
		System.out.println(Arrays.toString(vd));
	}

	for (EnumFacing face : EnumFacing.values()) {
		List<BakedQuad> faceQuads = m.getFaceQuads(face);
		for (BakedQuad q : faceQuads) {
			int[] vd = q.getVertexData();
			System.out.println(Arrays.toString(vd));
		}
	}

	return m;
}

 

When I run and select a vanila block sand, it appears to have no generalQuad data(the list of BakedQuads is empty), only faceQuad data. Can I assume that any model which has more than 6 standard sides will implement getGeneralQuads()?

 

Here is the output of vertex data from the faceQuads:

 

[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 0, 1065353216, -8421505, 1058537800, 1046480159, 0, 0, 0, 0, -8421505, 1058537800, 1048574689, 0, 1065353216, 0, 0, -8421505, 1059061432, 1048574689, 0, 1065353216, 0, 1065353216, -8421505, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 0, -1, 1058537800, 1046480159, 0, 0, 1065353216, 1065353216, -1, 1058537800, 1048574689, 0, 1065353216, 1065353216, 1065353216, -1, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -1, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [1065353216, 1065353216, 0, -3355444, 1058537800, 1046480159, 0, 1065353216, 0, 0, -3355444, 1058537800, 1048574689, 0, 0, 0, 0, -3355444, 1059061432, 1048574689, 0, 0, 1065353216, 0, -3355444, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 1065353216, -3355444, 1058537800, 1046480159, 0, 0, 0, 1065353216, -3355444, 1058537800, 1048574689, 0, 1065353216, 0, 1065353216, -3355444, 1059061432, 1048574689, 0, 1065353216, 1065353216, 1065353216, -3355444, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 0, -6710887, 1058537800, 1046480159, 0, 0, 0, 0, -6710887, 1058537800, 1048574689, 0, 0, 0, 1065353216, -6710887, 1059061432, 1048574689, 0, 0, 1065353216, 1065353216, -6710887, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [1065353216, 1065353216, 1065353216, -6710887, 1058537800, 1046480159, 0, 1065353216, 0, 1065353216, -6710887, 1058537800, 1048574689, 0, 1065353216, 0, 0, -6710887, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -6710887, 1059061432, 1046480159, 0]

 

Do I use the format from VertexFormat format = m.getFormat() to interpret these arrays of ints?

 

Also, there is no setQuads() method on IFlexibleBakedModel. Is this going to be a problem?

Link to comment
Share on other sites

Thanks TGG for the response.

You're welcome :)

 

When I run and select a vanila block sand, it appears to have no generalQuad data(the list of BakedQuads is empty), only faceQuad data. Can I assume that any model which has more than 6 standard sides will implement getGeneralQuads()?

Yes.  But in general a model may have any mixture of faceQuads and GeneralQuads - it may have all faceQuads, all generalQuads, or a mixture of both.  faceQuads is mostly useful for blocks which don't draw some of their faces when they are next to each other.  For example stone.  Two stone blocks next to each other don't need to draw the two faces where they are touching.

 

General quads are usually for odd-shaped faces such as the torch, or the ladder.

 

Here is the output of vertex data from the faceQuads:

 

[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 0, 1065353216, -8421505, 1058537800, 1046480159, 0, 0, 0, 0, -8421505, 1058537800, 1048574689, 0, 1065353216, 0, 0, -8421505, 1059061432, 1048574689, 0, 1065353216, 0, 1065353216, -8421505, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 0, -1, 1058537800, 1046480159, 0, 0, 1065353216, 1065353216, -1, 1058537800, 1048574689, 0, 1065353216, 1065353216, 1065353216, -1, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -1, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [1065353216, 1065353216, 0, -3355444, 1058537800, 1046480159, 0, 1065353216, 0, 0, -3355444, 1058537800, 1048574689, 0, 0, 0, 0, -3355444, 1059061432, 1048574689, 0, 0, 1065353216, 0, -3355444, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 1065353216, -3355444, 1058537800, 1046480159, 0, 0, 0, 1065353216, -3355444, 1058537800, 1048574689, 0, 1065353216, 0, 1065353216, -3355444, 1059061432, 1048574689, 0, 1065353216, 1065353216, 1065353216, -3355444, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 0, -6710887, 1058537800, 1046480159, 0, 0, 0, 0, -6710887, 1058537800, 1048574689, 0, 0, 0, 1065353216, -6710887, 1059061432, 1048574689, 0, 0, 1065353216, 1065353216, -6710887, 1059061432, 1046480159, 0]
[19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [1065353216, 1065353216, 1065353216, -6710887, 1058537800, 1046480159, 0, 1065353216, 0, 1065353216, -6710887, 1058537800, 1048574689, 0, 1065353216, 0, 0, -6710887, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -6710887, 1059061432, 1046480159, 0]

 

Do I use the format from VertexFormat format = m.getFormat() to interpret these arrays of ints?

Yes - you need to find the offset corresponding to VertexFormatElement.EnumUsage UV.

If it's the standard format, vertexToInts() in this class

https://github.com/TheGreyGhost/MinecraftByExample/blob/master/src/main/java/minecraftbyexample/mbe15_item_smartitemmodel/ChessboardSmartItemModel.java

gives you the info you need - also shows you how to go from float to int, you just need to find the function to go back the other way from rawInts to float

If you want to code for any generic VertextFormat, I think you should be able to iterate through its elements, find the one for UV, and get its offset.

 

Also, there is no setQuads() method on IFlexibleBakedModel. Is this going to be a problem?

No problem.  Just create your own class extending IFlexibleBakedmodel and store your modified BakedQuads in it, then return it from handleBlockState.  When your IFlexibleBakedModel instance is called i.e.getGeneralQuads or getFaceQuads, return your modified BakedQuads.

 

-TGG

 

 

 

 

Link to comment
Share on other sites

I have answered the last part of my question. Instead of returning the model looked up in handleBlockState() I return this (which is an IBakedModel). This gives me the oportunity to modify or rebuild the BakedQuads list returned from getFaceQuads() and getGeneralQuads():

 

package ds.plato.block;

import java.util.Arrays;
import java.util.List;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.IFlexibleBakedModel;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;

public class BlockSelectedModel implements ISmartBlockModel {

public static ModelResourceLocation modelResourceLocation = new ModelResourceLocation("plato:blockSelected");
private IBakedModel defaultModel;
private IFlexibleBakedModel model;
private IUnlistedProperty selectedBlockProperty;

public BlockSelectedModel(IBakedModel defaultModel, PropertySelectedBlock selectedBlockProperty) {
	this.defaultModel = defaultModel;
	this.selectedBlockProperty = selectedBlockProperty;
}

@Override
public IBakedModel handleBlockState(IBlockState state) {
	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
	IBlockState s = ((IExtendedBlockState) state).getValue(selectedBlockProperty);
	System.out.println("Selected block="+s);
	IBakedModel m = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(s);
	model = (IFlexibleBakedModel) m;
	return this;
}

@Override
public List getFaceQuads(EnumFacing face) {
	List<BakedQuad> faceQuads = model.getFaceQuads(face);
	for (BakedQuad q : faceQuads) {
		int[] vd = q.getVertexData();
		System.out.println(Arrays.toString(vd));
	}
	//Modify list here
	return faceQuads;
}

@Override
public List getGeneralQuads() {
	List<BakedQuad> generalQuads = model.getGeneralQuads();
	System.out.println(Arrays.toString(generalQuads.toArray()));
	for (BakedQuad q : generalQuads) {
		int[] vd = q.getVertexData();
		System.out.println(Arrays.toString(vd));
	}
	//Modify list here
	return generalQuads;
}

@Override
public boolean isAmbientOcclusion() {
	return model.isAmbientOcclusion();
}

@Override
public boolean isGui3d() {
	return model.isGui3d();
}

@Override
public boolean isBuiltInRenderer() {
	return model.isBuiltInRenderer();
}

@Override
public TextureAtlasSprite getTexture() {
	// return defaultModel.getTexture();
	return model.getTexture();
}

@Override
public ItemCameraTransforms getItemCameraTransforms() {
	return model.getItemCameraTransforms();
}
}

 

This runs fine. My questions are:

 

Why does BakedQuad.getVertexData() return ints, and what do they mean?

The vertex data seems to be the same for every model looked up in handleBlockState():

 

[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:35]: Selected block=minecraft:sand[variant=sand]
[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 0, 1065353216, -8421505, 1058537800, 1046480159, 0, 0, 0, 0, -8421505, 1058537800, 1048574689, 0, 1065353216, 0, 0, -8421505, 1059061432, 1048574689, 0, 1065353216, 0, 1065353216, -8421505, 1059061432, 1046480159, 0]
[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -1, 1058537800, 1046480159, 0, 0, 1065353216, 1065353216, -1, 1058537800, 1048574689, 0, 1065353216, 1065353216, 1065353216, -1, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -1, 1059061432, 1046480159, 0]
[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 0, -3355444, 1058537800, 1046480159, 0, 1065353216, 0, 0, -3355444, 1058537800, 1048574689, 0, 0, 0, 0, -3355444, 1059061432, 1048574689, 0, 0, 1065353216, 0, -3355444, 1059061432, 1046480159, 0]
[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 1065353216, -3355444, 1058537800, 1046480159, 0, 0, 0, 1065353216, -3355444, 1058537800, 1048574689, 0, 1065353216, 0, 1065353216, -3355444, 1059061432, 1048574689, 0, 1065353216, 1065353216, 1065353216, -3355444, 1059061432, 1046480159, 0]
[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -6710887, 1058537800, 1046480159, 0, 0, 0, 0, -6710887, 1058537800, 1048574689, 0, 0, 0, 1065353216, -6710887, 1059061432, 1048574689, 0, 0, 1065353216, 1065353216, -6710887, 1059061432, 1046480159, 0]
[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 1065353216, -6710887, 1058537800, 1046480159, 0, 1065353216, 0, 1065353216, -6710887, 1058537800, 1048574689, 0, 1065353216, 0, 0, -6710887, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -6710887, 1059061432, 1046480159, 0]
[10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getGeneralQuads:55]: []

{ds.plato.block.PropertySelectedBlock@15af3a9b=Optional.of(minecraft:dirt[snowy=false,variant=dirt])}
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:35]: Selected block=minecraft:dirt[snowy=false,variant=dirt]
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 0, 1065353216, -8421505, 1048576655, 1044383007, 0, 0, 0, 0, -8421505, 1048576655, 1046477537, 0, 1065353216, 0, 0, -8421505, 1049623921, 1046477537, 0, 1065353216, 0, 1065353216, -8421505, 1049623921, 1044383007, 0]
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -1, 1048576655, 1044383007, 0, 0, 1065353216, 1065353216, -1, 1048576655, 1046477537, 0, 1065353216, 1065353216, 1065353216, -1, 1049623921, 1046477537, 0, 1065353216, 1065353216, 0, -1, 1049623921, 1044383007, 0]
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 0, -3355444, 1048576655, 1044383007, 0, 1065353216, 0, 0, -3355444, 1048576655, 1046477537, 0, 0, 0, 0, -3355444, 1049623921, 1046477537, 0, 0, 1065353216, 0, -3355444, 1049623921, 1044383007, 0]
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 1065353216, -3355444, 1048576655, 1044383007, 0, 0, 0, 1065353216, -3355444, 1048576655, 1046477537, 0, 1065353216, 0, 1065353216, -3355444, 1049623921, 1046477537, 0, 1065353216, 1065353216, 1065353216, -3355444, 1049623921, 1044383007, 0]
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -6710887, 1048576655, 1044383007, 0, 0, 0, 0, -6710887, 1048576655, 1046477537, 0, 0, 0, 1065353216, -6710887, 1049623921, 1046477537, 0, 0, 1065353216, 1065353216, -6710887, 1049623921, 1044383007, 0]
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 1065353216, -6710887, 1048576655, 1044383007, 0, 1065353216, 0, 1065353216, -6710887, 1048576655, 1046477537, 0, 1065353216, 0, 0, -6710887, 1049623921, 1046477537, 0, 1065353216, 1065353216, 0, -6710887, 1049623921, 1044383007, 0]
[10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getGeneralQuads:55]: []

 

 

Link to comment
Share on other sites

Ok, after looking closely at your excelent example, I've come up with this really simple solution which works ...almost.

 

package ds.plato.block;

import java.awt.Color;
import java.util.List;

import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;

public class BlockSelectedModel implements ISmartBlockModel {

public static ModelResourceLocation modelResourceLocation = new ModelResourceLocation("plato:blockSelected");
private IBakedModel defaultModel, model;
private IUnlistedProperty selectedBlockProperty;
private final int tint = Color.RED.getRed();

public BlockSelectedModel(IBakedModel defaultModel, PropertySelectedBlock selectedBlockProperty) {
	this.defaultModel = defaultModel;
	this.selectedBlockProperty = selectedBlockProperty;
}

@Override
public IBakedModel handleBlockState(IBlockState state) {
	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
	IBlockState s = ((IExtendedBlockState) state).getValue(selectedBlockProperty);
	model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(s);
	return this;
}

@Override
public List getFaceQuads(EnumFacing face) {
	List<BakedQuad> faceQuads = model.getFaceQuads(face);
	for (BakedQuad q : faceQuads) {
		q = new BakedQuad(tint(q.getVertexData()), 0, face);
	}
	return faceQuads;
}

@Override
public List getGeneralQuads() {
	List<BakedQuad> generalQuads = model.getGeneralQuads();
	for (BakedQuad q : generalQuads) {
		q = new BakedQuad(tint(q.getVertexData()), 0, q.getFace());
	}
	return generalQuads;
}

@Override
public boolean isAmbientOcclusion() {
	return model.isAmbientOcclusion();
}

@Override
public boolean isGui3d() {
	return model.isGui3d();
}

@Override
public boolean isBuiltInRenderer() {
	return model.isBuiltInRenderer();
}

@Override
public TextureAtlasSprite getTexture() {
	return model.getTexture();
}

@Override
public ItemCameraTransforms getItemCameraTransforms() {
	return model.getItemCameraTransforms();
}

// Private-----------------------------------------------------

private int[] tint(int[] vertexData) {
	//int[] vd = new int[vertexData.length];
	//System.arraycopy(vertexData, 0, vd, 0, vertexData.length);
	int[] vd = vertexData;
	vd[3] = tint;
	vd[10] = tint;
	vd[17] = tint;
	vd[24] = tint;
	return vd;
}

}

 

Just to recap, I am replacing the selected block with a new block that uses the model of the selected block. I modify to vertex data to tint the texture red. This works fine! :)

 

The only problem is that some, but not all, of the blocks of the same type as the selected block are also tinted red:

 

2015-05-12_17.04.26.png

 

(How do I insert an image? file://~/image.png?, i'm on ubuntu.)

 

If I return a copy of the new vertex data arrray as commented out in private method tint(), the problem goes away, but my block is not tinted.

 

Any help appreciated.

Link to comment
Share on other sites

Solved my problems. Works great.

 

package ds.plato.block;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;

public class BlockSelectedModel implements ISmartBlockModel {

public static ModelResourceLocation modelResourceLocation = new ModelResourceLocation("plato:blockSelected");
private IBakedModel defaultModel, model;
private IUnlistedProperty selectedBlockProperty;
private final int tint = Color.RED.getRed();

public BlockSelectedModel(IBakedModel defaultModel, PropertySelectedBlock selectedBlockProperty) {
	this.defaultModel = defaultModel;
	this.selectedBlockProperty = selectedBlockProperty;
}

@Override
public IBakedModel handleBlockState(IBlockState state) {
	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
	IBlockState s = ((IExtendedBlockState) state).getValue(selectedBlockProperty);
	model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(s);
	return this;
}

@Override
public List getFaceQuads(EnumFacing face) {
	List<BakedQuad> quads = new ArrayList<>();
	List<BakedQuad> faceQuads = model.getFaceQuads(face);
	for (BakedQuad q : faceQuads) {
		quads.add(new BakedQuad(tint(q.getVertexData()), 0, face));
	}
	return quads;
}

@Override
public List getGeneralQuads() {
	List<BakedQuad> quads = new ArrayList<>();
	List<BakedQuad> generalQuads = model.getGeneralQuads();
	for (BakedQuad q : generalQuads) {
		quads.add( new BakedQuad(tint(q.getVertexData()), 0, q.getFace()));
	}
	return quads;
}

@Override
public boolean isAmbientOcclusion() {
	return model.isAmbientOcclusion();
}

@Override
public boolean isGui3d() {
	return model.isGui3d();
}

@Override
public boolean isBuiltInRenderer() {
	return model.isBuiltInRenderer();
}

@Override
public TextureAtlasSprite getTexture() {
	return model.getTexture();
}

@Override
public ItemCameraTransforms getItemCameraTransforms() {
	return model.getItemCameraTransforms();
}

// Private-----------------------------------------------------

private int[] tint(int[] vertexData) {
	int[] vd = new int[vertexData.length];
	System.arraycopy(vertexData, 0, vd, 0, vertexData.length);
	vd[3] = tint;
	vd[10] = tint;
	vd[17] = tint;
	vd[24] = tint;
	return vd;
}

}

 

Thanks TGG!

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
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.

 Share



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • So i just bought a RLcraft server for me and my friends to play on. I launched it and it is working fine but it tells me that i need to download all the mods i go to mods and press "minecraft forge" and nothing shows up that i can open files. If anyone have a suggestion i would need the help. This is the server hosting i  used 
    • i did it in 1.12.2 not walking for me can anyone help me get it pls???  
    • Got the rotation working. I had to look at LivingEntityRenderer#render and setupRotations a little more closely, and I realized that I needed to change the custom entity's yBodyRot and yBodyRotO.  private static boolean renderingCustomEntity = false; private static CustomEntity customEntity; private static void refreshCustomEntity(LocalPlayer localPlayer, LivingEntity livingEntity) { if (customEntity == null || customEntity.isRemoved()) { customEntity = ModEntities.CUSTOM_ENTITY.get().create(localPlayer.clientLevel); } if (!customEntity.level.dimension().equals(livingEntity.level.dimension())) { customEntity.discard(); } } @SubscribeEvent public static void replaceMobModel(RenderLivingEvent.Pre<LivingEntity, EntityModel<LivingEntity>> event) { LocalPlayer localPlayer = Minecraft.getInstance().player; if (localPlayer != null && event.getEntity() instanceof Mob mob) { if (/* put your own condition here */) { if (!renderingCustomEntity) { try { renderingCustomEntity = true; event.setCanceled(true); refreshCustomEntity(localPlayer, mob); // (truth be told, my custom entity does not have a "head", so these lines aren't needed) // customEntity.setYHeadRot(mob.getYHeadRot()); // customEntity.yHeadRotO = mob.yHeadRotO; customEntity.setYBodyRot(mob.yBodyRot); customEntity.yBodyRotO = mob.yBodyRotO; customEntity.setPose(mob.getPose()); Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(customEntity).render( customEntity, customEntity.yBodyRot, event.getPartialTick(), event.getPoseStack(), event.getMultiBufferSource(), event.getPackedLight() ); } finally { renderingCustomEntity = false; } } } } }   As shown in my code, if the mob whose model is replaced moves to a different dimension, I unload the custom entity with Entity#discard and then reinitialize it on the next tick. I wonder if I also have to unload the custom entity when the mob it is "replacing" dies.
    • Thank you for the video, but I found the issue. I had to update the Gradle from 7.2 to 7.3 in gradle/wrapper/gradle-wrapper.properties.
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.