Skip to content

Commit

Permalink
Add missing Adv. level select levels (v1.1.4.2)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
trigger-segfault committed Aug 11, 2022
1 parent 8dc455c commit 881de7e
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@
<Compile Include="Harmony\Assembly-CSharp\LevelSelectMenuLogic\Start.cs" />
<Compile Include="Harmony\Assembly-CSharp\LevelSelectMenuLogic\StartPlaylist.cs" />
<Compile Include="Harmony\Assembly-CSharp\LevelSelectMenuLogic\UpdateInput.cs" />
<Compile Include="Harmony\Assembly-CSharp\LevelSet\Initialize.cs" />
<Compile Include="Harmony\Assembly-CSharp\MainMenuLogic\Start.cs" />
<Compile Include="Harmony\Assembly-CSharp\OptionsMenuLogic\GetSubmenus.cs" />
<Compile Include="Helpers\MainMenuLevelSetHelper.cs" />
<Compile Include="Helpers\Sanitizer.cs" />
<Compile Include="Helpers\SteamworksHelper.cs" />
<Compile Include="Mod.cs" />
<Compile Include="Scripts\LevelGridButtonCurrentMainMenuLogic.cs" />
<Compile Include="Scripts\LevelPlaylistEntryUpdateLogic.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Distance.LevelSelectAdditions.Harmony
{
/// <summary>
/// Patch to fix missing levels in the Advanced level select menu. The following levels are missing:
/// <list type="bullet">
/// <item>Sprint: Zenith</item>
/// <item>ReverseTag: Stuntware 2051</item>
/// </list>
/// </summary>
[HarmonyPatch(typeof(LevelSet), nameof(LevelSet.Initialize))]
internal static class LevelSet__Initialize
{
[HarmonyPrefix]
internal static void Prefix(LevelSet __instance)
{
if (__instance.resourcesLevelNameAndPathPairsInSet_.Count > 0)
{
return; // Already initialized
}

// Re-add levels that are missing in the Advanced level select menu (this setting requires a restart).
// All official (but not community) levels are loaded from the `resourcesLevelFileNamesInSet_` field.
// This is likely initialized by UnityEngine at some point outside of our view of the code.
// This field stores file names without extension or relative path.
List<string> knownMissingFileNames = new List<string>();
switch (__instance.gameModeID_)
{
case GameModeID.Sprint:
//Mod.Instance.Logger.Debug("GameModeID.Sprint");
knownMissingFileNames.Add("Zenith");
break;

case GameModeID.ReverseTag:
//Mod.Instance.Logger.Debug("GameModeID.ReverseTag");
knownMissingFileNames.Add("Stuntware 2051");

// The following are neither in the Advanced level select menu, or any level set grids.
// However they still have ReverseTag as a supported mode - which is likely a mistake,
// as the Stunt map (Refraction) that was removed in the Radical Update had its mode properly removed.

// Unsure when this was removed, but probably for the same reason as below.
//knownMissingFileNames.Add("Quantum Core");

// These were intentionally removed as noted in the Radical Update changelog.
//knownMissingFileNames.Add("Space Skate");
//knownMissingFileNames.Add("Stunt Playground");
break;
}

if (knownMissingFileNames.Count > 0)
{
// Double-check to make sure these levels haven't already been added by another mod, or game update.
List<string> newResourceLevelFileNamesInSet = __instance.resourcesLevelFileNamesInSet_.ToList();
foreach (string fileName in knownMissingFileNames)
{
if (Array.IndexOf(__instance.resourcesLevelFileNamesInSet_, fileName) == -1)
{
newResourceLevelFileNamesInSet.Add(fileName);
}
}

int added = newResourceLevelFileNamesInSet.Count - __instance.resourcesLevelFileNamesInSet_.Length;
if (added > 0)
{
// Update the array with the added missing levels.
__instance.resourcesLevelFileNamesInSet_ = newResourceLevelFileNamesInSet.ToArray();

string header = $"{nameof(GameModeID)}.{__instance.gameModeID_}: ";
Mod.Instance.Logger.Info($"{header}Added {added} missing {GUtils.GetPlural("level", added)} to the Advanced level select menu.");
}
}
}
}
}
90 changes: 90 additions & 0 deletions Distance.LevelSelectAdditions/Helpers/SteamworksHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Diagnostics;
using System.Linq.Expressions;

