How to Modify Repair Durability with Anvil Repair & AOE Mining to items?

  • The FTB Forum is now read-only, and is here as an archive. To participate in our community discussions, please join our Discord! https://ftb.team/discord

ReignOfMagic

New Member
Jul 29, 2019
55
0
0
Repair Question.

So I'm using this method to repair my items

Code:
@Override
    public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack)
    {
    return par2ItemStack.isItemEqual(new ItemStack(ModItems.gemPutty)) || super.getIsRepairable(par1ItemStack, par2ItemStack);
    }
This works perfectly, I just wish to change the percentage repaired to 100% for a set level cost of 20. Is this possible? If not, no worries it is fine as is.

AOE tool question:
How does one implement this? I know it has something to do with onBlockBreak or onBlockDestroy then getting the xyz of the player and the face of the block, but everything I've found on it doesn't work for me. Any suggestions?


Link to Github
https://github.com/Reignofmagic/GTFO
 

Hlaaftana

New Member
Jul 29, 2019
304
0
0
Tinker's Construct AOE code

(not answer to first question) To give a repair item to your tools, all you have to do is put .setRepairItem(ItemStack) after your declared ToolMaterial.
Example:
Code:
    public static ToolMaterial FOO = addToolMaterial("Bar", 0, 0, 0, 0, 0).setRepairItem(new ItemStack(Items.snowball));
 

ljfa

New Member
Jul 29, 2019
2,761
-46
0
I think there is some kind of anvil event which you can use to add your own recipes for the anvil, so you can set the amount and cost however you like.
 

ReignOfMagic

New Member
Jul 29, 2019
55
0
0
Ok, is that any different from the code that I have in the item files themselves, aside from being in a unified location as opposed to spread across the 6 different files Hlaaftana? Because from what I can understand it is just adding the ability to repair to the tool/armor material line rather than the tool/armor file themselves.

Also by not answering the first question I assume you mean the set repair % and cost to do so correct? I am going to assume that is not easy unless I add my own workbench similar to tinker's does and use that over an anvil, which is a bit beyond the scope of what I want to do. The Gem Putty works well enough.

As for the aoe code, I have tried that in pieces before, and copying the entire file, plus the associated files with it (harvest Tool and ability helper) neither seemed to work as there was red everywhere. I just tried adding all the relevant parts to a single file and there is still red in quite a few areas. I think I'm just missing something here as to the how to implement it.

Sorry for being slow on the uptake on this.


As for the AnvilRepairEvent, I don't see how I can modifiy it to suit what I'm aiming to do as this is the entire event

Code:
package net.minecraftforge.event.entity.player;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;

public class AnvilRepairEvent extends PlayerEvent
{
    /**
     * Fired when the player removes a "repaired" item from the Anvil's Output slot.
     *
     * breakChance specifies as a percentage the chance that the anvil will be "damaged" when used.
     *
     * ItemStacks are the inputs/output from the anvil. They cannot be edited.
     */
   
    public final ItemStack left; // The left side of the input
    public final ItemStack right; // The right side of the input
    public final ItemStack output; // Set this to set the output stack
    public float breakChance; // Anvil's chance to break (reduced by 1 durability) when this is complete. Default is 12% (0.12f)

    public AnvilRepairEvent(EntityPlayer player, ItemStack output, ItemStack left, ItemStack right)
    {
        super(player);
        this.output = output;
        this.left = left;
        this.right = right;
        this.breakChance = 0.12f;
    }
}
 

ljfa

New Member
Jul 29, 2019
2,761
-46
0
As for the aoe code, I have tried that in pieces before, and copying the entire file, plus the associated files with it (harvest Tool and ability helper) neither seemed to work as there was red everywhere. I just tried adding all the relevant parts to a single file and there is still red in quite a few areas. I think I'm just missing something here as to the how to implement it.
Hum, I don't know either. Did you add all the needed imports?

As for the AnvilRepairEvent, I don't see how I can modifiy it to suit what I'm aiming to do as this is the entire event
I think what you need is the AnvilUpdateEvent.
 

Hlaaftana

New Member
Jul 29, 2019
304
0
0
Ok, is that any different from the code that I have in the item files themselves, aside from being in a unified location as opposed to spread across the 6 different files Hlaaftana? Because from what I can understand it is just adding the ability to repair to the tool/armor material line rather than the tool/armor file themselves.

