Skip to content

Commit 897f072

Browse files
authored
Merge pull request #94 from Zingabopp/dev
Bug Fixes
2 parents 4f8ecc8 + 3efa411 commit 897f072

15 files changed

+69
-37
lines changed

MultiplayerExtensions/Beatmaps/PreviewBeatmapStub.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ public PreviewBeatmapStub(PreviewBeatmapPacket packet)
9191
_rawCoverTask = Task.FromResult(packet.coverImage);
9292
}
9393

94-
public PreviewBeatmapStub(Beatmap bm)
94+
public PreviewBeatmapStub(string levelID, Beatmap bm)
9595
{
96-
this.levelID = bm.ID;
96+
this.levelID = levelID;
9797
this.levelHash = bm.Hash;
9898

9999
this.beatmap = bm;

MultiplayerExtensions/Environments/LobbyPlaceManager.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ public void SetCenterScreenScale()
5353
float angleBetweenPlayersWithEvenAdjustment = MultiplayerPlayerPlacement.GetAngleBetweenPlayersWithEvenAdjustment(_lobbyStateDataModel.maxPartySize, MultiplayerPlayerLayout.Circle);
5454
float outerCircleRadius = Mathf.Max(MultiplayerPlayerPlacement.GetOuterCircleRadius(angleBetweenPlayersWithEvenAdjustment, innerCircleRadius), minOuterCircleRadius);
5555
float scaleRatio = outerCircleRadius / minOuterCircleRadius;
56-
MultiplayerLobbyCenterStageManager centerscreen = Resources.FindObjectsOfTypeAll<MultiplayerLobbyCenterStageManager>().First();
56+
MultiplayerLobbyCenterStageManager[] centerscreens = Resources.FindObjectsOfTypeAll<MultiplayerLobbyCenterStageManager>();
57+
if (centerscreens.Length == 0)
58+
return;
59+
MultiplayerLobbyCenterStageManager centerscreen = centerscreens.First();
5760
centerscreen.transform.localScale = new Vector3(scaleRatio, scaleRatio, scaleRatio);
5861
}
5962

MultiplayerExtensions/HarmonyPatches/CustomSongsPatches.cs

+16-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace MultiplayerExtensions.HarmonyPatches
99
{
1010
[HarmonyPatch(typeof(MultiplayerLevelSelectionFlowCoordinator), "enableCustomLevels", MethodType.Getter)]
11-
public class EnableCustomLevelsPatch
11+
internal class EnableCustomLevelsPatch
1212
{
1313
/// <summary>
1414
/// Overrides getter for <see cref="MultiplayerLevelSelectionFlowCoordinator.enableCustomLevels"/>
@@ -20,8 +20,20 @@ static bool Prefix(ref bool __result)
2020
}
2121
}
2222

