コード例 #1
0
        public void Tick(OsuStatus status, OsuMemoryStatus rawStatus, StructuredOsuMemoryReader reader)
        {
            _notUpdatingTokens.WaitOne();
            _notUpdatingMemoryValues.Reset();
            lock (_lockingObject)
            {
                if (!ReferenceEquals(OsuMemoryData, reader.OsuMemoryAddresses))
                {
                    OsuMemoryData = reader.OsuMemoryAddresses;
                    _rawData.Play = OsuMemoryData.Player;
                }
                if ((OsuStatus)_liveTokens["status"].Token.Value != status)
                {
                    _liveTokens["status"].Token.Value = status;
                }

                _liveTokens["rawStatus"].Token.Value = rawStatus;

                if (status != OsuStatus.Playing && status != OsuStatus.Watching)
                {
                    var rawAudioTime = Retry.RetryMe(() =>
                                                     reader.ReadProperty(OsuMemoryData.GeneralData, nameof(GeneralData.AudioTime)), (val => val != null), 5);
                    if (int.TryParse(rawAudioTime?.ToString(), out var audioTime))
                    {
                        _rawData.PlayTime = audioTime;
                    }

                    reader.Read(OsuMemoryData.Skin);
                    UpdateLiveTokens(status);
                    _lastStatus = status;
                    _notUpdatingMemoryValues.Set();
                    return;
                }

                if (_lastStatus != OsuStatus.Playing && _lastStatus != OsuStatus.Watching)
                {
                    _newPlayStarted.Set();
                    Thread.Sleep(500);//Initial play delay
                }

                reader.Read(OsuMemoryData.Player);
                _rawData.PlayTime = OsuMemoryData.GeneralData.AudioTime;
                _liveTokens["time"].Update();

                _lastStatus = status;
            }

            _notUpdatingMemoryValues.Set();
        }
コード例 #2
0
        public void Tick(OsuStatus status, OsuMemoryStatus rawStatus, StructuredOsuMemoryReader reader)
        {
            _notUpdatingTokens.WaitOne();
            _notUpdatingMemoryValues.Reset();
            lock (_lockingObject)
            {
                if (!ReferenceEquals(OsuMemoryData, reader.OsuMemoryAddresses))
                {
                    OsuMemoryData = reader.OsuMemoryAddresses;
                }
                if ((OsuStatus)_liveTokens["status"].Token.Value != status)
                {
                    _liveTokens["status"].Token.Value = status;
                }

                _liveTokens["rawStatus"].Token.Value = rawStatus;
                int playTime = OsuMemoryData.GeneralData.AudioTime;
                switch (status)
                {
                case OsuStatus.Playing:
                case OsuStatus.Watching:
                    if (_lastStatus != OsuStatus.Playing && _lastStatus != OsuStatus.Watching)
                    {
                        _newPlayStarted.Set();
                        Thread.Sleep(500);    //Initial play delay
                    }

                    reader.TryRead(OsuMemoryData.Player);
                    if (!ReferenceEquals(_rawData.Play, OsuMemoryData.Player))
                    {
                        _rawData.Play = OsuMemoryData.Player;
                    }

                    //TODO: support for live multiplayer leaderboard
                    if (!ReadLeaderboard)
                    {
                        //Read whole leaderboard once
                        if (reader.TryRead(OsuMemoryData.LeaderBoard))
                        {
                            ReadLeaderboard = true;
                            if (!ReferenceEquals(_rawData.LeaderBoard, OsuMemoryData.LeaderBoard))
                            {
                                _rawData.LeaderBoard = OsuMemoryData.LeaderBoard;
                            }
                        }
                    }
                    else
                    {
                        //Throttle whole leaderboard reads - Temporary solution until multiplayer detection is implemented, this should be only done in multiplayer
                        if (_nextLeaderBoardUpdate < DateTime.UtcNow)
                        {
                            reader.TryRead(OsuMemoryData.LeaderBoard);
                            _nextLeaderBoardUpdate = DateTime.UtcNow.AddMilliseconds(_settings.Get <int>(MultiplayerLeaderBoardUpdateRate));
                        }
                        else
                        {
                            //...then update main player data
                            if (OsuMemoryData.LeaderBoard.HasLeaderBoard)
                            {
                                reader.TryRead(OsuMemoryData.LeaderBoard.MainPlayer);
                            }
                        }
                    }

                    break;

                case OsuStatus.ResultsScreen:
                    ReadLeaderboard = false;
                    reader.TryRead(OsuMemoryData.ResultsScreen);
                    if (!ReferenceEquals(_rawData.Play, OsuMemoryData.ResultsScreen))
                    {
                        _rawData.Play = OsuMemoryData.ResultsScreen;
                    }

                    playTime = Convert.ToInt32(_rawData.PpCalculator?.BeatmapLength ?? 0);
                    break;

                default:
                    ReadLeaderboard      = false;
                    _rawData.LeaderBoard = new LeaderBoard();
                    reader.TryRead(OsuMemoryData.Skin);
                    _lastStatus = status;
                    break;
                }

                _rawData.PlayTime = playTime;
                _liveTokens["time"].Update();

                _lastStatus = status;
            }

            _notUpdatingMemoryValues.Set();
        }
