Jump to content

TheTrollguy_

Forge Modder
  • Posts

    71
  • Joined

  • Last visited

Posts posted by TheTrollguy_

  1. Q: So I have this TileEntity that I only use to spawn particles every tick (yes, I do need it to be every tick) and I'm wondering since there's no other use for it, do I have to save its data.

    Is it possible to just create a TileEntity when the block is loaded and not write TileEntity's data to Chunk?

    It probably is but do I gain anything with it?

     

    A: Nope. A TileEntity has to at least write down its basic information to exist after the world is loaded.

  2. 1 minute ago, V0idWa1k3r said:

    This approach screams "static initializers" and static initializers are bad. Just instantinate your blocks/items/whatever directly in the registry event. Not in a static initializer, not in FML events. You are also doing extra unnecessary work, think about it. Thirst you instantinate your stuff somewhere, then you add them to the set in the constructor, then you loop through the set in the event. That's at the very least 3 lines of code per block. Now think of the recommended approach. You instantinate your stuff directly in the registry event as an argument passed to register. That's one line of code per thing. With the recommended approach you are doing only 33% of the work.

    Also CommonProxy makes no sense. Proxies are for separating sided only code. Common code goes whereever but your proxy.

     

    Well, I never actually thought about that approach. Now that I really think about it, it does make a lot of sense. Thanks for the heads up! :)

  3. The way I automized my registrations:

    • Make a HashSet of Blocks/Items in your CommonProxy.
    • In your Block/Item constructor, add the current instance of the class to the HashSet. (ie. CommonProxy.BLOCKS.add(this);)
    • During RegistryEvent.Register, go through your HashSet and register each object (if we're talking about IForgeRegistryEntrys, otherwise register it during the preInit or init phase). Use a Stream, a for-loop, whatever you want.

    The same applies to models and other client-side stuff.

  4. Hey, I've been recently playing a lot with TRSRTransformation class and I realized that it could probably be easier to use a builder for it rather than passing a million arguments (I know it's just 4, but it looks neater).

    Let me show you what I mean.

     

    First, a few arguments why I even created a TRSR Util class:

    1) I didn't know that there were cornerToCenter and centerToCorner methods and at first, they confused me since any rotation I do happens around the center of the block. (I think the majority of modders want it like that).

    2) Quaternions. I don't think anybody uses quaternions to in their head to picture a rotation. I know that there are static methods in the TRSRTransformation class to get a quaternion from XYZ degrees, but that makes a horrible mess.

    3) Readability. Tell me what is easier to read:

        

    TRSRTransformation tr = new TRSRTransformation(new Vector3f(0, 10F, 0), new Quat4f(0, 0.125F, 1, 0), new Vector3f(1, 1.25F, 1), null);
    
    VS
    
    TRSRTransformation tr = new TRSRTransformation.Builder()
    	.translate(0.125F, 0, 0)
    	.rotate(0, 90, 0)
    	.scale(2, 2, 2)
    	.postRotate(90, 0, 0)
    	.build()

     

    You could even specify in the Builder's constructor if you want to use the corner or center version as a boolean variable (true - center, false - corner).

     

    And then, the Builder would do all the messy work, while you would just move on with your life. I can even provide a working Builder class I made myself if you all think that this would be a great addition, no matter how small it is, it would help modders a lot.

    • Like 1
  5. Well this doesn't work:

     

    TRSRTransformation.blockCornerToCenter(new TRSRTransformation(
    					closed ? null : vector, 
    					null,
    					null,
    					TRSRTransformation.quatFromXYZ(0, (float) Math.toRadians(90 * direction.ID), 0)));

     

    It gets properly rotated, but again it also gets translated weirdly

    Spoiler

    image.thumb.png.575c5aa354e852f80edc6ff0ae7114c0.png

  6. Myproblem: weird rotation when using TRSRTransformation while baking IModels caused by the rotation axis not being in the center of the block.

    Solution: Use TRSRTransformation.blockCenterToCorner to convert your TRSRTransformation (even though you would intuitively use TRSRTransformation.blockCornerToCenter).

     

    Original post:

    Spoiler

    I tend to use TRSRTransformation quite a lot as I often do manual model baking. I noticed when constructing a new TRSRTransformation , my rotation around y-axis doesn't happen around the center of the block, but rather on one of its corners. And also mixing translating and rotating together doesn't happen as I expected it to happen.

     

    So how do I combine

    1) translating (let's say 0.5 blocks north) and then

    2) rotating by 90 degres around y-axis (with the axis going through the center of the block)

     

  7. Thanks diesieben07!

    Now another thing that makes zero sense to me related to IBakedModel.

     

    The method getQuads accepts EnumFacing as one of its arguments. While I was experimenting with something, I found out that sometimes, when the method gets called, null gets passed as the EnumFacing argument. Why is that? I know that if IBlockState argument is null, the quads are for an item model.

     

    The reason is written on the Forge Docs: mcforge.readthedocs.io/en/latest/models/advanced/ibakedmodel/#getquads

  8. Hi,

    I want to retexture my IModel, but the thing is I just end up with the 'missing texture' texture.

    I've been stuck with this problem for hours now, soo any help would be appreciated :)

     

    CODE:

     

    Spoiler
    
    package com.thetrollguy.traffic_stuff_mod.feature.cone.client;
    
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.function.Function;
    
    import javax.annotation.Nullable;
    import javax.vecmath.Tuple4f;
    import javax.vecmath.Vector4f;
    
    import com.google.common.collect.ImmutableMap;
    import com.thetrollguy.traffic_stuff_mod.feature.BlockAdaptable;
    import com.thetrollguy.traffic_stuff_mod.feature.BlockTrafficStuffMod;
    import com.thetrollguy.traffic_stuff_mod.feature.EnumBlockAdaptationType;
    import com.thetrollguy.traffic_stuff_mod.feature.cone.BlockCone;
    import com.thetrollguy.traffic_stuff_mod.feature.cone.ConeColor;
    import com.thetrollguy.traffic_stuff_mod.feature.cone.ConePosition;
    import com.thetrollguy.traffic_stuff_mod.feature.cone.ConeShape;
    import com.thetrollguy.traffic_stuff_mod.utils.Info;
    import com.thetrollguy.traffic_stuff_mod.utils.Utils;
    
    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.IBakedModel;
    import net.minecraft.client.renderer.block.model.ItemOverrideList;
    import net.minecraft.client.renderer.block.model.ModelResourceLocation;
    import net.minecraft.client.renderer.texture.TextureAtlasSprite;
    import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
    import net.minecraft.client.renderer.vertex.VertexFormat;
    import net.minecraft.client.renderer.vertex.VertexFormatElement;
    import net.minecraft.util.EnumFacing;
    import net.minecraft.util.ResourceLocation;
    import net.minecraft.util.math.Vec3d;
    import net.minecraftforge.client.model.IModel;
    import net.minecraftforge.client.model.ModelLoaderRegistry;
    import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
    import net.minecraftforge.client.model.pipeline.VertexTransformer;
    import net.minecraftforge.common.model.IModelState;
    import net.minecraftforge.common.property.IExtendedBlockState;
    
    public class BakedModelCone implements IBakedModel {
    	
    	public static HashMap<String, List<BakedQuad>> QUADS = new HashMap<String, List<BakedQuad>>();
    
    	private IModel model;
    	private boolean retextured = false;
    	private IModelState modelState;                                           // *THE JUNK* Is there any way
    	private VertexFormat vertexFormat;                                        // to make this tidy and not pass
    	private Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter;// a bunch of objects to the construcor?
    	
    	public BakedModelCone(IModel model, IModelState modelState, VertexFormat vertexFormat, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
    	{
    		this.model = model;
    		this.modelState = modelState;
    		this.vertexFormat = vertexFormat;
    		this.bakedTextureGetter = bakedTextureGetter;
    	}
    
    	@Override
    	public List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long random)
    	{	
    		ConeColor color = ((BlockCone) state.getBlock()).color;
    		List<BakedQuad> quads = new LinkedList<BakedQuad>();
    		
    		if (!retextured)
    		{
    			this.model = model.retexture(
    				ImmutableMap.of("particle",  "traffic_stuff_mod:textures/blocks/cone/cone_" + color + "_particle", 
    				 				"primary",   "traffic_stuff_mod:textures/blocks/cone/cone_" + color, 
    				 				"secondary", "traffic_stuff_mod:textures/blocks/cone/cone_" + color.getSecondaryColor()));
    			this.retextured = true;		
    		}
    		if (state instanceof IExtendedBlockState)
    		{
    			ConeShape shape = ((BlockCone) state.getBlock()).shape;
    			ConePosition position = state.getValue(BlockCone.POSITION);
    			EnumBlockAdaptationType type = ((IExtendedBlockState) state).getValue(BlockAdaptable.ADAPTATION_TYPE);
    			
    			String key = Utils.String.combineToString(shape, color, position, type);
    
    			if (QUADS.containsKey(key))
    			{
    				return QUADS.get(key);
    			}
    			else
    			{
    				IBakedModel bakedModel = model.bake(modelState, vertexFormat, bakedTextureGetter);
    				float heightReduction = ((IExtendedBlockState) state).getValue(BlockAdaptable.ADAPTATION_TYPE).heightReduction;
    				
    				for (BakedQuad quad : bakedModel.getQuads(state, side, random))
    				{
    					quads.add(translate(quad, shape.getTranslationVector(position, heightReduction)));				
    				}
    				QUADS.put(key, quads);
    			}
    		}
    		return quads;
    	}
    
    	protected static BakedQuad translate(BakedQuad quad, Vector4f translationVector)
    	{
    		UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.ITEM);
    
    		quad.pipe(new VertexTransformer(builder)
    		{
    			@Override
    			public void put(int element, float... data)
    			{
    				VertexFormatElement formatElement = DefaultVertexFormats.ITEM.getElement(element);
    				
    				if (formatElement.getUsage() == VertexFormatElement.EnumUsage.POSITION)
    				{
    					float[] newData = new float[4];
    					Vector4f vec = new Vector4f(data);
    					vec.add(translationVector);
    					vec.get(newData);
    					this.parent.put(element, newData);
    				}
    				else
    				{
    					this.parent.put(element, data);	
    				}
    			}
    		});
    		return builder.build();
    	}
    
    	@Override
    	public boolean isAmbientOcclusion() {
    		return true;
    	}
    
    	@Override
    	public boolean isGui3d() {
    		return true;
    	}
    
    	@Override
    	public boolean isBuiltInRenderer() {
    		return false;
    	}
    
    
    	@Override
    	public ItemOverrideList getOverrides() {
    		return null;
    	}
    
    	@Override
    	public TextureAtlasSprite getParticleTexture() {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    }

     

     

  9. So I'm trying to render my .obj model in my TESR, but it is always dark. If I don't disable the lighting, it renders completely black.

     

    What am I doing wrong? Is there something to tweak while exporting my models or?

     

    P.S. I'm using TESR because there are going to be some animations and whatnot, so don't bother telling me that I shouldn't use TESR when I should. 

     

    TESRCounter.java

    package tt.kitchenstuffmod.client.renderer.blockentity;
    
    import org.lwjgl.opengl.GL11;
    
    import net.minecraft.block.state.IBlockState;
    import net.minecraft.client.Minecraft;
    import net.minecraft.client.renderer.BlockModelRenderer;
    import net.minecraft.client.renderer.BufferBuilder;
    import net.minecraft.client.renderer.GlStateManager;
    import net.minecraft.client.renderer.Tessellator;
    import net.minecraft.client.renderer.block.model.IBakedModel;
    import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
    import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
    import net.minecraft.util.ResourceLocation;
    import net.minecraft.util.math.BlockPos;
    import net.minecraft.world.World;
    import net.minecraftforge.fml.relauncher.Side;
    import net.minecraftforge.fml.relauncher.SideOnly;
    import tt.kitchenstuffmod.blockentity.BlockEntityCounter;
    import tt.kitchenstuffmod.main.KitchenStuffMod;
    import tt.kitchenstuffmod.util.ModelLoader;
    
    @SideOnly(Side.CLIENT)
    public class TESRCounter extends TileEntitySpecialRenderer<BlockEntityCounter>
    {
    	private static IBakedModel top;
    	private static IBakedModel body;
    	private static IBakedModel lower;
    	private static IBakedModel upper;
    	
    	public static void loadModels()
    	{
    		
    		top = ModelLoader.loadModel("counter/counter_top"); // 'loadModel' just loads the models and handles exceptions, nothing special...
    		body = ModelLoader.loadModel("counter/top_01");
    		lower = ModelLoader.loadModel("counter/lowerdraw");
    		upper = ModelLoader.loadModel("counter/upperdraw"); 
    		KitchenStuffMod.log("Models loaded...");
    	}
    	
    	private Tessellator tessellator;
    	private BufferBuilder buffer;
    	private World world;
    	private BlockPos position;
    	private IBlockState block_state;
    
    	private BlockModelRenderer renderer = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelRenderer();
    		
    	@Override
    	public void render(BlockEntityCounter block_entity, double x, double y, double z, float partial_ticks, int destroy_stage, float alpha)
    	{
    		this.tessellator = Tessellator.getInstance();
    		this.buffer = this.tessellator.getBuffer();
    		this.world = block_entity.getWorld();
    		this.position = block_entity.getPos();
    		this.block_state = world.getBlockState(position);
    		
    		BlockPos entity_position = block_entity.getPos();
    		
    		push_all();
    
    		GlStateManager.translate(x - entity_position.getX(), y - entity_position.getY(), z - entity_position.getZ());
    		
            GlStateManager.disableLighting();
            
            // the name of the texture is wrong, on purpose (top get the purple-black thingy)
            render_model(body, new ResourceLocation("minecraft", "textures/blocks/planks_fbirch.png"));
      
            pop_all();    
    
    	}
    	
    	private void render_model(IBakedModel model, ResourceLocation texture)
    	{
    		this.buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);
    		this.bindTexture(texture);
    		this.renderer.renderModel(world, model, block_state, position, buffer, true);
    		this.tessellator.draw();
    	}
    	
    	private void push()
    	{
            GlStateManager.pushMatrix();
    	}
    	
    	private void push_all()
    	{
    		GlStateManager.pushAttrib();
            GlStateManager.pushMatrix();
    	}
    	
    	private void pop()
    	{
    		GlStateManager.popMatrix();
    	}
    	
    	private void pop_all()
    	{
    		GlStateManager.popMatrix();
            GlStateManager.popAttrib();
    	}
    }

     

  10. So I'm stuck on this silly problem. All I want is to render my .obj model in my TESR. Here's the back-story.

     

    I have a .obj model that I want to render in my TESR. The texture that I want to render on the model is determined by a 'type' enum that every tile entity holds. The reason why I'm using a TESR is that a few parts of the model should be rotated by some factors, etc. What am I supposed to do? What classes should I use to load the .obj file. I found a few tutorials, but most of them were outdated. Can someone give me any directions or some sources to base my code off?

  11. So I've been kinda stuck with this event with casting.

     

    event.player returns an instance of EntityPlayer, but I need EntityPlayerMP to give the player some recipes. If I cast it to EntityPlayerSP or EntityPlayerMP, it throws ClassCastException (casting it to 'MP crashes Minecraft). Is there any way I can get instances of EntityPlayerSP and EntityPlayerMP or is there a way to check on which side the code is run?

  12. Hi there!

     

    I have a block that HAS* to get its registry name changed but the thing is, it's going to ruin a lot of world-saves!

    Is it possible to change a registry name while the world loads? Here's what I have in mind:

    When you load a world, look for 'registryName1' in all block names (I think that block registry names are stored in something) and then replace it with 'registryName2'.

    Is there an event for something like that?

     

    * The block's registry name is used for a special mechanic, it's too complicated to explain what it does but the block's registry name HAS TO change.

     

  13. I have around 200 recipes that I registered in the code in 1.11. I built my mod in a way I could store recipes when I initialize my blocks. Everything was automatic that way. With the introduction of recipe .json files in 1.12, I noticed that I'm forced to use them. Now it seems that I will have to make a program that would convert all of my recipes into .json files. Is there a way to make a 'custom' crafting manager, aka can I do something so I can still register recipes from the code and if so what do I do?

  14. IDs have nothing to do with past Minecraft IDs and they are completely invisible to end-users and they can't change in any way unless I change them since they are only used for stuff that I created, not Forge. Anyway, the problem has been solved....

  15. Usually, I would go around this problem, but right now I can't.

     

    Whenever I make a class with more creative tab objects, their icon would always show up as blank. No matter how I register my blocks or whether I "pre-load" my class, it's always blank. The reason why is that the class with creative tabs loads way before my class with blocks and so my block objects end up being null. I have no idea what to do, and as usual, I expect it to be a simple solution as I tend to get stuck on retarded things... Here's the code:

    public class BSMCreativeTabs
    {
    	public static void initialize() {BSMSlab.initialize();} // a way to "pre-load" my block class
    	
    	public static final CreativeTabs tabWoodRelated = new CreativeTabs("tabWoodRelated")
    	{
    		@Override
    		@SideOnly(Side.CLIENT)
    		public ItemStack getTabIconItem()
    		{
    			return new ItemStack(BSMBlocks.OAK_WOOD_ON_Y_AXIS, 1);
    		}
    		
    		@Override
    		@SideOnly(Side.CLIENT)
    	    public void displayAllRelevantItems(NonNullList<ItemStack> list)
    	    {
    			int[][] blockIDs =
    			{
    				{26, 29, 32, 35, 137, 140, -1, -1, -1}, // WOOD 
    				{12, 13, 14, 15,  16,  17, -1, -1, -1}, // PLANKS
    				{37, 38, 39, 40, 142, 143, -1, -1, -1}  // LEAVES
    			};
    			getItemsFor(list, blockIDs);
    	    }
    		
    	}.setNoScrollbar();
    }     
    package tt.betterslabsmod.main;
    
    import java.util.HashMap;
    
    import net.minecraft.block.*;
    import net.minecraft.init.Blocks;
    import tt.betterslabsmod.blocks.*;
    import tt.betterslabsmod.blocks.BSMSlabBasic.BasicVariant;
    import tt.betterslabsmod.options.BSMOptions;
    
    public class BSMBlocks
    {
    /**
    All blocks are loaded this way
    **/
    	public static final BSMSlab STONE;
    	
    	private static BSMSlab getRegisteredBlock(int ID)
    	{
    		return BSMSlab.BLOCK_REGISTRY.get(ID);
    	}
    	
    	static
    	{
    		STONE = getRegisteredBlock(0);
    	}
    }

     

  16. Hello :D

    I'll try to explain this by using spruce wood texture as an example since generalizing it would be a little difficult for you to understand.

    As far as I know, Minecraft uses a Map for all textures used by blocks (I'm probably wrong). What I want to do is take the spruce wood texture, make a copy of it, and rename and rotate that same texture and then "give" it to Minecraft to use it. I was wondering if I'm even able to do so (in an easier way) and if there is a way, how can I do it?

     

    P.S. Again the spruce wood texture is just an example, I have loads of other textures to rotate. I don't want to make copies of vanilla textures and place it in my mod file because if a player changes their resource pack, I want my blocks to change their appearance too.

     

  17. I did everything you said, but the only thing I get is the black bounding box that you look at don't get rendered, instead, gray lines that form triangles on the block's face renders. The block itself is never shown.

    @SubscribeEvent
    	public void highlightGhostBlock(DrawBlockHighlightEvent event)
    	{
    		EntityPlayer player = event.getPlayer();
    		BlockPos position = event.getTarget().getBlockPos().offset(player.getHorizontalFacing());
    		
    		ItemStack stack = player.getHeldItemMainhand();
    		if (stack.getItem() instanceof BSMItemBlock)
    		{
    			IBlockState stateToRender = ((BSMItemBlock)stack.getItem()).getDetails(player.world, position, player, 0, 0, 0, event.getTarget().sideHit).getSecondElement();
    			
    			Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
    			
    			GlStateManager.pushMatrix();
                GlStateManager.disableLighting();
                GlStateManager.enableAlpha();
                //GlStateManager.alphaFunc(0, 0);
                
                Tessellator tessellator = Tessellator.getInstance();
                VertexBuffer vertexbuffer = tessellator.getBuffer();
                position.add(0.5, 0, 0.5);
                vertexbuffer.begin(7, DefaultVertexFormats.BLOCK);
                BlockPos blockpos = new BlockPos(position.getX(), position.getY(), position.getZ());
                GlStateManager.translate(position.getX(), position.getY(), position.getZ());
                
                BlockRendererDispatcher blockrendererdispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
                blockrendererdispatcher.getBlockModelRenderer().renderModel(event.getPlayer().world, blockrendererdispatcher.getModelForState(stateToRender), stateToRender, blockpos, vertexbuffer, false, MathHelper.getPositionRandom(position));
                tessellator.draw();
    
                GlStateManager.enableLighting();
                GlStateManager.popMatrix();
    		}
    	}

     

×
×
  • Create New...

Important Information

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