public static IEnumerable <CodeInstruction> TestTranspiler(IEnumerable <CodeInstruction> instructions) { savedInstructions = new CodeInstruction[instructions.Count()]; instructions.ToList().CopyTo(savedInstructions); foreach (var instruction in instructions) { if (instruction.opcode == insertLoc) { var blocks = instruction.blocks; instruction.blocks = new List <ExceptionBlock>(); var log = AccessTools.DeclaredField(typeof(Class3), "log"); var tst = typeof(string); var concat = AccessTools.Method(typeof(string), nameof(string.Concat), new Type[] { tst, tst }); yield return(new CodeInstruction(OpCodes.Ldarg_0) { blocks = blocks }); yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Ldfld, log)); yield return(new CodeInstruction(OpCodes.Ldstr, ",patch")); yield return(new CodeInstruction(OpCodes.Call, concat)); yield return(new CodeInstruction(OpCodes.Stfld, log)); } yield return(instruction); } }
// code from: https://github.com/Strdate/SmartIntersections/blob/master/SmartIntersections/Patch/LoadPathsPatch.cs public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var fTempNodeBuffer = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempNodeBuffer)) ?? throw new Exception("cound not find NetManager.m_tempNodeBuffer"); var mClear = AccessTools.DeclaredMethod(fTempNodeBuffer.FieldType, nameof(FastList <ushort> .Clear)) ?? throw new Exception("cound not find m_tempNodeBuffer.Clear"); var mAfterIntersectionBuilt = AccessTools.DeclaredMethod( typeof(LoadPathsPatch), nameof(AfterIntersectionBuilt)) ?? throw new Exception("cound not find AfterIntersectionBuilt()"); List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions); bool comp(int i) => codes[i].opcode == OpCodes.Ldfld && codes[i].operand == fTempNodeBuffer && codes[i + 1].opcode == OpCodes.Callvirt && codes[i + 1].operand == mClear; int index = TranspilerUtil.SearchGeneric(codes, comp, index: 0, counter: 2); index -= 1; // index to insert instructions. var newInstructions = new[] { new CodeInstruction(OpCodes.Ldarg_0), // load argument info new CodeInstruction(OpCodes.Call, mAfterIntersectionBuilt), }; TranspilerUtil.InsertInstructions(codes, newInstructions, index); return(codes); }
public static IEnumerable <CodeInstruction> Transpiler(ILGenerator il, IEnumerable <CodeInstruction> instructions) { var fTempSegmentBuffer = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempSegmentBuffer)) ?? throw new Exception("Could not find NetManager.m_tempSegmentBuffer"); var mSize = AccessTools.DeclaredField(fTempSegmentBuffer.FieldType, nameof(FastList <ushort> .m_size)) ?? throw new Exception("Could not find m_tempSegmentBuffer.m_size"); var mAfterIntersectionBuilt = AccessTools.DeclaredMethod( typeof(LoadPathsPatch), nameof(AfterIntersectionBuilt)) ?? throw new Exception("Could not find AfterIntersectionBuilt()"); List <CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions); bool predicate(int i) => codes[i].opcode == OpCodes.Blt && codes[i - 1].opcode == OpCodes.Ldfld && codes[i - 1].operand == mSize && codes[i - 2].opcode == OpCodes.Ldfld && codes[i - 2].operand == fTempSegmentBuffer; int index = TranspilerUtil.SearchGeneric(codes, predicate, index: 0, counter: 1); index += 1; // index to insert instructions. (end of the loop) var newInstructions = new[] { new CodeInstruction(OpCodes.Ldarg_0), // load argument info new CodeInstruction(OpCodes.Call, mAfterIntersectionBuilt), }; TranspilerUtil.InsertInstructions(codes, newInstructions, index); return(codes); }
private static IEnumerable <CodeInstruction> FilterDrops(IEnumerable <CodeInstruction> instructions) { return(new CodeMatcher(instructions) .MatchForward(false, new CodeMatch(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(CharacterDrop), nameof(CharacterDrop.m_drops)))) .SetInstructionAndAdvance(Transpilers.EmitDelegate(ConditionChecker.FilterOnDeath)) .InstructionEnumeration()); }
public void Test_AccessTools_Field2() { var classType = typeof(AccessToolsClass); Assert.NotNull(AccessTools.Field(classType, "field1")); Assert.NotNull(AccessTools.DeclaredField(classType, "field1")); Assert.Null(AccessTools.Field(classType, "unknown")); Assert.Null(AccessTools.DeclaredField(classType, "unknown")); var subclassType = typeof(AccessToolsSubClass); Assert.NotNull(AccessTools.Field(subclassType, "field1")); Assert.Null(AccessTools.DeclaredField(subclassType, "field1")); Assert.Null(AccessTools.Field(subclassType, "unknown")); Assert.Null(AccessTools.DeclaredField(subclassType, "unknown")); var structType = typeof(AccessToolsStruct); Assert.NotNull(AccessTools.Field(structType, "structField1")); Assert.NotNull(AccessTools.DeclaredField(structType, "structField1")); Assert.Null(AccessTools.Field(structType, "unknown")); Assert.Null(AccessTools.DeclaredField(structType, "unknown")); var interfaceType = typeof(IAccessToolsType); Assert.Throws(typeof(NullReferenceException), () => AccessTools.Field(interfaceType, "unknown")); // TODO: should return null, not throw NRE Assert.Null(AccessTools.DeclaredField(interfaceType, "unknown")); }
public void Test_AccessTools_Field2() { var classType = typeof(AccessToolsClass); Assert.NotNull(AccessTools.Field(classType, "field1")); Assert.NotNull(AccessTools.DeclaredField(classType, "field1")); Assert.Null(AccessTools.Field(classType, "unknown")); Assert.Null(AccessTools.DeclaredField(classType, "unknown")); var subclassType = typeof(AccessToolsSubClass); Assert.NotNull(AccessTools.Field(subclassType, "field1")); Assert.Null(AccessTools.DeclaredField(subclassType, "field1")); Assert.Null(AccessTools.Field(subclassType, "unknown")); Assert.Null(AccessTools.DeclaredField(subclassType, "unknown")); var structType = typeof(AccessToolsStruct); Assert.NotNull(AccessTools.Field(structType, "structField1")); Assert.NotNull(AccessTools.DeclaredField(structType, "structField1")); Assert.Null(AccessTools.Field(structType, "unknown")); Assert.Null(AccessTools.DeclaredField(structType, "unknown")); var interfaceType = typeof(IAccessToolsType); Assert.Null(AccessTools.Field(interfaceType, "unknown")); Assert.Null(AccessTools.DeclaredField(interfaceType, "unknown")); }
public static void AssertIsEmpty(Traverse trv) { foreach (var name in fieldNames) { Assert.AreEqual(null, AccessTools.DeclaredField(typeof(Traverse), name).GetValue(trv)); } }
public void Traverse_Has_Expected_Internal_Fields() { foreach (var name in fieldNames) { var fInfo = AccessTools.DeclaredField(typeof(Traverse), name); Assert.IsNotNull(fInfo); } }
public static IEnumerable <CodeInstruction> GetDataToUseTranspiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilGenerator) { var list = instructions.ToList(); var firstReturnNull = ilGenerator.DefineLabel(); var secondExpressionStart = ilGenerator.DefineLabel(); var originalEntry = ilGenerator.DefineLabel(); list[0].labels.Add(originalEntry); // if (SavedMemberType == SavedMemberType.Enum && (_typeDefinition == null || _typeDefinition.Type == typeof(object))) return null; list.InsertRange(0, new[] { new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Call, AccessTools.DeclaredPropertyGetter(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "SavedMemberType")), new CodeInstruction(OpCodes.Ldc_I4_5), new CodeInstruction(OpCodes.Bne_Un_S, secondExpressionStart), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")), new CodeInstruction(OpCodes.Brfalse_S, firstReturnNull), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")), new CodeInstruction(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(TypeDefinitionBase), "Type")), new CodeInstruction(OpCodes.Ldtoken, typeof(object)), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Type), nameof(Type.GetTypeFromHandle))), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Type), "op_Equality")), new CodeInstruction(OpCodes.Brfalse_S, secondExpressionStart), new CodeInstruction(OpCodes.Ldnull) { labels = { firstReturnNull } }, new CodeInstruction(OpCodes.Ret), }); // // if (_typeDefinition is NullTypeDefinition) return null; list.InsertRange(16, new[] { new CodeInstruction(OpCodes.Ldarg_0) { labels = { secondExpressionStart } }, new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")), new CodeInstruction(OpCodes.Isinst, typeof(NullTypeDefinition)), // Basic new CodeInstruction(OpCodes.Brfalse_S, originalEntry), new CodeInstruction(OpCodes.Ldnull), new CodeInstruction(OpCodes.Ret) }); // return(list); }
public void Test_AccessTools_Field2() { var type = typeof(AccessToolsClass); Assert.NotNull(AccessTools.Field(type, "field1")); Assert.NotNull(AccessTools.DeclaredField(type, "field1")); var subtype = typeof(AccessToolsSubClass); Assert.NotNull(AccessTools.Field(subtype, "field1")); Assert.Null(AccessTools.DeclaredField(subtype, "field1")); }
public static RectTransform TopLevelWindow(Transform parent) { GameObject obj = new GameObject("ToyBox.TopLevelWindow"); ToyBox.Main.Objects.Add(obj); crUI.obj = obj; RectTransform transform = obj.AddComponent <RectTransform>(); transform.SetParent(parent, false); transform.anchorMin = new Vector2(0.0f, 0.0f); transform.anchorMax = new Vector2(1.0f, 1.0f); transform.pivot = new Vector2(0.5f, 0.5f); transform.offsetMin = new Vector2(0.0f, 0.0f); transform.offsetMax = new Vector2(0.0f, 0.0f); VerticalLayoutGroupWorkaround group = obj.AddComponent <VerticalLayoutGroupWorkaround>(); group.SetLayoutVertical(); group.childControlWidth = true; group.childControlHeight = true; group.childForceExpandWidth = false; group.childForceExpandHeight = false; group.childScaleWidth = false; group.childScaleHeight = false; group.childAlignment = TextAnchor.UpperLeft; group.spacing = DefaultSpacing; group.padding = DefaultPadding; LayoutElement layout = obj.AddComponent <LayoutElement>(); layout.minWidth = -1.0f; layout.minHeight = -1.0f; layout.preferredWidth = -1.0f; layout.preferredHeight = -1.0f; layout.flexibleWidth = 1.0f; layout.flexibleHeight = 1.0f; CanvasGroup canvas = obj.AddComponent <CanvasGroup>(); ContentSizeFitterExtended fitter = obj.AddComponent <ContentSizeFitterExtended>(); AccessTools .DeclaredField(typeof(ContentSizeFitterExtended), "m_HorizontalFit") .SetValue(fitter, ContentSizeFitterExtended.FitMode.PreferredSize); AccessTools .DeclaredField(typeof(ContentSizeFitterExtended), "m_VerticalFit") .SetValue(fitter, ContentSizeFitterExtended.FitMode.PreferredSize); fitter.SetLayoutVertical(); return(transform); }
internal FieldInfo GetFieldInfo(Type type, string name) { if (fields.TryGetValue(type, out var fieldsByType) == false) { fieldsByType = new Dictionary <string, FieldInfo>(); fields.Add(type, fieldsByType); } if (fieldsByType.TryGetValue(name, out var field) == false) { field = AccessTools.DeclaredField(type, name); fieldsByType.Add(name, field); } return(field); }
public void Test_AccessTools_Field1() { var type = typeof(AccessToolsClass); Assert.Null(AccessTools.DeclaredField(null, null)); Assert.Null(AccessTools.DeclaredField(type, null)); Assert.Null(AccessTools.DeclaredField(null, "field1")); Assert.Null(AccessTools.DeclaredField(type, "unknown")); var field = AccessTools.DeclaredField(type, "field1"); Assert.NotNull(field); Assert.AreEqual(type, field.DeclaringType); Assert.AreEqual("field1", field.Name); }
public void AccessTools_Field1() { var type = typeof(AccessToolsClass); Assert.Throws <ArgumentNullException>(() => AccessTools.DeclaredField(null, null)); Assert.Throws <ArgumentNullException>(() => AccessTools.DeclaredField(type, null)); Assert.Throws <ArgumentNullException>(() => AccessTools.DeclaredField(null, "field1")); Assert.IsNull(AccessTools.DeclaredField(type, "unknown")); var field = AccessTools.DeclaredField(type, "field1"); Assert.IsNotNull(field); Assert.AreEqual(type, field.DeclaringType); Assert.AreEqual("field1", field.Name); }
public static void Init() { // there's definitely a better way to get sprites and images // but don't know how crUI.CommonPCView = AccessTools .DeclaredField(typeof(RootUIContext), "m_CommonView")? .GetValue(Game.Instance?.RootUiContext) as MonoBehaviour; crUI.FrameBackgroundImage = crUI.CommonPCView.transform .Find("FadeCanvas/InfoWindow/Window/Background")? .gameObject?.GetComponent <Image>(); Transform owlcat_checkbox = null; foreach (GameObject obj in Resources.FindObjectsOfTypeAll <GameObject>()) { if (obj.name == "ShowHelmContainer") { owlcat_checkbox = obj.transform.Find("ToggleOwlcatMultiSelectable"); if (owlcat_checkbox != null) { break; } } } crUI.CheckboxBackgroundImage = owlcat_checkbox?.Find("Background")? .GetComponent <Image>(); crUI.CheckboxCheckmarkImage = owlcat_checkbox?.Find("Background/Checkmark")? .GetComponent <Image>(); crUI.CheckboxLayerParts = AccessTools.DeclaredField(typeof(OwlcatSelectable), "m_CommonLayer") .GetValue(owlcat_checkbox?.GetComponent <OwlcatMultiButton>()) as List <OwlcatSelectableLayerPart>; Transform owlcat_save_button = crUI.CommonPCView.gameObject.transform .Find("FadeCanvas/EscMenuView/Window/ButtonBlock/SaveButton"); crUI.ButtonBackgroundImage = owlcat_save_button?.GetComponent <Image>(); List <OwlcatSelectableLayerPart> button_layer_parts = AccessTools.DeclaredField(typeof(OwlcatSelectable), "m_CommonLayer") .GetValue(owlcat_save_button?.GetComponent <OwlcatButton>()) as List <OwlcatSelectableLayerPart>; crUI.ButtonBackgroundSpriteState = button_layer_parts[0].SpriteState; }
public static IEnumerable <CodeInstruction> ReadTranspiler(IEnumerable <CodeInstruction> instructions, ILGenerator ilGenerator) { var list = instructions.ToList(); // if (_typeDefinition is NullTypeDefinition) return; var label = ilGenerator.DefineLabel(); list.InsertRange(92, new[] { new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(Type.GetType("TaleWorlds.SaveSystem.Load.VariableLoadData, TaleWorlds.SaveSystem"), "_typeDefinition")), new CodeInstruction(OpCodes.Isinst, typeof(NullTypeDefinition)), // Basic new CodeInstruction(OpCodes.Brfalse_S, label), new CodeInstruction(OpCodes.Ret) }); list[97].labels.Add(label); // return(list); }
public static RectTransform Frame(RectTransform parent) { GameObject obj = new GameObject("ToyBox.Frame"); RectTransform transform = obj.AddComponent <RectTransform>(); transform.SetParent(parent, false); transform.anchorMin = new Vector2(0.0f, 0.0f); transform.anchorMax = new Vector2(1.0f, 1.0f); transform.pivot = new Vector2(0.5f, 0.5f); transform.offsetMin = new Vector2(-16.0f, -16.0f); transform.offsetMax = new Vector2(16.0f, 16.0f); HorizontalLayoutGroupWorkaround group = obj.AddComponent <HorizontalLayoutGroupWorkaround>(); group.SetLayoutHorizontal(); group.childControlWidth = true; group.childControlHeight = true; group.childForceExpandWidth = false; group.childForceExpandHeight = false; group.childScaleWidth = false; group.childScaleHeight = false; group.childAlignment = TextAnchor.UpperRight; group.spacing = DefaultSpacing; group.padding = new RectOffset(left: 0, bottom: 0, right: 16, top: 8); LayoutElement layout = obj.AddComponent <LayoutElement>(); layout.ignoreLayout = true; layout.minWidth = -1.0f; layout.minHeight = -1.0f; layout.preferredWidth = -1.0f; layout.preferredHeight = -1.0f; layout.flexibleWidth = 1.0f; layout.flexibleHeight = 1.0f; CanvasRenderer renderer = obj.AddComponent <CanvasRenderer>(); Image image = obj.AddComponent <Image>(); image.sprite = crUI.FrameBackgroundImage?.sprite; DraggbleWindow drag = obj.AddComponent <DraggbleWindow>(); AccessTools .DeclaredField(typeof(DraggbleWindow), "m_OwnRectTransform") .SetValue(drag, parent); AccessTools .DeclaredField(typeof(DraggbleWindow), "m_ParentRectTransform") .SetValue(drag, parent.parent); RectTransform close = crUI.Button(transform, "Close"); LayoutElement close_layout = close.GetComponent <LayoutElement>(); close_layout.minWidth = 64.0f; close_layout.minHeight = 32.0f; close_layout.preferredWidth = close_layout.minWidth; close_layout.preferredHeight = close_layout.minHeight; close_layout.flexibleWidth = 0.0f; close_layout.flexibleHeight = 0.0f; OwlcatButton button = close.GetComponent <OwlcatButton>(); Button.ButtonClickedEvent evt = AccessTools .DeclaredField(typeof(OwlcatButton), "m_OnLeftClick").GetValue(button) as Button.ButtonClickedEvent; evt.AddListener(() => { parent.gameObject.SetActive(false); }); return(transform); }
public static RectTransform Checkbox(RectTransform parent) { GameObject obj = new GameObject("ToyBox.Checkbox"); RectTransform transform = obj.AddComponent <RectTransform>(); transform.SetParent(parent, false); transform.anchorMin = new Vector2(0.0f, 0.0f); transform.anchorMax = new Vector2(1.0f, 1.0f); transform.pivot = new Vector2(0.5f, 0.5f); transform.offsetMin = new Vector2(0.0f, 0.0f); transform.offsetMax = new Vector2(0.0f, 0.0f); HorizontalLayoutGroupWorkaround group = obj.AddComponent <HorizontalLayoutGroupWorkaround>(); group.SetLayoutHorizontal(); group.childControlWidth = true; group.childControlHeight = true; group.childForceExpandWidth = false; group.childForceExpandHeight = false; group.childScaleWidth = false; group.childScaleHeight = false; group.childAlignment = TextAnchor.UpperLeft; group.spacing = DefaultSpacing; group.padding = DefaultPadding; LayoutElement layout = obj.AddComponent <LayoutElement>(); layout.minWidth = 32.0f; layout.minHeight = 32.0f; layout.preferredWidth = -1.0f; layout.preferredHeight = -1.0f; layout.flexibleWidth = 0.0f; layout.flexibleHeight = 0.0f; OwlcatMultiButton button = obj.AddComponent <OwlcatMultiButton>(); button.ClickSoundType = -1; //button.HoverSoundType = 1; // background GameObject background_obj = new GameObject("ToyBox.Checkbox.Background"); RectTransform background_transform = background_obj.AddComponent <RectTransform>(); background_transform.SetParent(transform, false); background_transform.anchorMin = new Vector2(0.0f, 0.0f); background_transform.anchorMax = new Vector2(1.0f, 1.0f); background_transform.pivot = new Vector2(0.5f, 0.5f); background_transform.offsetMin = new Vector2(0.0f, 0.0f); background_transform.offsetMax = new Vector2(0.0f, 0.0f); HorizontalLayoutGroupWorkaround background_group = background_obj.AddComponent <HorizontalLayoutGroupWorkaround>(); background_group.SetLayoutHorizontal(); background_group.childControlWidth = true; background_group.childControlHeight = true; background_group.childForceExpandWidth = false; background_group.childForceExpandHeight = false; background_group.childScaleWidth = false; background_group.childScaleHeight = false; background_group.childAlignment = TextAnchor.UpperLeft; background_group.spacing = DefaultSpacing; background_group.padding = new RectOffset( (int)(layout.minWidth * 0.2f), (int)(layout.minHeight * 0.2f), (int)(layout.minWidth * 0.2f), (int)(layout.minHeight * 0.2f) ); LayoutElement background_layout = background_obj.AddComponent <LayoutElement>(); background_layout.minWidth = -1.0f; background_layout.minHeight = -1.0f; background_layout.preferredWidth = -1.0f; background_layout.preferredHeight = -1.0f; background_layout.flexibleWidth = 0.0f; background_layout.flexibleHeight = 0.0f; CanvasRenderer background_renderer = background_obj.AddComponent <CanvasRenderer>(); Image background_image = background_obj.AddComponent <Image>(); background_image.sprite = crUI.CheckboxBackgroundImage?.sprite; // checkmark GameObject checkmark_obj = new GameObject("ToyBox.Checkbox.Checkmark"); RectTransform checkmark_transform = checkmark_obj.AddComponent <RectTransform>(); checkmark_transform.SetParent(background_transform, false); checkmark_transform.anchorMin = new Vector2(0.0f, 0.0f); checkmark_transform.anchorMax = new Vector2(1.0f, 1.0f); checkmark_transform.pivot = new Vector2(0.5f, 0.5f); checkmark_transform.offsetMin = new Vector2(0.0f, 0.0f); checkmark_transform.offsetMax = new Vector2(0.0f, 0.0f); LayoutElement checkmark_layout = checkmark_obj.AddComponent <LayoutElement>(); checkmark_layout.minWidth = -1.0f; checkmark_layout.minHeight = -1.0f; checkmark_layout.preferredWidth = -1.0f; checkmark_layout.preferredHeight = -1.0f; checkmark_layout.flexibleWidth = 1.0f; checkmark_layout.flexibleHeight = 1.0f; CanvasRenderer checkmark_renderer = checkmark_obj.AddComponent <CanvasRenderer>(); Image checkmark_image = checkmark_obj.AddComponent <Image>(); checkmark_image.sprite = crUI.CheckboxCheckmarkImage?.sprite; SpriteState sprite_state = crUI.CheckboxLayerParts[0].SpriteState; OwlcatSelectableLayerPart layer0 = new OwlcatSelectableLayerPart(); layer0.Image = background_image; layer0.Transition = OwlcatTransition.SpriteSwap; layer0.SpriteState = sprite_state; button.AddLayerToMainPart(layer0); button.AddMultiLayer(); button.AddMultiLayer(); List <OwlcatMultiLayer> layers = AccessTools.DeclaredField(typeof(OwlcatMultiSelectable), "m_MultiLayers") .GetValue(button) as List <OwlcatMultiLayer>; layers[0].LayerName = "Unchecked"; OwlcatMultiLayer layer1 = layers[1]; layer1.LayerName = "Checked"; layer1.AddPart(); layer1.Parts[0].Transition = OwlcatTransition.Activate; AccessTools.DeclaredField(typeof(OwlcatSelectableLayerPart), "m_TargetGameObject") .SetValue(layer1.Parts[0], checkmark_obj); AccessTools.DeclaredMethod(typeof(OwlcatMultiSelectable), "DoSetLayers").Invoke(button, new object[] {}); Button.ButtonClickedEvent evt = AccessTools .DeclaredField(typeof(OwlcatMultiButton), "m_OnLeftClick").GetValue(button) as Button.ButtonClickedEvent; evt.AddListener(() => { List <OwlcatMultiLayer> layers = AccessTools.DeclaredField(typeof(OwlcatMultiSelectable), "m_MultiLayers") .GetValue(button) as List <OwlcatMultiLayer>; button.SetActiveLayer((button.ActiveLayerIndex + 1) % layers.Count); }); return(transform); }
private static void EmitCallParameter(ILEmitter il, MethodBase original, MethodInfo patch, Dictionary <string, VariableDefinition> variables, bool allowFirsParamPassthrough) { var isInstance = original.IsStatic == false; var originalParameters = original.GetParameters(); var originalParameterNames = originalParameters.Select(p => p.Name).ToArray(); // check for passthrough using first parameter (which must have same type as return type) var parameters = patch.GetParameters().ToList(); if (allowFirsParamPassthrough && patch.ReturnType != typeof(void) && parameters.Count > 0 && parameters[0].ParameterType == patch.ReturnType) { parameters.RemoveRange(0, 1); } foreach (var patchParam in parameters) { if (patchParam.Name == ORIGINAL_METHOD_PARAM) { if (original is MethodInfo method) { il.Emit(OpCodes.Ldtoken, method); } else if (original is ConstructorInfo constructor) { il.Emit(OpCodes.Ldtoken, constructor); } else { il.Emit(OpCodes.Ldnull); continue; } var type = original.ReflectedType; if (type != null && type.IsGenericType) { il.Emit(OpCodes.Ldtoken, type); } il.Emit(OpCodes.Call, type != null && type.IsGenericType ? GetMethodFromHandle2 : GetMethodFromHandle1); continue; } if (patchParam.Name == INSTANCE_PARAM) { if (original.IsStatic) { il.Emit(OpCodes.Ldnull); } else { var instanceIsRef = original.DeclaringType != null && AccessTools.IsStruct(original.DeclaringType); var parameterIsRef = patchParam.ParameterType.IsByRef; if (instanceIsRef == parameterIsRef) { il.Emit(OpCodes.Ldarg_0); } if (instanceIsRef && parameterIsRef == false) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldobj, original.DeclaringType); } if (instanceIsRef == false && parameterIsRef) { il.Emit(OpCodes.Ldarga, 0); } } continue; } if (patchParam.Name.StartsWith(INSTANCE_FIELD_PREFIX, StringComparison.Ordinal)) { var fieldName = patchParam.Name.Substring(INSTANCE_FIELD_PREFIX.Length); FieldInfo fieldInfo; if (fieldName.All(char.IsDigit)) { fieldInfo = AccessTools.DeclaredField(original.DeclaringType, int.Parse(fieldName)); if (fieldInfo == null) { throw new ArgumentException( $"No field found at given index in class {original.DeclaringType.FullName}", fieldName); } } else { fieldInfo = AccessTools.DeclaredField(original.DeclaringType, fieldName); if (fieldInfo == null) { throw new ArgumentException( $"No such field defined in class {original.DeclaringType.FullName}", fieldName); } } if (fieldInfo.IsStatic) { il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldsflda : OpCodes.Ldsfld, fieldInfo); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldflda : OpCodes.Ldfld, fieldInfo); } continue; } // state is special too since each patch has its own local var if (patchParam.Name == STATE_VAR) { if (variables.TryGetValue(patch.DeclaringType?.FullName ?? string.Empty, out var stateVar)) { il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc, stateVar); } else { il.Emit(OpCodes.Ldnull); } continue; } // treat __result var special if (patchParam.Name == RESULT_VAR) { var returnType = AccessTools.GetReturnedType(original); if (returnType == typeof(void)) { throw new InvalidHarmonyPatchArgumentException($"Cannot get result from void method", original, patch); } var resultType = patchParam.ParameterType; if (resultType.IsByRef) { resultType = resultType.GetElementType(); } if (resultType.IsAssignableFrom(returnType) == false) { throw new InvalidHarmonyPatchArgumentException( $"Cannot assign method return type {returnType.FullName} to {RESULT_VAR} type {resultType.FullName}", original, patch); } il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc, variables[RESULT_VAR]); continue; } // any other declared variables if (variables.TryGetValue(patchParam.Name, out var localBuilder)) { il.Emit(patchParam.ParameterType.IsByRef ? OpCodes.Ldloca : OpCodes.Ldloc, localBuilder); continue; } int idx; if (patchParam.Name.StartsWith(PARAM_INDEX_PREFIX, StringComparison.Ordinal)) { var val = patchParam.Name.Substring(PARAM_INDEX_PREFIX.Length); if (!int.TryParse(val, out idx)) { throw new InvalidHarmonyPatchArgumentException($"Parameter {patchParam.Name} does not contain a valid index", original, patch); } if (idx < 0 || idx >= originalParameters.Length) { throw new InvalidHarmonyPatchArgumentException($"No parameter found at index {idx}", original, patch); } } else { idx = GetArgumentIndex(patch, originalParameterNames, patchParam); if (idx == -1) { throw new InvalidHarmonyPatchArgumentException( $"Parameter \"{patchParam.Name}\" not found", original, patch); } } // original -> patch opcode // -------------------------------------- // 1 normal -> normal : LDARG // 2 normal -> ref/out : LDARGA // 3 ref/out -> normal : LDARG, LDIND_x // 4 ref/out -> ref/out : LDARG // var originalIsNormal = originalParameters[idx].IsOut == false && originalParameters[idx].ParameterType.IsByRef == false; var patchIsNormal = patchParam.IsOut == false && patchParam.ParameterType.IsByRef == false; var patchArgIndex = idx + (isInstance ? 1 : 0); // Case 1 + 4 if (originalIsNormal == patchIsNormal) { il.Emit(OpCodes.Ldarg, patchArgIndex); continue; } // Case 2 if (originalIsNormal && patchIsNormal == false) { il.Emit(OpCodes.Ldarga, patchArgIndex); continue; } // Case 3 il.Emit(OpCodes.Ldarg, patchArgIndex); il.Emit(GetIndOpcode(originalParameters[idx].ParameterType)); } }
public static IEnumerable <CodeInstruction> SetControlsTranspiler(IEnumerable <CodeInstruction> instructions) { bool foundCancelCrouch = false; bool foundAutoRunCondition = false; bool foundMoveDirCondition = false; bool foundCancelAutorunCondition = false; bool foundMoveDirAssignment = false; CodeInstruction branchEndAutoRun = null; List <CodeInstruction> codes = new List <CodeInstruction>(instructions); //DumpIL(codes); for (int i = 0; i < codes.Count(); i++) { CodeInstruction code = codes[i]; if (!foundCancelCrouch && codes[i + 0].opcode == OpCodes.Ldarg_0 && codes[i + 1].opcode == OpCodes.Ldc_I4_0 && codes[i + 2].Calls(AccessTools.Method(typeof(Character), nameof(Character.SetCrouch)))) { //Debug.Log("foundit0 " + i); // Nop out the call to "this.SetCrouch(false)" codes[i + 0].opcode = OpCodes.Nop; codes[i + 0].operand = null; codes[i + 1].opcode = OpCodes.Nop; codes[i + 1].operand = null; codes[i + 2].opcode = OpCodes.Nop; codes[i + 2].operand = null; foundCancelCrouch = true; } // We're looking for a ldfld of m_autoRun followed by a brfalse: "if(this.m_autoRun)" if (!foundAutoRunCondition && code.opcode == OpCodes.Ldfld && code.LoadsField(AccessTools.DeclaredField(typeof(Player), nameof(Player.m_autoRun))) && codes[i + 1].opcode == OpCodes.Brfalse) { //Debug.Log("foundit1 " + i); foundAutoRunCondition = true; } // Nop out the "jump || crouch || movedir != Vector3.zero" conditions if (foundAutoRunCondition && codes[i - 5].opcode == OpCodes.Ldarg_S && codes[i - 4].opcode == OpCodes.Or && codes[i - 3].opcode == OpCodes.Ldarg_S && codes[i - 2].opcode == OpCodes.Or && codes[i - 1].Branches(out Label? asdfasdfasdsa) && codes[i + 0].opcode == OpCodes.Ldarg_1 && codes[i + 1].opcode == OpCodes.Call) { //Debug.Log("foundit3 " + i); codes[i - 5].opcode = OpCodes.Nop; codes[i - 5].operand = null; codes[i - 4].opcode = OpCodes.Nop; codes[i - 4].operand = null; codes[i - 3].opcode = OpCodes.Nop; codes[i - 3].operand = null; codes[i - 2].opcode = OpCodes.Nop; codes[i - 2].operand = null; // Leave codes[i - 1] alone since it's the branching instruction for the very first condition codes[i + 0].opcode = OpCodes.Nop; codes[i + 0].operand = null; codes[i + 1].opcode = OpCodes.Nop; codes[i + 1].operand = null; codes[i + 2].opcode = OpCodes.Nop; codes[i + 2].operand = null; codes[i + 3].opcode = OpCodes.Nop; codes[i + 3].operand = null; // Add in our own autorun canceling conditions: if either forwards or backwards are pressed. branchEndAutoRun = codes[i - 1]; codes.InsertRange(i, new List <CodeInstruction>() { new CodeInstruction(OpCodes.Ldstr, "Forward"), CodeInstruction.Call(typeof(ZInput), nameof(ZInput.GetButton)), branchEndAutoRun.Clone(), new CodeInstruction(OpCodes.Ldstr, "Backward"), CodeInstruction.Call(typeof(ZInput), nameof(ZInput.GetButton)), branchEndAutoRun.Clone() }); foundCancelAutorunCondition = true; } // Convert "else if (autoRun || blockHold)" into "else" if (foundCancelAutorunCondition && codes[i + 0].opcode == OpCodes.Ldarg_S && //&& codes[i + 0].operand as string == "10" codes[i + 1].opcode == OpCodes.Ldarg_S && //&& codes[i + 1].operand as string == "6" codes[i + 2].opcode == OpCodes.Or && codes[i + 3].Branches(out Label? asdfasdfsad)) { //Debug.Log("foundit4 " + i); codes[i + 0].opcode = OpCodes.Nop; codes[i + 0].operand = null; codes[i + 1].opcode = OpCodes.Nop; codes[i + 1].operand = null; codes[i + 2].opcode = OpCodes.Nop; codes[i + 2].operand = null; codes[i + 3].opcode = OpCodes.Nop; codes[i + 3].operand = null; foundMoveDirCondition = true; } // Lastly, add "movedir.x * Vector3.Cross(Vector3.up, this.m_lookDir)" to the player's movedir so that they can strafe while autorunning if (foundMoveDirCondition && codes[i - 3].opcode == OpCodes.Ldarg_0 && codes[i - 2].opcode == OpCodes.Ldarg_0 && codes[i - 1].LoadsField(AccessTools.Field(typeof(Character), nameof(Character.m_lookDir))) && codes[i - 0].StoresField(AccessTools.Field(typeof(Character), nameof(Character.m_moveDir)))) { //Debug.Log("foundit5 " + i); codes.InsertRange(i, new List <CodeInstruction>() { new CodeInstruction(OpCodes.Ldarg_1), CodeInstruction.LoadField(typeof(Vector3), nameof(Vector3.x)), new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(Vector3), nameof(Vector3.up))), new CodeInstruction(OpCodes.Ldarg_0), CodeInstruction.LoadField(typeof(Player), nameof(Player.m_lookDir)), CodeInstruction.Call(typeof(Vector3), nameof(Vector3.Cross)), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Vector3), "op_Multiply", new Type[] { typeof(float), typeof(Vector3) })), new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Vector3), "op_Addition", new Type[] { typeof(Vector3), typeof(Vector3) })) }); foundMoveDirAssignment = true; break; // we done } } //DumpIL(codes); //Debug.Log(string.Format("{0} {1} {2} {3} {4}", foundAutoRunCondition, branchEndAutoRun != null, foundCancelAutorunCondition, foundMoveDirCondition, foundMoveDirAssignment)); if (!foundAutoRunCondition || branchEndAutoRun == null || !foundCancelAutorunCondition || !foundMoveDirCondition || !foundMoveDirAssignment) { throw new Exception("BetterAutoRun injection point NOT found!! Game has most likely updated and broken this mod!"); } if (!foundCancelCrouch) { Main.log.LogWarning("One of the BetterAutoRun injection points were not found, game has most likely updated and broken this mod."); Main.log.LogWarning("Autorun while crouching will not work but everything else should be fine."); } return(codes.AsEnumerable()); }
public static IEnumerable <CodeInstruction> FindPath(IEnumerable <CodeInstruction> instructions, ILGenerator iLGenerator) { //Type nodeFastType = AccessTools.TypeByName("Verse.AI.PathFinder+PathFinderNodeFast"); Type nodeFastType = typeof(PathFinderNodeFast); Type nodeFastTypeArray = nodeFastType.MakeArrayType(); LocalBuilder local_calcGrid = iLGenerator.DeclareLocal(nodeFastTypeArray); LocalBuilder local_statusOpenValue = iLGenerator.DeclareLocal(typeof(ushort)); LocalBuilder local_statusClosedValue = iLGenerator.DeclareLocal(typeof(ushort)); LocalBuilder local_regionCostCalculatorWrapper = iLGenerator.DeclareLocal(typeof(RegionCostCalculatorWrapper)); Type costNodeType = AccessTools.TypeByName("Verse.AI.PathFinder+CostNode"); Type costNodeType2 = typeof(CostNode2); Type icomparerCostNodeType1 = typeof(IComparer <>).MakeGenericType(costNodeType); Type icomparerCostNodeType2 = typeof(IComparer <>).MakeGenericType(costNodeType2); Type fastPriorityQueueCostNodeType1 = typeof(FastPriorityQueue <>).MakeGenericType(costNodeType); Type fastPriorityQueueCostNodeType2 = typeof(FastPriorityQueue <>).MakeGenericType(costNodeType2); LocalBuilder local_openList = iLGenerator.DeclareLocal(fastPriorityQueueCostNodeType2); //LocalBuilder tID = iLGenerator.DeclareLocal(typeof(int)); //LocalBuilder size = iLGenerator.DeclareLocal(typeof(int)); List <CodeInstruction> instructionsList = instructions.ToList(); int i = 0; // int managedThreadId = Thread.CurrentThread.ManagedThreadId; //IL_0000: call class [mscorlib]System.Threading.Thread[mscorlib] System.Threading.Thread::get_CurrentThread() //IL_0005: callvirt instance int32[mscorlib] System.Threading.Thread::get_ManagedThreadId() //IL_000a: stloc.0 //yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Thread), "get_CurrentThread")); //yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Thread), "get_ManagedThreadId")); //yield return new CodeInstruction(OpCodes.Stloc, tID.LocalIndex); // PathFinderNodeFast[] calcGrid = getCalcGrid(managedThreadId, __instance); //IL_000b: ldloc.0 //IL_000c: ldarg.0 //IL_000d: call valuetype RimThreaded.PathFinder_Patch / PathFinderNodeFast[] RimThreaded.PathFinder_Patch::getCalcGrid(int32, class ['Assembly-CSharp'] Verse.AI.PathFinder) //IL_0012: stloc.1 //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getCalcGrid"))); yield return(new CodeInstruction(OpCodes.Stloc, local_calcGrid.LocalIndex)); yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getRegionCostCalculatorWrapper"))); yield return(new CodeInstruction(OpCodes.Stloc, local_regionCostCalculatorWrapper.LocalIndex)); // FastPriorityQueue<CostNode2> openList = getOpenList(managedThreadId); //IL_0013: ldloc.0 //IL_0014: call class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2> RimThreaded.PathFinder_Patch::getOpenList(int32) //IL_0019: stloc.2 //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getOpenList"))); yield return(new CodeInstruction(OpCodes.Stloc, local_openList.LocalIndex)); // ushort local_statusOpenValue = getOpenValue(managedThreadId); //IL_001a: ldloc.0 //IL_001b: call uint16 RimThreaded.PathFinder_Patch::getOpenValue(int32) //IL_0020: stloc.3 //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getOpenValue"))); yield return(new CodeInstruction(OpCodes.Stloc, local_statusOpenValue.LocalIndex)); // ushort local_statusClosedValue = getClosedValue(managedThreadId); //IL_0021: ldloc.0 //IL_0022: call uint16 RimThreaded.PathFinder_Patch::getClosedValue(int32) //IL_0027: stloc.s 4 //yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "getClosedValue"))); yield return(new CodeInstruction(OpCodes.Stloc, local_statusClosedValue.LocalIndex)); /* * // int num = mapSizeXField(__instance) * mapSizeZField(__instance); * yield return new CodeInstruction(OpCodes.Ldarg_0); * yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "mapSizeX")); * yield return new CodeInstruction(OpCodes.Ldarg_0); * yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "mapSizeZ")); * yield return new CodeInstruction(OpCodes.Mul); * yield return new CodeInstruction(OpCodes.Stloc, size.LocalIndex); * * // if (!calcGrids.TryGetValue(managedThreadId, out PathFinderNodeFast[] value) || value.Length < num) * * //IL_0025: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]> RimThreaded.PathFinder_Patch::calcGrids * //IL_002a: ldloc.0 * //IL_002b: ldloca.s 2 * //IL_002d: callvirt instance bool class [mscorlib]System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]>::TryGetValue(!0, !1&) * //IL_0032: brfalse.s IL_003a * //IL_0034: ldloc.2 * //IL_0035: ldlen * //IL_0036: conv.i4 * //IL_0037: ldloc.1 * //IL_0038: bge.s IL_004d * * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "calcGrids")); * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloca, local_calcGrid.LocalIndex); * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, PathFinder_Patch.PathFinderNodeFast[]>), "TryGetValue")); * Label il_003a = iLGenerator.DefineLabel(); * yield return new CodeInstruction(OpCodes.Brfalse_S, il_003a); * * yield return new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldlen); * yield return new CodeInstruction(OpCodes.Conv_I4); * yield return new CodeInstruction(OpCodes.Ldloc, size.LocalIndex); * Label il_004d = iLGenerator.DefineLabel(); * yield return new CodeInstruction(OpCodes.Bge_S, il_004d); * * // value = new PathFinderNodeFast[num]; * //IL_003a: ldloc.1 * //IL_003b: newarr RimThreaded.PathFinder_Patch / PathFinderNodeFast * //IL_0040: stloc.2 * CodeInstruction ci_003a = new CodeInstruction(OpCodes.Ldloc, size.LocalIndex); * ci_003a.labels.Add(il_003a); * yield return ci_003a; * * yield return new CodeInstruction(OpCodes.Newarr, nodeFastType); * yield return new CodeInstruction(OpCodes.Stloc, local_calcGrid.LocalIndex); * * // calcGrids[managedThreadId] = value; * //IL_0041: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]> RimThreaded.PathFinder_Patch::calcGrids * //IL_0046: ldloc.0 * //IL_0047: ldloc.2 * //IL_0048: callvirt instance void class [mscorlib] System.Collections.Generic.Dictionary`2<int32, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[]>::set_Item(!0, !1) * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "calcGrids")); * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex); * yield return new CodeInstruction(OpCodes.Callvirt, * AccessTools.Method(typeof(Dictionary<int, PathFinder_Patch.PathFinderNodeFast[]>), "set_Item")); * * * // if (!openLists.TryGetValue(managedThreadId, out FastPriorityQueue<CostNode2> value2)) * //IL_004d: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>> RimThreaded.PathFinder_Patch::openLists * //IL_0052: ldloc.0 * //IL_0053: ldloca.s 3 * //IL_0055: callvirt instance bool class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>>::TryGetValue(!0, !1&) * //IL_005a: brtrue.s IL_0073 * CodeInstruction ci_004d = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openLists")); * ci_004d.labels.Add(il_004d); * yield return ci_004d; * * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloca, local_statusOpenValue); * yield return new CodeInstruction(OpCodes.Callvirt, * AccessTools.Method(typeof(Dictionary<int, FastPriorityQueue<PathFinder_Patch.CostNode2>>), "TryGetValue")); * Label il_0073 = iLGenerator.DefineLabel(); * yield return new CodeInstruction(OpCodes.Brtrue, il_0073); * * // value2 = new FastPriorityQueue<CostNode2>(new CostNodeComparer2()); * //IL_005c: newobj instance void RimThreaded.PathFinder_Patch / CostNodeComparer2::.ctor() * //IL_0061: newobj instance void class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>::.ctor(class [mscorlib] System.Collections.Generic.IComparer`1<!0>) * //IL_0066: stloc.3 * yield return new CodeInstruction(OpCodes.Newobj, typeof(CostNodeComparer2).GetConstructor(Type.EmptyTypes)); * yield return new CodeInstruction(OpCodes.Newobj, fastPriorityQueueCostNodeType2.GetConstructor(new Type[] { icomparerCostNodeType2 })); * yield return new CodeInstruction(OpCodes.Stloc, local_openList.LocalIndex); * * // openLists[managedThreadId] = value2; * //IL_0067: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>> RimThreaded.PathFinder_Patch::openLists * //IL_006c: ldloc.0 * //IL_006d: ldloc.3 * //IL_006e: callvirt instance void class [mscorlib] System.Collections.Generic.Dictionary`2<int32, class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode2>>::set_Item(!0, !1) * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openLists")); * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloc, local_openList.LocalIndex); * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, FastPriorityQueue<PathFinder_Patch.CostNode2>>), "set_Item")); * * // if (!openValues.TryGetValue(managedThreadId, out ushort value3)) * //IL_0073: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::openValues * //IL_0078: ldloc.0 * //IL_0079: ldloca.s 4 * //IL_007b: callvirt instance bool class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16>::TryGetValue(!0, !1&) * //IL_0080: brtrue.s IL_0085 * CodeInstruction ci_0073 = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openValues")); * ci_0073.labels.Add(il_0073); * yield return ci_0073; * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloca, local_statusOpenValue.LocalIndex); * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "TryGetValue")); * Label il_0085 = iLGenerator.DefineLabel(); * yield return new CodeInstruction(OpCodes.Brtrue, il_0085); * * // value3 = 1; * //IL_0082: ldc.i4.1 * //IL_0083: stloc.s 4 * yield return new CodeInstruction(OpCodes.Ldc_I4_1); * yield return new CodeInstruction(OpCodes.Stloc, local_statusOpenValue.LocalIndex); * * // if (!closedValues.TryGetValue(managedThreadId, out ushort value4)) * //IL_0085: ldsfld class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::closedValues * //IL_008a: ldloc.0 * //IL_008b: ldloca.s 5 * //IL_008d: callvirt instance bool class [mscorlib] System.Collections.Generic.Dictionary`2<int32, uint16>::TryGetValue(!0, !1&) * //IL_0092: brtrue.s IL_0097 * CodeInstruction ci__0085 = new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "closedValues")); * ci__0085.labels.Add(il_0085); * yield return ci__0085; * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloca, local_statusClosedValue.LocalIndex); * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "TryGetValue")); * Label il_0097 = iLGenerator.DefineLabel(); * yield return new CodeInstruction(OpCodes.Brtrue, il_0097); * * // value4 = 2; * //IL_0094: ldc.i4.2 * //IL_0095: stloc.s 5 * yield return new CodeInstruction(OpCodes.Ldc_I4_2); * yield return new CodeInstruction(OpCodes.Stloc, local_statusClosedValue.LocalIndex); * instructionsList[0].labels.Add(il_0097); * * //yield return new CodeInstruction(OpCodes.Newobj, costNodeType2.GetConstructor(Type.EmptyTypes)); * //yield return new CodeInstruction(OpCodes.Newobj, fastPriorityQueueCostNodeType2.GetConstructor(new Type[] { icomparerCostNodeType2 })); * //yield return new CodeInstruction(OpCodes.Stloc, local_openList.LocalIndex); */ while (i < instructionsList.Count) { // InitStatusesAndPushStartNode(ref curIndex, start); //IL_0363: ldarg.0 //IL_0364: ldloca.s 3 //IL_0366: ldarg.1 //IL_0367: call instance void Verse.AI.PathFinder::InitStatusesAndPushStartNode(int32 &, valuetype Verse.IntVec3) if ( i + 3 < instructionsList.Count && instructionsList[i + 3].opcode == OpCodes.Call && instructionsList[i + 3].operand.ToString().Equals("Void InitStatusesAndPushStartNode(Int32 ByRef, Verse.IntVec3)") ) { //IL_043b: ldsfld class ['0Harmony'] HarmonyLib.AccessTools/FieldRef`2<class ['Assembly-CSharp'] Verse.AI.PathFinder, class ['Assembly-CSharp'] Verse.CellIndices> RimThreaded.PathFinder_Patch::cellIndicesField //IL_0440: ldarg.0 //IL_0441: callvirt instance !1& class ['0Harmony'] HarmonyLib.AccessTools/FieldRef`2<class ['Assembly-CSharp'] Verse.AI.PathFinder, class ['Assembly-CSharp'] Verse.CellIndices>::Invoke(!0) //IL_0446: ldind.ref //IL_0447: ldloca.s 7 //IL_0449: ldarg.2 //IL_044a: ldloc.0 //IL_044b: ldloc.3 //IL_044c: ldloca.s 1 //IL_044e: ldloca.s 2 //IL_0450: call void RimThreaded.PathFinder_Patch::InitStatusesAndPushStartNode2(class ['Assembly-CSharp'] Verse.CellIndices, int32&, valuetype['Assembly-CSharp'] Verse.IntVec3, valuetype RimThreaded.PathFinder_Patch/PathFinderNodeFast[], class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype RimThreaded.PathFinder_Patch/CostNode>, uint16&, uint16&) instructionsList[i].opcode = OpCodes.Nop; yield return(instructionsList[i]); i++; yield return(instructionsList[i]); i++; yield return(instructionsList[i]); i += 2; yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "cellIndices"))); yield return(new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex)); //yield return new CodeInstruction(OpCodes.Ldarg_0); //yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "openList")); yield return(new CodeInstruction(OpCodes.Ldloca, local_statusOpenValue.LocalIndex)); yield return(new CodeInstruction(OpCodes.Ldloca, local_statusClosedValue.LocalIndex)); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "InitStatusesAndPushStartNode3"))); // openList.Clear(); // fastPriorityQueue.Clear(); //IL_0502: ldloc.3 //IL_0503: callvirt instance void class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype Verse.AI.PathFinder_Target/CostNode>::Clear() yield return(new CodeInstruction(OpCodes.Ldloc_S, local_openList.LocalIndex)); yield return(new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(fastPriorityQueueCostNodeType2, "Clear"))); // openList.Push(new CostNode(curIndex, 0)); // fastPriorityQueue.Push(new CostNode(num3, 0)); //IL_0508: ldloc.3 //IL_0509: ldloc.s 9 //IL_050b: ldc.i4.0 //IL_050c: newobj instance void Verse.AI.PathFinder_Target / CostNode::.ctor(int32, int32) //IL_0511: callvirt instance void class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype Verse.AI.PathFinder_Target/CostNode>::Push(!0) yield return(new CodeInstruction(OpCodes.Ldloc_S, local_openList.LocalIndex)); yield return(new CodeInstruction(OpCodes.Ldloc_3)); //curIndex yield return(new CodeInstruction(OpCodes.Ldc_I4_0)); Log.Message(costNodeType2.GetConstructor(new Type[] { typeof(Int32), typeof(Int32) }).ToString()); yield return(new CodeInstruction(OpCodes.Newobj, costNodeType2.GetConstructor(new Type[] { typeof(Int32), typeof(Int32) }))); yield return(new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(fastPriorityQueueCostNodeType2, "Push"))); //yield return new CodeInstruction(OpCodes.Ldloc_S, openList.LocalIndex); } //call instance class ['Assembly-CSharp']Verse.AI.PawnPath Verse.AI.PathFinder_Original::FinalizedPath(int32, bool) else if ( i + 3 < instructionsList.Count && instructionsList[i + 3].opcode == OpCodes.Call && instructionsList[i + 3].operand.ToString().Equals("Verse.AI.PawnPath FinalizedPath(Int32, Boolean)") ) { // PawnPath pawnPath = new PawnPath(); //IL_0535: newobj instance void ['Assembly-CSharp']Verse.AI.PawnPath::.ctor() //IL_0545: stloc.s 39 (emptyPawnPath.LocalIndex) // int num13 = curIndex; //IL_0547: ldloc.3 (curIndex) //IL_0549: stloc.s 40 (num1.LocalIndex) instructionsList[i].opcode = OpCodes.Nop; yield return(instructionsList[i]); i++; yield return(instructionsList[i]); i++; yield return(instructionsList[i]); i += 2; yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(PathFinder), "cellIndices"))); yield return(new CodeInstruction(OpCodes.Ldloc, local_calcGrid.LocalIndex)); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PathFinder_Patch), "FinalizedPath2"))); } //ldsfld valuetype Verse.AI.PathFinder_Original/PathFinderNodeFast[] Verse.AI.PathFinder_Original::calcGrid else if ( instructionsList[i].opcode == OpCodes.Ldsfld && instructionsList[i].operand.ToString().Equals("Verse.AI.PathFinder+PathFinderNodeFast[] calcGrid") ) { //ldloc.0 (local_calcGrid.LocalIndex) instructionsList[i].opcode = OpCodes.Ldloc; instructionsList[i].operand = local_calcGrid.LocalIndex; yield return(instructionsList[i]); i++; } //ldsfld uint16 Verse.AI.PathFinder_Original::statusOpenValue else if ( instructionsList[i].opcode == OpCodes.Ldsfld && instructionsList[i].operand.ToString().Equals("System.UInt16 statusOpenValue") ) { //ldloc.1 (local_statusOpenValue.LocalIndex) instructionsList[i].opcode = OpCodes.Ldloc; instructionsList[i].operand = local_statusOpenValue.LocalIndex; yield return(instructionsList[i]); i++; } //ldsfld uint16 Verse.AI.PathFinder_Original::statusClosedValue else if ( instructionsList[i].opcode == OpCodes.Ldsfld && instructionsList[i].operand.ToString().Equals("System.UInt16 statusClosedValue") ) { //ldloc.2(local_statusClosedValue.LocalIndex) instructionsList[i].opcode = OpCodes.Ldloc; instructionsList[i].operand = local_statusClosedValue.LocalIndex; yield return(instructionsList[i]); i++; } // ldarg.0 // ldfld class ['Assembly-CSharp'] Verse.FastPriorityQueue`1<valuetype Verse.AI.PathFinder_Target/CostNode> Verse.AI.PathFinder_Target::openList else if ( i + 1 < instructionsList.Count && instructionsList[i].opcode == OpCodes.Ldarg_0 && instructionsList[i + 1].opcode == OpCodes.Ldfld && instructionsList[i + 1].operand.ToString().Equals("Verse.FastPriorityQueue`1[Verse.AI.PathFinder+CostNode] openList") ) { // ldloc.3 (openlist) instructionsList[i].opcode = OpCodes.Ldloc; instructionsList[i].operand = local_openList.LocalIndex; yield return(instructionsList[i]); i += 2; } else if ( instructionsList[i].opcode == OpCodes.Callvirt && (MethodInfo)instructionsList[i].operand == AccessTools.Method(fastPriorityQueueCostNodeType1, "get_Count") ) { instructionsList[i].operand = AccessTools.Method(fastPriorityQueueCostNodeType2, "get_Count"); yield return(instructionsList[i]); i++; } else if ( instructionsList[i].opcode == OpCodes.Callvirt && (MethodInfo)instructionsList[i].operand == AccessTools.Method(fastPriorityQueueCostNodeType1, "Pop") ) { instructionsList[i].operand = AccessTools.Method(fastPriorityQueueCostNodeType2, "Pop"); yield return(instructionsList[i]); i++; } else if ( instructionsList[i].opcode == OpCodes.Callvirt && (MethodInfo)instructionsList[i].operand == AccessTools.Method(fastPriorityQueueCostNodeType1, "Push") ) { instructionsList[i].operand = AccessTools.Method(fastPriorityQueueCostNodeType2, "Push"); yield return(instructionsList[i]); i++; } else if ( instructionsList[i].opcode == OpCodes.Ldfld && (FieldInfo)instructionsList[i].operand == AccessTools.Field(costNodeType, "index") ) { instructionsList[i].operand = AccessTools.Field(costNodeType2, "index"); yield return(instructionsList[i]); i++; } else if ( instructionsList[i].opcode == OpCodes.Ldfld && (FieldInfo)instructionsList[i].operand == AccessTools.Field(costNodeType, "cost") ) { instructionsList[i].operand = AccessTools.Field(costNodeType2, "cost"); yield return(instructionsList[i]); i++; } else if ( instructionsList[i].opcode == OpCodes.Newobj && (ConstructorInfo)instructionsList[i].operand == costNodeType.GetConstructor(new Type[] { typeof(int), typeof(int) }) ) { instructionsList[i].operand = costNodeType2.GetConstructor(new Type[] { typeof(int), typeof(int) }); yield return(instructionsList[i]); i++; } else if ( instructionsList[i].opcode == OpCodes.Newobj && (ConstructorInfo)instructionsList[i].operand == fastPriorityQueueCostNodeType1.GetConstructor(new Type[] { icomparerCostNodeType1 }) ) { instructionsList[i].operand = fastPriorityQueueCostNodeType2.GetConstructor(new Type[] { icomparerCostNodeType2 }); yield return(instructionsList[i]); i++; } else if (i + 1 < instructionsList.Count && instructionsList[i + 1].opcode == OpCodes.Ldfld && (FieldInfo)instructionsList[i + 1].operand == AccessTools.DeclaredField(typeof(PathFinder), "regionCostCalculator") ) { instructionsList[i].opcode = OpCodes.Ldloc; instructionsList[i].operand = local_regionCostCalculatorWrapper.LocalIndex; yield return(instructionsList[i++]); i++; } /* * else if (i == instructionsList.Count - 1) * { * // openValues[managedThreadId] = value3; * //IL_0c30: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::openValues * //IL_0c35: ldloc.0 * //IL_0c36: ldloc.s 4 * //IL_0c38: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16>::set_Item(!0, !1) * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "openValues")); * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloc, local_statusOpenValue); * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "set_Item")); * * // closedValues[managedThreadId] = value4; * //IL_0c3d: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16> RimThreaded.PathFinder_Patch::closedValues * //IL_0c42: ldloc.0 * //IL_0c43: ldloc.s 5 * //IL_0c45: callvirt instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, uint16>::set_Item(!0, !1) * yield return new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PathFinder_Patch), "closedValues")); * yield return new CodeInstruction(OpCodes.Ldloc, tID.LocalIndex); * yield return new CodeInstruction(OpCodes.Ldloc, local_statusClosedValue); * yield return new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(Dictionary<int, ushort>), "set_Item")); * yield return instructionsList[i]; * i++; * } */ else { yield return(instructionsList[i]); i++; } } }
public static void WriteSyncObject(ByteWriter data, object obj, SyncType syncType) { MpContext context = data.MpContext(); Type type = syncType.type; var log = (data as LoggingByteWriter)?.Log; log?.Enter($"{type.FullName}: {obj ?? "null"}"); if (obj != null && !type.IsAssignableFrom(obj.GetType())) { throw new SerializationException($"Serializing with type {type} but got object of type {obj.GetType()}"); } try { if (typeof(object) == type) { return; } if (type.IsByRef) { return; } if (SyncDictFast.syncWorkers.TryGetValue(type, out var syncWorkerEntryEarly)) { syncWorkerEntryEarly.Invoke(new WritingSyncWorker(data), ref obj); return; } if (syncType.expose) { if (!typeof(IExposable).IsAssignableFrom(type)) { throw new SerializationException($"Type {type} can't be exposed because it isn't IExposable"); } IExposable exposable = obj as IExposable; byte[] xmlData = ScribeUtil.WriteExposable(exposable); LogXML(log, xmlData); data.WritePrefixedBytes(xmlData); return; } if (typeof(ISynchronizable).IsAssignableFrom(type)) { ((ISynchronizable)obj).Sync(new WritingSyncWorker(data)); return; } if (type.IsEnum) { Type enumType = Enum.GetUnderlyingType(type); WriteSyncObject(data, Convert.ChangeType(obj, enumType), enumType); return; } if (type.IsArray) { if (type.GetArrayRank() != 1) { throw new SerializationException("Multi dimensional arrays aren't supported."); } Type elementType = type.GetElementType(); Array arr = (Array)obj; if (arr == null) { data.WriteUShort(ushort.MaxValue); return; } if (arr.Length >= ushort.MaxValue) { throw new SerializationException($"Tried to serialize a {elementType}[] with too many ({arr.Length}) items."); } data.WriteUShort((ushort)arr.Length); foreach (object e in arr) { WriteSyncObject(data, e, elementType); } return; } if (type.IsGenericType) { Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(List <>)) { IList list = (IList)obj; Type listObjType = type.GetGenericArguments()[0]; if (list == null) { data.WriteUShort(ushort.MaxValue); return; } if (list.Count >= ushort.MaxValue) { throw new SerializationException($"Tried to serialize a {type} with too many ({list.Count}) items."); } data.WriteUShort((ushort)list.Count); foreach (object e in list) { WriteSyncObject(data, e, listObjType); } return; } if (genericTypeDefinition == typeof(IEnumerable <>)) { IEnumerable e = (IEnumerable)obj; Type elementType = type.GetGenericArguments()[0]; var listType = typeof(List <>).MakeGenericType(elementType); if (e == null) { WriteSyncObject(data, null, listType); return; } IList list = (IList)Activator.CreateInstance(listType); foreach (var o in e) { list.Add(o); } WriteSyncObject(data, list, listType); return; } if (genericTypeDefinition == typeof(Nullable <>)) { bool isNull = obj == null; data.WriteBool(isNull); if (isNull) { return; } WriteSyncObject(data, obj, Nullable.GetUnderlyingType(type)); return; } if (genericTypeDefinition == typeof(Dictionary <,>)) { IDictionary dictionary = (IDictionary)obj; Type[] arguments = type.GetGenericArguments(); if (dictionary == null) { WriteSyncObject(data, null, arguments[0].MakeArrayType()); return; } Array keyArray = Array.CreateInstance(arguments[0], dictionary.Count); dictionary.Keys.CopyTo(keyArray, 0); Array valueArray = Array.CreateInstance(arguments[1], dictionary.Count); dictionary.Values.CopyTo(valueArray, 0); WriteSyncObject(data, keyArray, keyArray.GetType()); WriteSyncObject(data, valueArray, valueArray.GetType()); return; } if (genericTypeDefinition == typeof(Pair <,>)) { Type[] arguments = type.GetGenericArguments(); WriteSyncObject(data, AccessTools.DeclaredField(type, "first").GetValue(obj), arguments[0]); WriteSyncObject(data, AccessTools.DeclaredField(type, "second").GetValue(obj), arguments[1]); return; } if (typeof(ITuple).IsAssignableFrom(genericTypeDefinition)) // ValueTuple or Tuple { Type[] arguments = type.GetGenericArguments(); ITuple tuple = (ITuple)obj; data.WriteInt32(tuple.Length); for (int i = 0; i < tuple.Length; i++) { WriteSyncObject(data, tuple[i], arguments[i]); } return; } } if (typeof(ISyncSimple).IsAssignableFrom(type)) { foreach (var field in AccessTools.GetDeclaredFields(type)) { WriteSyncObject(data, field.GetValue(obj), field.FieldType); } return; } // Special case if (typeof(Def).IsAssignableFrom(type)) { if (obj is not Def def) { data.WriteUShort(ushort.MaxValue); return; } var defTypeIndex = Array.IndexOf(DefSerialization.DefTypes, def.GetType()); if (defTypeIndex == -1) { throw new SerializationException($"Unknown def type {def.GetType()}"); } data.WriteUShort((ushort)defTypeIndex); data.WriteUShort(def.shortHash); return; } // Special case for Designators to change the type if (typeof(Designator).IsAssignableFrom(type)) { data.WriteUShort((ushort)Array.IndexOf(ImplSerialization.designatorTypes, obj.GetType())); } // Where the magic happens if (SyncDict.syncWorkers.TryGetValue(type, out var syncWorkerEntry)) { syncWorkerEntry.Invoke(new WritingSyncWorker(data), ref obj); return; } log?.Node("No writer for " + type); throw new SerializationException("No writer for type " + type); } catch { Log.Error($"Multiplayer: Error writing type: {type}, obj: {obj}, obj type: {obj?.GetType()}"); throw; } finally { log?.Exit(); } }
private static IEnumerable <CodeInstruction> InitializeTranspiler(IEnumerable <CodeInstruction> instructions, MethodBase method) { var instructionsList = instructions.ToList(); IEnumerable <CodeInstruction> ReturnDefault(string place) { Utils.DisplayUserWarning("Failed to patch WidgetPrefab.LoadFrom! {0}", place); return(instructionsList.AsEnumerable()); } var locals = method.GetMethodBody()?.LocalVariables; var typeLocal = locals?.FirstOrDefault(x => x.LocalType == typeof(Type)); if (typeLocal is null) { return(ReturnDefault("Local not found")); } var startIndex = -1; var endIndex = -1; for (var i = 0; i < instructionsList.Count - 5; i++) { if (!instructionsList[i + 0].IsLdarg(0)) { continue; } if (!instructionsList[i + 1].LoadsField(AccessTools.DeclaredField(typeof(WidgetFactory), "_builtinTypes"))) { continue; } if (!instructionsList[i + 2].IsLdloc()) { continue; } if (!instructionsList[i + 3].Calls(AccessTools.DeclaredPropertyGetter(typeof(MemberInfo), nameof(MemberInfo.Name)))) { continue; } if (!instructionsList[i + 4].IsLdloc()) { continue; } if (!instructionsList[i + 5].Calls(SymbolExtensions.GetMethodInfo((Dictionary <string, Type> d) => d.Add(null !, null !)))) { continue; } startIndex = i; endIndex = i + 5; break; } if (startIndex == -1) { return(ReturnDefault("Pattern not found")); } if (instructionsList[endIndex + 1].labels.Count == 0) { return(ReturnDefault("Jmp was not found")); } var jmpEnumerator = instructionsList[endIndex + 1].labels.FirstOrDefault(); // if (!this._builtinTypes.ContainsKey(type.Name)) instructionsList.InsertRange(startIndex, new List <CodeInstruction> { new(OpCodes.Ldarg_0), new(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(WidgetFactory), "_builtinTypes")), new(OpCodes.Ldloc, typeLocal.LocalIndex), new(OpCodes.Callvirt, AccessTools.DeclaredPropertyGetter(typeof(MemberInfo), nameof(MemberInfo.Name))), new(OpCodes.Callvirt, SymbolExtensions.GetMethodInfo((Dictionary <string, Type> d) => d.ContainsKey(null !))), new(OpCodes.Brtrue_S, jmpEnumerator) });
static void Prefix(Hud __instance) { if (!modEnabled.Value || !Player.m_localPlayer) { return; } float angle; if (usePlayerDirection.Value) { angle = Player.m_localPlayer.transform.eulerAngles.y; } else { angle = GameCamera.instance.transform.eulerAngles.y; } if (angle > 180) { angle -= 360; } angle *= -Mathf.Deg2Rad; Rect rect = compassObject.GetComponent <Image>().sprite.rect; float imageScale = GameObject.Find("GUI").GetComponent <CanvasScaler>().scaleFactor; compassObject.GetComponent <RectTransform>().localPosition = Vector3.right * (rect.width / 2) * angle / (2f * Mathf.PI) - new Vector3(rect.width * 0.125f, 0, 0); compassObject.GetComponent <Image>().color = compassColor.Value; compassObject.transform.parent.GetComponent <RectTransform>().localScale = Vector3.one * compassScale.Value; compassObject.transform.parent.GetComponent <RectTransform>().anchoredPosition = new Vector2(0f, (Screen.height / imageScale - compassObject.GetComponent <Image>().sprite.texture.height *compassScale.Value) / 2) - Vector2.up * compassYOffset.Value; centerObject.GetComponent <Image>().color = centerColor.Value; centerObject.SetActive(showCenterMarker.Value); int count = pinsObject.transform.childCount; List <string> oldPins = new List <string>(); for (int i = 0; i < count; i++) { oldPins.Add(pinsObject.transform.GetChild(i).name); } var pinList = new List <Minimap.PinData>(AccessTools.DeclaredField(typeof(Minimap), "m_pins").GetValue(Minimap.instance) as List <Minimap.PinData>); pinList.AddRange((AccessTools.DeclaredField(typeof(Minimap), "m_locationPins").GetValue(Minimap.instance) as Dictionary <Vector3, Minimap.PinData>).Values); if (showPlayerMarkers.Value) { pinList.AddRange((AccessTools.DeclaredField(typeof(Minimap), "m_playerPins").GetValue(Minimap.instance) as List <Minimap.PinData>)); } Minimap.PinData deathPin = AccessTools.DeclaredField(typeof(Minimap), "m_deathPin").GetValue(Minimap.instance) as Minimap.PinData; if (deathPin != null) { pinList.Add(deathPin); } string[] ignoredNames = ignoredMarkerNames.Value.Split(','); //string[] unlimitedRangeMarkerNamesList = unlimitedRangeMarkerNames.Value.Split(','); Transform pt = Player.m_localPlayer.transform; float zeroScaleDistance = maxMarkerDistance.Value / (1 - minMarkerScale.Value); foreach (Minimap.PinData pin in pinList) { string name = pin.m_pos.ToString(); oldPins.Remove(name); var t = pinsObject.transform.Find(name); if (ignoredNames.Contains(pin.m_name) || Array.Exists(ignoredNames, s => s.EndsWith("*") && name.StartsWith(s.Substring(0, s.Length - 1))) || Vector3.Distance(pt.position, pin.m_pos) > maxMarkerDistance.Value || Vector3.Distance(pt.position, pin.m_pos) < minMarkerDistance.Value) { if (t) { t.gameObject.SetActive(false); } continue; } if (t) { t.gameObject.SetActive(true); } Vector3 offset; if (usePlayerDirection.Value) { offset = pt.InverseTransformPoint(pin.m_pos); } else { offset = GameCamera.instance.transform.InverseTransformPoint(pin.m_pos); } angle = Mathf.Atan2(offset.x, offset.z); GameObject po; RectTransform rt; Image img; if (!t) { po = new GameObject(); po.name = pin.m_pos.ToString(); rt = po.AddComponent <RectTransform>(); rt.SetParent(pinsObject.transform); rt.anchoredPosition = Vector2.zero; img = po.AddComponent <Image>(); } else { po = t.gameObject; rt = t.GetComponent <RectTransform>(); img = t.GetComponent <Image>(); } float distanceScale = minMarkerScale.Value < 1 ? (zeroScaleDistance - Vector3.Distance(pt.position, pin.m_pos)) / zeroScaleDistance : 1; rt.localScale = Vector3.one * distanceScale * 0.5f * markerScale.Value; img.color = markerColor.Value; img.sprite = pin.m_icon; rt.localPosition = Vector3.right * (rect.width / 2) * angle / (2f * Mathf.PI); } foreach (string name in oldPins) { Destroy(pinsObject.transform.Find(name).gameObject); } }
public static IEnumerable <CodeInstruction> BuildingDecorationLoadPathsTranspiler <TypeExtension>(IEnumerable <CodeInstruction> instructions) where TypeExtension : IBaseNetAssetDataExtension { var segmentBufferField = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempSegmentBuffer)); var nodeBufferField = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempNodeBuffer)); var clearMethod = AccessTools.DeclaredMethod(nodeBufferField.FieldType, nameof(FastList <ushort> .Clear)); var matchCount = 0; var inserted = false; var enumerator = instructions.GetEnumerator(); var prevPrevInstruction = (CodeInstruction)null; var prevInstruction = (CodeInstruction)null; while (enumerator.MoveNext()) { var instruction = enumerator.Current; if (prevInstruction != null && prevInstruction.opcode == OpCodes.Ldfld && prevInstruction.operand == nodeBufferField && instruction.opcode == OpCodes.Callvirt && instruction.operand == clearMethod) { matchCount += 1; } if (!inserted && matchCount == 2) { yield return(new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(SingletonItem <TypeExtension>), nameof(SingletonItem <TypeExtension> .Instance)))); yield return(new CodeInstruction(OpCodes.Box, typeof(TypeExtension))); yield return(new CodeInstruction(OpCodes.Ldarg_0)); yield return(new CodeInstruction(OpCodes.Ldloc_0)); yield return(new CodeInstruction(OpCodes.Ldfld, segmentBufferField)); yield return(new CodeInstruction(OpCodes.Ldloc_0)); yield return(new CodeInstruction(OpCodes.Ldfld, nodeBufferField)); yield return(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(TypeExtension), nameof(IBaseNetAssetDataExtension.OnPlaceAsset)))); inserted = true; } if (prevPrevInstruction != null) { yield return(prevPrevInstruction); } prevPrevInstruction = prevInstruction; prevInstruction = instruction; } if (prevPrevInstruction != null) { yield return(prevPrevInstruction); } if (prevInstruction != null) { yield return(prevInstruction); } }
public static bool InitMenuItemScript(SceneEdit.SMenuItem mi, string f_strMenuFileName, bool f_bMan, out string IconTex) { var fetchedField = AccessTools.DeclaredField(typeof(SceneEdit), "m_byItemFileBuffer"); var fetchedVal = fetchedField.GetValue(@this) as byte[]; IconTex = null; if (f_strMenuFileName.IndexOf("mod_") == 0) { string modPathFileName = Menu.GetModPathFileName(f_strMenuFileName); return(!string.IsNullOrEmpty(modPathFileName) && SceneEdit.InitModMenuItemScript(mi, modPathFileName)); } try { using (AFileBase afileBase = GameUty.FileOpen(f_strMenuFileName, null)) { NDebug.Assert(afileBase.IsValid(), "メニューファイルが存在しません。 :" + f_strMenuFileName); if (fetchedVal == null) { fetchedVal = new byte[System.Math.Max(500000, afileBase.GetSize())]; } else if (fetchedVal.Length < afileBase.GetSize()) { fetchedVal = new byte[afileBase.GetSize()]; } afileBase.Read(ref fetchedVal, afileBase.GetSize()); } } catch (Exception ex) { Main.logger.LogError(string.Concat(new string[] { "メニューファイルがが読み込めませんでした。 : ", f_strMenuFileName, " : ", ex.Message, " : StackTrace :\n", ex.StackTrace })); throw ex; } BinaryReader binaryReader = new BinaryReader(new MemoryStream(fetchedVal), Encoding.UTF8); string text = binaryReader.ReadString(); NDebug.Assert(text == "CM3D2_MENU", "ProcScriptBin 例外 : ヘッダーファイルが不正です。" + text); int num = binaryReader.ReadInt32(); string path = binaryReader.ReadString(); string text2 = binaryReader.ReadString(); string text3 = binaryReader.ReadString(); string text4 = binaryReader.ReadString(); long num2 = (long)binaryReader.ReadInt32(); int num3 = 0; string text5 = null; string text6 = string.Empty; string text7 = string.Empty; try { for (; ;) { int num4 = (int)binaryReader.ReadByte(); text7 = text6; text6 = string.Empty; if (num4 == 0) { break; } for (int i = 0; i < num4; i++) { text6 = text6 + "\"" + binaryReader.ReadString() + "\" "; } if (!(text6 == string.Empty)) { string stringCom = UTY.GetStringCom(text6); string[] stringList = UTY.GetStringList(text6); if (stringCom == "name") { string text8 = stringList[1]; string text9 = string.Empty; string arg = string.Empty; int j = 0; while (j < text8.Length && text8[j] != '\u3000' && text8[j] != ' ') { text9 += text8[j]; j++; } while (j < text8.Length) { arg += text8[j]; j++; } mi.m_strMenuName = text9; } else if (stringCom == "setumei") { mi.m_strInfo = stringList[1]; mi.m_strInfo = mi.m_strInfo.Replace("《改行》", "\n"); } else if (stringCom == "category") { string strCateName = stringList[1].ToLower(); mi.m_strCateName = strCateName; try { mi.m_mpn = (MPN)Enum.Parse(typeof(MPN), mi.m_strCateName); } catch { Main.logger.LogWarning("カテゴリがありません。" + mi.m_strCateName); mi.m_mpn = MPN.null_mpn; } } else if (stringCom == "color_set") { try { mi.m_eColorSetMPN = (MPN)Enum.Parse(typeof(MPN), stringList[1].ToLower()); } catch { Main.logger.LogWarning("カテゴリがありません。" + mi.m_strCateName); } if (stringList.Length >= 3) { mi.m_strMenuNameInColorSet = stringList[2].ToLower(); } } else if (stringCom == "tex" || stringCom == "テクスチャ変更") { MaidParts.PARTS_COLOR pcMultiColorID = MaidParts.PARTS_COLOR.NONE; if (stringList.Length == 6) { string text10 = stringList[5]; try { pcMultiColorID = (MaidParts.PARTS_COLOR)Enum.Parse(typeof(MaidParts.PARTS_COLOR), text10.ToUpper()); } catch { NDebug.Assert("無限色IDがありません。" + text10, false); } mi.m_pcMultiColorID = pcMultiColorID; } } else if (stringCom == "icon" || stringCom == "icons") { text5 = stringList[1]; } else if (!(stringCom == "iconl")) { if (!(stringCom == "setstr")) { if (!(stringCom == "アイテムパラメータ")) { if (stringCom == "saveitem") { string text11 = stringList[1]; if (text11 == string.Empty) { Main.logger.LogError("err SaveItem \"" + text11); } if (text11 == null) { Main.logger.LogError("err SaveItem null=\"" + text11); } if (text11 != string.Empty) { } } else if (!(stringCom == "catno")) { if (stringCom == "additem") { num3++; } else if (stringCom == "unsetitem") { mi.m_boDelOnly = true; } else if (stringCom == "priority") { mi.m_fPriority = float.Parse(stringList[1]); } else if (stringCom == "メニューフォルダ" && stringList[1].ToLower() == "man") { mi.m_bMan = true; } } } } } } } } catch (Exception ex2) { Main.logger.LogError(string.Concat(new string[] { "Exception ", Path.GetFileName(path), " 現在処理中だった行 = ", text6, " 以前の行 = ", text7, " ", ex2.Message, "StackTrace:\n", ex2.StackTrace })); throw ex2; } if (text5 != null && text5 != string.Empty) { try { IconTex = text5; //mi.m_texIcon = ImportCM.CreateTexture(text5); } catch (Exception) { Main.logger.LogError("Error:"); } } binaryReader.Close(); return(true); }
static IEnumerable <CodeInstruction> OpportunisticJobs(IEnumerable <CodeInstruction> _codes, ILGenerator generator, MethodBase __originalMethod) { var t = new Transpiler(_codes, __originalMethod); var listerHaulablesIdx = t.TryFindCodeIndex(code => code.LoadsField(AccessTools.DeclaredField(typeof(Map), nameof(Map.listerHaulables)))); var skipMod = generator.DefineLabel(); t.TryInsertCodes( -3, (i, codes) => i == listerHaulablesIdx, (i, codes) => new List <CodeInstruction> { new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(Pawn_JobTracker_TryOpportunisticJob_Patch), nameof(IsEnabled))), new CodeInstruction(OpCodes.Brfalse_S, skipMod), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldarg_1), new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(Patch_TryOpportunisticJob), nameof(TryOpportunisticJob))), new CodeInstruction(OpCodes.Ret), }, true); t.codes[t.MatchIdx - 3].labels.Add(skipMod); return(t.GetFinalCodes()); }