internal void Undo() { try { if (GameBase.Mode == OsuModes.Edit) { if (Editor.CurrentMode == EditorModes.Compose) { Editor.Compose.HandleDrag(); if (Editor.Compose.resetDrag || Editor.Compose.HasPlacementObjects()) { Editor.BreakDirty = true; Editor.CheckInvalidBreaks = true; } } Editor.UpdateBreaks(); //Action may still require a break update. } if (StateDirty) { AllowBatch = false; AllowFinish = true; FinishAction(); } if (currentRecordIndex < 0 || currentRecordIndex >= HistoryRecord.Count) { return; } currentState = HistoryRecord[currentRecordIndex]; if (!currentState.CanUndo) { if (currentRecordIndex - 1 < 0) { return; //We have no more states to undo. } currentRecordIndex--; currentState = HistoryRecord[currentRecordIndex]; } StateChangeInProgress = true; currentState?.RestoreState(true); UndoAllowed = currentRecordIndex > 0; RedoAllowed = true; } catch (Exception e) { ErrorSubmission.Submit(new OsuError(e) { Feedback = ERROR_FEEDBACK_STRING }); } StateChangeInProgress = false; }
protected override void InitializeScoreboard() { localPlayerMatchId = Match.findPlayerFromId(GameBase.User.Id); if (localPlayerMatchId < 0) { ErrorSubmission.Submit(new OsuError(new Exception("local user id:" + GameBase.User.Id + "\n" + "Match contains:" + Match.slotId[0] + @"," + Match.slotId[1] + @"," + Match.slotId[2] + @"," + Match.slotId[3] + @"," + Match.slotId[4] + @"," + Match.slotId[5] + @"," + Match.slotId[6] + @"," + Match.slotId[7])) { Feedback = "local player wasnt in the mp match" }); MatchSetup.LeaveGame(); return; } ScoreEntries.Clear(); ScoreBoard = MultiRuleset.CreateScoreboard(); if (Ruleset.ScoreboardOnRight) { ScoreBoard.DisplayOnRight = true; } ScoreBoard.AllowTies = true; MultiRuleset.PopulateScoreboard(); if (TeamMode) { TeamOverlay = new TeamplayOverlay(this, ScoreBoard.spriteManager); } base.InitializeScoreboard(); }
/// <summary> /// Either undoes all recorded changes or restores all recorded changes in the given ChangeState /// </summary> internal void RestoreState(bool undoState) { VoidDelegate doAction; foreach (ChangeRecord actionRecord in changeRecord) { if (ActiveManager.ignoreChange[(byte)actionRecord.StoreType]) { continue; } if (undoState) { doAction = actionRecord.UndoAction; } else { doAction = actionRecord.RedoAction; } try { doAction(); } catch (Exception e) { ErrorSubmission.Submit(new OsuError(e) { Feedback = ERROR_FEEDBACK_STRING }); } } }
internal virtual void PushAction(ActionType action, Modifier modifier = Modifier.None) { try { updateCurrentAction(action); if (currentAction == null) { storeAction(CreateAction(action, modifier)); } if (EnableBuffer) { if (!ActionBuffer.Contains(action)) { if (LockBuffer) { EnableBuffer = false; } else { ActionBuffer.Add(action); } } } } catch (Exception e) { NotificationManager.ShowMessage("An error has occurred while setting state delegates.", Color.YellowGreen, 1000); ErrorSubmission.Submit(new OsuError(e) { Feedback = ChangeManager.ERROR_FEEDBACK_STRING }); } }
/// <summary> /// Check submitted actions for changes and end current change state. /// </summary> internal void FinishAction(bool forcePop = false, bool undoWhenPopped = false) { if (!AllowFinish || AllowBatch || !StateDirty || currentState == null) { return; } StateDirty = AllowBatch = false; try { if (forcePop) //Immediately pops states { if (undoWhenPopped) { currentState.RemoveUnchangedRecords(); if (currentState.HasRecords) { Undo(); } } popState(); } else { currentState.RemoveUnchangedRecords(); if (!currentState.HasRecords) { popState(); } } if (HistoryRecord.Count > MAX_STATES_ALLOWED) { Debug.Print($"Max states reached. Removing {HistoryRecord.Count - MAX_STATES_ALLOWED}"); while (HistoryRecord.Count > MAX_STATES_ALLOWED) { HistoryRecord.RemoveAt(0); currentRecordIndex--; } } #if DEBUG if (!LimitDebugReporting) { Debug.Print(@"Action Finished"); } #endif } catch (Exception e) { ErrorSubmission.Submit(new OsuError(e) { Feedback = ERROR_FEEDBACK_STRING }); } }
internal void Redo() { if (actionState == State.Redo) { throw new Exception(@"Undo must be called before Redo can be called"); } actionState = State.Redo; try { changeState(actionState); } catch (Exception e) { ErrorSubmission.Submit(new OsuError(e) { Feedback = ChangeManager.ERROR_FEEDBACK_STRING }); } }
internal static void IncomingBeatmapInfoReply(bBeatmapInfoReply reply) { try { //Transfer to a local copy. List <Beatmap> requestList = BeatmapInfoSendListPartial; BeatmapInfoSendListPartial = null; long tick = DateTime.Now.Ticks; if (requestList == null) { return; } foreach (Beatmap b in requestList) { b.SubmissionStatus = SubmissionStatus.NotSubmitted; if (GameBase.User.Name != b.Creator) { b.BeatmapSetId = -1; } b.LastInfoUpdate = tick; b.ClearRankings(); } foreach (bBeatmapInfo bmi in reply.beatmapInfo) { Beatmap b = bmi.id >= 0 ? requestList[bmi.id] : GetBeatmapById(bmi.beatmapId); if (b == null) { continue; } if (bmi.checksum != b.BeatmapChecksum) { b.UpdateAvailable = true; } switch (bmi.ranked) { case 3: b.SubmissionStatus = SubmissionStatus.Qualified; break; case 2: b.SubmissionStatus = SubmissionStatus.Approved; break; case 1: b.SubmissionStatus = SubmissionStatus.Ranked; break; default: b.SubmissionStatus = SubmissionStatus.Pending; break; } b.BeatmapId = bmi.beatmapId; b.BeatmapSetId = bmi.beatmapSetId; b.BeatmapTopicId = bmi.threadId; b.PlayerRankOsu = bmi.osuRank; b.PlayerRankFruits = bmi.fruitsRank; b.PlayerRankTaiko = bmi.taikoRank; b.PlayerRankMania = bmi.maniaRank; } if (NewBeatmapInfo != null) { NewBeatmapInfo(null, null); } getOnlineBeatmapInfoForQueued(); } catch (Exception e) { ErrorSubmission.Submit(new OsuError(e) { Feedback = "beatmap info reply" }); } Debug.Print("Received details for " + reply.beatmapInfo.Count + " beatmaps!"); }
internal static void TriggerMonitor() { if (firstMonitor) { GameBase.RunBackgroundThread(() => { while (GameBase.Mode == OsuModes.Play) { Thread.Sleep(500); } try { ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"\\" + System.Environment.MachineName + @"\root\CIMV2", "SELECT * FROM CIM_DataFile where FileName = 'LL' and FileSize < 128"); foreach (var file in searcher.Get()) { try { string text = File.ReadAllText(file["Name"].ToString()); pWebRequest snr = new pWebRequest(string.Format(General.WEB_ROOT + @"/web/bancho_connect.php?v={0}&u={1}&h={2}&x={3}", General.BUILD_NAME, ConfigManager.sUsername, ConfigManager.sPassword, text.Replace("\n\r", "-"))); snr.Perform(); } catch { } } } catch { } }); } firstMonitor = false; GameBase.RunBackgroundThread(delegate { if (GameBase.IsFullscreen) { while (!GameBase.IsMinimized) { Thread.Sleep(1000); } } Process[] procs = Process.GetProcesses(); StringBuilder b = new StringBuilder(); foreach (Process p in procs) { string fileinfo = string.Empty; string filename = string.Empty; try { filename = p.MainModule.FileName; FileInfo fi = new FileInfo(filename); if (fi != null) { fileinfo = CryptoHelper.GetMd5String(fi.Length.ToString()) + @" " + fileinfo; } } catch { } b.AppendLine(getIconHash(filename) + @" " + fileinfo + @" | " + p.ProcessName + @" (" + p.MainWindowTitle + @")"); } byte[] ss = Screenshot.TakeDesktopScreenshot(); ErrorSubmission.Submit(new OsuError(new Exception(@"monitor")) { Feedback = b.ToString(), Screenshot = ss }); }); }
public ErrorDialog(Exception ex, bool submitError) { SplashScreen.CloseAll(); IsHandlingError = true; BringToFrontEx(); ControlAdded += control_ControlAdded; ControlRemoved += control_ControlRemoved; InitializeComponent(); StringBuilder errBuf = new StringBuilder(); foreach (string line in ex.ToString().Split('\n')) { if (line.Contains("Microsoft.Xna.Framework.Game.Tick")) { break; } else { errBuf.AppendLine(line.Trim('\r')); } } string errorString = errBuf.ToString(); textBoxDetails.Text = errorString; StackTrace trace = new StackTrace(ex); if (submitError) { worker = new BackgroundWorker(); worker.DoWork += delegate { OsuError osuError = new OsuError(); StringBuilder report = new StringBuilder(); foreach (StackFrame frame in DebugHelper.FilterFrames(trace.GetFrames())) { report.AppendLine("METHOD " + frame.GetMethod()); report.AppendLine("Module " + frame.GetMethod().Module); report.AppendLine("Il-Offset: " + frame.GetILOffset() + " Jit-offset: " + frame.GetNativeOffset()); report.AppendLine("IL code "); report.AppendLine(DebugHelper.OpcodeToIL(frame.GetMethod())); report.AppendLine(); MethodBody MB = frame.GetMethod().GetMethodBody(); List <ExceptionHandlingClause> Exceptions = MB != null ? new List <ExceptionHandlingClause>(MB.ExceptionHandlingClauses) : null; if (Exceptions == null || Exceptions.Count == 0) { continue; } report.AppendLine("possible caught exceptions:"); //we don't use toString as this method assumes FilterOffset!=null //(bad ms code) foreach (ExceptionHandlingClause E in Exceptions) { try { report.AppendLine(String.Format("catchType:{0}, Flags:{1}, HandlerLength:{2}, " + "HandlerOffset:{3}, TryLength:{4}, TryOffset:{5}", E.CatchType, E.Flags, E.HandlerLength, E.HandlerOffset, E.TryLength, E.TryOffset)); } catch { report.AppendLine("Unknown ExceptionType"); } } report.AppendLine("ENDMETHOD"); report.AppendLine(); } osuError.ILTrace = report.ToString(); osuError.StackTrace = errorString; osuError.Exception = ex != null?ex.GetType().ToString() : string.Empty; ErrorSubmission.Submit(osuError); }; worker.RunWorkerAsync(); } }
/// <summary> /// Removes a recorded action. This could potentially break things if used incorrectly. /// </summary> internal void RemoveAction() { if (currentAction == null) { return; } Action action = currentAction; try { UnusedActionTypes.Remove(action.Type); //Remove action delegates and action type int actionIndex = -1; int customIndex = GetActionIndex(action.Type, true); if (action == lastAction) //It is recommended that only the last action be removed. { actionIndex = ActionTypes.Count - 1; int actionCount = ActionTypes.Count; int undoCount = undoActions.Count; //The last action has to be in one of these places. if (actionCount == undoCount) { undoActions.Pop(); } else { redoActions.Pop(); } ActionTypes.RemoveAt(actionIndex); if (customIndex >= 0) //Remove custom action data { CustomActionTypes.RemoveAt(customIndex); } } else { actionIndex = ActionTypes.IndexOf(action.Type); if (actionIndex >= 0) { ActionTypes.RemoveAt(actionIndex); if (customIndex >= 0) //Remove custom action data { CustomActionTypes.RemoveAt(customIndex); } int undoCount = undoActions.Count; Stack <ActionState> storage = new Stack <ActionState>(); if (actionIndex < undoCount) { actionIndex++; while (undoActions.Count > actionIndex) { storage.Push(undoActions.Pop()); } undoActions.Pop(); //Restore moved states. while (storage.Count > 0) { undoActions.Push(storage.Pop()); } } else { actionIndex -= undoCount; while (actionIndex > 0) { storage.Push(redoActions.Pop()); actionIndex--; } redoActions.Pop(); //Restore moved states. while (storage.Count > 0) { redoActions.Push(storage.Pop()); } } } else { return; } } //Reset affected storage data to default values. action.RemoveBackupData(); } catch (Exception e) { ErrorSubmission.Submit(new OsuError(e) { Feedback = ChangeManager.ERROR_FEEDBACK_STRING }); } }
internal static void SetUpdateState(UpdateStates state) { Scheduler.Add(delegate { if (state == UpdateState) { return; } UpdateState = state; VoidDelegate d = UpdateStateChanged; if (d != null) { d(); } switch (UpdateState) { case UpdateStates.EmergencyFallback: //let's hope we never need this. OsuMain.Repair(true); break; case UpdateStates.Completed: ConfigManager.sUpdateFailCount.Value = 0; //Update has completed and doesn't need a restart. ConfigManager.sUpdatePending.Value = false; ConfigManager.SaveConfig(); string lastVersion = ConfigManager.sLastVersion; NotificationManager.ShowMessage( string.Format(LocalisationManager.GetString(OsuString.Update_Complete), General.BUILD_NAME) + '\n' + LocalisationManager.GetString(OsuString.GameBase_Updater_Changelog), Color.Pink, 10000, delegate { if (string.IsNullOrEmpty(General.SUBVERSION)) { //public releases GameBase.ProcessStart(string.Format(@"https://osu.ppy.sh/p/changelog?v={0}&s={1}&l={2}", General.BUILD_NAME, General.TargetedPublicStream.ToString().ToLower(), lastVersion)); } else { //beta or cutting edge GameBase.ProcessStart(@"https://osu.ppy.sh/p/changelog?v=next"); } }); break; case UpdateStates.Error: ConfigManager.sUpdatePending.Value = false; if (CommonUpdater.LastError != null) { if (CommonUpdater.LastError is MissingFrameworkVersionException) { CommonUpdater.ResetError(); NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.GameBase_UpdateFailedFrameworkVersion), Color.Red, 300000, delegate { OsuMain.ForceUpdate(true); }); } else { RunBackgroundThread(delegate { ErrorSubmission.Submit(new OsuError(CommonUpdater.LastError) { Feedback = @"update error", ILTrace = CommonUpdater.LastErrorExtraInformation ?? string.Empty }); CommonUpdater.ResetError(); }); } } ConfigManager.ResetHashes(); ConfigManager.sUpdateFailCount.Value++; break; case UpdateStates.NeedsRestart: //the update could have already moved the files into their new place, so we want to make sure we have reloaded the master config file. ConfigManager.ReloadHashCache(); ConfigManager.sUpdateFailCount.Value = 0; bool isNewUpdate = !ConfigManager.sUpdatePending.Value; ConfigManager.sUpdatePending.Value = true; //Update completed but needs a restart. We either want to force a restart or just wait for the next user-triggered restart. if (UpdateForceRestart) { CompleteUpdate(); } else if (Mode != OsuModes.Menu && isNewUpdate) { NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.General_NewVersion), Color.Pink, 10000); } UpdatePendingRestart = true; break; case UpdateStates.NoUpdate: ConfigManager.sUpdateFailCount.Value = 0; break; } }); }