OldUnreal / UnrealTournamentPatches

Other
939 stars 27 forks source link

[469d] ScriptRays not able decompile method chaining #1570

Open SeriousBuggie opened 2 months ago

SeriousBuggie commented 2 months ago

Reproduce:

  1. Try decompile next code:
    
    class MyActor expands Actor;

function Tmp() { Target = Spawn(class'MyActor', self).Test(); }

function MyActor Test() { return self; }


Expected result: Whole class decompiled.
Actual result: in log appear `Warning: Failed to digest Function MyLevel.MyActor.Tmp`
And code not decompiled:
```unrealscript
//=============================================================================
// MyActor. Rebuild with ScriptRays.
//=============================================================================
class MyActor extends Actor;

//-----------------------------------------------------------------------------
// Global Functions.
//-----------------------------------------------------------------------------

function Tmp()
{
    //
    // 0x0000: EX_Let
    // 0x0001:   EX_InstanceVariable (Property=Engine.Actor.Target)
    // 0x0006:   EX_Context (SkipSize=0x0006,MemSize=0x04)
    // 0x0007:     EX_Native (iNative=278,Function=Engine.Actor.Spawn,OperatorType=0)
    // 0x0009:       EX_ObjectConst (ObjectConst=Class MyLevel.MyActor)
    // 0x000E:       EX_Self
    //

    #error nada
}

function MyActor Test()
{
    return Self;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

defaultproperties
{
}

If there no assign value, but few methods calls it failed too:

function Tmp() {
    Spawn(class'MyActor', self).Test().Test().Test().Test().Test().Test();
}
function Tmp()
{
    //
    // 0x0000: EX_Context
    // 0x0001:   EX_Context
    // 0x0002:     EX_Context
    // 0x0003:       EX_Context
    // 0x0004:         EX_Context
    // 0x0005:           EX_Context (SkipSize=0x0006,MemSize=0x04)
    // 0x0006:             EX_Native (iNative=278,Function=Engine.Actor.Spawn,OperatorType=0)
    // 0x0008:               EX_ObjectConst (ObjectConst=Class MyLevel.MyActor)
    // 0x000D:               EX_Self
    //

    #error nada
}
SeriousBuggie commented 2 months ago

Better test case:

class MyActor expands Actor;

function Tmp() {
    Target = Spawn(class'MyActor', self);
    Spawn(class'MyActor', self).Test();
    Target = Spawn(class'MyActor', self).Test().Test().Test();
    Spawn(class'MyActor', self).Target = None;
    Spawn(class'MyActor', self).Target = Spawn(class'MyActor', self);
    Spawn(class'MyActor', self).Target = Spawn(class'MyActor', self).Test().Test().Test();
    DrawScale = 42;
}

function MyActor Test() {
    return self;
}

img

SeriousBuggie commented 2 months ago

Caused by special case - function Spawn:

//
// Spawn an actor. Returns an actor of the specified class, not
// of class Actor (this is hardcoded in the compiler). Returns None
// if the actor could not be spawned (either the actor wouldn't fit in
// the specified location, or the actor list is full).
// Defaults to spawning at the spawner's location.
//
native(278) final function actor Spawn
(
    class<actor>      SpawnClass,