Code Monkey home page Code Monkey logo

readiefur / bsdatapuller Goto Github PK

View Code? Open in Web Editor NEW
38.0 6.0 10.0 23.28 MB

Gathers data about the current map you are playing to then be sent out over a websocket for other software to use, e.g. A web overlay like BSDP-Overlay. This mod works with multi PC setups!

Home Page: https://github.com/ReadieFur/BeatSaber-Overlay

License: GNU General Public License v3.0

C# 100.00%
beatsaber httpstatus extra-tweaks mod bsr bsdp-overlay websocket

bsdatapuller's Introduction

DataPuller

Gathers data about the current map you are playing to then be sent out over a websocket for other software to use, e.g. A web overlay like BSDP-Overlay. This mod works with multi PC setups!

Installation:

To install this mod, download the latest version and place the DataPuller.dll into your mods folder. Make sure to also have any of the dependencies listed below installed too.

Dependencies, these can all be found on the Mod Assistant app:

In order for this mod to function properly you must have installed the following mods:

Overlays:

There are few overlays that I know of at the moment that work with this mod but here are some:

Overlay Creator
BSDP-Overlay ReadieFur
Freakylay UnskilledFreak
HyldraZolxy HyldraZolxy

Project status:

This project is still maintianed though loosely, I will keep updating it to make sure it remains compatiable with the game but don't expect new features to constantly be added.
For a detailed view on the project status, check the TODO file.

Output data:

This mod outputs quite a bit of data to be used by other mods and overlays. Here is some of the data that the mod exposes:

  • Map info:
    • Hash
    • Song name
    • Song sub name
    • Song author
    • Mapper
    • BSR key
    • Cover image
    • Length
    • Time elapsed
  • Difficulty info:
    • Map type
    • Difficulty
    • PP
    • Star
    • BPM
    • NJS
    • Modifiers
    • Pratice mode
  • Level info:
    • Paused
    • Failed
    • Finished
    • Quit
  • Score info:
    • Score
    • Score with modifiers
    • Previous record
    • Full combo
    • Combo
    • Misses
    • Accuracy
    • Block hit score
    • Health

And more!

Developer documentation:

Obtaining the data via the Websocket:

Data is broadcasted over an unsecure websocket (plain ws) that runs on port 2946, the path to the data is /BSDataPuller/<TYPE>.
The reason for the use of an unsecure websocket is because it is pratically impossible to get a verified and signed SSL certificate for redistribution, that would break the whole point of SSL.
Each endpoint will send out a JSON object, check Data Types for the specific data that each endpoint sends out.

Obtaining the data via the C#:

It is possible to use the data that this mod exposes within your own mod if you wish to do so.
To get started, add the latest version of the mod to your project as a reference.
Data types can be accessed within the DataPuller.Data namespace.
All data types extend the AData class which contains an OnUpdate event that can be subscribed to that is fired whenever the data is updated.
Check Data Types for the specific data that each endpoint sends out.

Data types:

I will format each entry in the following way:

<TYPE>
	<DESCRIPTION>
	<LOCATION>
	<OBJECT>
		///<COMMENT>
		<TYPE> <NAME> = <DEFAULT_VALUE>;

All data types contain the following properties:

///The time that the data was serialized.
long UnixTimestamp;

Below is a list of all the specific data types:

MapData Description: Contains data about the current map and mod. Type: `class`
Method Location
Websocket /BSDataPuller/MapData
C# DataPuller.Data.MapData

This data gets updated whenever:

  • The map is changed
  • A level is quit/paused/failed/finished
//====LEVEL====
///This can remain false even if LevelFailed is true, when Modifiers.NoFailOn0Energy is true.
bool LevelPaused = false;

bool LevelFinished = false;

bool LevelFailed = false;

bool LevelQuit = false;

//====MAP====
///The hash ID for the current map.
///null if the hash could not be determined (e.g. if the map is not a custom level).
string? Hash = null;

///The name of the current map.
string SongName = "";

///The sub-name of the current map.
string SongSubName = "";

///The author of the song.
string SongAuthor = "";

///The mapper of the current chart.
string Mapper = "";

