Jump to content

Major Squirrel

Members
  • Posts

    117
  • Joined

  • Last visited

Posts posted by Major Squirrel

  1. 43 minutes ago, V0idWa1k3r said:

    Yes, but look at my comment:

    14 hours ago, V0idWa1k3r said:

    Rotation in the blockstates file can only be done by 90 degrees(0, 90, 180, 270).

    https://minecraft.gamepedia.com/Model#Block_states

     

    This is why I use the Forge blockstate format, with Forge marker set as 1.
     

    43 minutes ago, V0idWa1k3r said:

    or i think you can use a transform key

     

    Well this is exactly what I did in my blockstates file :
     

    {
    	"forge_marker": 1,
    	"defaults": {
    		"model": "mymod:standing_rp_sign",
    		"uvlock": true
    	},
    	"variants": {
    		"rotation": {
    			"0": {
    				"transform": { "rotation": { "y": 180 } }
    			},
    			"1": {
    				"transform": { "rotation": { "y": 157.5 } }
    			},
    			"2": {
    				"transform": { "rotation": { "y": 135 } }
    			},
    			"3": {
    				"transform": { "rotation": { "y": 112.5 } }
    			},
    			"4": {
    				"transform": { "rotation": { "y": 90 } }
    			},
    			"5": {
    				"transform": { "rotation": { "y": 67.5 } }
    			},
    			"6": {
    				"transform": { "rotation": { "y": 45 } }
    			},
    			"7": {
    				"transform": { "rotation": { "y": 22.5 } }
    			},
    			"8": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"9": {
    				"transform": { "rotation": { "y": 337.5 } }
    			},
    			"10": {
    				"transform": { "rotation": { "y": 315 } }
    			},
    			"11": {
    				"transform": { "rotation": { "y": 292.5 } }
    			},
    			"12": {
    				"transform": { "rotation": { "y": 270 } }
    			},
    			"13": {
    				"transform": { "rotation": { "y": 247.5 } }
    			},
    			"14": {
    				"transform": { "rotation": { "y": 225 } }
    			},
    			"15": {
    				"transform": { "rotation": { "y": 202.5 } }
    			}
    		}
        }
    }

     

    Following output :

    image.png.2ea5c1a1112098e4d39386ec290c804d.png

  2. 6 hours ago, V0idWa1k3r said:

    You'd need to use a TESR anyway to render the text, so...

     

    I don't want to render any text on the sign, that is why I would like to avoid using TESR.
     

    6 hours ago, V0idWa1k3r said:

    Rotation in the blockstates file can only be done by 90 degrees(0, 90, 180, 270).

     

    According to @diesieben07 in the link I've posted above, the TRSRTransformation rotation can achieve 22.5 degrees increments, that's why I don't really understand.

  3. 8 hours ago, desht said:

    If the data is only needed client-side for GUI display purposes (as opposed to block rendering purposes), you could just have that custom packet sync the necessary data and trigger the GUI opening client-side.


    Thank you @desht, I will give a try.

    Also, I'm trying to avoid using TESR by only using Forge Blockstate format. For the wall sign it is pretty easy as Vanilla blockstate increments rotation every 90 degrees, but for the standing sign it is a little bit more complicated as it has 16 possible rotations.

    I've read this post where it is advised to use the Forge Blockstate V1 specs available here but I guess I have difficulties in understanding the specs.

    Here is what I got :

     

    Spoiler

    image.png.84239ee243f55b95a348628a58bd15e6.png

     

    The original model for the block (the uniform face is purposely complete beige so I could see where it faces) :

     

    Spoiler

    image.png.5aaadb552e9e882518dec02b6010f962.png

     

    (blockstates/standing_rp_sign.json)

    Spoiler
    
    {
    	"forge_marker": 1,
    	"defaults": {
    		"model": "mymod:standing_rp_sign",
    		"uvlock": true
    	},
    	"variants": {
    		"rotation": {
    			"0": {
    				"transform": { "rotation": { "y": 180 } }
    			},
    			"1": {
    				"transform": { "rotation": { "y": 157.5 } }
    			},
    			"2": {
    				"transform": { "rotation": { "y": 135 } }
    			},
    			"3": {
    				"transform": { "rotation": { "y": 112.5 } }
    			},
    			"4": {
    				"transform": { "rotation": { "y": 90 } }
    			},
    			"5": {
    				"transform": { "rotation": { "y": 67.5 } }
    			},
    			"6": {
    				"transform": { "rotation": { "y": 45 } }
    			},
    			"7": {
    				"transform": { "rotation": { "y": 22.5 } }
    			},
    			"8": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"9": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"10": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"11": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"12": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"13": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"14": {
    				"transform": { "rotation": { "y": 0 } }
    			},
    			"15": {
    				"transform": { "rotation": { "y": 0 } }
    			}
    		}
        }
    }

     

     

    (block/standing_rp_sign.json)

    Spoiler
    
    {
    	"credit": "Made with Blockbench",
    	"textures": {
    		"0": "blocks/planks_oak",
    		"1": "blocks/log_oak",
    		"particle": "blocks/planks_oak"
    	},
    	"elements": [
    		{
    			"name": "pane",
    			"from": [ 2, 6, 7.5 ],
    			"to": [ 14, 12, 8.5 ],
    			"faces": {
    				"north": { "uv": [ 0, 0, 1, 1 ], "texture": "#0" },
    				"east": { "uv": [ 0, 2, 4, 14 ], "texture": "#0" },
    				"south": { "uv": [ 0, 2, 16, 14 ], "texture": "#0" },
    				"west": { "uv": [ 12, 2, 16, 14 ], "texture": "#0" },
    				"up": { "uv": [ 0, 0, 16, 2 ], "texture": "#0" },
    				"down": { "uv": [ 0, 14, 16, 16 ], "texture": "#0" }
    			}
    		},
    		{
    			"name": "stick",
    			"from": [ 7.5, 0, 7.5 ],
    			"to": [ 8.5, 6, 8.5 ],
    			"faces": {
    				"north": { "uv": [ 0, 2, 4, 14 ], "texture": "#1" },
    				"east": { "uv": [ 12, 2, 16, 14 ], "texture": "#1" },
    				"south": { "uv": [ 8, 2, 12, 14 ], "texture": "#1" },
    				"west": { "uv": [ 4, 2, 8, 14 ], "texture": "#1" },
    				"up": { "uv": [ 0, 0, 4, 4 ], "texture": "#1" },
    				"down": { "uv": [ 12, 12, 16, 16 ], "texture": "#1" }
    			}
    		}
    	],
    	"groups": [
    		{
    			"name": "group",
    			"children": [ 0, 1 ]
    		}
    	]
    }

     

     

    I don't really understand what is going on here tbh.

  4. 2 hours ago, desht said:

    If you need to open a containerless GUI from the server side, you'll need to send a custom packet to the client.  But if you're doing this from onBlockActivated(), is there a reason you can't just open the GUI if called client-side (maybe you want to do some server-side validation first, I haven't examined your code too closely) ?

     

    The purpose would be to display data stored in the TileEntity, inside a GUI. Then, I guess I would call the server to retrieve the data and to pass it to the GUI ?

  5. 53 minutes ago, V0idWa1k3r said:

    Show your code(without extending ITileEntityProvider)

     

    (BlockRPSign.java)

    Spoiler
    
    public class    BlockRPSign extends Block {
    
        private static final AxisAlignedBB  RP_SIGN_AABB = new AxisAlignedBB(0.25D, 0.0D, 0.25D, 0.75D, 0.8125D, 0.75D);
    
        protected   BlockRPSign() {
            super(Material.WOOD);
        }
    
        @Override
        public AxisAlignedBB    getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
            return (BlockRPSign.RP_SIGN_AABB);
        }
    
        @Nullable
        @Override
        public AxisAlignedBB    getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos) {
            return (NULL_AABB);
        }
    
        @Override
        public boolean  isFullCube(IBlockState state) {
            return (false);
        }
    
        @Override
        @SideOnly(Side.CLIENT)
        public boolean hasCustomBreakingProgress(IBlockState state) {
            return (true);
        }
    
        @Override
        public boolean  isPassable(IBlockAccess worldIn, BlockPos pos) {
            return (true);
        }
    
        @Override
        public boolean  isOpaqueCube(IBlockState state) {
            return (false);
        }
    
        @Override
        public boolean  canSpawnInBlock() {
            return (true);
        }
    
        @Override
        public boolean  hasTileEntity(IBlockState state) {
            return (true);
        }
    
        @Nullable
        @Override
        public TileEntity   createTileEntity(World world, IBlockState state) {
            return (new TileEntityRPSign());
        }
    
        @Override
        public Item getItemDropped(IBlockState state, Random rand, int fortune) {
            return (null);
        }
    
        @Override
        public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state) {
            return (new ItemStack(MyModItems.roleplay_sign));
        }
    
        @Override
        public boolean  onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
            if (!worldIn.isRemote) {
                // TODO: serverside GUI opening
                return (true);
            } else
                return (true);
        }
    
        @Override
        public BlockFaceShape   getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face) {
            return (BlockFaceShape.UNDEFINED);
        }
    }

     


    It works with the code above, I was overriding the wrong hasTileEntity method (the one without any parameter) , thank you.
     

    53 minutes ago, V0idWa1k3r said:

     

    Could you please explain a little more about why you indicate me to use a proxy ? I know this part of code is executed on the server thread and I'm calling clientside code with Minecraft#displayGuiScreen, but I don't find a way to open a GUI remotely of a TileEntity without any Container.

    EDIT: is it as simple as using a GuiHandler and returning null in getServerGuiElement ...?

  6. I've added "empty" blockstate files and model files like so :

    (blockstates/standing_rp_sign.json)

    Spoiler
    
    {
    	"variants": {
            "rotation=0": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=1": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=2": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=3": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=4": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=5": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=6": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=7": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=8": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=9": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=10": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=11": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=12": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=13": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=14": { "model": "mymodmenu:standing_rp_sign" },
    		"rotation=15": { "model": "mymodmenu:standing_rp_sign" }
        }
    }

     

     

    (blockstates/wall_rp_sign.json)

    Spoiler
    
    {
    	"variants": {
            "facing=east": { "model": "mymodmenu:wall_rp_sign" },
    		"facing=south": { "model": "mymodmenu:wall_rp_sign" },
    		"facing=west": { "model": "mymodmenu:wall_rp_sign" },
    		"facing=north": { "model": "mymodmenu:wall_rp_sign" }
        }
    }

     

     

    (models/block/standing_rp_sign.json and models/block/wall_rp_sign.json)

    Spoiler
    
    {	"textures": {
    		"particle": "blocks/planks_oak"
        }
    }

     

     

    It does fix all MissingVariant exceptions as well as emitted particles when signs are destroyed.

     

    However, when changing my BlockRPSign from BlockContainer to Block with Block#hasTileEntity and Block#createTileEntity overriden, the render() method from the TESR is not called anymore. Instead, I've made my class extend to Block, implementing ITileEntityProvider. It works now.

     

    40 minutes ago, V0idWa1k3r said:

    In that case use a proxy. You can't reference client-only classes(Minecraft, Gui) in common code anyways


    What do you mean by proxy ? Sending a packet to the server and the server opens a player GUI ?
     

  7. Good evening,

    Thank you @V0idWa1k3r for your answer.
     

    4 hours ago, V0idWa1k3r said:

    Minecraft itself marks the sign as having a "built-in" model and doesn't even attempt to load it's model as a result.

     

    I couldn't find it in Vanilla code earlier. Is it in the BlockModelShapes#registerAllBlocks method ?


    I guess I will have to create an "empty" blockstates file if I want to override emitted particles anyway.
     

    4 hours ago, V0idWa1k3r said:

    Use forge's method(EntityPlayer#openGui) to opeen GUI's.


    Isn't this method supposed to be used when there is a Container attached to the TileEntity ? My TileEntity has no Container, it just has some data stored (TextComponents) in it.

     

    For what is left, I simply copied/pasted Vanilla code. Now I've fixed the useless casts, boxing/unboxing, arrays, etc... Thank you for that.

  8. Good evening,

    I'm modding a custom sign which is translucent and smaller than the Vanilla's one.

     

    Spoiler

    image.png.d86dae174175b75cee3e0543c9ebee6e.png


    I've looked for Vanilla classes to mimic the existing BlockSign and its children BlockStandingSign and BlockWallSign. I've also made a custom TileEntitySpecialRenderer and registered it.

    (BlockRPSign.java)

    Spoiler
    
    public class    BlockRPSign extends BlockContainer {
    
        private static final AxisAlignedBB  RP_SIGN_AABB = new AxisAlignedBB(0.25D, 0.0D, 0.25D, 0.75D, 0.8125D, 0.75D);
    
        protected   BlockRPSign() {
            super(Material.WOOD);
        }
    
        @Override
        public AxisAlignedBB    getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
            return (BlockRPSign.RP_SIGN_AABB);
        }
    
        @Nullable
        @Override
        public AxisAlignedBB    getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos) {
            return (NULL_AABB);
        }
    
        @Override
        public boolean  isFullCube(IBlockState state) {
            return (false);
        }
    
        @Override
        @SideOnly(Side.CLIENT)
        public boolean hasCustomBreakingProgress(IBlockState state) {
            return (true);
        }
    
        @Override
        public boolean  isPassable(IBlockAccess worldIn, BlockPos pos) {
            return (true);
        }
    
        @Override
        public boolean  isOpaqueCube(IBlockState state) {
            return (false);
        }
    
        @Override
        public boolean  canSpawnInBlock() {
            return (true);
        }
    
        @Nullable
        @Override
        public TileEntity   createNewTileEntity(World worldIn, int meta) {
            return (new TileEntityRPSign());
        }
    
        @Override
        public Item getItemDropped(IBlockState state, Random rand, int fortune) {
            return (null);
        }
    
        @Override
        public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state) {
            return (new ItemStack(MyModItems.roleplay_sign));
        }
    
        @Override
        public boolean  onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
            if (!worldIn.isRemote) {
                Minecraft.getMinecraft().displayGuiScreen(new GuiRolePlayScreen());
                return (true);
            } else
                return (true);
        }
    
        @Override
        public boolean  canPlaceBlockAt(World worldIn, BlockPos pos) {
            return (!this.hasInvalidNeighbor(worldIn, pos) && super.canPlaceBlockAt(worldIn, pos));
        }
    
        @Override
        public BlockFaceShape   getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face) {
            return (BlockFaceShape.UNDEFINED);
        }
    }

     

     

    (BlockStandingRPSign.java)

    Spoiler
    
    public final class  BlockStandingRPSign extends BlockRPSign {
    
        public static final PropertyInteger ROTATION = PropertyInteger.create("rotation", 0, 15);
    
        public  BlockStandingRPSign() {
            super();
    
            this.setHardness(1.0F);
            this.setSoundType(SoundType.WOOD);
            this.disableStats();
    
            this.setDefaultState(this.blockState.getBaseState().withProperty(ROTATION, Integer.valueOf(0)));
        }
    
        @Override
        public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) {
            if (!worldIn.getBlockState(pos.down()).getMaterial().isSolid()) {
                this.dropBlockAsItem(worldIn, pos, state, 0);
                worldIn.setBlockToAir(pos);
            }
    
            super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
        }
    
        @Override
        public IBlockState getStateFromMeta(int meta) {
            return (this.getDefaultState().withProperty(ROTATION, Integer.valueOf(meta)));
        }
    
        @Override
        public int getMetaFromState(IBlockState state) {
            return (state.getValue(ROTATION).intValue());
        }
    
        @Override
        public IBlockState  withRotation(IBlockState state, Rotation rot) {
            return (state.withProperty(ROTATION, Integer.valueOf(rot.rotate(((Integer)state.getValue(ROTATION)).intValue(), 16))));
        }
    
        @Override
        public IBlockState  withMirror(IBlockState state, Mirror mirrorIn) {
            return (state.withProperty(ROTATION, Integer.valueOf(mirrorIn.mirrorRotation(((Integer)state.getValue(ROTATION)).intValue(), 16))));
        }
    
        @Override
        protected BlockStateContainer   createBlockState() {
            return (new BlockStateContainer(this, new IProperty[] {ROTATION}));
        }
    }

     

     

    (BlockWallRPSign.java)

    Spoiler
    
    public final class  BlockWallRPSign extends BlockRPSign {
    
        public static final PropertyDirection   FACING = BlockHorizontal.FACING;
        protected static final AxisAlignedBB    RP_SIGN_EAST_AABB = new AxisAlignedBB(0.0D, 0.3125D, 0.125D, 0.0625D, 0.6875D, 0.875D);
        protected static final AxisAlignedBB    RP_SIGN_WEST_AABB = new AxisAlignedBB(0.9375D, 0.3125D, 0.125D, 1.0D, 0.6875D, 0.875D);
        protected static final AxisAlignedBB    RP_SIGN_SOUTH_AABB = new AxisAlignedBB(0.125D, 0.3125D, 0.0D, 0.875D, 0.6875D, 0.0625D);
        protected static final AxisAlignedBB    RP_SIGN_NORTH_AABB = new AxisAlignedBB(0.125D, 0.3125D, 0.9375D, 0.875D, 0.6875D, 1.0D);
    
        public  BlockWallRPSign() {
            super();
    
            this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
    
            this.setHardness(1.0F);
            this.setSoundType(SoundType.WOOD);
            this.disableStats();
        }
    
        @Override
        public AxisAlignedBB    getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
            switch ((EnumFacing)state.getValue(FACING)) {
                case NORTH:
                default:
                    return (RP_SIGN_NORTH_AABB);
                case SOUTH:
                    return (RP_SIGN_SOUTH_AABB);
                case WEST:
                    return (RP_SIGN_WEST_AABB);
                case EAST:
                    return (RP_SIGN_EAST_AABB);
            }
        }
    
        @Override
        public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) {
            EnumFacing  enumfacing = (EnumFacing)state.getValue(FACING);
    
            if (!worldIn.getBlockState(pos.offset(enumfacing.getOpposite())).getMaterial().isSolid()) {
                this.dropBlockAsItem(worldIn, pos, state, 0);
                worldIn.setBlockToAir(pos);
            }
    
            super.neighborChanged(state, worldIn, pos, blockIn, fromPos);
        }
    
        @Override
        public IBlockState  getStateFromMeta(int meta) {
            EnumFacing  enumfacing = EnumFacing.getFront(meta);
    
            if (enumfacing.getAxis() == EnumFacing.Axis.Y) {
                enumfacing = EnumFacing.NORTH;
            }
    
            return (this.getDefaultState().withProperty(FACING, enumfacing));
        }
    
        @Override
        public int getMetaFromState(IBlockState state) {
            return (((EnumFacing)state.getValue(FACING)).getIndex());
        }
    
        @Override
        public IBlockState  withRotation(IBlockState state, Rotation rot) {
            return (state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING))));
        }
    
        @Override
        public IBlockState  withMirror(IBlockState state, Mirror mirrorIn) {
            return (state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING))));
        }
    
        @Override
        protected BlockStateContainer createBlockState() {
            return (new BlockStateContainer(this, new IProperty[] {FACING}));
        }
    }

     

     

    (ItemRPSign.java)

    Spoiler
    
    public class    ItemRPSign extends Item {
    
        public  ItemRPSign() {
            super();
    
            this.maxStackSize = 1;
            this.setCreativeTab(CreativeTabs.DECORATIONS);
        }
    
        @Override
        public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
            IBlockState iblockstate = worldIn.getBlockState(pos);
            boolean     flag = iblockstate.getBlock().isReplaceable(worldIn, pos);
    
            if (facing != EnumFacing.DOWN && (iblockstate.getMaterial().isSolid() || flag) && (!flag || facing == EnumFacing.UP)) {
                pos = pos.offset(facing);
                ItemStack   itemstack = player.getHeldItem(hand);
    
                if (player.canPlayerEdit(pos, facing, itemstack) && MyModBlocks.standing_rp_sign.canPlaceBlockAt(worldIn, pos)) {
                    if (worldIn.isRemote) {
                        return (EnumActionResult.SUCCESS);
                    } else {
                        pos = flag ? pos.down() : pos;
    
                        if (facing == EnumFacing.UP) {
                            int i = MathHelper.floor((double)((player.rotationYaw + 180.0F) * 16.0F / 360.0F) + 0.5D) & 15;
    
                            worldIn.setBlockState(pos, MyModBlocks.standing_rp_sign.getDefaultState().withProperty(BlockStandingRPSign.ROTATION, Integer.valueOf(i)), 11);
                        } else {
                            worldIn.setBlockState(pos, MyModBlocks.wall_rp_sign.getDefaultState().withProperty(BlockWallRPSign.FACING, facing), 11);
                        }
    
                        //  TODO: Implement custom sign edit here
    
                        if (player instanceof EntityPlayerMP) {
                            CriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP)player, pos, itemstack);
                        }
    
                        itemstack.shrink(1);
                        return (EnumActionResult.SUCCESS);
                    }
                } else {
                    return (EnumActionResult.FAIL);
                }
            } else {
                return (EnumActionResult.FAIL);
            }
        }
    }

     

     

    (TileEntityRPSignRenderer.java)

    Spoiler
    
    @SideOnly(Side.CLIENT)
    public final class  TileEntityRPSignRenderer extends TileEntitySpecialRenderer<TileEntityRPSign> {
    
        private static final ResourceLocation   RP_SIGN_TEXTURE = new ResourceLocation(MyModMenu.MODID + ":textures/entity/roleplay_sign.png");
    
        private final ModelSign model = new ModelSign();
    
        public void render(TileEntityRPSign te, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
            Block   block = te.getBlockType();
    
            GlStateManager.pushMatrix();
            if ("standing_rp_sign".equals(block.getUnlocalizedName().substring(5))) {
                GlStateManager.translate((float)x + 0.5F, (float)y + 0.5F, (float)z + 0.5F);
                GlStateManager.translate(0.0F, -0.125F, 0.0F);
                float   f1 = (float)(te.getBlockMetadata() * 360) / 16.0F;
                GlStateManager.rotate(-f1, 0.0F, 1.0F, 0.0F);
                this.model.signStick.showModel = true;
            } else {
                int     k = te.getBlockMetadata();
                float   f2 = 0.0F;
    
                if (k == 2) {
                    f2 = 180.0F;
                }
    
                if (k == 4) {
                    f2 = 90.0F;
                }
    
                if (k == 5) {
                    f2 = -90.0F;
                }
    
                GlStateManager.translate((float)x + 0.5F, (float)y + 0.5F, (float)z + 0.5F);
                GlStateManager.rotate(-f2, 0.0F, 1.0F, 0.0F);
                GlStateManager.translate(0.0F, -0.25F, -0.46875F);
                this.model.signStick.showModel = false;
            }
    
            if (destroyStage >= 0) {
                this.bindTexture(DESTROY_STAGES[destroyStage]);
                GlStateManager.matrixMode(5890);
                GlStateManager.pushMatrix();
                GlStateManager.scale(4.0F, 2.0F, 1.0F);
                GlStateManager.translate(0.0625F, 0.0625F, 0.0625F);
                GlStateManager.matrixMode(5888);
            } else {
                this.bindTexture(RP_SIGN_TEXTURE);
            }
    
            GlStateManager.enableRescaleNormal();
            GlStateManager.pushMatrix();
            GlStateManager.scale(0.5F, -0.5F, -0.5F);
            GlStateManager.enableBlend();
            GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
            this.model.renderSign();
            GlStateManager.disableBlend();
            GlStateManager.popMatrix();
    
            GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
            GlStateManager.popMatrix();
    
            if (destroyStage >= 0) {
                GlStateManager.matrixMode(5890);
                GlStateManager.popMatrix();
                GlStateManager.matrixMode(5888);
            }
        }
    }

     

     

    (MyModBlocks.java)

    Spoiler
    
    @GameRegistry.ObjectHolder(MyModMenu.MODID)
    public final class  MyModBlocks {
    
        public static final BlockStandingRPSign standing_rp_sign = null;
        public static final BlockWallRPSign     wall_rp_sign = null;
    
        @Mod.EventBusSubscriber(modid = MyModMenu.MODID)
        public static class RegistrationHandler {
    
            @SubscribeEvent
            public static void  registerBlocks(final RegistryEvent.Register<Block> event) {
                System.out.println("Registering blocks...");
    
                final IForgeRegistry<Block> registry = event.getRegistry();
    
                registry.register(NameUtils.setBlockName(new BlockStandingRPSign(), "standing_rp_sign"));
                registry.register(NameUtils.setBlockName(new BlockWallRPSign(), "wall_rp_sign"));
            }
    
            @SubscribeEvent
            public static void  registerItemBlocks(final RegistryEvent.Register<Item> event) {
                System.out.println("Registering itemblocks...");
    
                final IForgeRegistry<Item>  registry = event.getRegistry();
            }
    
            @SubscribeEvent
            @SideOnly(Side.CLIENT)
            public static void  registerModels(final ModelRegistryEvent event) {
                System.out.println("Registering blocks' models...");
    
                //RegistrationHandler.registerBlockModel(standing_rp_sign, 0);
                //RegistrationHandler.registerBlockModel(wall_rp_sign, 0);
    
                System.out.println("Registering itemblocks' models...");
    
                RegistrationHandler.registerItemBlockModels();
    
                System.out.println("Registering tileentities' special renderers...");
    
                ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRPSign.class, new TileEntityRPSignRenderer());
            }
    
            @SideOnly(Side.CLIENT)
            public static void  registerBlockModel(Block block, int metadata) {
                ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), metadata,
                        new ModelResourceLocation(MyModMenu.MODID + ":" + block.getUnlocalizedName().substring(5), "inventory"));
            }
    
            @SideOnly(Side.CLIENT)
            public static void  registerItemBlockModels() {
                
            }
    
            @SideOnly(Side.CLIENT)
            public static void  registerItemBlockModel(ItemBlock block, int metadata) {
                ModelLoader.setCustomModelResourceLocation(block, metadata,
                        new ModelResourceLocation(block.getRegistryName(), "inventory"));
            }
        }
    }

     

     

    (MyModItems.java)

    Spoiler
    
    @GameRegistry.ObjectHolder(MyModMenu.MODID)
    public final class  MyModItems {
    
        public static final ItemRPSign  roleplay_sign = null;
    
        @Mod.EventBusSubscriber(modid = MyModMenu.MODID)
        public static class RegistrationHandler {
    
            @SubscribeEvent
            public static void  registerItems(final RegistryEvent.Register<Item> event) {
                System.out.println("Registering items...");
    
                final IForgeRegistry<Item>  registry = event.getRegistry();
    
                registry.register(NameUtils.setItemName(new ItemRPSign(), "roleplay_sign"));
            }
    
            @SubscribeEvent
            public static void  registerModels(final ModelRegistryEvent event) {
                System.out.println("Registering items' models...");
    
                RegistrationHandler.registerItemModel(roleplay_sign, 0);
            }
    
            @SideOnly(Side.CLIENT)
            public static void  registerItemModel(Item item, int metadata) {
                ModelLoader.setCustomModelResourceLocation(item, metadata,
                        new ModelResourceLocation(item.getRegistryName(), "inventory"));
            }
        }
    }

     

     

    (MyModTileEntities.java)

    Spoiler
    
    public final class  MyModTileEntities {
    
        public static void  registerTileEntities() {
            System.out.println("Registering tileentities...");
    
            GameRegistry.registerTileEntity(TileEntityRPSign.class, new ResourceLocation(MyModMenu.MODID, "tile_rp_sign"));
        }
    }

     


    (As you may see, I'm using @jabelar mod structure from the GitHub repo here)

    I'm getting a net.minecraft.client.renderer.block.model.ModelBlockDefinition$MissingVariantException for my standing_rp_sign blockstate with rotation variants. I haven't created any blockstate file for both standing and wall signs since there is an existing TESR which handles the rendering. I've tried to look for a model loading from Vanilla's sign but I didn't find anything. My guess would be to indicate Forge to avoid handling models for those blocks but i don't know how to do that.

    Also, since there is no blockstate and no model attached to the blocks, there are random particles emitted when breaking the block. Vanilla sign has woods particles but I can't see any code or model file that indicates the texture to use for particles from Vanilla.


    Finally, as you can see in the TESR I'm trying to check the block type from the tileentity (this is done in Vanilla using Block#getBlockType which returns a Block). Is there a better way to do it ?

    Thank you for your help.

     

  9. Good evening,

    So as @Cadiboo stated above, I've been trying to avoid using an entity to render something above players head.
     

    The idea would be to send a CPacketPlayerTyping packet from the player typing to the server, then the server sends a SPacketNotifyTyping to every player around to render the indicator.


    (CPacketPlayerTyping.java)

    Spoiler
    
    public class    CPacketPlayerTyping implements IMessage {
    
        public  CPacketPlayerTyping() {}
    
        @Override
        public void fromBytes(ByteBuf buf) {}
    
        @Override
        public void toBytes(ByteBuf buf) {}
    
        public static class Handler implements IMessageHandler<CPacketPlayerTyping, IMessage> {
    
            @Override
            public IMessage onMessage(CPacketPlayerTyping message, MessageContext ctx) {
                EntityPlayerMP  serverPlayer = ctx.getServerHandler().player;
    
                serverPlayer.getServerWorld().addScheduledTask(() -> {
                    NetworkRegistry.TargetPoint targetPoint = new NetworkRegistry.TargetPoint(serverPlayer.dimension, serverPlayer.posX, serverPlayer.posY, serverPlayer.posZ, 20.0D);
    
                    MyModMenuPacketHandler.INSTANCE.sendToAllAround(new SPacketNotifyTyping(serverPlayer.posX, serverPlayer.posY, serverPlayer.posZ), targetPoint);
                });
    
                return (null);
            }
        }
    }

     

     

    (SPacketNotifyTyping.java)

    Spoiler
    
    public class    SPacketNotifyTyping implements IMessage {
    
        private double  posX;
        private double  posY;
        private double  posZ;
    
        public SPacketNotifyTyping() {}
    
        public SPacketNotifyTyping(double posX, double posY, double posZ) {
            this.posX = posX;
            this.posY = posY;
            this.posZ = posZ;
        }
    
        @Override
        public void fromBytes(ByteBuf buf) {
            this.posX = buf.readDouble();
            this.posY = buf.readDouble();
            this.posZ = buf.readDouble();
        }
    
        @Override
        public void toBytes(ByteBuf buf) {
            buf.writeDouble(this.posX);
            buf.writeDouble(this.posY);
            buf.writeDouble(this.posZ);
        }
    
        public static class Handler implements IMessageHandler<SPacketNotifyTyping, IMessage> {
    
            @Override
            public IMessage onMessage(SPacketNotifyTyping message, MessageContext ctx) {
                EntityPlayerSP  clientPlayer = Minecraft.getMinecraft().player;
    
                //  What to do here ?
                return (null);
            }
        }
    }

     


    (CustomGuiChat.java)

    Spoiler
    
    public class    CustomGuiChat extends GuiChat {
    
        @Override
        public void updateScreen() {
            super.updateScreen();
    
            MyModMenuPacketHandler.INSTANCE.sendToServer(new CPacketPlayerTyping());
        }
    }

     

     

    (MyModMenu.java)

    Spoiler
    
    @EventHandler
        public void preInit(FMLPreInitializationEvent event) {
            MyModMenu.logger = event.getModLog();
            MyModMenu.proxy.preInit();
    
            MyModMenuPacketHandler.registerPacket(ChatIndicatorMessage.ChatIndicatorMessageHandler.class, ChatIndicatorMessage.class, Side.SERVER);
            MyModMenuPacketHandler.registerPacket(CPacketPlayerTyping.Handler.class, CPacketPlayerTyping.class, Side.SERVER);
            MyModMenuPacketHandler.registerPacket(SPacketNotifyTyping.Handler.class, SPacketNotifyTyping.class, Side.CLIENT);
        }

     


    I don't know what to do next in the onMessage function of the SPacketNotifyTyping packet. I've tried to call Gl functions but it is not in an OpenGL context.

    Also, I'm wondering if this is a good idea to send a packet on every screen update, what do you think ?

  10. 16 hours ago, V0idWa1k3r said:

    Send all the clients within a 0 radius updates 0 times a second. Yeah, that's not what you want. You fixed one half of the issue, now fix the other half.

     

    I've updated the tracker accordingly, thank you. ? For now, it seems that it is working as intended (see screenshot below). I've tested it in singleplayer mode and I will test it in multiplayer mode later this day.
     

    Spoiler

    image.png.7bb4e954d13601e96dc091a6f9027207.png

     

    8 hours ago, Cadiboo said:

    You really don’t need to use an entity though


    You're right, I really don't need an entity. What I don't understand with your method is what should I do - on client side - after sending packets from server to client.

  11. My bad, I've created a new instance of EntityChatIndicator but completely forgot to spawn it in the world. The following code works :

    (ChatIndicatorMessage.java)

            @Override
            public IMessage onMessage(ChatIndicatorMessage message, MessageContext ctx) {
                EntityPlayerMP  serverPlayer = ctx.getServerHandler().player;
    
                switch (message.messageType) {
                    case 0: {
                        serverPlayer.getServerWorld().addScheduledTask(() -> {
                            Integer indicatorUniqueId = CHAT_INDICATORS.get(serverPlayer.getUniqueID());
    
                            if (indicatorUniqueId != null) {
                                EntityChatIndicator chatIndicator = (EntityChatIndicator) serverPlayer.world.getEntityByID(indicatorUniqueId);
    
                                if (chatIndicator != null) {
                                    chatIndicator.setDead();
                                    CHAT_INDICATORS.remove(serverPlayer.getUniqueID());
                                }
                            }
                        });
    
                        break;
                    }
                    case 1: {
                        serverPlayer.getServerWorld().addScheduledTask(() -> {
                            EntityChatIndicator chatIndicator = new EntityChatIndicator(serverPlayer.world, serverPlayer.posX, serverPlayer.posY + 0.5D, serverPlayer.posZ);
    
                            if (serverPlayer.world.spawnEntity(chatIndicator))
                                CHAT_INDICATORS.put(serverPlayer.getUniqueID(), chatIndicator.getEntityId());
                        });
    
                        break;
                    }
                    default:
                        break;
                }
                return null;
            }

     

    I also modified updateFrequency from 0 to 20 because it causes a "/ by zero" exception.

    Now, entity updates functions are correctly called but still the doRender function is not called. Any guess ?

  12. Good evening,

    I've decided to go through an Entity for now, meaning that when a player opens a GuiChat, it sends a packet to the server and the server spawns an Entity with a custom Renderer to render the chat indicator above players head.

    Here is what I did so far :

    (ClientProxy.java)

    public class    ClientProxy extends CommonProxy {
    
        @Override
        public void preInit() {
            super.preInit();
    
            RenderingRegistry.registerEntityRenderingHandler(EntityChatIndicator.class, RenderFactoryEntityChatIndicator.INSTANCE);
        }
    
        @Override
        public void init() {
            super.init();
    
            MinecraftForge.EVENT_BUS.register(this);
            MinecraftForge.EVENT_BUS.register(new EntityEventHandler());
        }
    
        @SubscribeEvent
        public void onOpenGui(GuiOpenEvent event) {
            if (event.getGui() != null) {
                if (event.getGui().getClass() == GuiChat.class) {
                    event.setGui(new CustomGuiChat());
                }
            }
        }
    }

     

    (CustomGuiChat.java)

    public class CustomGuiChat extends GuiChat {
    
        @Override
        public void initGui() {
            super.initGui();
    
            MyModMenuPacketHandler.INSTANCE.sendToServer(new ChatIndicatorMessage(1));
        }
    
        @Override
        public void onGuiClosed() {
            super.onGuiClosed();
    
            MyModMenuPacketHandler.INSTANCE.sendToServer(new ChatIndicatorMessage(0));
        }
    }

     

    (EntityEventHandler.java)

    @Mod.EventBusSubscriber(modid = MyModMenu.MODID)
    public final class EntityEventHandler {
    
        @SubscribeEvent
        public static void  onEntityConstructing(EntityEvent.EntityConstructing event) {
            if (event.getEntity() instanceof EntityChatIndicator) {
                System.out.println("EntityChatIndicator is being constructed !");
            }
        }
    
        @SubscribeEvent
        public static void  onEntityRegistering(final RegistryEvent.Register<EntityEntry> event) {
            System.out.println("Registering entities...");
    
            event.getRegistry().register(EntityEntryBuilder.create()
                    .entity(EntityChatIndicator.class)
                    .id(new ResourceLocation(MyModMenu.MODID, "chat_indicator"), 0)
                    .name("chat_indicator")
                    .tracker(0, 0, false)
                    .build()
            );
        }
    }

     

    (EntityChatIndicator.java)

    public class    EntityChatIndicator extends Entity {
    
        public  EntityChatIndicator(World worldIn) {
            this(worldIn, 0.0D, 0.0D, 0.0D);
        }
    
        public  EntityChatIndicator(World worldIn, double posX, double posY, double posZ) {
            super(worldIn);
    
            this.setSize(1.0F, 1.0F);
            this.posX = posX;
            this.posY = posY;
            this.posZ = posZ;
        }
    
        @Override
        protected void  entityInit() { }
    
        @Override
        public void onEntityUpdate() {
            super.onEntityUpdate();
    
            System.out.println("EntityChatIndicator position : (" + this.posX + ", " + this.posY + ", " + this.posZ + ") !");
        }
    
        @Override
        public void onUpdate() {
            super.onUpdate();
    
            System.out.println("EntityChatIndicator position : (" + this.posX + ", " + this.posY + ", " + this.posZ + ") !");
        }
    
        @Override
        protected void readEntityFromNBT(NBTTagCompound compound) {}
    
        @Override
        protected void writeEntityToNBT(NBTTagCompound compound) {}
    }

     

    (RenderChatIndicator.java)

    @SideOnly(Side.CLIENT)
    public final class  RenderChatIndicator extends Render<EntityChatIndicator> {
    
        public  RenderChatIndicator(RenderManager renderManager) {
            super(renderManager);
        }
    
        @Override
        public void doRender(EntityChatIndicator entity, double x, double y, double z, float entityYaw, float partialTicks) {
            System.out.println("Rendering EntityChatIndicator !");
    
            ItemStack   itemstack = new ItemStack(Items.PAPER, 1);
    
            if (!itemstack.isEmpty()) {
                GlStateManager.pushMatrix();
                GlStateManager.translate(x, y, z);
                GlStateManager.rotate(-this.renderManager.playerViewY, 0, 1, 0);
                GlStateManager.rotate(this.renderManager.playerViewX, 1, 0, 0);
                GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
                Minecraft.getMinecraft().getRenderItem().renderItem(itemstack, ItemCameraTransforms.TransformType.GROUND);
                GlStateManager.popMatrix();
            }
    
            super.doRender(entity, x, y, z, entityYaw, partialTicks);
        }
    
        @Nullable
        @Override
        protected ResourceLocation  getEntityTexture(EntityChatIndicator entity) {
            return (null);
        }
    }

     

    (RenderFactoryChatIndicator.java)

    public class RenderFactoryEntityChatIndicator implements IRenderFactory<EntityChatIndicator> {
    
        public static final RenderFactoryEntityChatIndicator    INSTANCE = new RenderFactoryEntityChatIndicator();
    
        @Override
        public Render<EntityChatIndicator>  createRenderFor(RenderManager manager) {
            return (new RenderChatIndicator(manager));
        }
    }

     

    (MyModMenuPacketHandler.java)

    public final class  MyModMenuPacketHandler {
    
        public static final SimpleNetworkWrapper    INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(MyModMenu.MODID);
    
        private static int  discriminator = 0;
    
        public static <REQ extends IMessage, REPLY extends IMessage>
        void registerPacket(Class<? extends IMessageHandler<REQ, REPLY>> messageHandler, Class<REQ> message, Side side) {
            INSTANCE.registerMessage(messageHandler, message, MyModMenuPacketHandler.discriminator++, side);
        }
    }

     

    (ChatIndicatorMessage.java)

    public final class  ChatIndicatorMessage implements IMessage {
    
        /**
         * First UUID key is player's UUID
         * Second Integer value is indicator's UUID
         */
        public static final Map<UUID, Integer> CHAT_INDICATORS = new HashMap<>();
    
        public  ChatIndicatorMessage() {}
    
        /**
         * 0 is to DESTROY a chat indicator
         * 1 is to CREATE a chat indicator
         */
        private int messageType;
    
        public  ChatIndicatorMessage(int messageType) {
            this.messageType = messageType;
        }
    
        @Override
        public void fromBytes(ByteBuf buf) {
            this.messageType = buf.readInt();
        }
    
        @Override
        public void toBytes(ByteBuf buf) {
            buf.writeInt(this.messageType);
        }
    
        public static final class   ChatIndicatorMessageHandler implements IMessageHandler<ChatIndicatorMessage, IMessage> {
    
            @Override
            public IMessage onMessage(ChatIndicatorMessage message, MessageContext ctx) {
                EntityPlayerMP  serverPlayer = ctx.getServerHandler().player;
    
                switch (message.messageType) {
                    case 0: {
                        serverPlayer.getServerWorld().addScheduledTask(() -> {
                            Integer indicatorUniqueId = CHAT_INDICATORS.get(serverPlayer.getUniqueID());
    
                            if (indicatorUniqueId != null) {
                                EntityChatIndicator chatIndicator = (EntityChatIndicator) serverPlayer.world.getEntityByID(indicatorUniqueId);
    
                                if (chatIndicator != null) {
                                    chatIndicator.setDead();
                                    CHAT_INDICATORS.remove(serverPlayer.getUniqueID());
                                }
                            }
                        });
    
                        break;
                    }
                    case 1: {
                        serverPlayer.getServerWorld().addScheduledTask(() -> {
                            EntityChatIndicator chatIndicator = new EntityChatIndicator(serverPlayer.world, serverPlayer.posX, serverPlayer.posY + 0.5D, serverPlayer.posZ);
    
                            CHAT_INDICATORS.put(serverPlayer.getUniqueID(), chatIndicator.getEntityId());
                        });
    
                        break;
                    }
                    default:
                        break;
                }
                return null;
            }
        }
    }

     

    (MyModMenu.java)

    @Mod(modid = MyModMenu.MODID, version = MyModMenu.VERSION)
    public class    MyModMenu
    {
        public static final String MODID = "mymodmenu";
        public static final String VERSION = "1.0.0";
    
        @Mod.Instance
        public static MyModMenu  instance;
        public static Logger            logger;
    
        @SidedProxy(clientSide = "net.theviolentsquirrels.proxy.ClientProxy", serverSide = "net.theviolentsquirrels.proxy.ServerProxy")
        public static CommonProxy       proxy;
    
        @EventHandler
        public void preInit(FMLPreInitializationEvent event) {
            MyModMenu.logger = event.getModLog();
            MyModMenu.proxy.preInit();
    
            MyModMenuPacketHandler.registerPacket(ChatIndicatorMessage.ChatIndicatorMessageHandler.class, ChatIndicatorMessage.class, Side.SERVER);
        }
    
        @EventHandler
        public void init(FMLInitializationEvent event) {
            MyModMenu.proxy.init();
        }
    
        @EventHandler
        public void postInit(FMLPostInitializationEvent event) {
    
        }
    }

     

    So when I'm opening a GuiChat, it correctly prints out that a packet has been sent to the server. Also, it creates a new EntityChatIndicator (caught in the EntityConstructing event). However, the doRender function and the entity updates functions do not seem to be called at all (no print at least). What I've checked is :

     

    • The packet is correctly registered
    • The custom renderer seems to be correctly registered with the factory way
    • The entity seems to be correctly registered with the recent builder

     

    I don't understand what is going on, maybe you could help me ?

    EDIT: is it because my EntityChatIndicator is simply an Entity, and not an EntityLiving ? Can a simple Entity be updated ?

  13. Good evening,

    I'm trying to develop a mod which renders a 2D texture above players to indicate other players that they're typing something in chat.


    AFAIK I would have to override the GuiChat to handle chat opening, update and chat closing & I would have to do something about rendering (I'm inspired by the way tags work above entities, is it the right way ?).

    I'm kind of confused right now because this is a client side part and I don't know how could I handle it to every player around the person typing in chat. Are packets the way to go ?

    Thank you for your replies.

  14. 3 hours ago, [NoOneButNo] said:

    But what's more interesting is that whatever value you put it will always yield 1 as if nothing is changed. The only way it changes is if you have a looting enchantment on the item you used to kill a particular entity.

     

    I have tried your function and the event had a lootingLevel value of 21. The context I tested it was killing a polar bear with a diamond sword (no enchants), it dropped me 12 fish.

     

    In which context have you tested your event ?

  15. 56 minutes ago, [NoOneButNo] said:

    Code: Really, it is just a basic:

    
    @SubscribeEvent(priority = EventPriority.NORMAL) 
    	public void HandleEnchant(LootingLevelEvent fEvent)
    	{	
    	
    		
    		int levelLooting = 10
    
            //Testing
    		
    		fEvent.setLootingLevel(fEvent.getLootingLevel() + 3 + ((levelLooting - 1) * 2));
    		
    		System.out.println(fEvent.getLootingLevel());
    }

     

    The way it "doesn't work" is that if you put any value in the setLootingLevel, it still returns 1 (1 refers to default looting value which is added by 1 per looting level). However. if you have a looting enchantment, it changes (e.g. 2, 3, 4, and etc.).


    Shouldn't your handle function be static ?

     

    public static void	HandleEnchant(final LootingLevelEvent event);


    Also, I suggest your event would be final.

     

    ---

     

    EDIT: my bad, I didn't see your handle function was properly called.

  16. 5 minutes ago, scaper12123 said:

    OK so as it turns out you're absolutely right and I had not realized that log was there until now. I think I have an idea of what my problem is, but it sadly means I'm going to be rewriting the entire code block that creates my ores. Whelp. Here's the log, if you're curious.

     

    What I believe the problem is is how I've coded it or, rather, how the tutorial I follow coded it. The tutorial encourages using variants by using an Enum. However, this originally created problems for me because each type of ore I had created a variant of ore for each of the ores. I.E. For copper ore, I had copper#copper, copper#tin, copper#mithril, etc etc. This turned 6 ores into 36. I eventually fixed this by removing the code that spawns in the extra variants, meaning only one variant would spawn in. I even fixed the issue where the ores had no textures (except for the placed block). However, according to this log the extra variants still exist; the game is just not able to add them cause the code to add them in is commented out. So the code still relies on variants, and it's still getting messed up.

     

    So instead of all this debauchery, I'll just code up each of the variants individually. It's more work and more code but, until I can figure out these variant issues, I'll have to go with that.

    fml-client-latest.log

     

    How many models do you have in your models folder ? What are they ?

     

    From the fml-client-latest.log file, your main error seems to be :

     

    Quote

    [13:34:41] [main/ERROR] [FML/]: Exception loading model for variant rm:copper_ore#variant=tin for blockstate "rm:copper_ore[variant=tin]"

     

    I suppose that either there is no such model file or there is a problem from registering block models.

  17. [UPDATE]

    I found out that there is the Forge event RenderSpecificHandEvent which is called for each hand (MAIN_HAND and OFF_HAND). I ended up subscribing to it and making my own rendering functions, based on the ItemRenderer class. Functions that I simply copy-pasted are renderItemInFirstPerson and renderMapFirstPerson.

    I find it a bit "dirty" that there is a conditional branching only to render an ItemMap inside the rendering pass of Minecraft. Also, certain rendering functions such as renderArms are private and thus could not be overriden or properly called : I have to copy-paste those functions to simulate the same behavior.

     

    Do you think it would be possible create a specific event for the map rendering, considering its unique condition in the code ? What do you think ?

  18. Good evening everyone,

     

    I am working on a custom map item (original MC is ItemEmptyMap and ItemMap which inherit from ItemMapBase), the purpose is to act the same way as the original one except that I would like some information rendered on it. Also, I would like it to be an item apart but I basically make my item inherit from ItemMap.

     

    The part I am struggling with is rendering the map in player's hand and in an item frame. From what I observe in the code, the concerned renderer is the ItemRenderer which renders instances of ItemMap and also MapItemRenderer which renders icons and decorations.

     

    Is there any way to affect a specific ItemRenderer for my custom map or an event that could catch the rendering and to play with ?

     

    Regards.

  19. Could you provide a sample screen of what kind of GUIs you're talking about ? I might be interested in it ! :)

     

    Personally, I just recycle some existing GUIs from Minecraft. For instance, there is the demo_background.png located in the Minecraft assets (textures/gui). It helps me to prototype a canvas for a beginning. Still, I am really curious of how do other developers achieve their GUIs (especially when we are not specialized designers haha).

  20. 53 minutes ago, Alexiy said:

    Clarify, do you want your messages in the console to look like this:

    [15:15:22] [main/INFO] [Fine Technology]: A message from mod logger

    or something else?


    It is already displayed so :
     

    [11:58:59] [main/DEBUG] [FML/]: Overriding dimension: using 0
    [11:59:04] [main/DEBUG] [questly/]: QuestBlock has received a right-click !

    (This is the content from fml-client-latest.log)

    Normally, a log message is displayed into the default IntelliJ Console window but for some reason it doesn't happen.

    PSHB9ic.png

    (The Console window is the default one from IntelliJ, the "fml-client-latest" one has been created by me, from the fml-client-latest.log file)

     

    Contents from each console is different :

    T9rwTp1.png

     

    I don't understand what is going on, to be honest. Why are my log messages not displayed into the default Console ?

  21. Good evening,

     

    Has anyone achieved to log their mod log messages into IntelliJ default Console when running/debugging Minecraft Client/Server ?

    My log messages are well written into the fml-client-latest.log file and I can create a new IntelliJ Log channel to display my log messages but I would like them to be into the default console.

     

    public static final Logger  logger = LogManager.getLogger(Questly.MODID);


    Can anyone help me on this one ?


    Thanks for you help !

×
×
  • Create New...

Important Information

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