コード例 #3
0
        private async void OnShown(object sender, EventArgs eventArgs)
        {
            if (!string.IsNullOrEmpty(_osuWindowTitleHint))
            {
                Text += $": {_osuWindowTitleHint}";
            }
            Text += $" ({(Environment.Is64BitProcess ? "x64" : "x86")})";
            _sreader.InvalidRead += SreaderOnInvalidRead;
            await Task.Run(async() =>
            {
                Stopwatch stopwatch;
                double readTimeMs, readTimeMsMin, readTimeMsMax;
                _sreader.WithTimes    = true;
                var readUsingProperty = false;
                var baseAddresses     = new OsuBaseAddresses();
                while (true)
                {
                    if (cts.IsCancellationRequested)
                    {
                        return;
                    }

                    if (!_sreader.CanRead)
                    {
                        Invoke((MethodInvoker)(() =>
                        {
                            textBox_Data.Text = "osu! process not found";
                        }));
                        await Task.Delay(_readDelay);
                        continue;
                    }

                    stopwatch = Stopwatch.StartNew();
                    if (readUsingProperty)
                    {
                        baseAddresses.Beatmap.Id            = ReadInt(baseAddresses.Beatmap, nameof(CurrentBeatmap.Id));
                        baseAddresses.Beatmap.SetId         = ReadInt(baseAddresses.Beatmap, nameof(CurrentBeatmap.SetId));
                        baseAddresses.Beatmap.MapString     = ReadString(baseAddresses.Beatmap, nameof(CurrentBeatmap.MapString));
                        baseAddresses.Beatmap.FolderName    = ReadString(baseAddresses.Beatmap, nameof(CurrentBeatmap.FolderName));
                        baseAddresses.Beatmap.OsuFileName   = ReadString(baseAddresses.Beatmap, nameof(CurrentBeatmap.OsuFileName));
                        baseAddresses.Beatmap.Md5           = ReadString(baseAddresses.Beatmap, nameof(CurrentBeatmap.Md5));
                        baseAddresses.Beatmap.Ar            = ReadFloat(baseAddresses.Beatmap, nameof(CurrentBeatmap.Ar));
                        baseAddresses.Beatmap.Cs            = ReadFloat(baseAddresses.Beatmap, nameof(CurrentBeatmap.Cs));
                        baseAddresses.Beatmap.Hp            = ReadFloat(baseAddresses.Beatmap, nameof(CurrentBeatmap.Hp));
                        baseAddresses.Beatmap.Od            = ReadFloat(baseAddresses.Beatmap, nameof(CurrentBeatmap.Od));
                        baseAddresses.Beatmap.Status        = ReadShort(baseAddresses.Beatmap, nameof(CurrentBeatmap.Status));
                        baseAddresses.Skin.Folder           = ReadString(baseAddresses.Skin, nameof(Skin.Folder));
                        baseAddresses.GeneralData.RawStatus = ReadInt(baseAddresses.GeneralData, nameof(GeneralData.RawStatus));
                        baseAddresses.GeneralData.GameMode  = ReadInt(baseAddresses.GeneralData, nameof(GeneralData.GameMode));
                        baseAddresses.GeneralData.Retries   = ReadInt(baseAddresses.GeneralData, nameof(GeneralData.Retries));
                        baseAddresses.GeneralData.AudioTime = ReadInt(baseAddresses.GeneralData, nameof(GeneralData.AudioTime));
                        baseAddresses.GeneralData.Mods      = ReadInt(baseAddresses.GeneralData, nameof(GeneralData.Mods));
                    }
                    else
                    {
                        _sreader.TryRead(baseAddresses.Beatmap);
                        _sreader.TryRead(baseAddresses.Skin);
                        _sreader.TryRead(baseAddresses.GeneralData);
                    }

                    if (baseAddresses.GeneralData.OsuStatus == OsuMemoryStatus.SongSelect)
                    {
                        _sreader.TryRead(baseAddresses.SongSelectionScores);
                    }
                    else
                    {
                        baseAddresses.SongSelectionScores.Scores.Clear();
                    }

                    if (baseAddresses.GeneralData.OsuStatus == OsuMemoryStatus.ResultsScreen)
                    {
                        _sreader.TryRead(baseAddresses.ResultsScreen);
                    }

                    if (baseAddresses.GeneralData.OsuStatus == OsuMemoryStatus.Playing)
                    {
                        _sreader.TryRead(baseAddresses.Player);
                        //TODO: flag needed for single/multi player detection (should be read once per play in singleplayer)
                        _sreader.TryRead(baseAddresses.LeaderBoard);
                        _sreader.TryRead(baseAddresses.KeyOverlay);
                        if (readUsingProperty)
                        {
                            //Testing reading of reference types(other than string)
                            _sreader.TryReadProperty(baseAddresses.Player, nameof(Player.Mods), out var dummyResult);
                        }
                    }
                    else
                    {
                        baseAddresses.LeaderBoard.Players.Clear();
                    }

                    var hitErrors = baseAddresses.Player?.HitErrors;
                    if (hitErrors != null)
                    {
                        var hitErrorsCount = hitErrors.Count;
                        hitErrors.Clear();
                        hitErrors.Add(hitErrorsCount);
                    }

                    stopwatch.Stop();
                    readTimeMs = stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond;
                    lock (_minMaxLock)
                    {
                        if (readTimeMs < _memoryReadTimeMin)
                        {
                            _memoryReadTimeMin = readTimeMs;
                        }
                        if (readTimeMs > _memoryReadTimeMax)
                        {
                            _memoryReadTimeMax = readTimeMs;
                        }
                        // copy value since we're inside lock
                        readTimeMsMin = _memoryReadTimeMin;
                        readTimeMsMax = _memoryReadTimeMax;
                    }

                    try
                    {
                        Invoke((MethodInvoker)(() =>
                        {
                            textBox_readTime.Text = $"         ReadTimeMS: {readTimeMs}{Environment.NewLine}" +
                                                    $" Min ReadTimeMS: {readTimeMsMin}{Environment.NewLine}" +
                                                    $"Max ReadTimeMS: {readTimeMsMax}{Environment.NewLine}";
                            textBox_Data.Text = JsonConvert.SerializeObject(baseAddresses, Formatting.Indented);
                            textBox_ReadTimes.Text =
                                JsonConvert.SerializeObject(_sreader.ReadTimes, Formatting.Indented);
                        }));
                    }
                    catch (ObjectDisposedException)
                    {
                        return;
                    }

                    _sreader.ReadTimes.Clear();
                    await Task.Delay(_readDelay);
                }
            }, cts.Token);
        }