///The BSR key of the current map.
///null if the BSR key could not be obtained.
string? BSRKey = null;

///The cover image of the current map.
///null if the cover image could not be obtained.
string? CoverImage = null;

///The duration of the map in seconds.
int Duration = 0;

//====DIFFICULTY====
///The type of map.
///i.e. Standard, 360, OneSaber, etc.
string MapType = "";

///The standard difficulty label of the map.
///i.e. Easy, Normal, Hard, etc.
string Difficulty = "";

///The custom difficulty label set by the mapper.
///null if there is none.
string? CustomDifficultyLabel = null;

///The beats per minute of the current map.
int BPM = 0;

///The note jump speed of the current map.
double NJS = 0;

///The modifiers selected by the player for the current level.
///i.e. No fail, No arrows, Ghost notes, etc.
Modifiers Modifiers = new Modifiers();

///The score multiplier set by the users selection of modifiers.
float ModifiersMultiplier = 1.0f;

bool PracticeMode = false;

///The modifiers selected by the user that are specific to practice mode.
PracticeModeModifiers PracticeModeModifiers = new PracticeModeModifiers();

///The amount Play Points this map is worth.
///0 if the map is unranked or the value was undetermined.
double PP = 0;

///0 if the value was undetermined.
double Star = 0;

//====MISC====
string GameVersion = ""; //Will be the current game version, e.g. 1.20.0

string PluginVersion = ""; //Will be the current version of the plugin, e.g. 2.1.0

bool IsMultiplayer = false;

///The previous local record set by the player for this map specific mode and difficulty.
///0 if the map variant hasn't never been played before.
int PreviousRecord = 0;

///The BSR key fore the last played map.
///null if there was no previous map or the previous maps BSR key was undetermined.
///This value won't be updated if the current map is the same as the last.
string? PreviousBSR = null;
Modifiers

This is a sub-object of MapData and does not get extend the AData class, there is no endpoint for this type.
Type: class

bool NoFailOn0Energy = false;
bool OneLife = false;
bool FourLives = false;
bool NoBombs = false;
bool NoWalls = false;
bool NoArrows = false;
bool GhostNotes = false;
bool DisappearingArrows = false;
bool SmallNotes = false;
bool ProMode = false;
bool StrictAngles = false;
bool ZenMode = false;
bool SlowerSong = false;
bool FasterSong = false;
bool SuperFastSong = false;
PracticeModeModifiers

This is a sub-object of MapData and does not get extend the AData class, there is no endpoint for this type.
Type: class

float SongSpeedMul;
bool StartInAdvanceAndClearNotes;
float SongStartTime;
LiveData Description: Contains data about the player status within the current map. Type: `class`
Method Location
Websocket /BSDataPuller/LiveData
C# DataPuller.Data.LiveData

This data gets updated whenever:

  • The players health changes
  • A block is hit or missed
  • The score changes
  • 1 game second passes (this varies depending on the speed multiplier)
//====SCORE====
///The current raw score.
int Score = 0;

///The current score with the player selected multipliers applied.
int ScoreWithMultipliers = 0;

///The maximum possible raw score for the current number of cut notes.
int MaxScore = 0;

///The maximum possible score with the player selected multipliers applied for the current number of cut notes.
int MaxScoreWithMultipliers = 0;

///The string rank label for the current score.
///i.e. SS, S, A, B, etc.
string Rank = "SSS";

bool FullCombo = true;

///The total number of notes spawned since the start position of the song until the current position in the song.
int NotesSpawned = 0;

///The current note cut combo count without error.
///Resets back to 0 when the player: misses a note, hits a note incorrectly, takes damage or hits a bomb.
int Combo = 0;

///The total number of missed and incorrectly hit notes since the start position of the song until the current position in the song.
int Misses = 0;

double Accuracy = 100;

///The individual scores for the last hit note.
SBlockHitScore BlockHitScore = new SBlockHitScore();

double PlayerHealth = 50;

///The colour of note that was last hit.
///ColorType.None if no note was previously hit or a bomb was hit.
ColorType ColorType = ColorType.None;

//====MISC====
///The total amount of time in seconds since the start of the map.
int TimeElapsed = 0;

///The event that caused the update trigger to be fired.
ELiveDataEventTriggers EventTrigger = ELiveDataEventTriggers.Unknown;
SBlockHitScore

This is a sub-object of LiveData and does not get extend the AData class, there is no endpoint for this type. Type: struct

///0 to 70.
int PreSwing = 0;
///0 to 30.
int PostSwing = 0;
///0 to 15.
int CenterSwing = 0;
ColorType

This is a sub-object of LiveData and does not get extend the AData class, there is no endpoint for this type. Type: enum

ColorA = 0,
ColorB = 1,
None = -1
ELiveDataEventTriggers

This is a sub-object of LiveData and does not get extend the AData class, there is no endpoint for this type.
Type: enum

Unknown = 0,
TimerElapsed,
NoteMissed,
EnergyChange,
ScoreChange

bsdatapuller's People

Contributors

chenxiaolong avatar macil avatar readie1593 avatar readiefur avatar unskilledfreak avatar zeph-yr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

bsdatapuller's Issues

DataPuller using an insane amount of CPU in BeatSaber.

Ok so recently i have installed one of your mods for BeatSaber called DataPuller. After a while of playing any map in beatsaber my game starts to use up more and more CPU gradually. It then started to use so much of my CPU that my CPU has gotten to 100%. Also having the game paused more more than 10 minutes then unpausing it causes BeatSaber to use up 100% of my CPU. I then started to remove mods one by one. Then i deleted DataPuller next and it fixed it. Then just to make sure it was DataPuller. I have completely deleted the BeatSaber folder and then i reinstalled BeatSaber and the mod loader then i put DataPuller back in and that is all. Then the issue occurred again. Then just to see if it was for sure DataPuller that was causing the issue. I then removed DataPuller and then my BeatSaber was fine again. I have a overclocked i5 9600K At 5GHz and BeatSaber should not be using 100% of it. I sent two pictures below showing with DataPuller installed and it without it installed. Keep in mind that i was having a map being played when i took those screenshots.

With DataPuller installed while playing a map.
2020 05 25-23 27
With DataPuller not installed while playing a map.
2020 05 25-23 53
Now you see the issue. DataPuller is causing BeatSaber to use all of my CPU while having the game paused for long enough. Or when playing a beatsaber map for long enough. So for right now i will be waiting for this to get fixed and i will not have the DataPuller mod installed. I just decided to let you know of this issue with DataPuller.

Critical error OnApp reload

I have had messages say that my mod was causing critical erorrs when the app was reloaded, e.g. a setting in the settings menu was changed. This would cause the ScoreController and GameEnergyController to stop working entirely.

Misses make you lose more health or kill you instantly in 90 degree custom maps.

https://streamable.com/1g7o1j
See at 0:45 I play 100$ bills 90 degree, where misses take off 15 health as expected, then after I play a custom where missing the first two blocks fails me instantly.
Removing DataPuller from my Plugins folder fixed the issue, and adding it back caused it to reappear.
Error Log
[DEBUG @ 01:31:37 | SiraUtil] Installing: SiraInstaller (SiraUtil) [DEBUG @ 01:31:37 | SiraUtil] Installing: HsvAppInstaller (HitScoreVisualizer) [DEBUG @ 01:31:37 | SiraUtil] Installing: AppInstaller (SaberFactory) [DEBUG @ 01:31:37 | SiraUtil] Installing: CustomNotesCoreInstaller (Custom Notes) [DEBUG @ 01:31:37 | SiraUtil] Installing: CoreInstaller (Counters+) [DEBUG @ 01:31:44 | SiraUtil] Installing: SiraMenuInstaller (SiraUtil) [DEBUG @ 01:31:44 | SiraUtil] Installing: HsvMenuInstaller (HitScoreVisualizer) [DEBUG @ 01:31:44 | SiraUtil] Installing: MenuInstaller (SaberFactory) [DEBUG @ 01:31:44 | SiraUtil] Installing: CustomNotesMenuInstaller (Custom Notes) [DEBUG @ 01:31:44 | SiraUtil] Installing: MenuUIInstaller (Counters+) [DEBUG @ 01:31:44 | SiraUtil] Installing: PlaylistViewInstaller (PlaylistManager) [DEBUG @ 01:32:08 | SiraUtil] Installing: SiraSaberInstaller (SiraUtil) [DEBUG @ 01:32:08 | SiraUtil] Installing: GameInstaller (SaberFactory) [DEBUG @ 01:32:08 | SiraUtil] Installing: CustomNotesGameInstaller (Custom Notes) [DEBUG @ 01:32:08 | SiraUtil] Installing: ClientInstaller (DataPuller) [DEBUG @ 01:32:08 | SiraUtil] Installing: SiraSaberEffectInstaller (SiraUtil) [DEBUG @ 01:32:08 | SiraUtil] Installing: SiraGameLevelInstaller (SiraUtil) [DEBUG @ 01:32:08 | SiraUtil] Installing: SiraGameInstaller (SiraUtil) [DEBUG @ 01:32:08 | SiraUtil] Installing: IntroSkipGameInstaller (IntroSkip) [DEBUG @ 01:32:08 | SiraUtil] Installing: HsvGameInstaller (HitScoreVisualizer) [DEBUG @ 01:32:08 | SiraUtil] Installing: CountersInstaller (Counters+) [CRITICAL @ 01:32:08 | SiraUtil] Error occurred while initializing IInitializable with type 'DataPuller.Client.MapEvents' [CRITICAL @ 01:32:08 | SiraUtil] System.ArgumentException: Requested value '90Degree' was not found. [CRITICAL @ 01:32:08 | SiraUtil] at System.Enum+EnumResult.SetFailure (System.Enum+ParseFailureKind failure, System.String failureMessageID, System.Object failureMessageFormatArgument) [0x00023] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:32:08 | SiraUtil] at System.Enum.TryParseEnum (System.Type enumType, System.String value, System.Boolean ignoreCase, System.Enum+EnumResult& parseResult) [0x0017a] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:32:08 | SiraUtil] at System.Enum.Parse (System.Type enumType, System.String value, System.Boolean ignoreCase) [0x00010] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:32:08 | SiraUtil] at System.Enum.Parse (System.Type enumType, System.String value) [0x00000] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:32:08 | SiraUtil] at DataPuller.Client.MapEvents.SetupMapDataAndMisc () [0x00223] in <db6dbc2d93ab49c5a5bfa6283cdd6c23>:0 [CRITICAL @ 01:32:08 | SiraUtil] at DataPuller.Client.MapEvents.Initialize () [0x001f2] in <db6dbc2d93ab49c5a5bfa6283cdd6c23>:0 [CRITICAL @ 01:32:08 | SiraUtil] at (wrapper dynamic-method) Zenject.InitializableManager.Zenject.InitializableManager.Initialize_Patch0(Zenject.InitializableManager) [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:32:08 | SiraUtil] Please tell kOF.Readie to fix this! [DEBUG @ 01:33:05 | SiraUtil] Installing: SiraSaberInstaller (SiraUtil) [DEBUG @ 01:33:05 | SiraUtil] Installing: GameInstaller (SaberFactory) [DEBUG @ 01:33:05 | SiraUtil] Installing: CustomNotesGameInstaller (Custom Notes) [DEBUG @ 01:33:05 | SiraUtil] Installing: ClientInstaller (DataPuller) [DEBUG @ 01:33:05 | SiraUtil] Installing: SiraSaberEffectInstaller (SiraUtil) [DEBUG @ 01:33:05 | SiraUtil] Installing: SiraGameLevelInstaller (SiraUtil) [DEBUG @ 01:33:05 | SiraUtil] Installing: SiraGameInstaller (SiraUtil) [DEBUG @ 01:33:05 | SiraUtil] Installing: IntroSkipGameInstaller (IntroSkip) [DEBUG @ 01:33:05 | SiraUtil] Installing: HsvGameInstaller (HitScoreVisualizer) [DEBUG @ 01:33:05 | SiraUtil] Installing: CountersInstaller (Counters+) [DEBUG @ 01:33:29 | SiraUtil] Installing: SiraSaberInstaller (SiraUtil) [DEBUG @ 01:33:29 | SiraUtil] Installing: GameInstaller (SaberFactory) [DEBUG @ 01:33:29 | SiraUtil] Installing: CustomNotesGameInstaller (Custom Notes) [DEBUG @ 01:33:29 | SiraUtil] Installing: ClientInstaller (DataPuller) [DEBUG @ 01:33:30 | SiraUtil] Installing: SiraSaberEffectInstaller (SiraUtil) [DEBUG @ 01:33:30 | SiraUtil] Installing: SiraGameLevelInstaller (SiraUtil) [DEBUG @ 01:33:30 | SiraUtil] Installing: SiraGameInstaller (SiraUtil) [DEBUG @ 01:33:30 | SiraUtil] Installing: IntroSkipGameInstaller (IntroSkip) [DEBUG @ 01:33:30 | SiraUtil] Installing: HsvGameInstaller (HitScoreVisualizer) [DEBUG @ 01:33:30 | SiraUtil] Installing: CountersInstaller (Counters+) [CRITICAL @ 01:33:30 | SiraUtil] Error occurred while initializing IInitializable with type 'DataPuller.Client.MapEvents' [CRITICAL @ 01:33:30 | SiraUtil] System.ArgumentException: Requested value '90Degree' was not found. [CRITICAL @ 01:33:30 | SiraUtil] at System.Enum+EnumResult.SetFailure (System.Enum+ParseFailureKind failure, System.String failureMessageID, System.Object failureMessageFormatArgument) [0x00023] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:33:30 | SiraUtil] at System.Enum.TryParseEnum (System.Type enumType, System.String value, System.Boolean ignoreCase, System.Enum+EnumResult& parseResult) [0x0017a] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:33:30 | SiraUtil] at System.Enum.Parse (System.Type enumType, System.String value, System.Boolean ignoreCase) [0x00010] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:33:30 | SiraUtil] at System.Enum.Parse (System.Type enumType, System.String value) [0x00000] in <9577ac7a62ef43179789031239ba8798>:0 [CRITICAL @ 01:33:30 | SiraUtil] at DataPuller.Client.MapEvents.SetupMapDataAndMisc () [0x00223] in <db6dbc2d93ab49c5a5bfa6283cdd6c23>:0 [CRITICAL @ 01:33:30 | SiraUtil] at DataPuller.Client.MapEvents.Initialize () [0x001f2] in <db6dbc2d93ab49c5a5bfa6283cdd6c23>:0 [CRITICAL @ 01:33:30 | SiraUtil] at (wrapper dynamic-method) Zenject.InitializableManager.Zenject.InitializableManager.Initialize_Patch0(Zenject.InitializableManager) [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this! [WARNING @ 01:33:30 | SiraUtil] Please tell kOF.Readie to fix this!

Potential Counter+ conflict / soft lock

Hello !
I've recently got an issue with Counter+ menu soft locking my game when in FPFC mod. I asked Caeden first and it might be because of conflicts with one or more mods, including DataPuller !

Here is the link for the specific lines of the logs and comments Caeden made :
NuggoDEV/CountersPlus#78 (comment)

here are the logs if you need to see more :

Counter+ log :
_latest.log

Beatsaber log :
_latest.log

Data puller log
_latest.log

If anything I might be able to give more details or specific infos if asked !

[2.1.0] LiveData.Combo is doubled

Game version 1.24.1

Example data (ingame combo is 50):

{
  "Score": 37083,
  "ScoreWithMultipliers": 37083,
  "MaxScore": 38755,
  "MaxScoreWithMultipliers": 38755,
  "Rank": "SS",
  "FullCombo": true,
  "NotesSpawned": 50,
  "Combo": 100,
  "Misses": 0,
  "Accuracy": 95.58081030845642,
  "BlockHitScore": {
    "PreSwing": 70,
    "PostSwing": 30,
    "CenterSwing": 15
  },
  "PlayerHealth": 99.99995422363281,
  "ColorType": 1,
  "TimeElapsed": 18,
  "EventTrigger": 4,
  "UnixTimestamp": 1665697934181
}

Note that Combo is 100 while NotesSpawned is 50

Finishing a replay = Timer breaks until game restart

Game Version: 1.16.4
DataPuller Version: 2.0.5

Bug related to replays.
If you finish watching a replay, the time data keeps displaying the length of the song that was replayed while trying to show the current song time as well. This doesn't happen if you pause and exit before the replay is done I think.

Work around seems to be restarting game.

DataPullerReplay.mp4

Potential CustomNotes conflict - [Zenject - critical error]

CustomNotes did a fix lately about disappearing notes, but the bug came back on me.
I noticed some critical entries in the logs.
After I excluded DataPuller from the game, the following log did not appear (and with it the CustomNotes bug):

[CRITICAL @ 02:55:54 | UnityEngine] NullReferenceException: Object reference not set to an instance of an object
[CRITICAL @ 02:55:54 | UnityEngine] DataPuller.MapEvents.SwingRatingCounter_didFinishEvent (ISaberSwingRatingCounter saberSwingRatingCounter) (at <6bab6d00ea9947f082625a105d0f287f>:0)
[CRITICAL @ 02:55:54 | UnityEngine] SaberSwingRatingCounter.ProcessNewData (BladeMovementDataElement newData, BladeMovementDataElement prevData, System.Boolean prevDataAreValid) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:55:54 | UnityEngine] SaberMovementData.AddNewData (UnityEngine.Vector3 topPos, UnityEngine.Vector3 bottomPos, System.Single time) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:55:54 | UnityEngine] Saber.ManualUpdate () (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:55:54 | UnityEngine] SaberManager.Update () (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] ArgumentException: An item with the same key has already been added. Key: SaberSwingRatingCounter
[CRITICAL @ 02:56:01 | UnityEngine] System.Collections.Generic.Dictionary2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at <437ba245d8404784b9fbab9b439ac908>:0) [CRITICAL @ 02:56:01 | UnityEngine] System.Collections.Generic.Dictionary2[TKey,TValue].Add (TKey key, TValue value) (at <437ba245d8404784b9fbab9b439ac908>:0)
[CRITICAL @ 02:56:01 | UnityEngine] CountersPlus.Counters.CutCounter.OnNoteCut (NoteData data, NoteCutInfo info) (at <7af112dd57e54cc6aa0061a0795de2e4>:0)
[CRITICAL @ 02:56:01 | UnityEngine] CountersPlus.Counters.Event_Broadcasters.NoteEventBroadcaster.NoteWasCutEvent (NoteController data, NoteCutInfo noteCutInfo) (at <7af112dd57e54cc6aa0061a0795de2e4>:0)
[CRITICAL @ 02:56:01 | UnityEngine] BeatmapObjectManager.HandleNoteWasCut (NoteController noteController, NoteCutInfo noteCutInfo) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] NoteController.SendNoteWasCutEvent (NoteCutInfo noteCutInfo) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] GameNoteController.HandleCut (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec, System.Boolean allowBadCut) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] GameNoteController.HandleBigWasCutBySaber (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] CuttableBySaber.CallWasCutBySaberEvent (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] BoxCuttableBySaber.Cut (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] NoteCutter.Cut (Saber saber) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] CuttingManager.HandleSaberManagerDidUpdateSaberPositions (Saber leftSaber, Saber rightSaber) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:01 | UnityEngine] SaberManager.Update () (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:02 | UnityEngine] ZenjectException: Assert hit! Tried to return an item to pool SiraPrefabContainer.Pool twice
[CRITICAL @ 02:56:02 | UnityEngine] ModestTree.Assert.That (System.Boolean condition, System.String message, System.Object p1) (at <299da3b42a70434ab7fac865debabf48>:0)
[CRITICAL @ 02:56:02 | UnityEngine] Zenject.MemoryPoolBase1[TContract].Despawn (TContract item) (at <299da3b42a70434ab7fac865debabf48>:0) [CRITICAL @ 02:56:02 | UnityEngine] CustomNotes.Managers.CustomNoteController.DidFinish (NoteController nc) (at <371d57a2079d48f69a69ea619e5f03fd>:0) [CRITICAL @ 02:56:02 | UnityEngine] CustomNotes.Managers.CustomNoteController.WasCut (NoteController nc, NoteCutInfo _) (at <371d57a2079d48f69a69ea619e5f03fd>:0) [CRITICAL @ 02:56:02 | UnityEngine] NoteController.SendNoteWasCutEvent (NoteCutInfo noteCutInfo) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] GameNoteController.HandleCut (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec, System.Boolean allowBadCut) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] GameNoteController.HandleBigWasCutBySaber (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] CuttableBySaber.CallWasCutBySaberEvent (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] BoxCuttableBySaber.Cut (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] NoteCutter.Cut (Saber saber) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] CuttingManager.HandleSaberManagerDidUpdateSaberPositions (Saber leftSaber, Saber rightSaber) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] SaberManager.Update () (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0) [CRITICAL @ 02:56:02 | UnityEngine] KeyNotFoundException: The given key was not present in the dictionary. [CRITICAL @ 02:56:02 | UnityEngine] System.Collections.Generic.Dictionary2[TKey,TValue].get_Item (TKey key) (at <437ba245d8404784b9fbab9b439ac908>:0)
[CRITICAL @ 02:56:02 | UnityEngine] CountersPlus.Counters.CutCounter.SaberSwingRatingCounter_didFinishEvent (ISaberSwingRatingCounter v) (at <7af112dd57e54cc6aa0061a0795de2e4>:0)
[CRITICAL @ 02:56:02 | UnityEngine] SaberSwingRatingCounter.ProcessNewData (BladeMovementDataElement newData, BladeMovementDataElement prevData, System.Boolean prevDataAreValid) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:02 | UnityEngine] SaberMovementData.AddNewData (UnityEngine.Vector3 topPos, UnityEngine.Vector3 bottomPos, System.Single time) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:02 | UnityEngine] Saber.ManualUpdate () (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:02 | UnityEngine] SaberManager.Update () (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] ZenjectException: Assert hit! Tried to return an item to pool SiraPrefabContainer.Pool twice
[CRITICAL @ 02:56:03 | UnityEngine] ModestTree.Assert.That (System.Boolean condition, System.String message, System.Object p1) (at <299da3b42a70434ab7fac865debabf48>:0)
[CRITICAL @ 02:56:03 | UnityEngine] Zenject.MemoryPoolBase`1[TContract].Despawn (TContract item) (at <299da3b42a70434ab7fac865debabf48>:0)
[CRITICAL @ 02:56:03 | UnityEngine] CustomNotes.Managers.CustomNoteController.DidFinish (NoteController nc) (at <371d57a2079d48f69a69ea619e5f03fd>:0)
[CRITICAL @ 02:56:03 | UnityEngine] CustomNotes.Managers.CustomNoteController.WasCut (NoteController nc, NoteCutInfo _) (at <371d57a2079d48f69a69ea619e5f03fd>:0)
[CRITICAL @ 02:56:03 | UnityEngine] NoteController.SendNoteWasCutEvent (NoteCutInfo noteCutInfo) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] GameNoteController.HandleCut (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec, System.Boolean allowBadCut) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] GameNoteController.HandleBigWasCutBySaber (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] CuttableBySaber.CallWasCutBySaberEvent (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] BoxCuttableBySaber.Cut (Saber saber, UnityEngine.Vector3 cutPoint, UnityEngine.Quaternion orientation, UnityEngine.Vector3 cutDirVec) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] NoteCutter.Cut (Saber saber) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] CuttingManager.HandleSaberManagerDidUpdateSaberPositions (Saber leftSaber, Saber rightSaber) (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)
[CRITICAL @ 02:56:03 | UnityEngine] SaberManager.Update () (at <7209c9bc21cd412681ca9f81c6a4ebb6>:0)

Feature request: timestamps

Please add timestamp field to update object
It will be useful to get the exact time when that update happened.

I am building a custom client for MapData and saving updates to a database. I'm using the timestamp of websocket message received because it is the most accurate one I could get.

But I noticed that there are some delays between game events and tracked timestamps. I think they are caused by network delays between sending the message and receiving it but I'm not sure.

Anyway, adding timestamp to update would be useful

[1.21] MaxScore, MaxScoreWithMultipliers, and BlockHitScore are always 0

Some sample data:

{
  "Score": 33754,
  "ScoreWithMultipliers": 33754,
  "MaxScore": 0,
  "MaxScoreWithMultipliers": 0,
  "Rank": "SS",
  "FullCombo": true,
  "Combo": 47,
  "Misses": 0,
  "Accuracy": 96.17918133735657,
  "BlockHitScore": [
    0,
    0,
    0
  ],
  "PlayerHealth": 96.99995422363281,
  "ColorType": 0,
  "TimeElapsed": 36,
  "unixTimestamp": 1650232162421,
  "EventTrigger": 2
}

{
  "Score": 36330,
  "ScoreWithMultipliers": 36330,
  "MaxScore": 0,
  "MaxScoreWithMultipliers": 0,
  "Rank": "SS",
  "FullCombo": true,
  "Combo": 49,
  "Misses": 0,
  "Accuracy": 95.94473838806152,
  "BlockHitScore": [
    0,
    0,
    0
  ],
  "PlayerHealth": 98.99995422363281,
  "ColorType": 0,
  "TimeElapsed": 38,
  "unixTimestamp": 1650232164087,
  "EventTrigger": 0
}

[Fix/Feature Request] CoverImage for non-BeatSaver songs

I have a working build that just copies the texture-reading code from HTTP Status, but I don't think it's pull-request-worthy.

diff --git a/src/Core/MapEvents.cs b/src/Core/MapEvents.cs
index 4dbbc91..55fa3db 100644
--- a/src/Core/MapEvents.cs
+++ b/src/Core/MapEvents.cs
@@ -178,7 +178,7 @@ namespace DataPuller.Core
             MapData.Instance.Send();
         }
 
-        public void LevelLoaded()
+        public async void LevelLoaded()
         {
             PlayerData playerData = Resources.FindObjectsOfTypeAll<PlayerDataModel>().FirstOrDefault().playerData;
             IBeatmapLevel levelData = gameplayCoreSceneSetupData.difficultyBeatmap.level;
@@ -204,6 +204,40 @@ namespace DataPuller.Core
             MapData.Instance.Difficulty = gameplayCoreSceneSetupData.difficultyBeatmap.difficulty.ToString("g");
             MapData.Instance.NJS = gameplayCoreSceneSetupData.difficultyBeatmap.noteJumpMovementSpeed;
             MapData.Instance.CustomDifficultyLabel = difficultyData?._difficultyLabel ?? null;
+            
+            // From HTTPStatus
+            try {
+                // From https://support.unity3d.com/hc/en-us/articles/206486626-How-can-I-get-pixels-from-unreadable-textures-
+                // Modified to correctly handle texture atlases. Fixes #82.
+                var active = RenderTexture.active;
+
+                var sprite = await levelData.GetCoverImageAsync(System.Threading.CancellationToken.None);
+                var texture = sprite.texture;
+                var temporary = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
+
+                Graphics.Blit(texture, temporary);
+                RenderTexture.active = temporary;
+
+                var spriteRect = sprite.rect;
+                var uv = sprite.uv[0];
+
+                var cover = new Texture2D((int) spriteRect.width, (int) spriteRect.height);
+                // Unity sucks. The coordinates of the sprite on its texture atlas are only accessible through the Sprite.uv property since rect always returns `x=0,y=0`, so we need to convert them back into texture space.
+                cover.ReadPixels(new Rect(
+                    uv.x * texture.width,
+                    texture.height - uv.y * texture.height,
+                    spriteRect.width,
+                    spriteRect.height
+                ), 0, 0);
+                cover.Apply();
+
+                RenderTexture.active = active;
+                RenderTexture.ReleaseTemporary(temporary);
+
+                MapData.Instance.CoverImage = "data:image/png;base64," + System.Convert.ToBase64String(ImageConversion.EncodeToPNG(cover));
+            } catch {
+                MapData.Instance.CoverImage = null;
+            }
 
             if (isCustomLevel)
             {
@@ -267,7 +301,6 @@ namespace DataPuller.Core
                         else
                         {
                             MapData.Instance.BSRKey = null;
-                            MapData.Instance.CoverImage = null;
                         }
                         MapData.Instance.Send();
                     });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.