GTFOModding-InjectLib icon

InjectLib

Dauda wants to inject things

Last updated a year ago
Total downloads 13168
Total rating 1 
Categories Libraries
Dependency string GTFOModding-InjectLib-1.0.2
Dependants 51 other packages depend on this package

This mod requires the following mods to function

BepInEx-BepInExPack_GTFO-3.2.1 icon
BepInEx-BepInExPack_GTFO

BepInEx pack for GTFO. Preconfigured and includes Unity Base DLLs.

Preferred version: 3.2.1

README

Features

  • Inject Custom Fields to Il2Cpp type
  • Inject Custom Json fields to Il2Cpp type

Referencing to your plugin

[BepInDependency("GTFO.InjectLib", BepInDependency.DependencyFlags.HardDependency)]
<BIECacheFolder>$(GameFolder)\BepInEx\cache</BIECacheFolder>

<!--
  This is "SAFE" il2cpp Newtonsoft.json.dll reference generated by patcher!
  You should start game at least once to get it generated!
-->
<Reference Include="$(BIECacheFolder)\Il2CppJsonNet.dll" Private="false" /> 

Inject Fields

  • Feature to extends il2cpp domain types and inject your own data to it!
//Defining Field is reqired in order to set/get data
FieldInjector<Il2CppType>.DefineValueField<UnmanagedType>(string fieldName);
FieldInjector<Il2CppType>.DefineManagedField<ManagedType>(string fieldName);

//Set data
bool FieldInjector<Il2CppType>.TrySetValueField<UnmanagedType>(Il2CppType obj, string fieldName, UnmanagedType value);
bool FieldInjector<Il2CppType>.TrySetManagedField<ManagedType>(Il2CppType obj, string fieldName, ManagedType value);

//Load Saved data
bool FieldInjector<Il2CppType>.TryGetValueField<UnmanagedType>(Il2CppType obj, string fieldName, out UnmanagedType value);
bool FieldInjector<Il2CppType>.TryGetManagedField<ManagedType>(Il2CppType obj, string fieldName, out ManagedType value);

Inject Custom Jsons to existing il2cpp type (base game json)

//SetConverter alter the whole json parse behaviour
//Useful if you want to fully alter the content of json
JsonInjector.SetConverter<Il2CppType>(Il2CppJsonReferenceTypeConverter<T> converter);
JsonInjector.SetConverter<UnmanagedIl2CppType>(Il2CppJsonUnmanagedTypeConverter<T> converter); //Type must be defined on il2cpp domain!!!

//AddHandler is similar to Harmony Postfix without out ref __result param
//You only can get JToken of parsed json and result object
//So you could inject your own field using FieldInjector
JsonInjector.AddHandler<Il2CppType>(Il2CppJsonReferenceTypeHandler<T> handler);
JsonInjector.AddHandler<UnmanagedIl2CppType>(Il2CppJsonUnmanagedTypeHandler<T> handler);
public abstract class Il2CppJsonReferenceTypeConverter<T> : INativeJsonConverter where T : Il2CppObjectBase
{
    protected abstract T Read(JToken jToken, T existingValue, JsonSerializer serializer);
    protected abstract void Write(JsonWriter writer, T value, JsonSerializer serializer);
}

public abstract class Il2CppJsonUnmanagedTypeConverter<T> : INativeJsonConverter where T : unmanaged
{
    protected abstract T Read(JToken jToken, T existingValue, JsonSerializer serializer);
    protected abstract void Write(JsonWriter writer, T value, JsonSerializer serializer);
    protected abstract Il2CppSystem.Object ToIl2CppObject(T value);
}

public abstract class Il2CppJsonReferenceTypeHandler<T> : INativeJsonHandler where T : Il2CppObjectBase
{
    public abstract void OnRead(in Il2CppSystem.Object result, in JToken jToken);
}

public abstract class Il2CppJsonUnmanagedTypeHandler<T> : INativeJsonHandler where T : unmanaged
{
    public abstract void OnRead(in Il2CppSystem.Object result, in JToken jToken);
}

Bare example of Json Injection

JsonInjector.SetConverter(new EventTypeConverter());
JsonInjector.AddHandler(new EventDataHandler());
//This converter alter the behaviour of reading/writing eWardenObjectiveEventType enum
//So you could Parse extended enum types!
internal class EventTypeConverter : Il2CppJsonUnmanagedTypeConverter<eWardenObjectiveEventType>
{
    protected override eWardenObjectiveEventType Read(JToken jToken, eWardenObjectiveEventType existingValue, JsonSerializer serializer)
    {
        int value = 0;
        switch(jToken.Type)
        {
            case JTokenType.Integer:
                value = (int)jToken;
                break;

            case JTokenType.String:
                var str = (string)jToken;
                if (Enum.TryParse<WEE_Type>(str, ignoreCase: true, out var weeResult))
                {
                    value = (int)weeResult;
                    break;
                }
                else if (Enum.TryParse<eWardenObjectiveEventType>(str, ignoreCase: true, out var woResult))
                {
                    value = (int)woResult;
                    break;
                }
                return eWardenObjectiveEventType.None;

            default:
                return eWardenObjectiveEventType.None;
        }

        return (eWardenObjectiveEventType)value;
    }

    protected override void Write(JsonWriter writer, eWardenObjectiveEventType value, JsonSerializer serializer)
    {
        writer.WriteValue((int)value);
    }

    protected override Il2CppSystem.Object ToIl2CppObject(eWardenObjectiveEventType value)
    {
        return new Il2CppSystem.Int32() { m_value = (int)value }.BoxIl2CppObject();
    }
}
//This one reads Custom Fields from WardenObjectiveEventData type!
internal class EventDataHandler : Il2CppJsonReferenceTypeHandler<WardenObjectiveEventData>
{
    private readonly static JsonSerializerOptions _JsonOption;
    static EventDataHandler()
    {
        _JsonOption = new JsonSerializerOptions(JSON.DefaultSerializerSettings);
        _JsonOption.Converters.Add(new LocalizedTextConverter());
    }

    public override void OnRead(in Il2CppSystem.Object result, in JToken jToken)
    {
        var data = result.Cast<WardenObjectiveEventData>();
        if (Enum.IsDefined((WEE_Type)data.Type))
        {
            var extData = JSON.Deserialize<WEE_EventData>(jToken.ToString(), _JsonOption);
            data.SetWEEData(extData);
        }
    }
}