CraftTweaker

CraftTweaker

151M Downloads

[1.12.2] Problem casting java.util.List to array

TCreopargh opened this issue ยท 6 comments

commented

Intro:

Issue Description:

It seems like java.util.List isn't properly casted to array in CraftTweaker when assigning a List to an array. Trying to iterate over this array will produce "Bad type on operand stack in array length" exception.

What happens:

For example, the getter IEntityLiving#activePotionEffects return a List instead of an array in the java source code.
This piece of code is perfectly ok:

var effects = player.activePotionEffects;
for effect in effects {
     player.sendChat(effect.potion.name + " Duration: " + effect.duration);
}

This works either:

var effects as IPotionEffect[] = player.activePotionEffects as IPotionEffect[];
for effect in effects {
      player.sendChat(effect.potion.name + " Duration: " + effect.duration);
}

However, this doesn't work and will produce an error when trying to iterate over it:
(Note: /ct syntax can't find this error)

var effects as IPotionEffect[] = player.activePotionEffects;
for effect in effects {
    player.sendChat(effect.potion.name + " Duration: " + effect.duration);
}

What you expected to happen:

The 3rd piece of code should also work, as assigning a List to an array in ZenScript should be allowed and produce no problem.

Script used:

This is the entire script used for testing, although all other parts of the code has nothing to do with the problem. The errored code is already presented as code blocks above.
https://paste.ubuntu.com/p/FmX467XYQH/

crafttweaker.log file:

This is the log with the error information on the 3rd piece of code.
https://paste.ubuntu.com/p/jWwkns8nq6/


Environment:

  • Minecraft Version:
  • Forge Version: 14.23.5.2854
  • CraftTweaker Version: CraftTweaker2-1.12-4.1.20.617
  • Are you using a server: no
  • If yes, does the client have the exact same scripts?

Game log:

https://paste.ubuntu.com/p/dXqVfQTPvn/

commented

Always put your as type on the righthandside of the =. Putting it solely on the Lefthandside will cause the assignment to be unchecked.

commented

in what scenarios should the cast be unchecked

commented

In scenarios where you already checked the type.
For example when in combination with an instanceof.

Think of something like

/*Imports left out*/

events.onEntityLivingDeath(function(event as EntityLivingDeathEvent) {
    var trueSource = event.damageSource.trueSource;

    if(trueSource instanceof IPlayer) {
        var player as IPlayer = trueSource;
        player.addGameStage("killer");
        player.removeGameStage("pacifist");
    }
});
commented

@TCreopargh is this resolved?

commented

@TCreopargh is this resolved?

The 3rd piece of code still doesn't work in the latest version, but if you mean this is intended I can close it now

commented

Closing this then.

As a general rule of thumb, if you are declaring and initializing variables in one step, always put the as type at least on the RightHandSide of the =. As you have already seen you can also put it on both sides if you want to be sure, but the RHS usually should be enough. Using the cast on the LHS only is unchecked in that case, so only use it when you absolutely have to.

To sum up:

//Ok.
var variable_1 = <expression> as type; 
var variable_2 as type = <expression> as type; 

//Mostly okay.
//May get confused when your <expression> is a new array expression, or a few other times where inference doesn't work properly.
var variable_3 = <expression>;

//Don't use unless necessary and you know what you're doing! 
//ZS will assume that <expression> is of the given type and will not perform any checks or conversions!
 var variable_4 as type = <expression>;