CraftTweaker

CraftTweaker

151M Downloads

[1.12.2] more than 2 items/tools using IItemCondition | IItemTransformer not working properly

Xelbayria opened this issue ยท 9 comments

commented

Issue description

The Issue

myitem.transformDamage(8).onlyDamageAtMost(8) and mytool.reuse() in the same recipe of any.
I've run a few tests and got the Result. I also ran a simple test. Just use myitem.transformDamage(8).onlyDamageAtMost(8) without mytool.reuse(). The result is that transformDamage(8) and onlyDamageAtMost(8) are working correctly

Pick any wood recipe or metal recipe and add both mytool and myitem above. "mytool" can be any tools or a hammer while "myitem" can be a rod (think of it as a nail) to craft a wood product. myitem with 8 or less of damage won't work no matter what.

I also tried varying numbers from 2 to 8 in both transformDamage( integer ) and onlyDamageAtMost( integer ). Same result.

I tried to use mytool.reuse() and myitem.transformDamage(8) without onlyDamageAtMost(). It works correctly.

What happened?

NOTE: myitem is set to have maxDamage of 16
I want to craft a wood product by using myitem and mytool. I already inputted ingredients and the rest in the Crafting Table. The result is I got the wood product. mytool stayed in the Crafting Table for reuse. myitem got damage from 16 to 8.

now myitem has only 8 uses left to go after the crafting. I want to craft another same product by using the same mytool and myitem. I repeated the same action in Crafting Table but myitem of 8 uses is not valid, so no wood product shows up.

Expectation:

I expected that myitem with only 8 uses left is valid in the Crafting Table, so I can get the wood product. You may see my simple script.

I suspected that reuse() of one tool somehow caused myitem.transformDamage(8).onlyDamageAtMost(8) 's onlyDamageAtmost() to pretend like it don't exist (in other words, don't work at all).

Steps to reproduce

  1. Use my script and start your minecraft

  2. Get what you need in creative mode:

  • tfc:wood/support/acacia
  • tfc:wood/lumber/acacia
  • tfc:metal/rod/wrought_iron
  • any hammer
  1. Input them in the Crafting Table according to the recipe

  2. get the wood product from "output" and leave the hammer and the rod where it is currently at.
    Note: The rod should have shown its damage is now half (yellow colour)

  3. input the ingredient/items in the crafting table again.

  4. the wood product doesn't show up unlike before.

that's it.

Script used

https://gist.github.com/Xelbayria/d953b4de2c7d937a002c4f0cada68900

The crafttweaker.log file

https://pastebin.com/rEwqJeGC

Minecraft version

1.12

Modloader

Forge

Modloader version

14.23.5.2860

CraftTweaker version

4.1.20.680

Other relevant information

  • TerraFirmacraft 1.7.23.181
  • pyrotech 1.6.4
  • patchouli 23.6
  • optifine G5
  • mouseTweaks 3.1.2
  • loliasm 5.6
  • jei 4.16.1.301
  • foamfix 0.10.15
  • contenttweaker 4.10.0
  • born in a barn v1.8-1.12-1.1
  • base 3.14
  • attributeFix-1.0.4
  • athenaeum 1.19.5
  • !mixinbooter-5.0

Note: all of them are the latest version to date.

The latest.log file

https://hastebin.com/sabagewawu.swift

commented

Try adding meta wildcard (or .anyDamage()) in the item bracket handler?

val myitem = <tfc:metal/rod/wrought_iron:*>; // change here, or <tfc:metal/rod/wrought_iron>.anyDamage()
myitem.maxDamage = 16;
commented

Try adding meta wildcard (or .anyDamage()) in the item bracket handler?

val myitem = <tfc:metal/rod/wrought_iron:*>; // change here, or <tfc:metal/rod/wrought_iron>.anyDamage()
myitem.maxDamage = 16;

There is no wild card for <tfc:metal/rod/wrough_iron> and it has no maxDamage, just a rod as an item/ingredient for crafting.

and I have run tests by adding .anyDamage() to the val myitem ... as you suggested. here's the code:

val myitem = <tfc:metal/rod/wrought_iron:*>; 
myitem.maxDamage = 16;
myitem.anyDamage();  // it's because of .maxDamage setter has to be finished before .anyDamage can be called

and

val myitem = <tfc:metal/rod/wrought_iron:*>; 
myitem.maxDamage = 16;
myitem.onlyDamageAtMost(8);  // it's because of .maxDamage setter has to be finished before .anyDamage can be called

result: both .anyDamage() and .onlyDamageAtMost(8) have undamaged rod working normally but the half-damaged rod does not work as the output do not show up at all.

commented

Although there is no need to call maxDamage setter before anyDamage...

val myitem = <tfc:metal/rod/wrought_iron>;
myitem.maxDamage = 16;

recipes.addShaped(<tfc:wood/fence/acacia>, [
    [<tfc:wood/support/acacia>, <tfc:wood/lumber/acacia>, <tfc:wood/support/acacia>],
    [<ore:hammer>.reuse(), <tfc:wood/lumber/acacia>, myitem.anyDamage().onlyDamageAtMost(8).transformDamage(8)]
]);

Use both .anyDamage() and .onlyDamageAtMost(8), instead of just one of them. anyDamage() or :* metadata wildcard set metadata to 32767. So if you like, <tfc:metal/rod/wrought_iron:32767> will be nice, too. They stop the exact metadata matching. .onlyDamageAtMost(8) provides a relaxed metadata matching, but you should disable exact one first.

commented

Although there is no need to call maxDamage setter before anyDamage...

val myitem = <tfc:metal/rod/wrought_iron>;
myitem.maxDamage = 16;

recipes.addShaped(<tfc:wood/fence/acacia>, [
    [<tfc:wood/support/acacia>, <tfc:wood/lumber/acacia>, <tfc:wood/support/acacia>],
    [<ore:hammer>.reuse(), <tfc:wood/lumber/acacia>, myitem.anyDamage().onlyDamageAtMost(8).transformDamage(8)]
]);

Use both .anyDamage() and .onlyDamageAtMost(8), instead of just one of them. anyDamage() or :* metadata wildcard set metadata to 32767. So if you like, <tfc:metal/rod/wrought_iron:32767> will be nice, too. They stop the exact metadata matching. .onlyDamageAtMost(8) provides a relaxed metadata matching, but you should disable exact one first.

ah, I forgot to try that (my idea I just came up with). Brb. I'll run a test using both .anyDamage() and .onlyDamageAtMost()

commented

Alright, I ran test where I increase the damage on myitem by one. until I reach 9 or 10. It still works (shouldn't be used to craft the product when it has that much damage)

i've used this myitem.anyDamage().onlyDamageAtMost(8).transformDamage(1)

and I also tried wildcard on myitem, it makes no difference ๐Ÿค”


and a bit more additional information I forgot to mention:

I've not used reuse() only use myitem.onlyDamageAtMost(8).transformDamage(8). the result is correct and working properly. This is why I think either reuse() or other zenMethods for one tool along with 3 zenMethod for myitem would not work properly.

commented

Okay, so some things I'd recommend:

First, have you tried using a base item that already has damage properties (e.g. a wooden sword)?

Second, I recommend you define conditions first, then the transformers, like in your last example
In other words, do item.onlyDamaged().reuse() instead of item.reuse().onlyDamaged()
This should make matching easier, I don't quite remember how it was implemented back in 1.12, though.

Third, giveBack() and reuse() use two different concepts of transformers.
In the code they are called IItemTransformer and IItemTransformerNew.
I advise against using IItemTransformer (which giveBack) uses, and instead recommend using the new one (which reuse uses).
Reason for the distinction is that the old transformer has access to the player crafting the item, but will only work in certain scenarios (such as, a Player crafting in a crafting table; NOT when working with autocrafters etc).
The old Transformers are a remnant from MC 1.7, where the features used by the New Transformers did not yet exist in the MC code base.

I do not remember how well CrT handles it when ingredients with both kinds of transformers are present in a Recipe at the same time.

And lastly, if all hell breaks loose, you could try using a hand-written condition/transformer and see if they work:

var myCustomIngredient = myItem.only(
    function(item) { 
        return item.damage < 10; 
    }
  ).transformNew(
    function(item) { 
        return item; 
    }
  );

If you test with these you can always add print statements to specific places inside the function to write information to the log file. This way, you can check if a condition/transformer has been applied and with what item it was called. Maybe that helps you identify what went wrong.

commented

And lastly, if all hell breaks loose, you could try using a hand-written condition/transformer and see if they work:

var myCustomIngredient = myItem.only(
    function(item) { 
        return item.damage < 10; 
    }
  ).transformNew(
    function(item) { 
        return item; 
    }
  );

If you test with these you can always add print statements to specific places inside the function to write information to the log file. This way, you can check if a condition/transformer has been applied and with what item it was called. Maybe that helps you identify what went wrong.


var myCustomIngredient = myItem.only(
    function(item) { 
        return item.damage < 10; 
    }

Okay, so this one is to allow item with less than of 10 damages to be used in the crafting, correct?

and this one:
.transformNew( function(item) { return item; } );
what does it do? When i understand what is it for. I'll run tests.

EDIT:

ok i played around with the code above. now I understand how it works. I also included print(). weird why does it print like 10 times? CraftTweaker log

commented

Second, I recommend you define conditions first, then the transformers, like in your last example
In other words, do item.onlyDamaged().reuse() instead of item.reuse().onlyDamaged()
This should make matching easier, I don't quite remember how it was implemented back in 1.12, though.

Can you provide a bit more detail โ˜๏ธ.

commented

Ignore the box below:

ok here's the code: </s>
```zs
val myitem = <tfc:metal/rod/wrought_iron>.anyDamage() | <tfc:metal/rod/gold>.anyDamage() | <tfc:metal/rod/steel>.anyDamage(); 
myitem.maxDamage = 16;

var transformedRods = myitem.only(
        function(myitem) {
            var state = myitem.damage; 
            print("The current damage is: " + state);
            return state < 8; 
        }
    ).transformNew(
        function(myitem) {
            print("Returning the item"); 
            return myitem; 
        }
    );

recipes.addShaped(<tfc:wood/fence/acacia>, [
    [<tfc:wood/support/acacia>, <tfc:wood/lumber/acacia>, <tfc:wood/support/acacia>],
    [<ore:hammer>.reuse(), <tfc:wood/lumber/acacia>, transformedRod.transformDamage(1)]
]);
```

the result is it's working if i use this `myitem = <tfc:metal/rod/wrought_iron>.anyDamage()` instead of above.
However it partially doesn't work when there are multiple items in `myitem` as you can see. The reason is due to this `myitem.only()` is not working because it doesn't know which item to use and check for damage in the item. 

---------

>First, have you tried using a base item that already has damage properties (e.g. a wooden sword)?

yes, I just tried that and it works without any problem. I just swapped the role of myitem and mytool like this:
`myitem.reuse()` and `mytool.onlyDamageAtMost(25).transformDamage(10)`. the result is expected and working properly...

strange, my custom items are added through contentTweaker where they have the damage properties and yet they don't work at all. ๐Ÿค” 

EDIT:

The issue has been solved using

val myitem = [ <tfc:metal/rod/wrought_iron:*>, <tfc:metal/rod/gold:*>, <tfc:metal/rod/steel:*> ]; 
myitem.maxDamage = 16;

var currentRod as IIngredient = null;

for rod in myitem {   // getting the current rod used in the craftingTable
         if (isNull(currentContainer)) {
             currentRod = rod;
         }
         else {
             currentRod |= rod;
         }
     }
}

var transformedRods = myitem.only(   // conditioned item to be used in craftingTable with less than 8 damages 
        function(myitem) {
            var state = myitem.damage; 
            print("The current damage is: " + state);
            return state < 8; 
        }    
).transformNew(   
        function(myitem) {
            print("Returning the item"); 
            return myitem; 
        }
);

.onlyDamageAtMost and .onlyDamageAtLeast only works with tools but not custom items or custom tools that have damage properties added. Here and here are recommended and will explain the method used in the block.