private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundAheadTime = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundAheadTime && instructionList[i].opcode == OpCodes.Ldfld && ((FieldInfo)instructionList[i].operand).Name == "aheadTime") { foundAheadTime = true; instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, _getAheadTime)); instructionList.Insert(i - 1, new CodeInstruction(OpCodes.Ldloc_3)); instructionList.Insert(i - 1, new CodeInstruction(OpCodes.Ldloc_1)); } } if (!foundAheadTime) { NoodleLogger.Log("Failed to find aheadTime ldfld!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
public static void TryGetPointData(dynamic customData, string pointName, out PointDefinition pointData, Dictionary <string, PointDefinition> pointDefinitions) { dynamic pointString = Trees.at(customData, pointName); switch (pointString) { case null: pointData = null; break; case PointDefinition castedData: pointData = castedData; break; case string castedString: if (!pointDefinitions.TryGetValue(castedString, out pointData)) { NoodleLogger.Log($"Could not find point definition {castedString}!", IPA.Logging.Logger.Level.Error); pointData = null; } break; default: pointData = PointDefinition.DynamicToPointData(pointString); if (pointData != null) { ((IDictionary <string, object>)customData)[pointName] = pointData; } break; } }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundHeadLocalPos = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundHeadLocalPos && instructionList[i].opcode == OpCodes.Call && ((MethodInfo)instructionList[i].operand).Name == "HeadOffsetZ") { foundHeadLocalPos = true; instructionList[i].operand = _headOffsetZNotPsuedo; instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldfld, _headTransformField)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Callvirt, _localPositionMethod)); instructionList.RemoveAt(0); } } if (!foundHeadLocalPos) { NoodleLogger.Log("Failed to find call to HeadOffsetZ!", IPA.Logging.Logger.Level.Error); } instructionList.ForEach(n => NoodleLogger.Log(n)); return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundJumpDuration = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundJumpDuration && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_jumpDuration") { foundJumpDuration = true; instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, _getJumpDuration)); instructionList.Insert(i - 2, new CodeInstruction(OpCodes.Ldarg_1)); } } if (!foundJumpDuration) { NoodleLogger.Log("Failed to find get_jumpDuration call!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundTime = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundTime && instructionList[i].opcode == OpCodes.Stloc_0) { foundTime = true; instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldfld, _obstacleDataField)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 3, new CodeInstruction(OpCodes.Ldfld, _move1DurationField)); instructionList.Insert(i + 4, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 5, new CodeInstruction(OpCodes.Ldfld, _finishMovementTime)); instructionList.Insert(i + 6, new CodeInstruction(OpCodes.Call, _obstacleTimeAdjust)); } } if (!foundTime) { NoodleLogger.Log("Failed to find stloc.0!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundBeatmapData = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundBeatmapData && instructionList[i].opcode == OpCodes.Call && ((MethodInfo)instructionList[i].operand).Name == "CreateTransformedBeatmapData") { foundBeatmapData = true; instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldloc_S, 9)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Ldloc_S, 10)); instructionList.Insert(i + 3, new CodeInstruction(OpCodes.Call, _reorderLineData)); } } if (!foundBeatmapData) { NoodleLogger.Log("Failed to find V_12 stloc.s!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundCondition = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundCondition && instructionList[i].operand is Label && instructionList[i].operand.GetHashCode() == 1) { foundCondition = true; instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldloc_1)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Call, FakeNoteHelper._boundsNullCheck)); instructionList.Insert(i + 3, new CodeInstruction(OpCodes.Brtrue_S, instructionList[i].operand)); } } if (!foundCondition) { NoodleLogger.Log("Failed to find brtrue.s to IL_004E!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
public static IEnumerable <Track> GetTrackArray(dynamic customData, string name = TRACK) { IEnumerable <string> trackNames = ((List <object>)Trees.at(customData, name)).Cast <string>(); if (trackNames == null) { return(null); } HashSet <Track> tracks = new HashSet <Track>(); foreach (string trackName in trackNames) { if (Tracks.TryGetValue(trackName, out Track track)) { tracks.Add(track); } else { NoodleLogger.Log($"Could not find track {trackName}!", IPA.Logging.Logger.Level.Error); } } return(tracks); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundSpawnFlyingSprite = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundSpawnFlyingSprite && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "SpawnFlyingSprite") { foundSpawnFlyingSprite = true; instructionList[i] = new CodeInstruction(OpCodes.Call, SpawnFlyingSpriteHelper._conditionedSpawnFlyingSprite); instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_2)); } } if (!foundSpawnFlyingSprite) { NoodleLogger.Log("Failed to find call to SpawnFlyingSprite", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
// This stupid assert runs a Contains() which is laggy when spawning an insane amount of walls private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundAssert = false; int instructrionListCount = instructionList.Count; for (int i = 0; i < instructrionListCount; i++) { if (!foundAssert && instructionList[i].opcode == OpCodes.Call && ((MethodInfo)instructionList[i].operand).Name == "That") { foundAssert = true; instructionList.RemoveRange(i - 9, 10); } } if (!foundAssert) { NoodleLogger.Log("Failed to find call to That!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundFlipYSide = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundFlipYSide && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_flipYSide") { foundFlipYSide = true; instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, _getFlipYSide)); instructionList.Insert(i - 2, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i - 1, new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(NoteController), "_noteData"))); } } if (!foundFlipYSide) { NoodleLogger.Log("Failed to find Get_flipYSide call!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundBeatmapData = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundBeatmapData && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "GetCopy") { foundBeatmapData = true; // yoink label5 so we can insert our code w/o breaking shit CodeInstruction sourceLabel = instructionList[i - 4]; CodeInstruction newLabel = new CodeInstruction(instructionList[i - 4]); sourceLabel.labels.Clear(); instructionList.Insert(i - 4, newLabel); instructionList.Insert(i - 3, new CodeInstruction(OpCodes.Call, _reorderLineData)); instructionList.Insert(i - 2, new CodeInstruction(OpCodes.Stloc_0)); } } if (!foundBeatmapData) { NoodleLogger.Log("Failed to find GetCopy!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IReadonlyBeatmapData ReorderLineData(IReadonlyBeatmapData beatmapData) { if (beatmapData is CustomBeatmapData) { CustomBeatmapData customBeatmapData = (CustomBeatmapData)beatmapData.GetCopy(); // there is some ambiguity with these variables but who frikkin cares float startHalfJumpDurationInBeats = 4; float maxHalfJumpDistance = 18; float moveDuration = 0.5f; for (int i = 0; i < customBeatmapData.beatmapLinesData.Count; i++) { BeatmapLineData beatmapLineData = customBeatmapData.beatmapLinesData[i] as BeatmapLineData; foreach (BeatmapObjectData beatmapObjectData in beatmapLineData.beatmapObjectsData) { dynamic customData; if (beatmapObjectData is CustomObstacleData || beatmapObjectData is CustomNoteData || beatmapObjectData is CustomWaypointData) { customData = beatmapObjectData; } else { NoodleLogger.Log("beatmapObjectData was not CustomObstacleData, CustomNoteData, or CustomWaypointData"); continue; } dynamic dynData = customData.customData; float noteJumpMovementSpeed = (float?)Trees.at(dynData, NOTEJUMPSPEED) ?? GameplayCoreInstallerInstallBindings.CachedNoteJumpMovementSpeed; float noteJumpStartBeatOffset = (float?)Trees.at(dynData, NOTESPAWNOFFSET) ?? GameplayCoreInstallerInstallBindings.CachedNoteJumpStartBeatOffset; // how do i not repeat this in a reasonable way float num = 60f / (float)Trees.at(dynData, "bpm"); float num2 = startHalfJumpDurationInBeats; while (noteJumpMovementSpeed * num * num2 > maxHalfJumpDistance) { num2 /= 2f; } num2 += noteJumpStartBeatOffset; if (num2 < 1f) { num2 = 1f; } float jumpDuration = num * num2 * 2f; dynData.aheadTime = moveDuration + (jumpDuration * 0.5f); } _beatmapObjectsDataAccessor(ref beatmapLineData) = beatmapLineData.beatmapObjectsData.OrderBy(n => n.time - (float)((dynamic)n).customData.aheadTime).ToList(); } return(customBeatmapData); } NoodleLogger.Log("beatmapData was not CustomBeatmapData", IPA.Logging.Logger.Level.Error); return(beatmapData); }
private void Update() { if (_hitsoundQueue.Count > 0 && Time.frameCount != _lastFrame) { List <NoteController> noteControllers = new List <NoteController>(_hitsoundQueue); _hitsoundQueue.Clear(); noteControllers.ForEach(n => _noteCutSoundEffectManager.HandleNoteWasSpawned(n)); NoodleLogger.Log($"{noteControllers.Count} cut sounds moved to next frame!"); } }
internal void AddPoint(string pointDataName, PointDefinition pointData) { if (!PointData.TryGetValue(pointDataName, out _)) { PointData.Add(pointDataName, pointData); } else { NoodleLogger.Log($"Duplicate point defintion name, {pointDataName} could not be registered!", IPA.Logging.Logger.Level.Error); } }
internal static void Callback(CustomEventData customEventData) { if (customEventData.type == ASSIGNTRACKPARENT) { NoodleParentTrackEventData noodleData = (NoodleParentTrackEventData)NoodleEventDatas[customEventData]; IEnumerable <Track> tracks = noodleData.ChildrenTracks; Track parentTrack = noodleData.ParentTrack; if (tracks != null && parentTrack != null) { ParentObject.AssignTrack(tracks, parentTrack, noodleData.Position, noodleData.Rotation, noodleData.LocalRotation, noodleData.Scale); } else { NoodleLogger.Log($"Missing _parentTrack or _childrenTracks!", IPA.Logging.Logger.Level.Error); } } }
/*public static Track GetTrack(dynamic customData, string name = TRACK) * { * string trackName = Trees.at(customData, name); * if (trackName == null) * { * return null; * } * * if (Tracks.TryGetValue(trackName, out Track track)) * { * return track; * } * else * { * NoodleLogger.Log($"Could not find track {trackName}!", IPA.Logging.Logger.Level.Error); * return null; * } * }*/ public static Track GetTrackPreload(dynamic customData, IReadonlyBeatmapData beatmapData, string name = TRACK) { string trackName = Trees.at(customData, name); if (trackName == null) { return(null); } if (((CustomBeatmapData)beatmapData).customData.tracks.TryGetValue(trackName, out Track track)) { return(track); } else { NoodleLogger.Log($"Could not find track {trackName}!", IPA.Logging.Logger.Level.Error); return(null); } }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundLabel = false; bool foundBounds = false; Label?label = null; for (int i = 0; i < instructionList.Count; i++) { if (!foundLabel && instructionList[i].operand is Label operandLabel && instructionList[i].operand.GetHashCode() == 0) { foundLabel = true; label = operandLabel; } if (!foundBounds && label.HasValue && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_bounds") { foundBounds = true; instructionList.Insert(i - 1, new CodeInstruction(OpCodes.Ldloc_1)); instructionList.Insert(i, new CodeInstruction(OpCodes.Call, FakeNoteHelper._boundsNullCheck)); instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Brtrue_S, label.Value)); } } if (!foundLabel) { NoodleLogger.Log("Failed to find br to IL_0134!", IPA.Logging.Logger.Level.Error); } if (!foundBounds) { NoodleLogger.Log("Failed to find callvirt to get_bounds!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
public static Track GetTrack(dynamic customData, string name = TRACK) { string trackName = Trees.at(customData, name); if (trackName == null) { return(null); } if (Tracks.TryGetValue(trackName, out Track track)) { return(track); } else { NoodleLogger.Log($"Could not find track {trackName}!", IPA.Logging.Logger.Level.Error); return(null); } }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundInit = false; bool foundJumpStartPos = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundJumpStartPos && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_jumpStartPos") { foundJumpStartPos = true; instructionList.RemoveRange(i - 2, 4); instructionList.Insert(i - 2, new CodeInstruction(OpCodes.Call, _getNoteControllerPosition)); } } for (int i = 0; i < instructionList.Count; i++) { if (!foundInit && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "Init") { foundInit = true; instructionList[i - 1] = new CodeInstruction(OpCodes.Call, _getNoteControllerRotation); } } if (!foundJumpStartPos) { NoodleLogger.Log("Failed to find callvirt to get_jumpStartPos!", IPA.Logging.Logger.Level.Error); } if (!foundInit) { NoodleLogger.Log("Failed to find callvirt to Init!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundFinalPosition = false; bool foundPosition = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundFinalPosition && instructionList[i].opcode == OpCodes.Stfld && ((FieldInfo)instructionList[i].operand).Name == "_localPosition") { foundFinalPosition = true; instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, _definiteNoteFloorMovement)); } if (!foundPosition && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "set_position") { foundPosition = true; instructionList[i].operand = _setLocalPosition; } } if (!foundFinalPosition) { NoodleLogger.Log("Failed to find _localPosition stfld!", IPA.Logging.Logger.Level.Error); } if (!foundPosition) { NoodleLogger.Log("Failed to find callvirt to set_position!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
// Because we reorder beatmapLinesData for per object njs/offset, it messes up this script (which is super pepega pls beat games fix), so we resort beatmapLinesData in here private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundLinesData = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundLinesData && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_beatmapLinesData") { foundLinesData = true; instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, _sortBeatmapLinesData)); } } if (!foundLinesData) { NoodleLogger.Log("Failed to find callvirt to get_beatmapLinesData!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundIntersectingObstacles = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundIntersectingObstacles && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_intersectingObstacles") { foundIntersectingObstacles = true; instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, FakeNoteHelper._obstacleFakeCheck)); } } if (!foundIntersectingObstacles) { NoodleLogger.Log("Failed to find callvirt to get_intersectingObstacles!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> instructionList = instructions.ToList(); bool foundTime = false; bool foundFinalPosition = false; bool foundZOffset = false; bool foundLook = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundTime && instructionList[i].opcode == OpCodes.Stloc_0) { foundTime = true; instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldfld, _jumpDurationField)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Call, _noteJumpTimeAdjust)); } if (!foundFinalPosition && instructionList[i].opcode == OpCodes.Stind_R4) { foundFinalPosition = true; instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 3, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 4, new CodeInstruction(OpCodes.Ldfld, _localPositionField)); instructionList.Insert(i + 5, new CodeInstruction(OpCodes.Ldloc_1)); instructionList.Insert(i + 6, new CodeInstruction(OpCodes.Call, _definiteNoteJump)); instructionList.Insert(i + 7, new CodeInstruction(OpCodes.Stfld, _localPositionField)); } // is there a better way of checking labels? if (!foundZOffset && instructionList[i].operand is Label && instructionList[i].operand.GetHashCode() == 21) { foundZOffset = true; // Add addition check to our quirky little variable to skip end position offset when we are using definitePosition instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldsfld, _definitePositionField)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Brtrue_S, instructionList[i].operand)); } // Override all the rotation stuff if (!foundLook && instructionList[i].opcode == OpCodes.Bge_Un && instructionList[i].operand.GetHashCode() == 6) { Label label = (Label)instructionList[i].operand; int endIndex = instructionList.FindIndex(n => n.labels.Contains(label)); foundLook = true; instructionList.RemoveRange(i + 1, endIndex - i - 1); // This is where the fun begins CodeInstruction[] codeInstructions = new CodeInstruction[] { new CodeInstruction(OpCodes.Ldloc_1), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _startRotationField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _middleRotationField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _endRotationField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _playerTransformsField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _rotatedObjectField), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Call, _getTransform), new CodeInstruction(OpCodes.Ldarg_0), new CodeInstruction(OpCodes.Ldfld, _inverseWorldRotationField), new CodeInstruction(OpCodes.Call, _doNoteLook), }; instructionList.InsertRange(i + 1, codeInstructions); } } if (!foundTime) { NoodleLogger.Log("Failed to find stloc.0!", IPA.Logging.Logger.Level.Error); } if (!foundFinalPosition) { NoodleLogger.Log("Failed to find stind.r4!", IPA.Logging.Logger.Level.Error); } if (!foundZOffset) { NoodleLogger.Log("Failed to find brfalse.s to Label21!", IPA.Logging.Logger.Level.Error); } if (!foundLook) { NoodleLogger.Log("Failed to find bge.un to Label6!", IPA.Logging.Logger.Level.Error); } return instructionList.AsEnumerable(); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundTime = false; bool foundFinalPosition = false; bool foundTransformUp = false; bool foundZOffset = false; for (int i = 0; i < instructionList.Count; i++) { if (!foundTime && instructionList[i].opcode == OpCodes.Stloc_0) { foundTime = true; instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldfld, _jumpDurationField)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Call, _noteJumpTimeAdjust)); } if (!foundFinalPosition && instructionList[i].opcode == OpCodes.Stind_R4) { foundFinalPosition = true; instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 3, new CodeInstruction(OpCodes.Ldarg_0)); instructionList.Insert(i + 4, new CodeInstruction(OpCodes.Ldfld, _localPositionField)); instructionList.Insert(i + 5, new CodeInstruction(OpCodes.Ldloc_1)); instructionList.Insert(i + 6, new CodeInstruction(OpCodes.Call, _definiteNoteJump)); instructionList.Insert(i + 7, new CodeInstruction(OpCodes.Stfld, _localPositionField)); } if (!foundTransformUp && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_up") { foundTransformUp = true; instructionList[i] = new CodeInstruction(OpCodes.Call, _convertToLocalSpace); instructionList.RemoveRange(i + 1, 8); instructionList.RemoveRange(i - 5, 3); instructionList.Insert(i - 5, new CodeInstruction(OpCodes.Ldloc_S, 5)); instructionList.Insert(i - 5, new CodeInstruction(OpCodes.Ldloca_S, 6)); } // is there a better way of checking labels? if (!foundZOffset && instructionList[i].operand is Label && instructionList[i].operand.GetHashCode() == 21) { foundZOffset = true; // Add addition check to our quirky little variable to skip end position offset when we are using definitePosition instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Ldsfld, _definitePositionField)); instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Brtrue_S, instructionList[i].operand)); } } if (!foundTime) { NoodleLogger.Log("Failed to find stloc.0!", IPA.Logging.Logger.Level.Error); } if (!foundFinalPosition) { NoodleLogger.Log("Failed to find stind.r4!", IPA.Logging.Logger.Level.Error); } if (!foundTransformUp) { NoodleLogger.Log("Failed to find call to get_up!", IPA.Logging.Logger.Level.Error); } if (!foundZOffset) { NoodleLogger.Log("Failed to find brfalse.s to Label21!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
private static IEnumerable <CodeInstruction> Transpiler(IEnumerable <CodeInstruction> instructions) { List <CodeInstruction> instructionList = instructions.ToList(); bool foundRotation = false; bool foundWidth = false; bool foundLength = false; int instructrionListCount = instructionList.Count; for (int i = 0; i < instructrionListCount; i++) { if (!foundRotation && instructionList[i].opcode == OpCodes.Stfld && ((FieldInfo)instructionList[i].operand).Name == "_worldRotation") { foundRotation = true; instructionList[i - 1] = new CodeInstruction(OpCodes.Call, _getWorldRotation); instructionList[i - 4] = new CodeInstruction(OpCodes.Ldarg_1); instructionList.RemoveAt(i - 2); instructionList.RemoveRange(i + 1, 2); instructionList[i + 1] = new CodeInstruction(OpCodes.Ldarg_0); instructionList[i + 2] = new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(ObstacleController), "_worldRotation")); instructionList[i + 3] = new CodeInstruction(OpCodes.Call, _invertQuaternion); } if (!foundWidth && instructionList[i].opcode == OpCodes.Callvirt && ((MethodInfo)instructionList[i].operand).Name == "get_width") { foundWidth = true; instructionList.Insert(i + 2, new CodeInstruction(OpCodes.Ldarg_1)); instructionList.Insert(i + 3, new CodeInstruction(OpCodes.Call, _getCustomWidth)); } if (!foundLength && instructionList[i].opcode == OpCodes.Stloc_2) { foundLength = true; instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_1)); instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, _getCustomLength)); } } if (!foundRotation) { NoodleLogger.Log("Failed to find _worldRotation stfld!", IPA.Logging.Logger.Level.Error); } if (!foundWidth) { NoodleLogger.Log("Failed to find get_width call!", IPA.Logging.Logger.Level.Error); } if (!foundLength) { NoodleLogger.Log("Failed to find stloc.2!", IPA.Logging.Logger.Level.Error); } return(instructionList.AsEnumerable()); }
internal static void StartEventCoroutine(CustomEventData customEventData, EventType eventType) { Track track = GetTrack(customEventData.data); if (track != null) { float duration = (float?)Trees.at(customEventData.data, DURATION) ?? 0f; duration = 60f * duration / Instance.BeatmapObjectSpawnController.currentBpm; // Convert to real time; string easingString = (string)Trees.at(customEventData.data, EASING); Functions easing = Functions.easeLinear; if (easingString != null) { easing = (Functions)Enum.Parse(typeof(Functions), easingString); } List <string> excludedStrings = new List <string> { TRACK, DURATION, EASING }; IDictionary <string, object> eventData = new Dictionary <string, object>(customEventData.data as IDictionary <string, object>); // Shallow copy IDictionary <string, Property> properties = null; switch (eventType) { case EventType.AnimateTrack: properties = track.Properties; break; case EventType.AssignPathAnimation: properties = track.PathProperties; break; default: return; } foreach (KeyValuePair <string, object> valuePair in eventData) { if (!excludedStrings.Any(n => n == valuePair.Key)) { if (!properties.TryGetValue(valuePair.Key, out Property property)) { NoodleLogger.Log($"Could not find property {valuePair.Key}!", IPA.Logging.Logger.Level.Error); continue; } TryGetPointData(customEventData.data, valuePair.Key, out PointDefinition pointData); if (property.Coroutine != null) { Instance.StopCoroutine(property.Coroutine); } if (pointData == null) { switch (eventType) { case EventType.AnimateTrack: property.Value = null; break; case EventType.AssignPathAnimation: ((PointDefinitionInterpolation)property.Value).Init(null); break; } } else { switch (eventType) { case EventType.AnimateTrack: property.Coroutine = Instance.StartCoroutine(AnimateTrack.AnimateTrackCoroutine(pointData, property, duration, customEventData.time, easing)); break; case EventType.AssignPathAnimation: ((PointDefinitionInterpolation)property.Value).Init(pointData); property.Coroutine = Instance.StartCoroutine(AssignPathAnimation.AssignPathAnimationCoroutine(property, duration, customEventData.time, easing)); break; } } } } } }
private static NoodleCoroutineEventData ProcessCoroutineEvent(CustomEventData customEventData, IReadonlyBeatmapData beatmapData) { NoodleCoroutineEventData noodleEventData = new NoodleCoroutineEventData(); string easingString = (string)Trees.at(customEventData.data, EASING); noodleEventData.Easing = Functions.easeLinear; if (easingString != null) { noodleEventData.Easing = (Functions)Enum.Parse(typeof(Functions), easingString); } noodleEventData.Duration = (float?)Trees.at(customEventData.data, DURATION) ?? 0f; Track track = GetTrackPreload(customEventData.data, beatmapData); if (track == null) { return(null); } EventType eventType; switch (customEventData.type) { case ANIMATETRACK: eventType = EventType.AnimateTrack; break; case ASSIGNPATHANIMATION: eventType = EventType.AssignPathAnimation; break; default: return(null); } List <string> excludedStrings = new List <string> { TRACK, DURATION, EASING }; IDictionary <string, object> eventData = new Dictionary <string, object>(customEventData.data as IDictionary <string, object>); // Shallow copy IDictionary <string, Property> properties = null; switch (eventType) { case EventType.AnimateTrack: properties = track.Properties; break; case EventType.AssignPathAnimation: properties = track.PathProperties; break; } foreach (KeyValuePair <string, object> valuePair in eventData) { if (!excludedStrings.Any(n => n == valuePair.Key)) { if (!properties.TryGetValue(valuePair.Key, out Property property)) { NoodleLogger.Log($"Could not find property {valuePair.Key}!", IPA.Logging.Logger.Level.Error); continue; } Dictionary <string, PointDefinition> pointDefinitions = Trees.at(((CustomBeatmapData)beatmapData).customData, "pointDefinitions"); TryGetPointData(customEventData.data, valuePair.Key, out PointDefinition pointData, pointDefinitions); NoodleCoroutineEventData.CoroutineInfo coroutineInfo = new NoodleCoroutineEventData.CoroutineInfo() { PointDefinition = pointData, Property = property, }; noodleEventData.CoroutineInfos.Add(coroutineInfo); } } return(noodleEventData); }