namespace Distance.LevelSelectAdditions.Helpers
{
/// <summary>
/// Optimized and organized reflection for use with Steamworks,
/// which is needed due to the lack of <c>Assembly-CSharp-firstpass.dll</c> dependency.
/// <para/>
/// <see cref="SteamworksHelper.Init()"/> must be called before using.
/// </summary>
public static class SteamworksHelper
{
public const int VoteIndex_For = 0;
public const int VoteIndex_Against = 1;
public const int VoteIndex_None = 2;


//private static Assembly assembly_FirstPass;

public static void Init()
{
// Nothing here yet...

//assembly_FirstPass = typeof(SteamworksLeaderboard.Leaderboard).GetField("steamHandle_").FieldType.Assembly;
}

// WIP:
/*private static Expression ParseMethodAccessor(Expression body, string member)
{
string method = member.Substring(0, member.Length - 2); // Remove "()"
int sepIndex = method.LastIndexOf("::");
if (sepIndex != -1)
{
string classPath = method.Substring(0, sepIndex);
method = method.Substring(sepIndex + 2);
classPath = classPath.Replace("::", ".");
Type staticType = typeof(GameManager).Assembly.GetType(classPath, false);
if (staticType == null)
{
staticType = assembly_FirstPass.GetType(classPath, false);
}
if (staticType == null)
{
throw new ArgumentException($"Could not find declaring type for \"{member}\"");
}
return Expression.Call(staticType, method, null, body);
}
else
{
return Expression.Call(body, method, null);
}
}*/

// Using this allows for compiling expressions that may need to access non-public fields or properties.
// see: <https://stackoverflow.com/a/16208620/7517185>
private static Delegate CreateAccessor(Type type, string accessorPath)
{
Mod.Instance.Logger.Debug($"CreateAccessor: {type.Name}.{accessorPath}");
Stopwatch watch = Stopwatch.StartNew();

ParameterExpression param = Expression.Parameter(type, "x");
Expression body = param;
foreach (string member in accessorPath.Split('.'))
{
// WIP:
//if (member.EndsWith("()"))
//{
// body = ParseMethodAccessor(body, member);
//}
//else
//{
body = Expression.PropertyOrField(body, member);
//}
}
Delegate compiled = Expression.Lambda(body, param).Compile();

watch.Stop();
Mod.Instance.Logger.Debug($"CreateAccessor: {watch.ElapsedMilliseconds}ms");
return compiled;
}

private static Func<T, R> CreateAccessor<T, R>(string accessorPath)
{
return (Func<T, R>)CreateAccessor(typeof(T), accessorPath);
}
}
}
12 changes: 12 additions & 0 deletions Distance.LevelSelectAdditions/Mod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Centrifuge.Distance.GUI.Controls;
using Centrifuge.Distance.GUI.Data;
using Distance.LevelSelectAdditions.Extensions;
using Distance.LevelSelectAdditions.Helpers;
using Distance.LevelSelectAdditions.Scripts;
using Distance.LevelSelectAdditions.Scripts.Menus;
using Distance.LevelSelectAdditions.Sorting;
Expand Down Expand Up @@ -79,6 +80,17 @@ public void Initialize(IManager manager)
throw;
}

try
{
SteamworksHelper.Init(); // Handle this here for early error reporting.
}
catch (Exception ex)
{
Logger.Error(Mod.Name + ": Error during SteamworksHelper.Init()");
Logger.Exception(ex);
throw;
}

try
{
CreateSettingsMenu();
Expand Down
4 changes: 2 additions & 2 deletions Distance.LevelSelectAdditions/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.4.1")]
[assembly: AssemblyFileVersion("1.1.4.1")]
[assembly: AssemblyVersion("1.1.4.2")]
[assembly: AssemblyFileVersion("1.1.4.2")]



Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using UnityEngine;
using Distance.LevelSelectAdditions.Helpers;
using UnityEngine;

namespace Distance.LevelSelectAdditions.Scripts
{
Expand Down Expand Up @@ -212,17 +213,17 @@ private void SetRatingText()

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

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

//case 2: // No vote
//case SteamworksHelper.VoteIndex_None: // No vote
default:
this.votingLabel_.text = "My Rating: None";
break;
Expand Down
2 changes: 1 addition & 1 deletion Distance.LevelSelectAdditions/Sorting/LevelSort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ private static Comparison<LevelSortEntry> GetComparison(SortingMethod sortingMet
/// </summary>
internal static string GetAuthorName(LevelInfo levelInfo)
{
string authorName = "Unknown";
string authorName = SteamworksManager.defaultUserName_;
if (levelInfo.levelType_ == LevelType.Official)
{
authorName = "Refract";
Expand Down

0 comments on commit 881de7e

Please sign in to comment.