Skip to content

Commit

Permalink
Update for Beat Saber 1.37.0 (#50)
Browse files Browse the repository at this point in the history
* wip(1.35): initial refactor and cleanup

* feat: "required" flag for RequiredMod check

* wip(1.35): new extended status fields

https://github.com/Goobwabber/MultiplayerCore/wiki/Multiplayer-Status

* wip(1.35): updated / consistent custom MUR error messages

* wip(1.35): mark statusUrl as nullable in NetworkConfigPatcher

* wip(1.35): level loader - don't wait for non-players, quest consistency

* wip(1.35): level loader - fix flipped countdown time logic

* Setup code to make the requirement UI work again with non-downloaded maps, also setup code to make the right list and main levelbar work with maps from beatmap packets

* Fix null list

* More fixes and workarounds for problems with song lists

* Add additional logging to entitlement check

* Fix level load

* Fix entitlement not sent

* Fix logging transpiler

* Temp fix exception when selecting other players suggestion

* Fix patch not working properly
Patreon release

* Fix entitlement spam during level load

* Fix node pose sync state and added score sync controls

* Fix sync state values being multiplied

* Change from Setup to SetupData on LevelBar, BS 1.37

* Change check for requirements in packet

* Disable score validation when BeatmapBasicData notesCount is 0

* Cleanup code

* Fix MpBeatmapPacket ordering (#51)

* Add compat for 1.35, code cleanup

* Fix MpNodePoseSyncStatePacket should use VarLong

* Code cleanup/optimization

* No score validation for custom levels

* Add POC UI for per player difficulty and placeholder VCs

* Adjust UI, move start/unready button down

* Rename packets

* Add a RegisterType function to register a type without callback, mostly useful for testing

* Working POC UI for ppd/ppm

* Add support for 1.37.1 with backwards compat

* Fix potential null dereference

* Update difficulty selection when selecting suggestion, set alpha on difficulty selection at game start

* Debug logging attempt getting id of failed packet

* Allow changing difficulty during normal countdown

* Fix send MpBeatmapPacket logic for non-local levels

* Add Temporay patch for compatiblity between 1.37.1 and 1.37.0

* ForwardCompat use simpler method to patch

* Move PerPlayerUI into new class MpPerPlayerUI

* Align code and UI xml to better match the Quest port

* Tweak show toggles disabled, when not party owner, fix toggles dissappearing with ready/start button, update manifest

* Ensure newly joined players receive map selection

* Fix missing used function in MpPerPlayerUI

* Fix toggles not enabling when becoming lobby host

* Fix ScoreSyncState Packet

* Don't reference types not available in older game versions

* Fallback to beatsaver data when MpBeatmapPacket is missing

* Comment unused code, attempt move toggles when partyhost changes (not working)

* Use IPA WaitForTask instead of a WaitUntil, remove unused using statements

* Cleanup and improve code

* Fix blackscreen when map can't be downloaded / download fails

* Update NodePoseSTM to use long and avoid unnecessary type casts

* Remove todo comment

* Make entitlement checker public

* Make LevelBar patch version dependand

* Use Newtonsoft deserializer

* Check status and override before enablind toggles

* LevelDownloader install to custom folder when version 1.37.3+

* Use Setup instead of SetupData

* Bump up game version

* Per player modifiers, disable song speed modifiers

* NoLevelSpectator, patch ResultView instead of LevelBar

* BeatSaver bm ignore Chroma, MpPerPlayerUI unregister status callback on dispose

* MpPlayerData default initialize GameVersion with current gameversion, MpPlayerManager fixed not sending local MpPlayerData

* Removed unused UI classes

* add separate folder for mp songs (#39)

Co-authored-by: Michael R. <enderdrachelp@elp.quest>

* Fix typo

* Remove deleted reference

* Re-fix ordering from #51
Allow sending beatmap to single player (newly joined)

Co-authored-by: rcelyte <rcelyte@battletrains.org>

* On player connected, check if selected map is valid

* Fixes to map selection

* Disable sending MpPlayerData again, I forgot that it's sent from the server not the client

---------

Co-authored-by: Roy de Jong <roy@softwarepunt.nl>
Co-authored-by: RedBrumbler <redbrumbler.official+github@gmail.com>
Co-authored-by: cubic <cubicgraphics98@gmail.com>
Co-authored-by: rcelyte <rcelyte@battletrains.org>
Co-authored-by: ehlor <38947148+ehlor@users.noreply.github.com>
  • Loading branch information
6 people authored Aug 30, 2024
1 parent 9239705 commit 6881e8a
Show file tree
Hide file tree
Showing 53 changed files with 2,483 additions and 807 deletions.
3 changes: 3 additions & 0 deletions MultiplayerCore.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=beatmap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Beatmaps/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
112 changes: 0 additions & 112 deletions MultiplayerCore/Beatmaps/Abstractions/DifficultyColors.cs

This file was deleted.

36 changes: 36 additions & 0 deletions MultiplayerCore/Beatmaps/Abstractions/MpBeatmap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MultiplayerCore.Beatmaps.Serializable;
using UnityEngine;
using static SongCore.Data.ExtraSongData;

namespace MultiplayerCore.Beatmaps.Abstractions
{
/// <summary>
/// Base class for Beatmap data that can be used in multiplayer.
/// </summary>
public abstract class MpBeatmap
{
/// <summary>
/// The hash of the level. Should be the same on all clients.
/// </summary>
public abstract string LevelHash { get; protected set; }
/// <summary>
/// The local ID of the level. Can vary between clients.
/// </summary>
public string LevelID => $"custom_level_{LevelHash}";
public abstract string SongName { get; }
public abstract string SongSubName { get; }
public abstract string SongAuthorName { get; }
public abstract string LevelAuthorName { get; }
public virtual float BeatsPerMinute { get; protected set; }
public virtual float SongDuration { get; protected set; }
public virtual Dictionary<string, Dictionary<BeatmapDifficulty, string[]>> Requirements { get; protected set; } = new();
public virtual Dictionary<string, Dictionary<BeatmapDifficulty, DifficultyColors>> DifficultyColors { get; protected set; } = new();
public virtual Contributor[]? Contributors { get; protected set; } = null!;

public virtual Task<Sprite> TryGetCoverSpriteAsync(CancellationToken cancellationToken)
=> Task.FromResult<Sprite>(null!);
}
}
49 changes: 0 additions & 49 deletions MultiplayerCore/Beatmaps/Abstractions/MpBeatmapLevel.cs

This file was deleted.

36 changes: 18 additions & 18 deletions MultiplayerCore/Beatmaps/BeatSaverBeatmapLevel.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
using BeatSaverSharp.Models;
using MultiplayerCore.Beatmaps.Abstractions;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BeatSaverSharp.Models;
using MultiplayerCore.Beatmaps.Abstractions;
using UnityEngine;
using static BeatSaverSharp.Models.BeatmapDifficulty;
using static SongCore.Data.ExtraSongData;

namespace MultiplayerCore.Beatmaps
{
/// <summary>
/// An <see cref="IPreviewBeatmapLevel"/> created from data from BeatSaver.
/// Beatmap level data that was loaded remotely from the BeatSaver API.
/// </summary>
public class BeatSaverBeatmapLevel : MpBeatmapLevel
public class BeatSaverBeatmapLevel : MpBeatmap
{
public override string levelHash { get; protected set; }
public override string LevelHash { get; protected set; }

public override string songName => _beatmap.Metadata.SongName;
public override string songSubName => _beatmap.Metadata.SongSubName;
public override string songAuthorName => _beatmap.Metadata.SongAuthorName;
public override string levelAuthorName => _beatmap.Metadata.LevelAuthorName;
public override float beatsPerMinute => _beatmap.Metadata.BPM;
public override float songDuration => _beatmap.Metadata.Duration;
public override string SongName => _beatmap.Metadata.SongName;
public override string SongSubName => _beatmap.Metadata.SongSubName;
public override string SongAuthorName => _beatmap.Metadata.SongAuthorName;
public override string LevelAuthorName => _beatmap.Metadata.LevelAuthorName;
public override float BeatsPerMinute => _beatmap.Metadata.BPM;
public override float SongDuration => _beatmap.Metadata.Duration;

public override Dictionary<string, Dictionary<BeatmapDifficulty, string[]>> requirements
public override Dictionary<string, Dictionary<BeatmapDifficulty, string[]>> Requirements
{
get
{
Expand All @@ -46,8 +46,8 @@ public override Dictionary<string, Dictionary<BeatmapDifficulty, string[]>> requ
if (!reqs.ContainsKey(characteristic))
reqs.Add(characteristic, new());
string[] diffReqs = new string[0];
if (difficulty.Chroma)
diffReqs.Append("Chroma");
//if (difficulty.Chroma)
// diffReqs.Append("Chroma");
if (difficulty.NoodleExtensions)
diffReqs.Append("Noodle Extensions");
if (difficulty.MappingExtensions)
Expand All @@ -58,7 +58,7 @@ public override Dictionary<string, Dictionary<BeatmapDifficulty, string[]>> requ
}
}

public override Contributor[] contributors => new Contributor[] { new Contributor
public override Contributor[] Contributors => new Contributor[] { new Contributor
{
_role = "Uploader",
_name = _beatmap.Uploader.Name,
Expand All @@ -69,11 +69,11 @@ public override Dictionary<string, Dictionary<BeatmapDifficulty, string[]>> requ

public BeatSaverBeatmapLevel(string hash, Beatmap beatmap)
{
levelHash = hash;
LevelHash = hash;
_beatmap = beatmap;
}

public override async Task<Sprite> GetCoverImageAsync(CancellationToken cancellationToken)
public override async Task<Sprite> TryGetCoverSpriteAsync(CancellationToken cancellationToken)
{
byte[]? coverBytes = await _beatmap.LatestVersion.DownloadCoverImage(cancellationToken);
if (coverBytes == null || coverBytes.Length == 0)
Expand Down
62 changes: 62 additions & 0 deletions MultiplayerCore/Beatmaps/BeatSaverPreviewMediaData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BeatSaverSharp;
using BeatSaverSharp.Models;

namespace MultiplayerCore.Beatmaps
{
public class BeatSaverPreviewMediaData : IPreviewMediaData
{

public string LevelHash { get; private set; }
public BeatSaver BeatSaverClient { get; private set; }
public Sprite? CoverImagesprite { get; private set; }

public BeatSaverPreviewMediaData(string levelHash) : this(Plugin._beatsaver, levelHash) {}

public BeatSaverPreviewMediaData(BeatSaver beatsaver, string levelHash)
{
BeatSaverClient = beatsaver;
LevelHash = levelHash;
}

private Beatmap? _beatmap = null;
private async Task<Beatmap> GetBeatsaverBeatmap()
{
if (_beatmap != null) return _beatmap;
_beatmap = await BeatSaverClient.BeatmapByHash(LevelHash);
return _beatmap;
}

public async Task<Sprite> GetCoverSpriteAsync(CancellationToken cancellationToken)
{
if (CoverImagesprite != null) return CoverImagesprite;

var bm = await GetBeatsaverBeatmap();
if (bm == null) return null!;

byte[]? coverBytes = await bm.LatestVersion.DownloadCoverImage(cancellationToken);
if (coverBytes == null || coverBytes.Length == 0) return null!;

Texture2D texture = new Texture2D(2, 2);
texture.LoadImage(coverBytes);
CoverImagesprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0, 0), 100.0f);
return CoverImagesprite;
}

public async Task<AudioClip> GetPreviewAudioClip(CancellationToken cancellationToken)
{
// TODO: something with preview url
// var bm = await GetBeatsaverBeatmap();
// bm.LatestVersion.PreviewURL
return null;
}

public void UnloadPreviewAudioClip() {}
}
}
Loading

0 comments on commit 6881e8a

Please sign in to comment.