private static void Commands_Render(ILContext il) { // Hijack string.Format("\n level: {0}, {1}", xObj, yObj) new ILCursor(il).FindNext(out ILCursor[] found, i => i.MatchLdstr("\n level: {0}, {1}"), i => i.MatchCall(typeof(string), "Format") ); ILCursor c = found[1]; c.Remove(); c.EmitDelegate <Func <string, object, object, string> >((text, xObj, yObj) => { Level level = Engine.Scene as Level; int x = (int)xObj; int y = (int)yObj; int worldX = (int)Math.Round(x + level.LevelOffset.X); int worldY = (int)Math.Round(y + level.LevelOffset.Y); if (MouseButtons.Left.Pressed) { Entity clickedEntity = InfoWatchEntity.FindClickedEntity(); if (clickedEntity != null) { Type type = clickedEntity.GetType(); clickedEntityInfo = "\n entity type: "; if (type.Assembly == typeof(Celeste.Celeste).Assembly) { clickedEntityInfo += type.Name; } else { // StartExport uses a comma as a separator, so we can't use comma, // use @ to place it and replace it back with a comma when looking for the type clickedEntityInfo += type.FullName + "@" + type.Assembly.GetName().Name; } if (clickedEntity.GetEntityData() is { } entityData) { clickedEntityInfo += $"\n entity name: {entityData.Name}"; clickedEntityInfo += $"\n entity id : {entityData.ToEntityId()}"; } ("Info of clicked entity: " + clickedEntityInfo).Log(); } else { clickedEntityInfo = string.Empty; } } else if (MouseButtons.Right.Pressed) { clickedEntityInfo = string.Empty; } return ((string.IsNullOrEmpty(clickedEntityInfo) ? string.Empty : clickedEntityInfo) + $"\n world: {worldX}, {worldY}" + $"\n level: {x}, {y}"); }); }
private static void ExportInfo(InputFrame inputFrame) { InputController controller = Manager.Controller; string output; if (Engine.Scene is Level level) { Player player = level.Tracker.GetEntity <Player>(); if (player == null) { return; } string time = GameInfo.GetChapterTime(level); string pos = player.ToSimplePositionString(CelesteTasModuleSettings.MaxDecimals); string speed = player.Speed.ToSimpleString(Settings.SpeedDecimals); int dashCooldown = (int)GameInfo.GetDashCooldownTimer(player); string statuses = GameInfo.GetStatuses(level, player, dashCooldown); output = string.Join("\t", inputFrame.Line + 1, $"{controller.CurrentFrameInInput}/{inputFrame}", controller.CurrentFrameInTas, time, pos, speed, PlayerStates.GetStateName(player.StateMachine.State), statuses); foreach (string typeName in trackedEntities.Keys) { List <Entity> entities = trackedEntities[typeName].Invoke(); if (entities == null) { continue; } foreach (Entity entity in entities) { output += $"\t{typeName}: {entity.ToSimplePositionString(Settings.CustomInfoDecimals)}"; } } if (InfoCustom.Parse() is { } customInfo&& customInfo.IsNotEmpty()) { output += $"\t{customInfo.ReplaceLineBreak(" ")}"; } if (InfoWatchEntity.GetWatchingEntitiesInfo("\t", true) is { } watchInfo&& watchInfo.IsNotEmpty()) { output += $"\t{watchInfo}"; } } else { string sceneName; if (Engine.Scene is Overworld overworld) { sceneName = $"Overworld {(overworld.Current ?? overworld.Next).GetType().Name}"; } else { sceneName = Engine.Scene.GetType().Name; } output = string.Join("\t", inputFrame.Line + 1, $"{controller.CurrentFrameInInput}/{inputFrame}", controller.CurrentFrameInTas, sceneName); } streamWriter.WriteLine(output); streamWriter.Flush(); }