ItsDeltin / Overwatch-Script-To-Workshop

Converts scripts to Overwatch workshops.
207 stars 24 forks source link

Appending a class instances to an array doesn't work properly #485

Closed PatrickSzela closed 1 month ago

PatrickSzela commented 1 month ago

Somewhere between release v3.0.0 and current master build, appending a class instance to an array stopped working correctly.

Based on this example code:

globalvar String[] texts = [
  "Text 1",
  "Text 2",
  "Text 3",
  "Text 4",
  "Text 5"
];

class Test {
  public String text;

  public constructor(String text) {
    this.text = text;
    LogToInspector($"Created class: {text}");
  }
}

rule: 'My Rule'
{
  Test[] settingByIndex = [];
  Test[] appending = [];

  LogToInspector($"Creating {texts.Length} classes....");

  for(Number i = 0; i < texts.Length; i++) {
    settingByIndex[i] = new Test(texts[i]); // this works
    appending += new Test(texts[i]); // this doesn't
  }

  LogToInspector($"Amount of class instances added to array by specifying index manually: {settingByIndex.Length} (should be {texts.Length})");
  LogToInspector($"Amount of class instances added to array by appending: {appending.Length} (should be {texts.Length})");
}

After compiling and executing the code in game - even though 5 class instances per array are being created - for some reason appending array ends up containing only 2 elements, compared to 5 elements in settingByIndex

Output of the Workshop Inspector: image One day Blizzard is going to fix the Variables view, right? 😩

ItsDeltin commented 1 month ago

Thank you for letting me know about this. There are three workarounds to this:

  1. Replace appending += new Test(texts[i]) with appending.ModAppend(new Test(texts[i]))
  2. Add a file to the root of your project named ds.toml and add the line: new_class_register_optimization = false
  3. Temp variable before appending:
    Test item = new Test(texts[i]);
    appending += item;

This bug was introduced in a recent commit: 520c266. That commit introduced an optimization for this scenario:

// Rather than creating a new register for assigning to the heap, `a` is used instead since it is being overwritten anyway.
a = new Test();

This optimization incorrectly triggers with the += operator, which is a modification and not an overwrite.