Also by not answering the first question I assume you mean the set repair % and cost to do so correct? I am going to assume that is not easy unless I add my own workbench similar to tinker's does and use that over an anvil, which is a bit beyond the scope of what I want to do. The Gem Putty works well enough.

As for the aoe code, I have tried that in pieces before, and copying the entire file, plus the associated files with it (harvest Tool and ability helper) neither seemed to work as there was red everywhere. I just tried adding all the relevant parts to a single file and there is still red in quite a few areas. I think I'm just missing something here as to the how to implement it.
No, it's adding an item to the tool to repair with. It doesn't give it a custom anvil recipe, just simply gives it a repair item, that's what I meant by not answering the first question.

I don't really mean for you to copy and paste the code I posted and expect it to work, I just wanted you to check it out. You only need one method from AbilityHelper, you don't need to extend HarvestTool. If you want a class for AOE pickaxes, you'd need it to extend ItemPickaxe.
 

ReignOfMagic

New Member
Jul 29, 2019
55
0
0
Hum, I don't know either. Did you add all the needed imports?
I think what you need is the AnvilUpdateEvent.

Here is the code that I added to my Hoe file, it seems to ignore all the anvil things that I changed, although the repair part still work as it does in vanilla. I haven't pushed this to github because it isn't working, so see the spoiler below.

Code:
    @Override
    public boolean getIsRepairable(ItemStack par1ItemStack, ItemStack par2ItemStack)
    {
    return par2ItemStack.isItemEqual(new ItemStack(ModItems.gemPutty)) || super.getIsRepairable(par1ItemStack, par2ItemStack);
    }
    @EventHandler
    public void init(AnvilUpdateEvent event)
    {
        class AnvilUpdateEvent extends Event
        {
           public final ItemStack left;  // The left side of the input
           public final ItemStack right; // The right side of the input
           public final String name;     // The name to set the item, if the user specified one.
           public ItemStack output;      // Set this to set the output stack
           public int cost;              // The base cost, set this to change it if output != null
           public int materialCost; // The number of items from the right slot to be consumed during the repair. Leave as 0 to consume the entire stack.

           public AnvilUpdateEvent(ItemStack left, ItemStack right, String name, int cost)
           {
               this.left = left;
               this.right = right;
               this.name = name;
               this.cost = 10;
               this.materialCost = 1;
           }
    }
}

No, it's adding an item to the tool to repair with. It doesn't give it a custom anvil recipe, just simply gives it a repair item, that's what I meant by not answering the first question.

I don't really mean for you to copy and paste the code I posted and expect it to work, I just wanted you to check it out. You only need one method from AbilityHelper, you don't need to extend HarvestTool. If you want a class for AOE pickaxes, you'd need it to extend ItemPickaxe.

For the repair adding to the tool material. I added it in the ModItems, for both topaz and malachite, changing the Item.snowball to ModItems.gemPutty, and it did not recognize it for repair in the anvil either with the gem, or with the putty (tested both just to make sure). So for the time being each repair function is in the specific tool type file with the Override from my initial post


Hmm.. Maybe you can take a look at the code and see what I'm doing wrong. Note there are a few errors/changes made.

Lines 21: int baseDamage ---- ToolMaterial material
Line 22: Super(baseDamage) ---- super(material)
--- To make the AOE Harvest class into an item since it is extending ItemPickaxe I would assume. This removed the error

Line 62: MovingObjectPosition mop = raytraceFromEntity(player.worldObj, player, false, 4.5d);
---- Error, unreachable code.
---- I tried to consolidate the one area from ability helper to this file as well, this says it didn't work. This is the only error that persists.


A few other errors I was able to fix via importing the correct thing, or changing to match my mod. Examples include importing world, vec3, mathhelper, forgehooks.

Let me know if you would prefer me to push it to github in an alternate branch rather than viewing the code here. I shall do so.

Code:
package com.reignofmagic.gems.init;

import com.reignofmagic.gems.items.ItemToolTest;

import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;

import net.minecraftforge.common.ForgeHooks;

public abstract class AOEHarvest extends ItemPickaxe {
    public int breakRadius;
    public int breakDepth;

    public AOEHarvest(ToolMaterial material, int breakRadius, int breakDepth) {
        super(material);

        this.breakRadius = breakRadius;
        this.breakDepth = breakDepth;
    }

