Integrated Dynamics

Integrated Dynamics

63M Downloads

Client crash on materializing zero-arity operator (ArrayIndexOutOfBoundsException)

narwhalfire opened this issue ยท 7 comments

commented

Issue type:

  • ๐Ÿ› Bug

Short description:

I have a chain of operators and one of them in the chain ends up with a signature of -> Operator according to the materailizer. When I materialized a card based on this, the client crashed trying to render what I think was the tool tip.

Steps to reproduce the problem:

Construct variable cards based on the following Haskell code:

    type NBT = String
    type Item = String

-- implement integrated dynamics operators --
    pipe :: (a -> b) -> (b -> c) -> (a -> c)
    pipe = flip (.)
    pipe2 :: (a -> b) -> (a -> c) -> (b -> c -> d) -> (a -> d)
    pipe2 f g h = \x -> h (f x) (g x)
    apply :: (a -> b) -> a -> b
    apply f x = f x
    apply2 :: (a -> b -> c) -> a -> b -> c
    apply2 f x y = f x y
    apply3 :: (a -> b -> c -> d) -> a -> b -> c -> d
    apply3 f x y z = f x y z

-- materialized operators confirmed to work, implementation here not important --
    getBloodAltarAmount :: NBT -> Int
    getBloodAltarAmount _ = 0
    areItemsEmpty :: NBT -> Bool
    areItemsEmpty _ = True
    eqNoNBT :: Item -> Item -> Bool
    eqNoNBT _ _ = True

-- variable card chain --
    t1 = pipe getBloodAltarAmount (>)
    t2 = flip t1
    t3 = pipe t2 pipe2
    t4 = flip t3
    t5 = pipe t4 flip
    t6 = apply2 t5 areItemsEmpty (&&) -- materializes to -> Op
    t7 = pipe t6 pipe -- crash when rendering the tool tip of the materialized card
    t8 = flip t7
    t9 = apply t8 (&&)
    t10 = pipe eqNoNBT pipe
    t11 = flip t10
    t12 = pipe t9 flip
    t13 = flip t12
    t14 = apply t11 t13
    t15 = pipe t14 flip
    t16 = pipe t15 pipe
    t17 = flip t16
    t18 = apply t17 flip
    t19 = flip t18
    t20 = pipe t19 flip
    t21 = flip t20

Expected behaviour:

I was using the above code to help me combine operators to get from a few operators to one with a desired type signature.
Given:

getBloodAltarAmount :: NBT -> Int
areItemsEmpty :: NBT -> Bool
eqNoNBT :: Item -> Item -> Bool
&& :: Bool -> Bool -> Bool
> :: Int -> Int -> Bool

Target:

NBT -> Int -> Item -> Item -> Bool

Running in ghci:

> :t t21
t21 :: NBT -> Int -> Item -> Item -> Bool
> :t t6
t6 :: Int -> NBT -> Bool

Other notes:

I also tried just materializing t21 with the full chain unmaterialized and got an error presumably related to #352

I'm trying to get an operator with a signature of NBT -> Int -> Item -> Item -> Bool so I can have it materialized to just one variable card and apply the NBT of my altar, the blood amount I want, and the item I want to result in a predicate, Item -> Bool. The goal of the predicate is that it returns true if the given item matches an item in an item frame, the altar has greater than a specified amount of blood, and there are no items in it. I'm not really sure how to avoid the problem of #352 since half of this was trial and error with getting the right type siganture out of haskell.


Versions:

This mod:
1.12.2-1.0.11 (Dynamics),
1.12.2-1.6.8 (Tunnels)
Minecraft: 1.12.2
Forge: 14.23.5.2838
Pack: FTB:Interactions 1.9.1
Launcher: MultiMC 0.6.5-1302

Log file:

https://pastebin.com/nFkZdmSQ

commented

You seem to be running a couple of versions behind. Could you check if the issue still persists on the latest ID version?

commented

Just confirmed this to still persist in ID 1.12.2-1.0.16. Recreated the variable card chain up to t7 exactly.
https://pastebin.com/DvEjqEDQ

Pastebin
commented

Thanks for checking! Will look into this asap.

commented

I just tried reproducing this after the fix of #754, and everything seems to be working properly.

@narwhalfire Could you try out the latest dev build if that fix indeed resolves the problem on your end as well?

commented

The flip operator probably needs to perform a check to see if an arity-1 operator that it received returns another operator when applied. The flip operator should still be able to execute, in that case.

It might be a good idea to go through and find any other instances where an operator strictly depends on the actual/unexpanded arity of an operator that it receives as an argument. I can't think of any off the top of my head, though; there really aren't that many combinational operators.

Edit: Perhaps the third argument of pipe2? It's a little hard to follow how that operator is implemented in the source. I know that argument must be an operator of at least arity-2.

Edie: Nevermind, I see. Pipe.pipeVariablesToOperators is pulling double duty for both pipe and pipe2.

commented

Cool, yeah looks like that fixed the crash as t7 :: Int -> (Bool -> c) -> NBT -> c materializes to Number -> Operator -> Operator.

Unfortunately t8 :: (Bool -> c) -> Int -> NBT -> c materializes to Any -> Any which may or may not be related to an error with t13 down the line.

t13 errors with The operator Flip received the operator Piped Operator with input length 1 while length 2 is required. while t12 should be Int -> Bool -> NBT -> Bool but materializes to Any -> Any as well. But I think that's an entirely different issue.

commented

Great! I'm closing this issue then.

@narwhalfire Could you open up a new issue for the flip problem you are experiencing (if possible, with a more minimal example)?