23+
[HarmonyPatch(typeof(HostLobbySetupViewController), "SetPlayersMissingLevelText", MethodType.Normal)]
24+
internal class MissingLevelStartPatch
25+
{
26+
/// <summary>
27+
/// Disables starting of game if not all players have song.
28+
/// </summary>
29+
static void Prefix(HostLobbySetupViewController __instance, string playersMissingLevelText)
30+
{
31+
__instance.SetStartGameEnabled(playersMissingLevelText == null, HostLobbySetupViewController.CannotStartGameReason.None);
32+
}
33+
}
34+
2335
[HarmonyPatch(typeof(NetworkPlayerEntitlementChecker), "GetEntitlementStatus", MethodType.Normal)]
24-
public class CustomLevelEntitlementPatch
36+
internal class CustomLevelEntitlementPatch
2537
{
2638
/// <summary>
2739
/// Changes the return value of the entitlement checker if it is a custom song.
@@ -32,7 +44,7 @@ static bool Prefix(string levelId, ref Task<EntitlementsStatus> __result)
3244
if (hash == null)
3345
return true;
3446

35-
if (SongCore.Loader.GetLevelByHash(hash) != null)
47+
if (SongCore.Collections.songWithHashPresent(hash))
3648
__result = Task.FromResult(EntitlementsStatus.Ok);
3749
else
3850
__result = Plugin.BeatSaver.Hash(hash).ContinueWith<EntitlementsStatus>(r =>
@@ -48,7 +60,7 @@ static bool Prefix(string levelId, ref Task<EntitlementsStatus> __result)
4860
}
4961

5062
[HarmonyPatch(typeof(NetworkPlayerEntitlementChecker), "GetPlayerLevelEntitlementsAsync", MethodType.Normal)]
51-
public class StartGameLevelEntitlementPatch
63+
internal class StartGameLevelEntitlementPatch
5264
{
5365
/// <summary>
5466
/// Changes the return value if it returns 'NotDownloaded' so that the host can start the game.

MultiplayerExtensions/HarmonyPatches/HarmonyManager.cs

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static HarmonyManager()
4040
AddDefaultPatch<PlayerPlacementAnglePatch>();
4141
AddDefaultPatch<IncreaseMaxPlayersClampPatch>();
4242
AddDefaultPatch<IncreaseMaxPlayersPatch>();
43+
AddDefaultPatch<MissingLevelStartPatch>();
4344
//AddDefaultPatch<RemoveByteLimitPatch>(); (doesn't support generics)
4445
}
4546

MultiplayerExtensions/HarmonyPatches/NetworkingPatches.cs

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using HarmonyLib;
2+
using System;
23
using System.Collections.Generic;
34
using System.Linq;
5+
using System.Reflection;
46
using System.Reflection.Emit;
57
using UnityEngine;
68

@@ -57,24 +59,27 @@ internal static bool Prefix()
5759
}
5860
}
5961

60-
[HarmonyPatch(typeof(ConnectedPlayerManager), "FlushUnreliableQueue", MethodType.Normal)]
62+
[HarmonyPatch(typeof(ConnectedPlayerManager), "PollUpdate", MethodType.Normal)]
6163
internal class UpdateUnreliableFrequencyPatch
6264
{
63-
private static float nextTime = 0f;
64-
private static float frequency = 0.1f;
65+
private static readonly MethodInfo _updateUnreliableMethod = typeof(ConnectedPlayerManager).GetMethod("FlushUnreliableQueue", BindingFlags.NonPublic | BindingFlags.Instance);
6566

66-
internal static bool Prefix()
67+
internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
6768
{
68-
if (Time.time > nextTime)
69+
var codes = instructions.ToList();
70+
for (int i = 0; i < codes.Count; i++)
6971
{
70-
nextTime = Time.time + frequency;
71-
return true;
72+
if (codes[i].opcode == OpCodes.Ldarg_0 && codes[i+1].Calls(_updateUnreliableMethod))
73+
{
74+
codes.RemoveRange(i, 2);
75+
}
7276
}
73-
return false;
77+
78+
return codes.AsEnumerable();
7479
}
7580
}
7681

77-
//Make this work with harmony manager
82+
// TODO: Make this work with harmony manager
7883
[HarmonyPatch(typeof(ConnectedPlayerManager), "SendUnreliable", MethodType.Normal)]
7984
internal class RemoveByteLimitPatch
8085
{

MultiplayerExtensions/Installers/MultiplayerInstaller.cs MultiplayerExtensions/Installers/MPCoreInstaller.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace MultiplayerExtensions.Installers
77
{
8-
class MultiplayerInstaller : MonoInstaller
8+
class MPCoreInstaller : MonoInstaller
99
{
1010
public HarmonyPatchInfo? lobbyPlayerDataPatch;
1111
public HarmonyPatchInfo? levelLoaderPatch;

MultiplayerExtensions/Installers/InterfaceInstaller.cs MultiplayerExtensions/Installers/MPMenuInstaller.cs

+7-4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
using MultiplayerExtensions.Environments;
33
using MultiplayerExtensions.OverrideClasses;
44
using MultiplayerExtensions.UI;
5+
using UnityEngine;
56
using Zenject;
67

78
namespace MultiplayerExtensions.Installers
89
{
9-
class InterfaceInstaller : MonoInstaller
10+
class MPMenuInstaller : MonoInstaller
1011
{
1112
public override void InstallBindings()
1213
{
@@ -33,9 +34,11 @@ public override void Start()
3334
ServerPlayerListController playerListController = Container.Resolve<ServerPlayerListController>();
3435
GameServerPlayersTableView playersTableView = playerListController.GetField<GameServerPlayersTableView, ServerPlayerListController>("_gameServerPlayersTableView");
3536
GameServerPlayerTableCell playerTableCell = playersTableView.GetField<GameServerPlayerTableCell, GameServerPlayersTableView>("_gameServerPlayerCellPrefab");
36-
PlayerTableCellStub playerTableCellStub = playerTableCell.gameObject.AddComponent<PlayerTableCellStub>();
37-
playerTableCellStub.Construct(playerTableCell);
38-
Destroy(playerTableCell.GetComponent<GameServerPlayerTableCell>());
37+
GameServerPlayerTableCell newPlayerTableCell = GameObject.Instantiate(playerTableCell);
38+
newPlayerTableCell.gameObject.SetActive(false);
39+
PlayerTableCellStub playerTableCellStub = newPlayerTableCell.gameObject.AddComponent<PlayerTableCellStub>();
40+
playerTableCellStub.Construct(newPlayerTableCell);
41+
Destroy(newPlayerTableCell.GetComponent<GameServerPlayerTableCell>());
3942
playersTableView.SetField<GameServerPlayersTableView, GameServerPlayerTableCell>("_gameServerPlayerCellPrefab", playerTableCellStub);
4043
}
4144
}

MultiplayerExtensions/MultiplayerExtensions.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<OutputType>Library</OutputType>
55
<AppDesignerFolder>Properties</AppDesignerFolder>
66
<AssemblyName>MultiplayerExtensions</AssemblyName>
7-
<AssemblyVersion>0.4.4</AssemblyVersion>
7+
<AssemblyVersion>0.4.5</AssemblyVersion>
88
<TargetFramework>net472</TargetFramework>
99
<DebugSymbols>true</DebugSymbols>
1010
<DebugType>portable</DebugType>

MultiplayerExtensions/OverrideClasses/LevelLoaderStub.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public override void LoadLevel(BeatmapIdentifierNetSerializable beatmapId, Gamep
1010
{
1111
string? levelId = beatmapId.levelID;
1212
string? hash = Utilities.Utils.LevelIdToHash(beatmapId.levelID);
13-
if (SongCore.Loader.GetLevelById(levelId) != null || hash == null)
13+
if (SongCore.Collections.songWithHashPresent(hash) || hash == null)
1414
{
1515
Plugin.Log?.Debug($"(SongLoader) Level with ID '{levelId}' already exists.");
1616
base.LoadLevel(beatmapId, gameplayModifiers, initialStartTime);

MultiplayerExtensions/OverrideClasses/PlayerTableCellStub.cs

+11-3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ public override void Awake() {
7272

7373
public override void SetData(IConnectedPlayer connectedPlayer, ILobbyPlayerDataModel playerDataModel, bool isHost, Task<AdditionalContentModel.EntitlementStatus> getLevelEntitlementTask)
7474
{
75+
if (getLevelEntitlementTask != null)
76+
getLevelEntitlementTask = getLevelEntitlementTask.ContinueWith<AdditionalContentModel.EntitlementStatus>(r => AdditionalContentModel.EntitlementStatus.Owned);
7577
base.SetData(connectedPlayer, playerDataModel, isHost, getLevelEntitlementTask);
7678
GetLevelEntitlement(connectedPlayer);
7779
lastPlayer = connectedPlayer;
@@ -84,12 +86,18 @@ private async void GetLevelEntitlement(IConnectedPlayer player)
8486
entitlementCts = new CancellationTokenSource();
8587

8688
string? levelId = _playersDataModel.GetPlayerBeatmapLevel(_playersDataModel.hostUserId)?.levelID;
87-
if (levelId == null)
89+
if (levelId == null)
8890
return;
8991

9092
lastLevelId = levelId;
91-
EntitlementsStatus entitlement = player.isMe ? await _entitlementChecker.GetEntitlementStatus(levelId) : await _entitlementChecker.GetTcsTaskCanPlayerPlayLevel(player, levelId, entitlementCts.Token, out _);
92-
SetLevelEntitlement(player, entitlement);
93+
94+
bool needsRpc = false;
95+
Task<EntitlementsStatus> entitlement = player.isMe ?
96+
_entitlementChecker.GetEntitlementStatus(levelId) :
97+
_entitlementChecker.GetTcsTaskCanPlayerPlayLevel(player, levelId, entitlementCts.Token, out needsRpc);
98+
if (needsRpc)
99+
_menuRpcManager.GetIsEntitledToLevel(levelId);
100+
SetLevelEntitlement(player, await entitlement);
93101
}
94102

95103
private void SetLevelEntitlement(IConnectedPlayer player, EntitlementsStatus status)

MultiplayerExtensions/OverrideClasses/PlayersDataModelStub.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public override void HandleMenuRpcManagerClearBeatmap(string userId)
8080
public async override void HandleMenuRpcManagerGetSelectedBeatmap(string userId)
8181
{
8282
ILobbyPlayerDataModel lobbyPlayerDataModel = this.GetLobbyPlayerDataModel(this.localUserId);
83-
if (_multiplayerSessionManager.GetPlayerByUserId(userId).HasState("modded") && lobbyPlayerDataModel?.beatmapLevel is PreviewBeatmapStub preview)
83+
if (lobbyPlayerDataModel != null && MPState.CurrentGameType != MultiplayerGameType.QuickPlay && _multiplayerSessionManager.GetPlayerByUserId(userId).HasState("modded") && lobbyPlayerDataModel?.beatmapLevel is PreviewBeatmapStub preview)
8484
_packetManager.Send(await PreviewBeatmapPacket.FromPreview(preview, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty));
8585
else if (lobbyPlayerDataModel != null && lobbyPlayerDataModel.beatmapLevel != null)
8686
this._menuRpcManager.SelectBeatmap(new BeatmapIdentifierNetSerializable(lobbyPlayerDataModel.beatmapLevel.levelID, lobbyPlayerDataModel.beatmapCharacteristic.serializedName, lobbyPlayerDataModel.beatmapDifficulty));
@@ -109,7 +109,7 @@ public async override void HandleMenuRpcManagerSelectedBeatmap(string userId, Be
109109
if (localPreview != null)
110110
preview = new PreviewBeatmapStub(hash, localPreview);
111111
if (preview == null)
112-
preview = await FetchBeatSaverPreview(hash);
112+
preview = await FetchBeatSaverPreview(beatmapId.levelID, hash);
113113
HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(userId, preview, beatmapId.difficulty, characteristic));
114114
}
115115
}
@@ -123,7 +123,7 @@ public async override void HandleMenuRpcManagerSelectedBeatmap(string userId, Be
123123
public async new void SetLocalPlayerBeatmapLevel(string levelId, BeatmapDifficulty beatmapDifficulty, BeatmapCharacteristicSO characteristic)
124124
{
125125
string? hash = Utilities.Utils.LevelIdToHash(levelId);
126-
Plugin.Log?.Debug($"Local user selected song '{hash}'.");
126+
Plugin.Log?.Debug($"Local user selected song '{hash ?? levelId}'.");
127127
if (hash != null)
128128
{
129129
if (_playersData.Values.Any(playerData => playerData.beatmapLevel?.levelID == levelId))
@@ -139,7 +139,7 @@ public async override void HandleMenuRpcManagerSelectedBeatmap(string userId, Be
139139
if (localPreview != null)
140140
preview = new PreviewBeatmapStub(hash, localPreview);
141141
if (preview == null)
142-
preview = await FetchBeatSaverPreview(hash);
142+
preview = await FetchBeatSaverPreview(levelId, hash);
143143

144144
HMMainThreadDispatcher.instance.Enqueue(() => base.SetPlayerBeatmapLevel(base.localUserId, preview, beatmapDifficulty, characteristic));
145145
_packetManager.Send(await PreviewBeatmapPacket.FromPreview(preview, characteristic.serializedName, beatmapDifficulty));
@@ -195,12 +195,12 @@ private void OnSelectedBeatmap(string userId, BeatmapIdentifierNetSerializable?
195195
/// <summary>
196196
/// Creates a preview from a BeatSaver request.
197197
/// </summary>
198-
public async Task<PreviewBeatmapStub?> FetchBeatSaverPreview(string hash)
198+
public async Task<PreviewBeatmapStub?> FetchBeatSaverPreview(string levelID, string hash)
199199
{
200200
try
201201
{
202202
Beatmap bm = await Plugin.BeatSaver.Hash(hash);
203-
return new PreviewBeatmapStub(bm);
203+
return new PreviewBeatmapStub(levelID, bm);
204204
}
205205
catch(Exception ex)
206206
{

MultiplayerExtensions/Plugin.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ public Plugin(IPALogger logger, Config conf, Zenjector zenjector, PluginMetadata
4343
PluginMetadata = pluginMetadata;
4444
Log = logger;
4545
Config = conf.Generated<PluginConfig>();
46-
zenjector.OnApp<MultiplayerInstaller>();
47-
zenjector.OnMenu<InterfaceInstaller>();
46+
zenjector.OnApp<MPCoreInstaller>();
47+
zenjector.OnMenu<MPMenuInstaller>();
4848
HttpOptions options = new HttpOptions("MultiplayerExtensions", new Version(pluginMetadata.Version.ToString()));
4949
BeatSaver = new BeatSaver(options);
5050
}

MultiplayerExtensions/UI/ClientLobbySetupPanel.bsml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<vertical>
2-
<horizontal pad-top='30'>
2+
<horizontal pad-top='0'>
33
<vertical min-width='45' horizontal-fit='MinSize'>
44
<toggle-setting id='CustomSongsToggle' value='CustomSongs' on-change='SetCustomSongs' text='Custom Songs' interactable='false' hover-hint='Whether the host has custom songs enabled'></toggle-setting>
55
<toggle-setting id='EnforceModsToggle' value='EnforceMods' on-change='SetEnforceMods' text='Enforce Mods' interactable='false' hover-hint='Whether players without MultiplayerExtensions will be kicked'></toggle-setting>

MultiplayerExtensions/UI/HostLobbySetupPanel.bsml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<vertical>
2-
<horizontal pad-top='30'>
2+
<horizontal pad-top='0'>
33
<vertical min-width='45' horizontal-fit='MinSize'>
44
<toggle-setting id='CustomSongsToggle' value='CustomSongs' on-change='SetCustomSongs' text='Custom Songs' hover-hint='Toggles custom songs for all players'></toggle-setting>
55
<toggle-setting id='EnforceModsToggle' value='EnforceMods' on-change='SetEnforceMods' text='Enforce Mods' hover-hint='Toggles kicking players without MultiplayerExtensions'></toggle-setting>

MultiplayerExtensions/manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"id": "MultiplayerExtensions",
44
"name": "MultiplayerExtensions",
55
"author": "Zingabopp and Goobwabber",
6-
"version": "0.4.4",
6+
"version": "0.4.5",
77
"description": "Expands the functionality of Beat Saber Multiplayer.",
88
"gameVersion": "1.13.2",
99
"dependsOn": {

0 commit comments

Comments
 (0)