    public static MovingObjectPosition raytraceFromEntity (World world, Entity player, boolean par3, double range)
    {
        float f = 1.0F;
        float f1 = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * f;
        float f2 = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * f;
        double d0 = player.prevPosX + (player.posX - player.prevPosX) * (double) f;
        double d1 = player.prevPosY + (player.posY - player.prevPosY) * (double) f;
        if (!world.isRemote && player instanceof EntityPlayer)
            d1 += 1.62D;
        double d2 = player.prevPosZ + (player.posZ - player.prevPosZ) * (double) f;
        Vec3 vec3 = Vec3.createVectorHelper(d0, d1, d2);
        float f3 = MathHelper.cos(-f2 * 0.017453292F - (float) Math.PI);
        float f4 = MathHelper.sin(-f2 * 0.017453292F - (float) Math.PI);
        float f5 = -MathHelper.cos(-f1 * 0.017453292F);
        float f6 = MathHelper.sin(-f1 * 0.017453292F);
        float f7 = f4 * f5;
        float f8 = f3 * f5;
        double d3 = range;
        if (player instanceof EntityPlayerMP)
        {
            d3 = ((EntityPlayerMP) player).theItemInWorldManager.getBlockReachDistance();
        }
        Vec3 vec31 = vec3.addVector((double) f7 * d3, (double) f6 * d3, (double) f8 * d3);
        return world.func_147447_a(vec3, vec31, par3, !par3, par3);
    }

    public boolean onBlockStartBreak(ItemStack stack, int x, int y, int z, EntityPlayer player) {
        // only effective materials matter. We don't want to aoe when beraking dirt with a hammer.
        net.minecraft.block.Block block = player.worldObj.getBlock(x,y,z);
        int meta = player.worldObj.getBlockMetadata(x,y,z);
    
            return super.onBlockStartBreak(stack, x,y,z, player);

        MovingObjectPosition mop = raytraceFromEntity(player.worldObj, player, false, 4.5d);
        if(mop == null)
            return super.onBlockStartBreak(stack, x,y,z, player);
        int sideHit = mop.sideHit;
        //int sideHit = Minecraft.getMinecraft().objectMouseOver.sideHit;

        // we successfully destroyed a block. time to do AOE!
        int xRange = breakRadius;
        int yRange = breakRadius;
        int zRange = breakDepth;
        switch (sideHit) {
            case 0:
            case 1:
                yRange = breakDepth;
                zRange = breakRadius;
                break;
            case 2:
            case 3:
                xRange = breakRadius;
                zRange = breakDepth;
                break;
            case 4:
            case 5:
                xRange = breakDepth;
                zRange = breakRadius;
                break;
        }

        for (int xPos = x - xRange; xPos <= x + xRange; xPos++)
            for (int yPos = y - yRange; yPos <= y + yRange; yPos++)
                for (int zPos = z - zRange; zPos <= z + zRange; zPos++) {
                    // don't break the originally already broken block, duh
                    if (xPos == x && yPos == y && zPos == z)
                        continue;

                    if(!super.onBlockStartBreak(stack, xPos, yPos, zPos, player))
                        breakExtraBlock(player.worldObj, xPos, yPos, zPos, sideHit, player, x,y,z);
                }


        return super.onBlockStartBreak(stack, x, y, z, player);
    }
    protected void breakExtraBlock(World world, int x, int y, int z, int sidehit, EntityPlayer playerEntity, int refX, int refY, int refZ) {
        // prevent calling that stuff for air blocks, could lead to unexpected behaviour since it fires events
        if (world.isAirBlock(x, y, z))
            return;

        // what?
        if(!(playerEntity instanceof EntityPlayerMP))
            return;
        EntityPlayerMP player = (EntityPlayerMP) playerEntity;

        // check if the block can be broken, since extra block breaks shouldn't instantly break stuff like obsidian
        // or precious ores you can't harvest while mining stone
        net.minecraft.block.Block block = world.getBlock(x, y, z);
        int meta = world.getBlockMetadata(x, y, z);

        // only effective materials


        Block refBlock = world.getBlock(refX, refY, refZ);
        float refStrength = ForgeHooks.blockStrength(refBlock, player, world, refX, refY, refZ);
        float strength = ForgeHooks.blockStrength(block, player, world, x,y,z);
}

}
 

ljfa