コード例 #4
0
        private void OnShown(object sender, EventArgs eventArgs)
        {
            if (!string.IsNullOrEmpty(_osuWindowTitleHint))
            {
                Text += $": {_osuWindowTitleHint}";
            }
            _ = Task.Run(async() =>
            {
                try
                {
                    Stopwatch stopwatch;
                    double readTimeMs, readTimeMsMin, readTimeMsMax;
                    var playContainer = new PlayContainerEx();
                    var playReseted   = false;
                    var baseAddresses = new OsuBaseAddresses();
                    while (true)
                    {
                        if (cts.IsCancellationRequested)
                        {
                            return;
                        }

                        var patternsToRead = GetPatternsToRead();

                        stopwatch = Stopwatch.StartNew();

                        #region OsuBase

                        var mapId         = -1;
                        var mapSetId      = -1;
                        var songString    = string.Empty;
                        var mapMd5        = string.Empty;
                        var mapFolderName = string.Empty;
                        var osuFileName   = string.Empty;
                        var retrys        = -1;
                        var gameMode      = -1;
                        var mapData       = string.Empty;
                        var status        = OsuMemoryStatus.Unknown;
                        var statusNum     = -1;
                        var playTime      = -1;
                        if (patternsToRead.OsuBase)
                        {
                            mapId         = _reader.GetMapId();
                            mapSetId      = _reader.GetMapSetId();
                            songString    = _reader.GetSongString();
                            mapMd5        = _reader.GetMapMd5();
                            mapFolderName = _reader.GetMapFolderName();
                            osuFileName   = _reader.GetOsuFileName();
                            retrys        = _reader.GetRetrys();
                            gameMode      = _reader.ReadSongSelectGameMode();
                            mapData       =
                                $"HP:{_reader.GetMapHp()} OD:{_reader.GetMapOd()}, CS:{_reader.GetMapCs()}, AR:{_reader.GetMapAr()}, setId:{_reader.GetMapSetId()}";
                            status   = _reader.GetCurrentStatus(out statusNum);
                            playTime = _reader.ReadPlayTime();
                        }

                        #endregion

                        #region Mods

                        var mods = -1;
                        if (patternsToRead.Mods)
                        {
                            mods = _reader.GetMods();
                        }

                        #endregion

                        #region CurrentSkinData

                        var skinFolderName = string.Empty;
                        if (patternsToRead.CurrentSkinData)
                        {
                            skinFolderName = _reader.GetSkinFolderName();
                        }

                        #endregion

                        #region IsReplay

                        bool isReplay = false;
                        if (status == OsuMemoryStatus.Playing && patternsToRead.IsReplay)
                        {
                            isReplay = _reader.IsReplay();
                        }

                        #endregion

                        #region PlayContainer

                        double hp                = 0;
                        var playerName           = string.Empty;
                        var hitErrorCount        = -1;
                        var playingMods          = -1;
                        double displayedPlayerHp = 0;
                        int scoreV2              = -1;
                        if (status == OsuMemoryStatus.Playing && patternsToRead.PlayContainer)
                        {
                            playReseted = false;
                            _reader.GetPlayData(playContainer);
                            hp                = _reader.ReadPlayerHp();
                            playerName        = _reader.PlayerName();
                            hitErrorCount     = _reader.HitErrors()?.Count ?? -2;
                            playingMods       = _reader.GetPlayingMods();
                            displayedPlayerHp = _reader.ReadDisplayedPlayerHp();
                            scoreV2           = _reader.ReadScoreV2();
                        }
                        else if (!playReseted)
                        {
                            playReseted = true;
                            playContainer.Reset();
                        }

                        #endregion

                        #region TourneyBase

                        // TourneyBase
                        var tourneyIpcState       = TourneyIpcState.Unknown;
                        var tourneyIpcStateNumber = -1;
                        var tourneyLeftStars      = -1;
                        var tourneyRightStars     = -1;
                        var tourneyBO             = -1;
                        var tourneyStarsVisible   = false;
                        var tourneyScoreVisible   = false;
                        if (status == OsuMemoryStatus.Tourney && patternsToRead.TourneyBase)
                        {
                            tourneyIpcState     = _reader.GetTourneyIpcState(out tourneyIpcStateNumber);
                            tourneyLeftStars    = _reader.ReadTourneyLeftStars();
                            tourneyRightStars   = _reader.ReadTourneyRightStars();
                            tourneyBO           = _reader.ReadTourneyBO();
                            tourneyStarsVisible = _reader.ReadTourneyStarsVisible();
                            tourneyScoreVisible = _reader.ReadTourneyScoreVisible();
                        }

                        #endregion

                        stopwatch.Stop();

                        readTimeMs = stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond;
                        lock (_minMaxLock)
                        {
                            if (readTimeMs < _memoryReadTimeMin)
                            {
                                _memoryReadTimeMin = readTimeMs;
                            }
                            if (readTimeMs > _memoryReadTimeMax)
                            {
                                _memoryReadTimeMax = readTimeMs;
                            }
                            // copy value since we're inside lock
                            readTimeMsMin = _memoryReadTimeMin;
                            readTimeMsMax = _memoryReadTimeMax;
                        }

                        Invoke((MethodInvoker)(() =>
                        {
                            textBox_readTime.Text = $"         ReadTimeMS: {readTimeMs}{Environment.NewLine}" +
                                                    $" Min ReadTimeMS: {readTimeMsMin}{Environment.NewLine}" +
                                                    $"Max ReadTimeMS: {readTimeMsMax}{Environment.NewLine}";

                            textBox_mapId.Text = $"Id:{mapId} setId:{mapSetId}";
                            textBox_strings.Text = $"songString: \"{songString}\" {Environment.NewLine}" +
                                                   $"md5: \"{mapMd5}\" {Environment.NewLine}" +
                                                   $"mapFolder: \"{mapFolderName}\" {Environment.NewLine}" +
                                                   $"fileName: \"{osuFileName}\" {Environment.NewLine}" +
                                                   $"Retrys:{retrys} {Environment.NewLine}" +
                                                   $"mods:{(Mods)mods}({mods}) {Environment.NewLine}" +
                                                   $"SkinName: \"{skinFolderName}\"";
                            textBox_time.Text = playTime.ToString();
                            textBox_mapData.Text = mapData;
                            textBox_Status.Text = status + " " + statusNum + " " + gameMode;

                            textBox_CurrentPlayData.Text =
                                playContainer + Environment.NewLine +
                                $"scoreV2: {scoreV2} {Environment.NewLine}" +
                                $"IsReplay: {isReplay} {Environment.NewLine}" +
                                $"hp________: {hp:00.##} {Environment.NewLine}" +
                                $"displayedHp: {displayedPlayerHp:00.##} {Environment.NewLine}" +
                                $"playingMods:{(Mods)playingMods} ({playingMods}) " +
                                $"PlayerName: {playerName}{Environment.NewLine}" +
                                $"HitErrorCount: {hitErrorCount} ";

                            if (status == OsuMemoryStatus.Tourney)
                            {
                                textBox_TourneyStuff.Text =
                                    $"IPC-State: {tourneyIpcState} ({tourneyIpcStateNumber}) | BO {tourneyBO}{Environment.NewLine}" +
                                    $"Stars: {tourneyLeftStars} | {tourneyRightStars}{Environment.NewLine}" +
                                    $"Warmup/Stars State: {(tourneyStarsVisible ? "stars visible, warmup disabled" : "stars hidden, warmup enabled")}{Environment.NewLine}" +
                                    $"Score/Chat state: {(tourneyScoreVisible ? "chat hidden, score visible or no lobby joined" : "chat visible, score hidden")}{Environment.NewLine}";
                            }
                            else
                            {
                                textBox_TourneyStuff.Text = "no data since not in tourney mode";
                            }
                        }));
                        await Task.Delay(_readDelay);
                    }
                }
                catch (ThreadAbortException)
                {
                }
            });
        }