Skip to content

Commit 881de7e

Browse files
Add missing Adv. level select levels (v1.1.4.2)
Vanilla Fixes: * Fixed vanilla bug where in the Advanced level select menu. Two instances of levels in level sets wouldn't show up in the list: * Sprite: Zenith * Reverse Tag: Stuntware 2051 Refactors: * Switch to more uses of constants for WorkshopVoteIndex and "Unknown" default username.
1 parent 8dc455c commit 881de7e

File tree

7 files changed

+194
-10
lines changed

7 files changed

+194
-10
lines changed

Distance.LevelSelectAdditions/Distance.LevelSelectAdditions.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,12 @@
121121
<Compile Include="Harmony\Assembly-CSharp\LevelSelectMenuLogic\Start.cs" />
122122
<Compile Include="Harmony\Assembly-CSharp\LevelSelectMenuLogic\StartPlaylist.cs" />
123123
<Compile Include="Harmony\Assembly-CSharp\LevelSelectMenuLogic\UpdateInput.cs" />
124+
<Compile Include="Harmony\Assembly-CSharp\LevelSet\Initialize.cs" />
124125
<Compile Include="Harmony\Assembly-CSharp\MainMenuLogic\Start.cs" />
125126
<Compile Include="Harmony\Assembly-CSharp\OptionsMenuLogic\GetSubmenus.cs" />
126127
<Compile Include="Helpers\MainMenuLevelSetHelper.cs" />
127128
<Compile Include="Helpers\Sanitizer.cs" />
129+
<Compile Include="Helpers\SteamworksHelper.cs" />
128130
<Compile Include="Mod.cs" />
129131
<Compile Include="Scripts\LevelGridButtonCurrentMainMenuLogic.cs" />
130132
<Compile Include="Scripts\LevelPlaylistEntryUpdateLogic.cs" />
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using HarmonyLib;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace Distance.LevelSelectAdditions.Harmony
7+
{
8+
/// <summary>
9+
/// Patch to fix missing levels in the Advanced level select menu. The following levels are missing:
10+
/// <list type="bullet">
11+
/// <item>Sprint: Zenith</item>
12+
/// <item>ReverseTag: Stuntware 2051</item>
13+
/// </list>
14+
/// </summary>
15+
[HarmonyPatch(typeof(LevelSet), nameof(LevelSet.Initialize))]
16+
internal static class LevelSet__Initialize
17+
{
18+
[HarmonyPrefix]
19+
internal static void Prefix(LevelSet __instance)
20+
{
21+
if (__instance.resourcesLevelNameAndPathPairsInSet_.Count > 0)
22+
{
23+
return; // Already initialized
24+
}
25+
26+
// Re-add levels that are missing in the Advanced level select menu (this setting requires a restart).
27+
// All official (but not community) levels are loaded from the `resourcesLevelFileNamesInSet_` field.
28+
// This is likely initialized by UnityEngine at some point outside of our view of the code.
29+
// This field stores file names without extension or relative path.
30+
List<string> knownMissingFileNames = new List<string>();
31+
switch (__instance.gameModeID_)
32+
{
33+
case GameModeID.Sprint:
34+
//Mod.Instance.Logger.Debug("GameModeID.Sprint");
35+
knownMissingFileNames.Add("Zenith");
36+
break;
37+
38+
case GameModeID.ReverseTag:
39+
//Mod.Instance.Logger.Debug("GameModeID.ReverseTag");
40+
knownMissingFileNames.Add("Stuntware 2051");
41+
42+
// The following are neither in the Advanced level select menu, or any level set grids.
43+
// However they still have ReverseTag as a supported mode - which is likely a mistake,
44+
// as the Stunt map (Refraction) that was removed in the Radical Update had its mode properly removed.
45+
46+
// Unsure when this was removed, but probably for the same reason as below.
47+
//knownMissingFileNames.Add("Quantum Core");
48+
49+
// These were intentionally removed as noted in the Radical Update changelog.
50+
//knownMissingFileNames.Add("Space Skate");
51+
//knownMissingFileNames.Add("Stunt Playground");
52+
break;
53+
}
54+
55+
if (knownMissingFileNames.Count > 0)
56+
{
57+
// Double-check to make sure these levels haven't already been added by another mod, or game update.
58+
List<string> newResourceLevelFileNamesInSet = __instance.resourcesLevelFileNamesInSet_.ToList();
59+
foreach (string fileName in knownMissingFileNames)
60+
{
61+
if (Array.IndexOf(__instance.resourcesLevelFileNamesInSet_, fileName) == -1)
62+
{
63+
newResourceLevelFileNamesInSet.Add(fileName);
64+
}
65+
}
66+
67+
int added = newResourceLevelFileNamesInSet.Count - __instance.resourcesLevelFileNamesInSet_.Length;
68+
if (added > 0)
69+
{
70+
// Update the array with the added missing levels.
71+
__instance.resourcesLevelFileNamesInSet_ = newResourceLevelFileNamesInSet.ToArray();
72+
73+
string header = $"{nameof(GameModeID)}.{__instance.gameModeID_}: ";
74+
Mod.Instance.Logger.Info($"{header}Added {added} missing {GUtils.GetPlural("level", added)} to the Advanced level select menu.");
75+
}
76+
}
77+
}
78+
}
79+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Linq.Expressions;
4+
5+
namespace Distance.LevelSelectAdditions.Helpers
6+
{
7+
/// <summary>
8+
/// Optimized and organized reflection for use with Steamworks,
9+
/// which is needed due to the lack of <c>Assembly-CSharp-firstpass.dll</c> dependency.
10+
/// <para/>
11+
/// <see cref="SteamworksHelper.Init()"/> must be called before using.
12+
/// </summary>
13+
public static class SteamworksHelper
14+
{
15+
public const int VoteIndex_For = 0;
16+
public const int VoteIndex_Against = 1;
17+
public const int VoteIndex_None = 2;
18+
19+
20+
//private static Assembly assembly_FirstPass;
21+
22+
public static void Init()
23+
{
24+
// Nothing here yet...
25+
26+
//assembly_FirstPass = typeof(SteamworksLeaderboard.Leaderboard).GetField("steamHandle_").FieldType.Assembly;
27+
}
28+
29+
// WIP:
30+
/*private static Expression ParseMethodAccessor(Expression body, string member)
31+
{
32+
string method = member.Substring(0, member.Length - 2); // Remove "()"
33+
int sepIndex = method.LastIndexOf("::");
34+
if (sepIndex != -1)
35+
{
36+
string classPath = method.Substring(0, sepIndex);
37+
method = method.Substring(sepIndex + 2);
38+
classPath = classPath.Replace("::", ".");
39+
40+
Type staticType = typeof(GameManager).Assembly.GetType(classPath, false);
41+
if (staticType == null)
42+
{
43+
staticType = assembly_FirstPass.GetType(classPath, false);
44+
}
45+
if (staticType == null)
46+
{
47+
throw new ArgumentException($"Could not find declaring type for \"{member}\"");
48+
}
49+
return Expression.Call(staticType, method, null, body);
50+
}
51+
else
52+
{
53+
return Expression.Call(body, method, null);
54+
}
55+
}*/
56+
57+
// Using this allows for compiling expressions that may need to access non-public fields or properties.
58+
// see: <https://stackoverflow.com/a/16208620/7517185>
59+
private static Delegate CreateAccessor(Type type, string accessorPath)
60+
{
61+
Mod.Instance.Logger.Debug($"CreateAccessor: {type.Name}.{accessorPath}");
62+
Stopwatch watch = Stopwatch.StartNew();
63+
64+
ParameterExpression param = Expression.Parameter(type, "x");
65+
Expression body = param;
66+
foreach (string member in accessorPath.Split('.'))
67+
{
68+
// WIP:
69+
//if (member.EndsWith("()"))
70+
//{
71+
// body = ParseMethodAccessor(body, member);
72+
//}
73+
//else
74+
//{
75+
body = Expression.PropertyOrField(body, member);
76+
//}
77+
}
78+
Delegate compiled = Expression.Lambda(body, param).Compile();
79+
80+
watch.Stop();
81+
Mod.Instance.Logger.Debug($"CreateAccessor: {watch.ElapsedMilliseconds}ms");
82+
return compiled;
83+
}
84+
85+
private static Func<T, R> CreateAccessor<T, R>(string accessorPath)
86+
{
87+
return (Func<T, R>)CreateAccessor(typeof(T), accessorPath);
88+
}
89+
}
90+
}

Distance.LevelSelectAdditions/Mod.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Centrifuge.Distance.GUI.Controls;
33
using Centrifuge.Distance.GUI.Data;
44
using Distance.LevelSelectAdditions.Extensions;
5+
using Distance.LevelSelectAdditions.Helpers;
56
using Distance.LevelSelectAdditions.Scripts;
67
using Distance.LevelSelectAdditions.Scripts.Menus;
78
using Distance.LevelSelectAdditions.Sorting;
@@ -79,6 +80,17 @@ public void Initialize(IManager manager)
7980
throw;
8081
}
8182

