forked from nikita/muzika-gromche
				
			Compare commits
	
		
			4 Commits
		
	
	
		
			2e938dfc8d
			...
			8b2f4428bb
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 8b2f4428bb | |
|  | 0dca416958 | |
|  | 1aa8c1ddfa | |
|  | 75d0ee2c1d | 
|  | @ -1,5 +1,10 @@ | ||||||
| # Changelog | # Changelog | ||||||
| 
 | 
 | ||||||
|  | ## MuzikaGromche 1337.69.420 - It's All Connected Edition | ||||||
|  | 
 | ||||||
|  | - Fix certain object hanging around after being disabled. | ||||||
|  | - CSync proved to be unreliable for config syncing, so rewrote track selection to custom netcode. | ||||||
|  | 
 | ||||||
| ## MuzikaGromche 13.37.9001 - Chromaberrated Edition | ## MuzikaGromche 13.37.9001 - Chromaberrated Edition | ||||||
| 
 | 
 | ||||||
| - Fixed more missing flickering behaviours for some animators controllers. | - Fixed more missing flickering behaviours for some animators controllers. | ||||||
|  |  | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | <Project> | ||||||
|  |     <Target Name="NetcodePatch" AfterTargets="PostBuildEvent"> | ||||||
|  |         <Exec Command="dotnet netcode-patch -nv 1.5.2 "$(TargetPath)" @(ReferencePathWithRefAssemblies->'"%(Identity)"', ' ')"/> | ||||||
|  |     </Target> | ||||||
|  | </Project> | ||||||
|  | @ -113,7 +113,7 @@ namespace MuzikaGromche | ||||||
| 
 | 
 | ||||||
|             foreach (var discoBall in CachedDiscoBalls) |             foreach (var discoBall in CachedDiscoBalls) | ||||||
|             { |             { | ||||||
|                 discoBall.SetActive(true); |                 discoBall.SetActive(on); | ||||||
|             } |             } | ||||||
|             foreach (var animator in CachedDiscoBallAnimators) |             foreach (var animator in CachedDiscoBallAnimators) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -8,11 +8,14 @@ | ||||||
|         <AssemblyName>Ratijas.MuzikaGromche</AssemblyName> |         <AssemblyName>Ratijas.MuzikaGromche</AssemblyName> | ||||||
|         <Product>Muzika Gromche</Product> |         <Product>Muzika Gromche</Product> | ||||||
|         <Description>Add some content to your inverse teleporter experience on Titan!</Description> |         <Description>Add some content to your inverse teleporter experience on Titan!</Description> | ||||||
|         <Version>13.37.9001</Version> |         <Version>1337.69.420</Version> | ||||||
|         <AllowUnsafeBlocks>true</AllowUnsafeBlocks> |         <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||||
|         <LangVersion>latest</LangVersion> |         <LangVersion>latest</LangVersion> | ||||||
|         <Nullable>enable</Nullable> |         <Nullable>enable</Nullable> | ||||||
| 
 | 
 | ||||||
|  |         <!-- NetcodePatch requires anything but 'full' --> | ||||||
|  |         <DebugType>portable</DebugType> | ||||||
|  | 
 | ||||||
|         <PackageReadmeFile>../README.md</PackageReadmeFile> |         <PackageReadmeFile>../README.md</PackageReadmeFile> | ||||||
|         <PackageProjectUrl>https://git.vilunov.me/ratijas/muzika-gromche</PackageProjectUrl> |         <PackageProjectUrl>https://git.vilunov.me/ratijas/muzika-gromche</PackageProjectUrl> | ||||||
|         <RepositoryUrl>https://git.vilunov.me/ratijas/muzika-gromche</RepositoryUrl> |         <RepositoryUrl>https://git.vilunov.me/ratijas/muzika-gromche</RepositoryUrl> | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ using LethalConfig.ConfigItems.Options; | ||||||
| using LobbyCompatibility.Attributes; | using LobbyCompatibility.Attributes; | ||||||
| using LobbyCompatibility.Enums; | using LobbyCompatibility.Enums; | ||||||
| using System; | using System; | ||||||
|  | using System.Collections; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|  | @ -16,6 +17,7 @@ using System.Net.NetworkInformation; | ||||||
| using System.Net.Sockets; | using System.Net.Sockets; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
| using System.Security.Cryptography; | using System.Security.Cryptography; | ||||||
|  | using Unity.Netcode; | ||||||
| using UnityEngine; | using UnityEngine; | ||||||
| using UnityEngine.Networking; | using UnityEngine.Networking; | ||||||
| 
 | 
 | ||||||
