Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. Instead of coding it yourself, you could also use a mod like [url=http://2091981/]VersionChecker[/url] - all you do is add 2 lines of code to your main class and place a 'versionlist.json' online, such as in your Github repository, and voilá, version checking implemented with a nice interface from the main game menu, ability to download your mod directly from there / see the change log, etc.
    
    Example code:
    [code
    // put this within FMLInitializationEvent
    String link = "https://raw.githubusercontent.com/coolAlias/ZeldaSwordSkills/master/src/main/resources/versionlist.json";
    FMLInterModComms.sendRuntimeMessage(ModInfo.ID, "VersionChecker", "addVersionCheck", link);
    

    Note that it's important to use the 'raw' form of the .json, otherwise VC can't read it.

  2. Well I would assume I am handling it being null because

    if (stack == null) continue;
    and
    if (this.mc.thePlayer.inventory.getCurrentItem() != null)
    

    should handle it, correct?

    Is that the line that your crash log pointed to when it gave you the NPE? No, it isn't, i.e. this is not where the problem is.

  3. So I did that and it appears to go null on the .getIconName() method

    So... you can fix it now, right, since you know what is null?

     

    Specifically: "Calling the instance method of a null object."

     

    i.e. You cannot call a class method if you do not have an object of that class. You are trying to call getIconName() on a NULL object.

  4. You don't. It's a Forge method - tampering with it would bring the world crashing down.

     

    To clarify, you want the player to mine ALL blocks at the same speed, regardless of tool? In that case, just check in your BreakEvent if the player's currently held item can harvest the block - if it cannot, multiply your break speed by (100 / 30) to compensate for the difference.

  5. It's because if the current tool (or hand) cannot break the block, the speed is divided by 100 instead of 30:

    // in ForgeHooks:
    public static float blockStrength(IBlockState state, EntityPlayer player, World world, BlockPos pos)
        {
            float hardness = state.getBlock().getBlockHardness(world, pos);
            if (hardness < 0.0F)
            {
                return 0.0F;
            }
    
            if (!canHarvestBlock(state.getBlock(), player, world, pos))
            {
                return player.getBreakSpeed(state, pos) / hardness / 100F;
            }
            else
            {
                return player.getBreakSpeed(state, pos) / hardness / 30F;
            }
        }
    

    As you can see, always returning 5 will yield pretty different results based on the above algorithm.

     

    Btw, you can easily find out such things yourself by utilizing the power of your IDE - select a method, right click and 'open call hierarchy' to see where it is called from, then keep following the rabbit hole. ;)

  6. TextureAtlasSprite textureAtlasSprite = mc.getTextureMapBlocks().getAtlasSprite(ibakedmodel.getTexture().getIconName()); // This is where the crash points to
    

    Whenever you get a NULL pointer exception, the first thing you should do is put a break point on that line and fire up the debugger.

     

    If you are not comfortable doing that, then you can still quickly debug it by putting everything on its own line:

    TextureAtlasSprite textureAtlasSprite = mc
        .getTextureMapBlocks()
        .getAtlasSprite(ibakedmodel
            .getTexture()
            .getIconName()
        );
    

    Now when you run your code again, you will find out EXACTLY which of those is null.

  7. If Item#onBlockDestroyed doesn't allow preventing then using BlockEvent.HarvestDropsEvent would be best to use

    You could probably override Item#canHarvestBlock(Block) to return false if the block has a smelting result - thus preventing any normal harvesting, and then dropping the smelting result from #onBlockDestroyed.

     

    @OP Of course you can drop stone instead of cobblestone - the problem you are running into, however, is that the block being destroyed is stone, which does not have a smelting result.

     

    You should instead be checking the actual item dropped from the block, not the block itself. You could do this with Block#getItemDropped and Block#getDamageValue, but that may or may not produce the actual desired result, and you wouldn't be able to check for it in #canHarvestBlock due to the lack of a World and BlockPos.

     

    Jedispencer's suggestion of using the HarvestDropsEvent may be your only recourse in this matter, which is fine - that's what it's there for - but it's always good to explore other options first.

  8. so I tried to add it into my if statement and the only place I could add it in was here 'if (stack.copy() != null)' but it still crashed

    This is what I meant:

    if (stack != null) {
       player.entityDropItem(stack.copy());
    }
    

     

    why don't you try using BlockEvent.HarvestDropsEvent and check if the player is using your tool then get the smelting result and drop that instead of the normal block

    He could, but why do so when he already has a custom Item class ? Subscribing to Forge events should always be considered somewhat of a 'last resort', as the event handler is called for EVERY harvest, whether or not the player is wielding the pickaxe, whereas the code in the pickaxe is only called when it is actually used to break the block.

     

    On the other hand, the harvest event lets you prevent the normal drop, whereas I don't think Item#onBlockDestroyed does. Hmm.

  9. No, it's because the smelting result might return null, but you immediately call copy() on it:

    FurnaceRecipes.smelting()
       .getSmeltingResult(new ItemStack(block)) // this returned null
       .copy() // so this crashes
    

    Simply move the call to copy() to inside your 'if (stack != null) ' clause and you're good to go.

  10. You can of course alter a JSON file at any time, but Minecraft only reads them in once when it first loads the models, blockstates, etc., so in this case that would not have any benefit unless you forced it to reload for every single one of your blocks / TileEntities every single tick, because they're all different, right?

     

    File I/O is relatively expensive, so I recommend you avoid it if you can. Luckily for you, there are ISmartBlockModels, IFlexibleBlockModels, TileEntitySpecialRenderers, and that sort of thing which allow you to dynamically render your blocks / TileEntities.

     

    You can also register a custom IStateMapper for your block to drastically reduce the number of variants and models you need in your blockstate file - most useful in combination with the above.

  11. It looks like you are trying to mimic the vanilla Iron Golem attack animation, correct? In any case, you should look at the Iron Golem code, both the Entity and the Model, to see how it handles the attack timer / animation.

     

    Here's what you should pay attention to / learn as you look through the IronGolem classes:

    1. Golem attacks, calls world.setEntityState(this, byteFlag)

    2. Minecraft sends a packet for you that calls golem#handleHealthUpdate(byteFlag) on the client side

    3. When byteFlag is received, it starts the golem's attack timer - again, this is on the client side, which is important

    4. attack timer is decremented every tick in the entity's onLivingUpdate method

    5. In the model class, which is client side, it can now see that the attack timer is ticking and animate accordingly in setLivingAnimations

  12. Which player? Do you have an EntityPlayer available in your projectile, e.g. the thrower / shooter? If so, you can use player.getHeldItem() to get the currently held ItemStack, if any, and do whatever you want with it, e.g. stack.getTagCompound() to get the NBTTagCompound, if any.

  13. which forge event? @SideOnly(Side.CLIENT) this?

    Well, it's not really a Forge event, but it looks as though you copied it from a Forge event and may have been expecting it to act like one:

    // in your Model class:
    public void LivingAttackEvent(EntityLivingBase entity, float par1, float par2, float par3){
    

    Where are you calling that from? Are you calling it at all?

     

    Perhaps you should check out Jabelar's tutorial on animations / entities.

  14. Why are you using a Forge Event to handle your animation?!?!?!?! No no no. Not good.

     

    It's YOUR entity class, and YOUR model, use the methods already available to you: ModelBase#setLivingAnimations has access to any of your entity fields that have been synced to the client, whether by packet, DataWatcher, or World#setEntityState + YourEntity#handleHealthUpdate.

  15. Unless you added it yourself, there isn't any such thing as 'RegisterHelper' - there is a GameRegistry class which is the one most modders use to register their items and blocks.

     

    You shouldn't be inline instantiating your items, either - I suggest you find a tutorial author that knows what they are doing. Items and blocks need to be declared, and then instantiated during the FMLPreInitializationEvent.

     

    Inline instantiation looks like this:

    public static Item whatever; // that's a declaration
    public static Item whatever = new Item(); // that's inline instantiation
    

     

    As for your second error, my guess is that ItemEXTS does not extend Item, and thus has no method for setUnlocalizedName.

×
×
  • Create New...

Important Information

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