83+
try
84+
{
85+
SteamworksHelper.Init(); // Handle this here for early error reporting.
86+
}
87+
catch (Exception ex)
88+
{
89+
Logger.Error(Mod.Name + ": Error during SteamworksHelper.Init()");
90+
Logger.Exception(ex);
91+
throw;
92+
}
93+
8294
try
8395
{
8496
CreateSettingsMenu();

Distance.LevelSelectAdditions/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("1.1.4.1")]
36-
[assembly: AssemblyFileVersion("1.1.4.1")]
35+
[assembly: AssemblyVersion("1.1.4.2")]
36+
[assembly: AssemblyFileVersion("1.1.4.2")]
3737

3838

3939

Distance.LevelSelectAdditions/Scripts/LevelSelectWorkshopRateButtonLogic.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using UnityEngine;
1+
using Distance.LevelSelectAdditions.Helpers;
2+
using UnityEngine;
23

34
namespace Distance.LevelSelectAdditions.Scripts
45
{
@@ -212,17 +213,17 @@ private void SetRatingText()
212213

213214
var entry = this.levelSelectMenu_.selectedEntry_;
214215
// CHANGE: Use `[c][/c]` tags to ensure we get the exact color we want.
215-
switch (entry?.myWorkshopVoteIndex_ ?? 2) // Fallback to 'No vote' if no entry is selected.
216+
switch (entry?.myWorkshopVoteIndex_ ?? SteamworksHelper.VoteIndex_None) // Fallback to 'No vote' if no entry is selected.
216217
{
217-
case 0: // Vote for
218-
this.votingLabel_.text = "My Rating: [c][96FFB1]+[-][/c]";
218+
case SteamworksHelper.VoteIndex_For: // Vote for
219+
this.votingLabel_.text = "My Rating: [c][96FFB1]" + GConstants.upVoteChar_ + "[-][/c]";
219220
break;
220221

221-
case 1: // Vote against
222-
this.votingLabel_.text = "My Rating: [c][FF9796]-[-][/c]";
222+
case SteamworksHelper.VoteIndex_Against: // Vote against
223+
this.votingLabel_.text = "My Rating: [c][FF9796]" + GConstants.downVoteChar_ + "[-][/c]";
223224
break;
224225

225-
//case 2: // No vote
226+
//case SteamworksHelper.VoteIndex_None: // No vote
226227
default:
227228
this.votingLabel_.text = "My Rating: None";
228229
break;

Distance.LevelSelectAdditions/Sorting/LevelSort.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ private static Comparison<LevelSortEntry> GetComparison(SortingMethod sortingMet
198198
/// </summary>
199199
internal static string GetAuthorName(LevelInfo levelInfo)
200200
{
201-
string authorName = "Unknown";
201+
string authorName = SteamworksManager.defaultUserName_;
202202
if (levelInfo.levelType_ == LevelType.Official)
203203
{
204204
authorName = "Refract";

0 commit comments

Comments
 (0)