|  | @ -482,6 +484,11 @@ namespace MuzikaGromche | ||||||
|             return tracks[trackId]; |             return tracks[trackId]; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         public static Track? FindTrackNamed(string name) | ||||||
|  |         { | ||||||
|  |             return Tracks.FirstOrDefault(track => track.Name == name); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         internal static Track? CurrentTrack; |         internal static Track? CurrentTrack; | ||||||
|         internal static BeatTimeState? BeatTimeState; |         internal static BeatTimeState? BeatTimeState; | ||||||
| 
 | 
 | ||||||
|  | @ -547,6 +554,7 @@ namespace MuzikaGromche | ||||||
|                 DiscoBallManager.Load(); |                 DiscoBallManager.Load(); | ||||||
|                 PoweredLightsAnimators.Load(); |                 PoweredLightsAnimators.Load(); | ||||||
|                 var harmony = new Harmony(PluginInfo.PLUGIN_NAME); |                 var harmony = new Harmony(PluginInfo.PLUGIN_NAME); | ||||||
|  |                 harmony.PatchAll(typeof(GameNetworkManagerPatch)); | ||||||
|                 harmony.PatchAll(typeof(JesterPatch)); |                 harmony.PatchAll(typeof(JesterPatch)); | ||||||
|                 harmony.PatchAll(typeof(EnemyAIPatch)); |                 harmony.PatchAll(typeof(EnemyAIPatch)); | ||||||
|                 harmony.PatchAll(typeof(PoweredLightsAnimatorsPatch)); |                 harmony.PatchAll(typeof(PoweredLightsAnimatorsPatch)); | ||||||
|  | @ -554,6 +562,7 @@ namespace MuzikaGromche | ||||||
|                 harmony.PatchAll(typeof(DiscoBallTilePatch)); |                 harmony.PatchAll(typeof(DiscoBallTilePatch)); | ||||||
|                 harmony.PatchAll(typeof(DiscoBallDespawnPatch)); |                 harmony.PatchAll(typeof(DiscoBallDespawnPatch)); | ||||||
|                 harmony.PatchAll(typeof(SpawnRatePatch)); |                 harmony.PatchAll(typeof(SpawnRatePatch)); | ||||||
|  |                 NetcodePatcher(); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|  | @ -561,6 +570,23 @@ namespace MuzikaGromche | ||||||
|                 Logger.LogError("Could not load audio file " + string.Join(", ", failed)); |                 Logger.LogError("Could not load audio file " + string.Join(", ", failed)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         private static void NetcodePatcher() | ||||||
|  |         { | ||||||
|  |             var types = Assembly.GetExecutingAssembly().GetTypes(); | ||||||
|  |             foreach (var type in types) | ||||||
|  |             { | ||||||
|  |                 var methods = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); | ||||||
|  |                 foreach (var method in methods) | ||||||
|  |                 { | ||||||
|  |                     var attributes = method.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), false); | ||||||
|  |                     if (attributes.Length > 0) | ||||||
|  |                     { | ||||||
|  |                         method.Invoke(null, null); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     public readonly record struct Language(string Short, string Full) |     public readonly record struct Language(string Short, string Full) | ||||||
|  | @ -680,7 +706,7 @@ namespace MuzikaGromche | ||||||
|         public AudioClip LoadedLoop = null!; |         public AudioClip LoadedLoop = null!; | ||||||
| 
 | 
 | ||||||
|         // How often this track should be chosen, relative to the sum of weights of all tracks. |         // How often this track should be chosen, relative to the sum of weights of all tracks. | ||||||
|         public SyncedEntry<int> Weight = null!; |         public ConfigEntry<int> Weight = null!; | ||||||
| 
 | 
 | ||||||
|         public string FileNameStart => $"{Name}Start.{Ext}"; |         public string FileNameStart => $"{Name}Start.{Ext}"; | ||||||
|         public string FileNameLoop => $"{Name}Loop.{Ext}"; |         public string FileNameLoop => $"{Name}Loop.{Ext}"; | ||||||
|  | @ -1428,7 +1454,7 @@ namespace MuzikaGromche | ||||||
| 
 | 
 | ||||||
|         public static ConfigEntry<bool> SkipExplicitTracks { get; private set; } = null!; |         public static ConfigEntry<bool> SkipExplicitTracks { get; private set; } = null!; | ||||||
| 
 | 
 | ||||||
|         public static SyncedEntry<bool> OverrideSpawnRates { get; private set; } = null!; |         public static ConfigEntry<bool> OverrideSpawnRates { get; private set; } = null!; | ||||||
| 
 | 
 | ||||||
|         public static bool ShouldSkipWindingPhase { get; private set; } = false; |         public static bool ShouldSkipWindingPhase { get; private set; } = false; | ||||||
| 
 | 
 | ||||||
|  | @ -1456,12 +1482,11 @@ namespace MuzikaGromche | ||||||
| 
 | 
 | ||||||
|             SkipExplicitTracks = configFile.Bind("General", "Skip Explicit Tracks", false, |             SkipExplicitTracks = configFile.Bind("General", "Skip Explicit Tracks", false, | ||||||
|                 new ConfigDescription("When choosing tracks at random, skip the ones with Explicit Content/Lyrics.")); |                 new ConfigDescription("When choosing tracks at random, skip the ones with Explicit Content/Lyrics.")); | ||||||
|             LethalConfigManager.AddConfigItem(new BoolCheckBoxConfigItem(SkipExplicitTracks, requiresRestart: false)); |             LethalConfigManager.AddConfigItem(new BoolCheckBoxConfigItem(SkipExplicitTracks, Default(new BoolCheckBoxOptions()))); | ||||||
| 
 | 
 | ||||||
|             OverrideSpawnRates = configFile.BindSyncedEntry("General", "Override Spawn Rates", false, |             OverrideSpawnRates = configFile.Bind("General", "Override Spawn Rates", false, | ||||||
|                 new ConfigDescription("Deviate from vanilla spawn rates to experience content of this mod more often.")); |                 new ConfigDescription("Deviate from vanilla spawn rates to experience content of this mod more often.")); | ||||||
|             LethalConfigManager.AddConfigItem(new BoolCheckBoxConfigItem(OverrideSpawnRates.Entry, Default(new BoolCheckBoxOptions()))); |             LethalConfigManager.AddConfigItem(new BoolCheckBoxConfigItem(OverrideSpawnRates, Default(new BoolCheckBoxOptions()))); | ||||||
|             CSyncHackAddSyncedEntry(OverrideSpawnRates); |  | ||||||
| 
 | 
 | ||||||
| #if DEBUG | #if DEBUG | ||||||
|             SetupEntriesToSkipWinding(configFile); |             SetupEntriesToSkipWinding(configFile); | ||||||
|  | @ -1489,11 +1514,11 @@ namespace MuzikaGromche | ||||||
|                         if (CanModifyWeightsNow()) |                         if (CanModifyWeightsNow()) | ||||||
|                         { |                         { | ||||||
|                             var tracks = Plugin.Tracks.Where(t => t.Language.Equals(language)).ToList(); |                             var tracks = Plugin.Tracks.Where(t => t.Language.Equals(language)).ToList(); | ||||||
|                             var isOff = tracks.All(t => t.Weight.LocalValue == 0); |                             var isOff = tracks.All(t => t.Weight.Value == 0); | ||||||
|                             var newWeight = isOff ? 50 : 0; |                             var newWeight = isOff ? 50 : 0; | ||||||
|                             foreach (var t in tracks) |                             foreach (var t in tracks) | ||||||
|                             { |                             { | ||||||
|                                 t.Weight.LocalValue = newWeight; |                                 t.Weight.Value = newWeight; | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
|  | @ -1504,13 +1529,12 @@ namespace MuzikaGromche | ||||||
|                 // Create slider entry for track |                 // Create slider entry for track | ||||||
|                 string warning = track.IsExplicit ? "Explicit Content/Lyrics!\n\n" : ""; |                 string warning = track.IsExplicit ? "Explicit Content/Lyrics!\n\n" : ""; | ||||||
|                 string description = $"Language: {language.Full}\n\n{warning}Random (relative) chance of selecting this track.\n\nSet to zero to effectively disable the track."; |                 string description = $"Language: {language.Full}\n\n{warning}Random (relative) chance of selecting this track.\n\nSet to zero to effectively disable the track."; | ||||||
|                 track.Weight = configFile.BindSyncedEntry( |                 track.Weight = configFile.Bind( | ||||||
|                     new ConfigDefinition(section, track.Name), |                     new ConfigDefinition(section, track.Name), | ||||||
|                     50, |                     50, | ||||||
|                     new ConfigDescription(description, chanceRange, track)); |                     new ConfigDescription(description, chanceRange, track)); | ||||||
| 
 | 
 | ||||||
|                 LethalConfigManager.AddConfigItem(new IntSliderConfigItem(track.Weight.Entry, Default(new IntSliderOptions()))); |                 LethalConfigManager.AddConfigItem(new IntSliderConfigItem(track.Weight, Default(new IntSliderOptions()))); | ||||||
|                 CSyncHackAddSyncedEntry(track.Weight); |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             ConfigManager.Register(this); |             ConfigManager.Register(this); | ||||||
|  | @ -1774,6 +1798,78 @@ namespace MuzikaGromche | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     [HarmonyPatch(typeof(GameNetworkManager))] | ||||||
|  |     static class GameNetworkManagerPatch | ||||||
|  |     { | ||||||
|  |         const string JesterEnemyPrefabName = "JesterEnemy"; | ||||||
|  | 
 | ||||||
|  |         [HarmonyPatch(nameof(GameNetworkManager.Start))] | ||||||
|  |         [HarmonyPrefix] | ||||||
|  |         static void StartPrefix(GameNetworkManager __instance) | ||||||
|  |         { | ||||||
|  |             var networkPrefab = NetworkManager.Singleton.NetworkConfig.Prefabs.Prefabs | ||||||
|  |                 .FirstOrDefault(prefab => prefab.Prefab.name == JesterEnemyPrefabName); | ||||||
|  |             if (networkPrefab == null) | ||||||
|  |             { | ||||||
|  |                 Debug.LogError($"{nameof(MuzikaGromche)} JesterEnemy prefab not found!"); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"{nameof(MuzikaGromche)} Patching {nameof(JesterAI)} with {nameof(MuzikaGromcheJesterNetworkBehaviour)} component"); | ||||||
|  |                 networkPrefab.Prefab.AddComponent<MuzikaGromcheJesterNetworkBehaviour>(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     class MuzikaGromcheJesterNetworkBehaviour : NetworkBehaviour | ||||||
|  |     { | ||||||
|  |         public override void OnNetworkSpawn() | ||||||
|  |         { | ||||||
|  |             ChooseTrackDeferred(); | ||||||
|  |             foreach (var track in Plugin.Tracks) | ||||||
|  |             { | ||||||
|  |                 track.Weight.SettingChanged += (_, _) => ChooseTrackDeferred(); | ||||||
|  |             } | ||||||
|  |             Config.SkipExplicitTracks.SettingChanged += (_, _) => ChooseTrackDeferred(); | ||||||
|  |             base.OnNetworkSpawn(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Batch multiple weights changes in a single network RPC | ||||||
|  |         private Coroutine? DeferredCoroutine = null; | ||||||
|  | 
 | ||||||
|  |         private void ChooseTrackDeferred() | ||||||
|  |         { | ||||||
|  |             if (DeferredCoroutine != null) | ||||||
|  |             { | ||||||
|  |                 StopCoroutine(DeferredCoroutine); | ||||||
|  |                 DeferredCoroutine = null; | ||||||
|  |             } | ||||||
|  |             DeferredCoroutine = StartCoroutine(ChooseTrackDeferredCoroutine()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private IEnumerator ChooseTrackDeferredCoroutine() | ||||||
|  |         { | ||||||
|  |             yield return new WaitForEndOfFrame(); | ||||||
|  |             DeferredCoroutine = null; | ||||||
|  |             ChooseTrackServerRpc(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         [ClientRpc] | ||||||
|  |         public void SetTrackClientRpc(string name) | ||||||
|  |         { | ||||||
|  |             Debug.Log($"{nameof(MuzikaGromche)} SetTrackClientRpc {name}"); | ||||||
|  |             Plugin.CurrentTrack = Plugin.FindTrackNamed(name); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         [ServerRpc] | ||||||
|  |         public void ChooseTrackServerRpc() | ||||||
|  |         { | ||||||
|  |             var track = Plugin.ChooseTrack(); | ||||||
|  |             Debug.Log($"{nameof(MuzikaGromche)} ChooseTrackServerRpc {track.Name}"); | ||||||
|  |             SetTrackClientRpc(track.Name); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // farAudio is during windup, Start overrides popGoesTheWeaselTheme |     // farAudio is during windup, Start overrides popGoesTheWeaselTheme | ||||||
|     // creatureVoice is when popped, Loop overrides screamingSFX |     // creatureVoice is when popped, Loop overrides screamingSFX | ||||||
|     [HarmonyPatch(typeof(JesterAI))] |     [HarmonyPatch(typeof(JesterAI))] | ||||||
|  | @ -1820,6 +1916,14 @@ namespace MuzikaGromche | ||||||
|         [HarmonyPostfix] |         [HarmonyPostfix] | ||||||
|         static void JesterUpdatePostfix(JesterAI __instance, State __state) |         static void JesterUpdatePostfix(JesterAI __instance, State __state) | ||||||
|         { |         { | ||||||
|  |             if (Plugin.CurrentTrack == null) | ||||||
|  |             { | ||||||
|  | #if DEBUG | ||||||
|  |                 Debug.Log($"{nameof(MuzikaGromche)} CurrentTrack is not set!"); | ||||||
|  | #endif | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             if (__instance.previousState == 1 && __state.previousState != 1) |             if (__instance.previousState == 1 && __state.previousState != 1) | ||||||
|             { |             { | ||||||
|                 // if just started winding up |                 // if just started winding up | ||||||
|  | @ -1828,7 +1932,6 @@ namespace MuzikaGromche | ||||||
|                 __instance.creatureVoice.Stop(); |                 __instance.creatureVoice.Stop(); | ||||||
| 
 | 
 | ||||||
|                 //  ...and start modded music |                 //  ...and start modded music | ||||||
|                 Plugin.CurrentTrack = Plugin.ChooseTrack(); |  | ||||||
|                 Plugin.BeatTimeState = new BeatTimeState(Plugin.CurrentTrack); |                 Plugin.BeatTimeState = new BeatTimeState(Plugin.CurrentTrack); | ||||||
|                 // Set up custom popup timer, which is shorter than Start audio |                 // Set up custom popup timer, which is shorter than Start audio | ||||||
|                 __instance.popUpTimer = Plugin.CurrentTrack.WindUpTimer; |                 __instance.popUpTimer = Plugin.CurrentTrack.WindUpTimer; | ||||||
|  | @ -1878,9 +1981,9 @@ namespace MuzikaGromche | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Manage the timeline: switch color of the lights according to the current playback/beat position. |             // Manage the timeline: switch color of the lights according to the current playback/beat position. | ||||||
|             if (__instance.previousState == 1 || __instance.previousState == 2) |             if ((__instance.previousState == 1 || __instance.previousState == 2) && Plugin.BeatTimeState != null) | ||||||
|             { |             { | ||||||
|                 var events = Plugin.BeatTimeState!.Update(start: __instance.farAudio, loop: __instance.creatureVoice); |                 var events = Plugin.BeatTimeState.Update(start: __instance.farAudio, loop: __instance.creatureVoice); | ||||||
|                 foreach (var ev in events) |                 foreach (var ev in events) | ||||||
|                 { |                 { | ||||||
|                     switch (ev) |                     switch (ev) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | { | ||||||
|  |   "version": 1, | ||||||
|  |   "isRoot": true, | ||||||
|  |   "tools": { | ||||||
|  |     "evaisa.netcodepatcher.cli": { | ||||||
|  |       "version": "4.3.0", | ||||||
|  |       "commands": [ | ||||||
|  |         "netcode-patch" | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| { | { | ||||||
|     "name": "MuzikaGromche", |     "name": "MuzikaGromche", | ||||||
|     "version_number": "13.37.9001", |     "version_number": "1337.69.420", | ||||||
|     "author": "Ratijas", |     "author": "Ratijas", | ||||||
|     "description": "Add some content to your inverse teleporter experience on Titan!", |     "description": "Add some content to your inverse teleporter experience on Titan!", | ||||||
|     "website_url": "https://git.vilunov.me/ratijas/muzika-gromche", |     "website_url": "https://git.vilunov.me/ratijas/muzika-gromche", | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue