Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.IO;
- using System.Text;
- using System.Threading;
- using Microsoft.Xna.Framework;
- using osu.Configuration;
- using osu.Constants;
- using osu.GameModes.Play;
- using osu.GameplayElements.Beatmaps;
- using osu.GameplayElements.Scoring.Processors;
- using osu.Graphics.Notifications;
- using osu.Helpers;
- using osu.Online;
- using osu.Online.Drawable;
- using osu_common;
- using osu_common.Bancho;
- using osu_common.Bancho.Objects;
- using osu_common.Helpers;
- using SevenZip.Compression.LZMA;
- namespace osu.GameplayElements.Scoring
- {
- internal class Score : bSerializable, IComparable<Score>, ICloneable
- {
- internal virtual bool AllowFrameSkipping => true;
- internal virtual float Accuracy => TotalHits > 0 ? (float)(Count50 * 50 + Count100 * 100 + Count300 * 300) / (TotalHits * 300) : 1;
- internal string LocalScoreChecksum => CryptoHelper.GetMd5String(MaxCombo + @"osu" + PlayerName + FileChecksum + TotalScore + Rank);
- internal virtual int TotalHits => Count50 + Count100 + Count300 + CountMiss;
- internal virtual int TotalSuccessfulHits => Count50 + Count100 + Count300;
- internal string ReplayString
- {
- get
- {
- StringBuilder replayData = new StringBuilder();
- if (Replay != null)
- {
- bReplayFrame lastF = new bReplayFrame(0, 0, 0, pButtonState.None);
- foreach (bReplayFrame f in Replay)
- {
- replayData.AppendFormat(@"{0}|{1}|{2}|{3},",
- f.time - lastF.time, (f.mouseX).ToString(GameBase.nfi),
- (f.mouseY).ToString(GameBase.nfi),
- (int)f.buttonState);
- lastF = f;
- }
- }
- replayData.AppendFormat(@"{0}|{1}|{2}|{3},", -12345, 0, 0, Seed);
- return replayData.ToString();
- }
- }
- internal virtual Ranks Rank
- {
- get
- {
- float ratio300 = (float)Count300 / TotalHits;
- float ratio50 = (float)Count50 / TotalHits;
- if (!Pass) //something has gone wrong.
- return Ranks.F;
- if (ratio300 == 1)
- return ModManager.CheckActive(EnabledMods, Mods.Hidden) ||
- ModManager.CheckActive(EnabledMods, Mods.Flashlight)
- ? Ranks.XH
- : Ranks.X;
- if (ratio300 > 0.9 && ratio50 <= 0.01 && CountMiss == 0)
- return ModManager.CheckActive(EnabledMods, Mods.Hidden) ||
- ModManager.CheckActive(EnabledMods, Mods.Flashlight)
- ? Ranks.SH
- : Ranks.S;
- if ((ratio300 > 0.8 && CountMiss == 0) || (ratio300 > 0.9))
- return Ranks.A;
- if ((ratio300 > 0.7 && CountMiss == 0) || (ratio300 > 0.8))
- return Ranks.B;
- if (ratio300 > 0.6)
- return Ranks.C;
- return Ranks.D;
- }
- }
- internal string GhostFilename => ReplayFilename.Replace(@".osr", @".osg");
- internal string ReplayFilename
- {
- get
- {
- long dateConverted;
- try
- {
- dateConverted = Date.ToFileTimeUtc();
- }
- catch
- {
- dateConverted = DateTime.Now.ToFileTimeUtc();
- }
- return Path.Combine(ScoreManager.ReplayCachePath, $@"{FileChecksum}-{dateConverted}.osr");
- }
- }
- internal bool LocalReplayPresent => File.Exists(ReplayFilename);
- internal ushort Count100;
- internal ushort Count300;
- internal ushort Count50;
- internal ushort CountGeki;
- internal ushort CountKatu;
- internal ushort CountMiss;
- internal DateTime Date;
- internal Obfuscated<Mods> EnabledMods = Mods.None;
- internal PlayModes PlayMode;
- internal string FileChecksum = string.Empty;
- internal List<Vector2> HpGraph = new List<Vector2>();
- internal bool IsOnline;
- internal int MaxCombo;
- internal long OnlineId;
- internal int OnlineRank;
- internal bool Pass;
- internal bool Exit;
- internal int FailTime;
- internal bool Perfect;
- internal string PlayerName;
- internal string HpGraphString;
- internal byte[] ReplayCompressed;
- internal List<bReplayFrame> Replay;
- internal List<int> HitErrors = new List<int>();
- internal List<int> SpinningRates = new List<int>();
- internal List<bool> SectionResults = new List<bool>();
- internal List<bScoreFrame> Frames = new List<bScoreFrame>();
- private int totalScore;
- internal virtual int TotalScore
- {
- get
- {
- return Processor?.TotalScore ?? totalScore;
- }
- set
- {
- Debug.Assert(Processor == null, "TotalScore cannot be modified when a ScoreProcessor is attached to a Score.");
- totalScore = value;
- }
- }
- //todo: move this clusterfuck to ScoreMania
- internal double TotalScoreDouble;
- internal User User;
- internal int Version = General.VERSION;
- internal double CurrentHp;
- internal ushort CurrentCombo;
- internal string SubmissionResponseString;
- internal MemoryStream ExtraData;
- internal int Seed;
- internal ScoreProcessor Processor;
- internal Beatmap Beatmap;
- private bool allowSubmission = true;
- internal bool AllowSubmission
- {
- get
- {
- return
- Processor == null && //score submission should not be allowed with a new score processing algorithm for now.
- allowSubmission;
- }
- }
- internal ScoreSubmissionStatus SubmissionStatus { get; private set; }
- internal bool HasOnlineReplay { get; private set; }
- private string visualSettingsString => $@"{Beatmap.DimLevel}:{Beatmap.DisableSamples}:{Beatmap.DisableSkin}:{Beatmap.DisableStoryboard}:{Beatmap.BackgroundVisible}";
- private string onlineFormatted
- {
- get
- {
- string specialFlag = string.Empty;
- for (int i = 0; i < (int)Player.flag; i++)
- specialFlag += ' ';
- Player.flag = 0;
- string player = PlayerName;
- #if DEBUG
- if (player != ConfigManager.sUsername)
- player += @"/" + ConfigManager.sUsername;
- #endif
- return
- string.Format(@"{0}:{1}:{2}:{3}:{4}:{5}:{6}:{7}:{8}:{9}:{10}:{11}:{12}:{13}:{14}:{15}:{16:yyMMddHHmmss}:{17}", FileChecksum,
- player + ((BanchoClient.Permission & Permissions.Supporter) > 0 ? " " : ""), onlineScoreChecksum, Count300, Count100, Count50,
- CountGeki, CountKatu, CountMiss, TotalScore, MaxCombo, Perfect, Rank, (int)(Mods)EnabledMods, Pass, (int)PlayMode, Date.ToUniversalTime(),
- General.VERSION + specialFlag);
- }
- }
- private string onlineScoreChecksum
- {
- get
- {
- string checkString =
- string.Format(@"chickenmcnuggets{0}o15{1}{2}smustard{3}{4}uu{5}{6}{7}{8}{9}{10}{11}" + (char)0x51 + @"{12}{13}{15}{14:yyMMddHHmmss}{16}", Count100 + Count300, Count50,
- CountGeki, CountKatu, CountMiss, FileChecksum, MaxCombo, Perfect,
- PlayerName, TotalScore, Rank, (int)(Mods)EnabledMods, Pass, (int)PlayMode, Date.ToUniversalTime(), General.VERSION, GameBase.ClientHash);
- string md5 = CryptoHelper.GetMd5String(checkString);
- if (md5.Length != 32)
- throw new Exception(@"checksum failure");
- return md5;
- }
- }
- internal Score()
- {
- Replay = new List<bReplayFrame>();
- Date = DateTime.Now;
- }
- internal Score(Beatmap beatmap, string playerName)
- {
- if (beatmap != null)
- FileChecksum = beatmap.BeatmapChecksum;
- Beatmap = beatmap;
- PlayerName = playerName ?? string.Empty;
- Date = DateTime.Now;
- Pass = false;
- Perfect = false;
- Replay = new List<bReplayFrame>();
- }
- internal Score(string input, Beatmap beatmap)
- {
- User = new User();
- IsOnline = true;
- if (beatmap != null)
- {
- Beatmap = beatmap;
- FileChecksum = beatmap.BeatmapChecksum;
- }
- Perfect = false;
- Replay = new List<bReplayFrame>();
- string[] line = input.Split('|');
- int i = 0;
- Pass = true;
- OnlineId = Convert.ToInt64(line[i++]);
- PlayerName = line[i++];
- User.Name = PlayerName;
- TotalScore = Convert.ToInt32(line[i++]);
- MaxCombo = Convert.ToUInt16(line[i++]);
- Count50 = Convert.ToUInt16(line[i++]);
- Count100 = Convert.ToUInt16(line[i++]);
- Count300 = Convert.ToUInt16(line[i++]);
- CountMiss = Convert.ToUInt16(line[i++]);
- CountKatu = Convert.ToUInt16(line[i++]);
- CountGeki = Convert.ToUInt16(line[i++]);
- Perfect = line[i++] == @"1";
- EnabledMods = (Mods)Convert.ToInt32(line[i++]);
- User.Id = Convert.ToInt32(line[i++]);
- if (line[i].Length > 0)
- OnlineRank = Convert.ToInt32(line[i]);
- i++;
- try
- {
- Date = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(int.Parse(line[i++]));
- if (Date < new DateTime(1990, 5, 31) /*|| date > DateTime.Now*/)
- Date = DateTime.Now; // when trying to export a corrupted replay file
- }
- catch
- {
- Date = DateTime.Now;
- }
- HasOnlineReplay = line[i++] == @"1";
- }
- internal Score(bScoreFrame sf, string name)
- {
- Pass = sf.pass;
- PlayerName = name;
- Count300 = sf.count300;
- Count100 = sf.count100;
- Count50 = sf.count50;
- CountGeki = sf.countGeki;
- CountKatu = sf.countKatu;
- CountMiss = sf.countMiss;
- TotalScore = sf.totalScore;
- MaxCombo = sf.maxCombo;
- Perfect = sf.perfect;
- CurrentHp = sf.currentHp;
- CurrentCombo = sf.currentCombo;
- EnabledMods = ModManager.ModStatus; //todo: wtf check this?
- Date = DateTime.Now;
- }
- public void ReadFromStream(SerializationReader sr)
- {
- if (sr.BaseStream.Position == 1)
- ReadHeaderFromStream(sr);
- ReplayCompressed = sr.ReadByteArray();
- if (Version >= 20140721)
- OnlineId = sr.ReadInt64();
- else if (Version >= General.VERSION_FIRST_OSZ2)
- OnlineId = sr.ReadInt32();
- ReadModSpecificData(sr);
- }
- public void ReadHeaderFromStream(SerializationReader sr)
- {
- Pass = true;
- Version = sr.ReadInt32();
- FileChecksum = sr.ReadString();
- PlayerName = sr.ReadString();
- var localScoreChecksum = sr.ReadString();
- Count300 = sr.ReadUInt16();
- Count100 = sr.ReadUInt16();
- Count50 = sr.ReadUInt16();
- CountGeki = sr.ReadUInt16();
- CountKatu = sr.ReadUInt16();
- CountMiss = sr.ReadUInt16();
- TotalScore = sr.ReadInt32();
- MaxCombo = sr.ReadUInt16();
- Perfect = sr.ReadBoolean();
- EnabledMods = (Mods)sr.ReadInt32();
- HpGraphString = sr.ReadString();
- Date = sr.ReadDateTime();
- }
- public void WriteToStream(SerializationWriter sw)
- {
- Pass = true;
- sw.Write((byte)PlayMode); //Note that this is written out but not read back in. ScoreFactory needs it.
- sw.Write(General.VERSION);
- sw.Write(FileChecksum);
- sw.Write(PlayerName);
- sw.Write(LocalScoreChecksum);
- sw.Write(Count300);
- sw.Write(Count100);
- sw.Write(Count50);
- sw.Write(CountGeki);
- sw.Write(CountKatu);
- sw.Write(CountMiss);
- sw.Write(TotalScore);
- sw.Write((ushort)MaxCombo);
- sw.Write(Perfect);
- sw.Write((int)(Mods)EnabledMods);
- sw.Write(GetGraphFormatted());
- sw.Write(Date);
- sw.WriteByteArray(ReplayCompressed);
- sw.Write(OnlineId);
- WriteModSpecificData(sw);
- }
- public int CompareTo(Score other)
- {
- int comparison = other.TotalScore.CompareTo(TotalScore);
- return comparison == 0 ? Date.CompareTo(other.Date) : comparison;
- }
- #region ICloneable Members
- public object Clone()
- {
- return MemberwiseClone();
- }
- #endregion
- internal void InvalidateSubmission()
- {
- allowSubmission = false;
- }
- internal string GetGraphFormatted()
- {
- if (!string.IsNullOrEmpty(HpGraphString))
- return HpGraphString;
- StringBuilder graphData = new StringBuilder();
- float last = 0;
- if (HpGraph == null)
- return null;
- for (int i = 0; i < HpGraph.Count; i++)
- {
- Vector2 v = HpGraph[i];
- if (v.X - last > 2000 || i == HpGraph.Count - 1 || i == 0)
- {
- last = v.X;
- graphData.AppendFormat(@"{0}|{1},", Math.Round(v.X, 2).ToString(GameBase.nfi),
- Math.Round(v.Y, 2).ToString(GameBase.nfi));
- }
- }
- HpGraph.Clear();
- HpGraph = null;
- HpGraphString = graphData.ToString();
- return HpGraphString;
- }
- internal void Submit()
- {
- if (SubmissionStatus > ScoreSubmissionStatus.NotSubmitted)
- return;
- SubmissionStatus = ScoreSubmissionStatus.Submitting;
- if (!GameBase.HasLogin)
- return;
- BackgroundWorker b = new BackgroundWorker();
- b.DoWork += submit;
- b.RunWorkerAsync();
- }
- internal void GetReplayData()
- {
- pWebRequest dnr = new pWebRequest(string.Format(General.WEB_ROOT + @"/web/osu-getreplay.php?c={0}&m={1}&u={2}&h={3}",
- OnlineId, (int)PlayMode, ConfigManager.sUsername, ConfigManager.sPassword));
- dnr.Finished += dnr_onFinish;
- dnr.Perform();
- }
- internal void ReadReplayData()
- {
- if (ReplayCompressed == null || ReplayCompressed.Length == 0) return;
- if (Replay == null)
- Replay = new List<bReplayFrame>();
- else
- Replay.Clear();
- try
- {
- ReadReplayData(new ASCIIEncoding().GetString(SevenZipHelper.Decompress(ReplayCompressed)));
- }
- catch (Exception)
- {
- Replay.Clear();
- }
- #if DEBUG
- StreamWriter w = File.CreateText(@"replay.txt");
- foreach (bReplayFrame f in Replay)
- w.WriteLine(@"{0} {1} {2} {3} {4} {5} {6}", f.time, f.mouseX, f.mouseY, f.mouseLeft1, f.mouseLeft2,
- f.mouseRight1, f.mouseRight2);
- w.Close();
- #endif
- }
- internal void ReadReplayData(string replayData)
- {
- if (replayData.Length > 0)
- {
- string[] replaylines = replayData.Split(',');
- bReplayFrame lastF;
- if (Replay.Count > 0)
- lastF = Replay[Replay.Count - 1];
- else
- lastF = new bReplayFrame(0, 0, 0, pButtonState.None);
- foreach (string replayline in replaylines)
- {
- if (replayline.Length == 0)
- continue;
- string[] data = replayline.Split('|');
- if (data.Length < 4)
- continue;
- if (data[0] == @"-12345")
- {
- Seed = int.Parse(data[3]);
- continue;
- }
- pButtonState buttons = (pButtonState)Enum.Parse(typeof(pButtonState), data[3]);
- bReplayFrame newF = new bReplayFrame(int.Parse(data[0]) + lastF.time,
- float.Parse(data[1], GameBase.nfi),
- float.Parse(data[2], GameBase.nfi),
- buttons);
- Replay.Add(newF);
- lastF = newF;
- }
- }
- }
- internal void ReadGraphData(string graphData)
- {
- HpGraph = new List<Vector2>();
- if (graphData.Length > 0)
- {
- string[] graphlines = graphData.Split(',');
- foreach (string graphline in graphlines)
- {
- if (graphline.Length == 0)
- continue;
- string[] data = graphline.Split('|');
- HpGraph.Add(
- new Vector2((float)decimal.Parse(data[0], GameBase.nfi),
- (float)decimal.Parse(data[1], GameBase.nfi)));
- }
- }
- }
- internal void DisposeHpGraph()
- {
- GetGraphFormatted();
- if (HpGraph != null)
- {
- HpGraph.Clear();
- HpGraph = null;
- }
- }
- internal virtual void Reset(bool storeStatistics = false)
- {
- if (Processor != null)
- Processor.Reset(storeStatistics);
- else
- {
- TotalScore = 0;
- TotalScoreDouble = 0;
- }
- CurrentCombo = 0;
- MaxCombo = 0;
- CountMiss = 0;
- Count50 = 0;
- Count100 = 0;
- Count300 = 0;
- CountGeki = 0;
- CountMiss = 0;
- CountKatu = 0;
- }
- internal void ClearReplayData()
- {
- Replay = null;
- ReplayCompressed = null;
- HpGraphString = null;
- }
- internal void LoadLocalData()
- {
- if (!LocalReplayPresent)
- return;
- Score inScore = ScoreManager.ReadReplayFromFile(ReplayFilename, false);
- if (inScore != null)
- {
- ReplayCompressed = inScore.ReplayCompressed;
- HpGraphString = inScore.HpGraphString;
- }
- }
- internal void PurgeReplay()
- {
- File.Delete(ReplayFilename);
- File.Delete(GhostFilename);
- }
- protected virtual void ReadModSpecificData(SerializationReader sr)
- {
- }
- protected virtual void WriteModSpecificData(SerializationWriter sw)
- {
- }
- private void dnr_onFinish(pWebRequest r, Exception e)
- {
- ReplayCompressed = r.ResponseData;
- ReadReplayData();
- if (GotReplayData != null)
- GotReplayData(this);
- }
- private void submit(object sender, DoWorkEventArgs e)
- {
- #if ARCADE
- //Don't submit scores yet, no matter what.
- return;
- #endif
- #if NO_SCORE_SUBMIT
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_SubmissionDisabled));
- return;
- #endif
- GameBase.User.spriteInfo.Text = LocalisationManager.GetString(OsuString.Score_SubmittingScore);
- try
- {
- byte[] zipped = new byte[0];
- if (Pass)
- {
- if (BeatmapManager.Current.onlinePersonalScore != null &&
- TotalScore > BeatmapManager.Current.onlinePersonalScore.TotalScore)
- BeatmapManager.Current.Scores.Clear();
- //We should re-retrieve online scores no matter what, otherwise when clicking 'retry' the personal score won't be updated.
- ReplayCompressed = SevenZipHelper.Compress(new ASCIIEncoding().GetBytes(ReplayString));
- #if DEBUG
- if (ReplayCompressed.Length < 100)
- LoadLocalData();
- #endif
- zipped = ReplayCompressed;
- }
- pWebRequest req = new pWebRequest(General.WEB_ROOT + @"/web/osu-submit-modular.php");
- req.AddFile(@"score", zipped);
- string iv = null;
- #if SUBMISSION_DEBUG
- File.AppendAllText(@"DEBUG.txt", @"Debug at " + DateTime.Now + @"\n");
- #endif
- if (Pass)
- {
- Process[] procs = GameBase.Processes;
- GameBase.Processes = null;
- if (procs == null || procs.Length == 0)
- procs = Process.GetProcesses();
- StringBuilder b = new StringBuilder();
- foreach (Process p in procs)
- {
- string filename = string.Empty;
- try
- {
- filename = p.MainModule.FileName;
- FileInfo fi = new FileInfo(filename);
- if (fi != null)
- filename = CryptoHelper.GetMd5String(fi.Length.ToString()) + @" " + filename;
- }
- catch
- {
- }
- b.AppendLine(filename + @" | " + p.ProcessName + @" (" + p.MainWindowTitle + @")");
- }
- #if SUBMISSION_DEBUG
- File.AppendAllText(@"DEBUG.txt", @"Running Processes:\n" + b + @"\n\n");
- #endif
- req.AddParameter(@"pl", CryptoHelper.EncryptString(b.ToString(), Secrets.GetScoreSubmissionKey(), ref iv));
- }
- else
- {
- req.AddParameter(@"x", Exit ? @"1" : @"0");
- req.AddParameter(@"ft", FailTime.ToString());
- }
- #if SUBMISSION_DEBUG
- File.AppendAllText(@"DEBUG.txt", @"\n1:" + onlineFormatted + @"\n");
- File.AppendAllText(@"DEBUG.txt", @"\n2:" + GameBase.clientHash + @"\n");
- File.AppendAllText(@"DEBUG.txt", @"\n3:" + iv + @"\n");
- #endif
- req.AddParameter(@"score", CryptoHelper.EncryptString(onlineFormatted, Secrets.GetScoreSubmissionKey(), ref iv));
- req.AddParameter(@"fs", CryptoHelper.EncryptString(visualSettingsString, Secrets.GetScoreSubmissionKey(), ref iv));
- req.AddParameter(@"c1", GameBase.CreateUniqueId());
- req.AddParameter(@"pass", ConfigManager.sPassword);
- req.AddParameter(@"osuver", General.VERSION.ToString());
- req.AddParameter(@"s", CryptoHelper.EncryptString(GameBase.ClientHash, Secrets.GetScoreSubmissionKey(), ref iv));
- try
- {
- if (Pass && ExtraData != null)
- req.AddFile(@"i", ExtraData.ToArray());
- else
- req.AddParameter(@"i", string.Empty);
- }
- catch
- {
- }
- GameBase.ChangeAllowance++;
- ExtraData = null;
- req.AddParameter(@"iv", iv);
- int retryCount = Pass ? 10 : 2;
- int retryDelay = 7500;
- bool didError = false;
- while (retryCount-- > 0)
- {
- try
- {
- req.BlockingPerform();
- SubmissionResponseString = req.ResponseString;
- #if SUBMISSION_DEBUG
- Debug.Print(SubmissionResponseString);
- File.AppendAllText(@"DEBUG.txt", @"\nres:" + SubmissionResponseString + @"\n\n\n\n\n-------------------\n\n\n\n");
- #endif
- if (SubmissionResponseString.Contains(@"error:"))
- {
- switch (SubmissionResponseString.Replace(@"error: ", string.Empty))
- {
- case @"reset":
- BanchoClient.HandlePasswordReset();
- break;
- case @"verify":
- BanchoClient.RequireVerification();
- break;
- case @"nouser":
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorNoUser));
- break;
- case @"pass":
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorPassword));
- break;
- case @"inactive":
- case @"ban":
- NotificationManager.ShowMessage("ERROR: Your account is no longer active. Please send an email to accounts@ppy.sh if you think this is a mistake.");
- break;
- case @"beatmap":
- if (Beatmap != null && Beatmap.SubmissionStatus > osu_common.SubmissionStatus.Pending)
- {
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorBeatmap));
- Beatmap.SubmissionStatus = osu_common.SubmissionStatus.Unknown;
- }
- break;
- case @"disabled":
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorDisabled));
- break;
- case @"oldver":
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.Score_ErrorVersion));
- GameBase.CheckForUpdates(true);
- break;
- case @"no":
- break;
- }
- didError = true;
- }
- break;
- }
- catch
- {
- }
- if (retryDelay >= 60000)
- NotificationManager.ShowMessage(string.Format(LocalisationManager.GetString(OsuString.Score_SubmissionFailed), (retryDelay / 60000)));
- Thread.Sleep(retryDelay);
- retryDelay *= 2;
- }
- if (didError)
- {
- SubmissionStatus = ScoreSubmissionStatus.Complete;
- return;
- }
- }
- catch (Exception ex)
- {
- }
- if (SubmissionComplete != null)
- SubmissionComplete(this);
- SubmissionStatus = ScoreSubmissionStatus.Complete;
- if (!Pass)
- GameBase.User.Refresh();
- }
- internal event GotReplayDataHandler GotReplayData;
- internal event GotReplayDataHandler SubmissionComplete;
- }
- internal enum ScoreSubmissionStatus
- {
- NotSubmitted,
- Submitting,
- Complete
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement