Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding method overrides #8

Open
Zetrith opened this issue Jan 30, 2023 · 2 comments
Open

Adding method overrides #8

Zetrith opened this issue Jan 30, 2023 · 2 comments
Labels
api Related to Prepatcher API enhancement New feature or request

Comments

@Zetrith
Copy link
Owner

Zetrith commented Jan 30, 2023

Example

class A {
    public int Method() {
        return 0;
    }

    public virtual int VirtualMethod() {
        return 0;
    }
}

class B : A {
}

// Static override template methods (first parameter specifies the target)
[PrepatcherOverride]
public static int Method(B b){
    return 1;
}

[PrepatcherOverride]
public static int VirtualMethod(B b){
    return 1;
}

A a = new B();
a.Method(); // returns 1
a.VirtualMethod(); // returns 1

class C : A {
    // Instance override template method
    [PrepatcherOverride]
    public new int Method() {
        return 1;
    }
}

A a = new C();
a.Method(); // returns 1

Implementation

A static override template method is copied into the the target class becoming a new instance method within it.

  • If a method with the same signature already exists, the result is a failure.
  • (*) If there exists a virtual method in the inheritance hierarchy of the target which can be overriden by the new method the process is done.
  • If there's no such virtual method but there exists a method in the hierarchy with the correct signature to be overriden, the first such method going up from the target is marked virtual, all call IL instructions with it as an operand in all game and mod assemblies get turned into callvirt instructions and the process is done.
  • Else the process fails with an error.

For an instance override template method, the process is the same but (*) results in an error because it doesn't make sense to use Prepatcher there - you can just override as usual using the C# keyword (unless the method was turned virtual by Prepatcher).

Compatibility

Poses some incompatibility risk with transpilers because call instructions to methods made virtual need to be turned into callvirt instructions.

@Zetrith Zetrith added enhancement New feature or request api Related to Prepatcher API labels Jan 30, 2023
@Zetrith
Copy link
Owner Author

Zetrith commented Feb 24, 2023

A point I missed: there's potential for conflict in mods overwriting each other's overrides when multiple are requested on the same method.

Amendments:

  • [PrepatcherOverride] will just request the existence of a virtual method calling base.
  • Any further modifications will be done using Prepatcher's future Harmony-like general method patching. For example, you will need to prefix, transpile or postfix the new virtual method to make it do something you want.

@SokyranTheDragon
Copy link

I feel the example should (for extra clarity) show the methods for the class A being called along the classes B and C. For a moment, I got slightly confused by what PrepatcherOverride does - thinking it replaces the method in class A instead of adding the overrides in B and C.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Related to Prepatcher API enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants