Details

Last Updated
4 weeks ago
First Uploaded
4 weeks ago
Downloads
19K
Likes
1
Size
91KB
Dependency string
GTFOModding-InjectLib-1.1.0
Dependants

Categories

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);
        }
    }
}
Thunderstore development is made possible with ads. Please consider making an exception to your adblock.
Thunderstore development is made possible with ads. Please consider making an exception to your adblock.
Thunderstore development is made possible with ads. Please consider making an exception to your adblock.