New Member
Jul 29, 2019
2,761
-46
0
Here is the code that I added to my Hoe file, it seems to ignore all the anvil things that I changed, although the repair part still work as it does in vanilla. I haven't pushed this to github because it isn't working, so see the spoiler below.
No, that's pretty much completely wrong. First of all, why are you defining a local class there ("class AnvilUpdateEvent extends Event") ? AnvilUpdateEvent is a class that is already defined by Forge. You have an event handler function that takes a AnvilUpdateEvent object and modifies it.
Secondly, it's probably not a good idea to put your event handler function into the hoe item class. Create a new class and put the event handler in there. Also, Forge event handlers must be annotated with "@SubscribeEvent" and not "@EventHandler" (except for the initialization functions in your main mod class).
Also, the name of event handlers doesn't matter. "init" is probably not a good choice here. You might want to call it "onAnvilUpdate" or something like that.
And lastly, when you have the class with your event handler, you need to register it to an event bus during mod initialization. Unfortunately there are besically two different event buses, some events get fired on the one and some on the other. You have to look into the event's documentation for that.

Example: This could be your class with the handler:
Code:
public class AnvilHandler {
    @SubscribeEvent
    public void onAnvilUpdate(AnvilUpdateEvent event) {
        if(event.left.getItem() == ... && event.right.getItem() == ...)
            event.output = ...
    }
}
One thing to note here is that it's not your item that will recieve the AnvilUpdateEvent. The AnvilUpdateEvent will be fired whenever anything gets placed in the anvil, so you have to check if the input items actually are what you're looking for. That's why I said you should probably create a new class for this. If you really wanted to, you could take your item object and register it to an event bus. Might be a bit strange though.
To register the event handler, you need this:
Code:
MinecraftForge.EVENT_BUS.register(new AnvilHandler());
Make sure this code gets called when your mod gets initialized. For instance, you could put it into the "init" function in your main mod class.
Now I said there are two event buses. The other one is used like this:
Code:
FMLCommonHandler.instance().bus().register(...);
(Also, you can have more than one event handler in one class. If you do this, you might have to register your object to both event buses, if you use events from both of them. It's probably a good idea to put related handlers into one class.)

---- Error, unreachable code.
Well, you have a return statement right there:
Code:
return super.onBlockStartBreak(stack, x,y,z, player);
Obviously, code after this can never be executed. If you look at the original TiC code, there is an if-statement before this that you didn't copy over.

By the way, I don't know which IDE you use, but it probably has a key shortcut for automatically adding all needed imports (and removing unneeded ones). In Eclipse, it's Ctrl+Shift+O.
 

Hlaaftana

New Member
Jul 29, 2019
304
0
0
Even though @ljfa answered your question, I recommend crediting the TiC team for the code. While I don't think it's legally required, I suggest it for ethicality.
 

ReignOfMagic

New Member
Jul 29, 2019
55
0
0
Even though @ljfa answered your question, I recommend crediting the TiC team for the code. While I don't think it's legally required, I suggest it for ethicality.
Of course. I put everyone in the MCMod.Info file that I get some code from, and I'll start adding comments to my files themselves + my forum post. I had no intention of not doing it, but thanks for the reminder non-the less.

As for the AOE Mining code, I'll take another crack at it this evening when I have some time.
 

ReignOfMagic

New Member
Jul 29, 2019
55
0
0
Thank you to all of you! I got the repair code working (side effect is that this affects all items, not just my mod. I'm ok with that although as I always thought Vanilla repairs were too expensive level wise)
https://github.com/Reignofmagic/GTF...com/reignofmagic/gems/init/onAnvilUpdate.java


I also implemented the AOEHarvest code, although it doesn't seem to be functioning. I probably did something basic wrong.
Test Tool (The 5, 5 after the tool material is what I assume is break width and depth. If removed I get an error code to add arguments to match this : super(material, breakDepth, breakDepth); )

Tool: https://github.com/Reignofmagic/GTF...com/reignofmagic/gems/items/ItemToolTest.java
Harvest: https://github.com/Reignofmagic/GTF...va/com/reignofmagic/gems/init/AOEHarvest.java
 

Hlaaftana

New Member
Jul 29, 2019
304
0
0
The second #setHarvestTool method in ItemToolTest won't work. In fact, since a tool class named "Shovel" doesn't exist, I'm pretty sure it made the tool useless.
 

ReignOfMagic

New Member
Jul 29, 2019
55
0
0
The second #setHarvestTool method in ItemToolTest won't work. In fact, since a tool class named "Shovel" doesn't exist, I'm pretty sure it made the tool useless.


Well I commented all that out and no change from before (aside from the shovel portion no longer working). Also the that line, in addition to the overrides allow it to be both a pickaxe and a shovel. It is the code I use for my dual tools as well. All I know is that it works.