HOME преди 1 година
родител
ревизия
e41e9931da
променени са 3 файла, в които са добавени 899 реда и са изтрити 403 реда
  1. 410 0
      BsWidget/BSDataPuller/BsDataPullerClient.cs
  2. 1 0
      BsWidget/BsWidget.csproj
  3. 488 403
      BsWidget/MainForm.cs

+ 410 - 0
BsWidget/BSDataPuller/BsDataPullerClient.cs

@@ -0,0 +1,410 @@
+using System;
+using System.ComponentModel;
+using System.Reflection;
+using Newtonsoft.Json;
+using WebSocketSharp;
+
+namespace BsWidget.BSDataPuller;
+
+internal sealed class BsDataPullerClient
+{
+    private bool _isRunning;
+    private WebSocket _webSocketLd;
+    private WebSocket _webSocketMd;
+
+    public event EventHandler<BsDataPullerEventArgs> Event;
+
+    public void Start()
+    {
+        _isRunning = true;
+
+        _webSocketLd = new WebSocket($"ws://{Program.Host}:2946/BSDataPuller/LiveData");
+        _webSocketLd.OnClose += WebSocket_OnClose;
+        _webSocketLd.OnError += WebSocket_OnError;
+        _webSocketLd.OnMessage += WebSocketLd_OnMessage;
+        _webSocketLd.ConnectAsync();
+
+        _webSocketMd = new WebSocket($"ws://{Program.Host}:2946/BSDataPuller/MapData");
+        _webSocketMd.OnClose += WebSocket_OnClose;
+        _webSocketMd.OnError += WebSocket_OnError;
+        _webSocketMd.OnMessage += WebSocketMd_OnMessage;
+        _webSocketMd.ConnectAsync();
+    }
+
+    public void Stop()
+    {
+        _isRunning = false;
+        _webSocketLd.Close();
+        _webSocketMd.Close();
+    }
+
+    private void WebSocket_OnError(object sender, ErrorEventArgs e)
+    {
+        if (_isRunning) ((WebSocket)sender).Connect();
+    }
+
+    private void WebSocket_OnClose(object sender, CloseEventArgs e)
+    {
+        if (_isRunning) ((WebSocket)sender).Connect();
+    }
+
+    private void WebSocketLd_OnMessage(object sender, MessageEventArgs e)
+    {
+        var evt = JsonConvert.DeserializeObject<LiveData>(e.Data);
+        OnEvent(new BsDataPullerEventArgs { Type = BsDataPullerEventArgsType.LiveData, LiveData = evt });
+    }
+
+    private void WebSocketMd_OnMessage(object sender, MessageEventArgs e)
+    {
+        var evt = JsonConvert.DeserializeObject<MapData>(e.Data);
+        OnEvent(new BsDataPullerEventArgs { Type = BsDataPullerEventArgsType.MapData, MapData = evt });
+    }
+
+    private void OnEvent(BsDataPullerEventArgs e) => Event?.Invoke(this, e);
+}
+
+internal class BsDataPullerEventArgs
+{
+    public BsDataPullerEventArgsType Type { get; set; }
+    public LiveData LiveData { get; set; }
+    public MapData MapData { get; set; }
+}
+
+internal enum BsDataPullerEventArgsType
+{
+    LiveData = 1,
+    MapData = 2,
+}
+
+public class MapData
+{
+    #region Level
+
+    /// <summary></summary>
+    /// <remarks>
+    /// This can remain <see href="false"/> even if <see cref="LevelFailed"/> is <see href="true"/>,
+    /// when <see cref="Modifiers.NoFailOn0Energy"/> is <see href="true"/>.
+    /// </remarks>
+    /// <value>Default is <see href="false"/>.</value>
+    public bool InLevel { get; set; }
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="false"/>.</value>
+    public bool LevelPaused { get; set; }
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="false"/>.</value>
+    public bool LevelFinished { get; set; }
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="false"/>.</value>
+    public bool LevelFailed { get; set; }
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="false"/>.</value>
+    public bool LevelQuit { get; set; }
+
+    #endregion Level
+
+    #region Map
+
+    /// <summary>The hash ID for the current map.</summary>
+    /// <remarks><see href="null"/> if the hash could not be determined (e.g. if the map is not a custom level).</remarks>
+    /// <value>Default is <see href="null"/>.</value>
+    public string? Hash { get; set; }
+
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+
+    /// <summary>The name of the current map.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see cref="string.Empty"/>.</value>
+    [DefaultValue("")]
+    public string SongName { get; set; }
+
+    /// <summary>The sub-name of the current map.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see cref="string.Empty"/>.</value>
+    [DefaultValue("")]
+    public string SongSubName { get; set; }
+
+    /// <summary>The author of the song.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see cref="string.Empty"/>.</value>
+    [DefaultValue("")]
+    public string SongAuthor { get; set; }
+
+    /// <summary>The mapper of the current chart.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see cref="string.Empty"/>.</value>
+    [DefaultValue("")]
+    public string Mapper { get; set; }
+
+#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+
+    /// <summary></summary>
+    /// <remarks><see href="null"/> if the BSR key could not be obtained.</remarks>
+    /// <value>Default is <see href="null"/>.</value>
+    public string? BSRKey { get; set; }
+
+    /// <summary></summary>
+    /// <remarks><see href="null"/> if the cover image could not be obtained.</remarks>
+    /// <value>Default is <see href="null"/>.</value>
+    public string? CoverImage { get; set; }
+
+    /// <summary>The duration of the map in seconds.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int Duration { get; set; }
+
+    #endregion Map
+
+    #region Difficulty
+
+#pragma warning disable CS8618
+
+    /// <summary>The type of map.</summary>
+    /// <remarks>i.e. Standard, 360, OneSaber, etc.</remarks>
+    /// <value>Default is <see cref="string.Empty"/>.</value>
+    [DefaultValue("")]
+    public string MapType { get; set; }
+
+    /// <summary>The standard difficulty label of the map.</summary>
+    /// <remarks>i.e. Easy, Normal, Hard, etc.</remarks>
+    /// <value>Default is <see cref="string.Empty"/>.</value>
+    [DefaultValue("")]
+    public string Difficulty { get; set; }
+
+#pragma warning restore CS8618
+
+    /// <summary>The custom difficulty label set by the mapper.</summary>
+    /// <remarks><see href="null"/> if there is none.</remarks>
+    /// <value>Default is <see cref="string.Empty"/>.</value>
+    public string? CustomDifficultyLabel { get; set; }
+
+    /// <summary>The beats per minute of the current map.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int BPM { get; set; }
+
+    /// <summary>The note jump speed of the current map.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public double NJS { get; set; }
+
+#pragma warning disable CS8618
+
+    /// <summary>The modifiers selected by the player for the current level.</summary>
+    /// <remarks>i.e. No fail, No arrows, Ghost notes, etc.</remarks>
+    /// <value>Default is <see cref="Data.Modifiers"/>.</value>
+    public Modifiers Modifiers { get; set; }
+
+#pragma warning restore CS8618
+
+    /// <summary>The score multiplier set by the users selection of modifiers.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="1.0"/>.</value>
+    [DefaultValue(1.0f)]
+    public float ModifiersMultiplier { get; set; }
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="false"/>.</value>
+    public bool PracticeMode { get; set; }
+
+    /// <summary>The modifiers selected by the user that are specific to practice mode.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see cref="Data.PracticeModeModifiers"/>.</value>
+#pragma warning disable CS8618
+    public PracticeModeModifiers PracticeModeModifiers { get; set; }
+
+    /// <summary>The amount Play Points this map is worth.</summary>
+    /// <remarks><see href="0"/> if the map is unranked or the value was undetermined.</remarks>
+    /// <value>Default is <see href="0"/>.</value>
+#pragma warning restore CS8618
+    public double PP { get; set; }
+
+    /// <summary></summary>
+    /// <remarks><see href="0"/> if the value was undetermined.</remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public double Star { get; set; }
+
+    #endregion Difficulty
+
+    #region Misc
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see cref="UnityEngine.Application.version"/>.</value>
+    [JsonProperty]
+    public static readonly string GameVersion;
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value><see cref="System.Version"/>.</value>
+    [JsonProperty]
+    public static readonly string PluginVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(3);
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="false"/>.</value>
+    [DefaultValue(false)]
+    public bool IsMultiplayer { get; set; }
+
+    /// <summary>The previous local record set by the player for this map specific mode and difficulty.</summary>
+    /// <remarks><see href="0"/> if the map variant hasn't never been played before.</remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int PreviousRecord { get; set; }
+
+    /// <summary>The BSR key fore the last played map.</summary>
+    /// <remarks><para>
+    /// <see href="null"/> if there was no previous map or the previous maps BSR key was undetermined.<br/>
+    /// This value won't be updated if the current map is the same as the last.
+    /// </para></remarks>
+    /// <value>Default is <see href="null"/>.</value>
+    public string? PreviousBSR { get; set; }
+
+    #endregion Misc
+}
+
+public class LiveData
+{
+    #region Score
+
+    /// <summary>The current raw score.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int Score { get; set; }
+
+    /// <summary>The current score with the player selected multipliers applied.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int ScoreWithMultipliers { get; set; }
+
+    /// <summary>The maximum possible raw score for the current number of cut notes.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int MaxScore { get; set; }
+
+    /// <summary>The maximum possible score with the player selected multipliers applied for the current number of cut notes.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int MaxScoreWithMultipliers { get; set; }
+
+#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+
+    /// <summary>The <see cref="string"/> rank label for the current score.</summary>
+    /// <remarks>i.e. SS, S, A, B, etc.</remarks>
+    /// <value>Default is <see href="SSS"/>.</value>
+    [DefaultValue("SSS")]
+    public string Rank { get; set; }
+
+#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="true"/>.</value>
+    [DefaultValue(true)]
+    public bool FullCombo { get; set; }
+
+    /// <summary>The total number of notes spawned since the start position of the song until the current position in the song.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int NotesSpawned { get; set; }
+
+    /// <summary>The current note cut combo count without error.</summary>
+    /// <remarks>Resets back to <see href="0"/> when the player: misses a note, hits a note incorrectly, takes damage or hits a bomb.</remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int Combo { get; set; }
+
+    /// <summary>The total number of missed and incorrectly hit notes since the start position of the song until the current position in the song.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    public int Misses { get; set; }
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="100"/>.</value>
+    [DefaultValue(100)]
+    public double Accuracy { get; set; }
+
+    /// <summary></summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="50"/>.</value>
+    [DefaultValue(50)]
+    public double PlayerHealth { get; set; }
+
+    /// <summary>The individual scores for the last hit note.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="Data.SBlockHitScore"/>.</value>
+    public SBlockHitScore BlockHitScore { get; set; }
+
+
+    #endregion Score
+
+    #region Misc
+
+    /// <summary>The total amount of time in seconds since the start of the map.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see href="0"/>.</value>
+    [DefaultValue(0)]
+    public int TimeElapsed { get; set; }
+
+    /// <summary>The event that caused the update trigger to be fired.</summary>
+    /// <remarks></remarks>
+    /// <value>Default is <see cref="ELiveDataEventTriggers.Unknown"/>.</value>
+    [DefaultValue(ELiveDataEventTriggers.Unknown)]
+    public ELiveDataEventTriggers EventTrigger { get; set; }
+
+    #endregion Misc
+}
+
+public enum ELiveDataEventTriggers
+{
+    Unknown = 0,
+    TimerElapsed,
+    NoteMissed,
+    EnergyChange,
+    ScoreChange
+}
+
+public class PracticeModeModifiers
+{
+    public float SongSpeedMul { get; set; }
+    public bool StartInAdvanceAndClearNotes { get; set; }
+    public float SongStartTime { get; set; }
+}
+
+public class Modifiers
+{
+    public bool NoFailOn0Energy { get; internal set; }
+    public bool OneLife { get; internal set; }
+    public bool FourLives { get; internal set; }
+    public bool NoBombs { get; internal set; }
+    public bool NoWalls { get; internal set; }
+    public bool NoArrows { get; internal set; }
+    public bool GhostNotes { get; internal set; }
+    public bool DisappearingArrows { get; internal set; }
+    public bool SmallNotes { get; internal set; }
+    public bool ProMode { get; internal set; }
+    public bool StrictAngles { get; internal set; }
+    public bool ZenMode { get; internal set; }
+    public bool SlowerSong { get; internal set; }
+    public bool FasterSong { get; internal set; }
+    public bool SuperFastSong { get; internal set; }
+}
+
+public struct SBlockHitScore
+{
+    /// <summary><see href="0"/> to <see href="70"/></summary>
+    public int PreSwing { get; internal set; }
+    /// <summary><see href="0"/> to <see href="30"/></summary>
+    public int PostSwing { get; internal set; }
+    /// <summary><see href="0"/> to <see href="15"/></summary>
+    public int CenterSwing { get; internal set; }
+
+    public int Total => PreSwing + PostSwing + CenterSwing;
+}

+ 1 - 0
BsWidget/BsWidget.csproj

@@ -76,6 +76,7 @@
     <Compile Include="BaseForm.Designer.cs">
       <DependentUpon>BaseForm.cs</DependentUpon>
     </Compile>
+    <Compile Include="BSDataPuller\BsDataPullerClient.cs" />
     <Compile Include="BsYurHttpStatus\BsYurHttpStatusClient.cs" />
     <Compile Include="GdiPlusExt.cs" />
     <Compile Include="MainForm.cs">

Файловите разлики са ограничени, защото са твърде много
+ 488 - 403
BsWidget/MainForm.cs