mirror of
https://github.com/TheJordanDev/PEAK-JordanMod.git
synced 2026-10-17 08:05:25 +02:00
0.1.11 | Fix for last update
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<!-- This is the display name of your mod. Example: BepInEx Template -->
|
||||
<AssemblyTitle>JordanMod</AssemblyTitle>
|
||||
<!-- This is the version number of your mod. -->
|
||||
<Version>0.1.10</Version>
|
||||
<Version>0.1.11</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -16,6 +16,12 @@ public partial class Plugin : BaseUnityPlugin
|
||||
private static Harmony? _harmony;
|
||||
private ModuleManager? _moduleManager;
|
||||
|
||||
private static readonly System.Collections.Concurrent.ConcurrentQueue<Action> _mainThreadQueue = new();
|
||||
|
||||
// Unity APIs (e.g. StartCoroutine) can only be called from the main thread;
|
||||
// background work (Task.Run, etc.) must hop back through here to touch them.
|
||||
public static void RunOnMainThread(Action action) => _mainThreadQueue.Enqueue(action);
|
||||
|
||||
private static readonly List<Type> _globalPatches = [
|
||||
typeof(Patches.PassportPatch),
|
||||
];
|
||||
@@ -84,6 +90,11 @@ public partial class Plugin : BaseUnityPlugin
|
||||
|
||||
private void Update()
|
||||
{
|
||||
while (_mainThreadQueue.TryDequeue(out Action? action))
|
||||
{
|
||||
try { action(); }
|
||||
catch (Exception e) { Log.LogError($"Main thread action failed: {e}"); }
|
||||
}
|
||||
_moduleManager?.Update();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using pworld.Scripts.Extensions;
|
||||
|
||||
namespace JordanMod.Events;
|
||||
@@ -7,12 +8,16 @@ public class GlobalEventListener
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
GlobalEvents.OnItemThrown += OnItemThrown;
|
||||
// GlobalEvents.OnItemThrown += OnItemThrown;
|
||||
}
|
||||
|
||||
private static void OnItemThrown(Item item)
|
||||
{
|
||||
item.gameObject.GetOrAddComponent<Bonkable>();
|
||||
// Bonkable bonkable = item.gameObject.GetOrAddComponent<Bonkable>();
|
||||
// // A Bonkable added at runtime has no serialized prefab data, so its `bonk` SFX array
|
||||
// // defaults to null (not empty) and Bonkable.Bonk() NREs on bonk.Length. Give it an
|
||||
// // empty array so a bonk still ragdolls/knocks back the target, just without a sound.
|
||||
// bonkable.bonk ??= Array.Empty<SFX_Instance>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,16 +38,25 @@ class EasyBackpackModule : Module
|
||||
Character localCharacter = Character.localCharacter;
|
||||
if (localCharacter == null) return;
|
||||
|
||||
bool hasBackpack = localCharacter.player.backpackSlot.hasBackpack;
|
||||
Character carriedCharacter = localCharacter.data.carriedPlayer;
|
||||
bool carriedHasBackpack = carriedCharacter != null && carriedCharacter.player.backpackSlot.hasBackpack;
|
||||
|
||||
BackpackReference backpackRefs;
|
||||
if (hasBackpack) backpackRefs = BackpackReference.GetFromEquippedBackpack(localCharacter);
|
||||
else if (carriedHasBackpack) backpackRefs = BackpackReference.GetFromEquippedBackpack(carriedCharacter);
|
||||
Character targetCharacter;
|
||||
BackpackSlot targetSlot;
|
||||
if (localCharacter.player.backpackSlot.backpackType != BackpackSlot.BackpackType.None)
|
||||
{
|
||||
targetCharacter = localCharacter;
|
||||
targetSlot = localCharacter.player.backpackSlot;
|
||||
}
|
||||
else if (carriedCharacter != null && carriedCharacter.player.backpackSlot.backpackType != BackpackSlot.BackpackType.None)
|
||||
{
|
||||
targetCharacter = carriedCharacter;
|
||||
targetSlot = carriedCharacter.player.backpackSlot;
|
||||
}
|
||||
else return;
|
||||
|
||||
GUIManager.instance.OpenBackpackWheel(backpackRefs);
|
||||
BackpackReference backpackRefs = BackpackReference.GetFromEquippedBackpack(targetCharacter);
|
||||
int slotCount = (targetSlot.prefab as Backpack)?.slotCount ?? 4;
|
||||
GUIManager.instance.OpenBackpackWheel(backpackRefs, slotCount, targetSlot.backpackType);
|
||||
_isBackpackOpen = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class StashedBugleModule : Module
|
||||
localCharacter.player.EmptySlot(localCharacter.refs.items.currentSelectedSlot);
|
||||
localCharacter.player.RPCRemoveItemFromSlot(localCharacter.refs.items.currentSelectedSlot.Value);
|
||||
|
||||
localCharacter.refs.items.SpawnItemInHand(_megaphoneItemName);
|
||||
SpawnItemByDisplayName(localCharacter, _megaphoneItemName);
|
||||
}
|
||||
else if (heldItem.UIData.itemName == _megaphoneItemName)
|
||||
{
|
||||
@@ -54,8 +54,22 @@ class StashedBugleModule : Module
|
||||
withBugleSlot = itemSlot;
|
||||
break;
|
||||
}
|
||||
if (withBugleSlot == null) localCharacter.refs.items.SpawnItemInHand(_bugleItemName);
|
||||
if (withBugleSlot == null) SpawnItemByDisplayName(localCharacter, _bugleItemName);
|
||||
else localCharacter.refs.items.EquipSlot(Optionable<byte>.Some(withBugleSlot.itemSlotID));
|
||||
}
|
||||
}
|
||||
|
||||
// SpawnItemInHand expects the item's Resources prefab name, which is not
|
||||
// guaranteed to match its UIData.itemName display string, so resolve it
|
||||
// via the ItemDatabase instead of assuming the two are identical.
|
||||
private static void SpawnItemByDisplayName(Character character, string displayName)
|
||||
{
|
||||
Item? match = Helper.ItemDatabase.Objects.Find(item => item.UIData != null && item.UIData.itemName == displayName);
|
||||
if (match == null)
|
||||
{
|
||||
Debug.LogWarning($"[StashedBugle] Could not find an item with UIData.itemName '{displayName}' in ItemDatabase.");
|
||||
return;
|
||||
}
|
||||
character.refs.items.SpawnItemInHand(match.name);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public class BagsForEveryonePatch
|
||||
bool isFirstSpawner = spawner.transform.IsChildOf(GameObject.Find("Biome_1").transform);
|
||||
if (!isFirstSpawner) return;
|
||||
|
||||
int playerCount = PhotonNetwork.PlayerList.Length - 1;
|
||||
int playerCount = PhotonNetwork.PlayerList.Length - 1; // Already one bag
|
||||
if (playerCount <= 0) return;
|
||||
for (int i = 1; i <= playerCount; i++)
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@ public class BetterBuglePatch
|
||||
// BetterBugleUI.Instance?.ShowActionbar("No songs available.");
|
||||
// return;
|
||||
// }
|
||||
if (AudioSyncWorker.IsLoading) return;
|
||||
if (AudioSyncWorker.IsLoading || AudioSyncWorker.IsSyncing) return;
|
||||
if (!BetterBugleModule.HadConfirmation)
|
||||
{
|
||||
BetterBugleUI.Instance?.ShowActionbar("Are you sure you want to refresh songs ? Right-click again to reload.");
|
||||
@@ -57,15 +57,18 @@ public class BetterBuglePatch
|
||||
{
|
||||
BetterBugleModule.HadConfirmation = false; // Reset confirmation state
|
||||
BetterBugleUI.Instance?.ShowActionbar("Refreshing songs...");
|
||||
AudioSyncService.GetAudioClips();
|
||||
// Refresh = unload everything and reload from local files only (no network).
|
||||
// For downloading from the audio bank API, use the Sync keybind instead.
|
||||
AudioSyncService.ClearAudioClips();
|
||||
AudioSyncWorker.GetAudioClips();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static IEnumerator ResetConfirmation()
|
||||
{
|
||||
if (!BetterBugleModule.HadConfirmation) yield break;
|
||||
yield return new WaitForSeconds(2f);
|
||||
if (!BetterBugleModule.HadConfirmation) yield break; // already confirmed (or reset) in the meantime
|
||||
BetterBugleUI.Instance?.ShowActionbar("No answer, not refreshing songs.");
|
||||
BetterBugleModule.HadConfirmation = false;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,12 @@ class EasyBackpackPatch
|
||||
[HarmonyPrefix]
|
||||
static bool BackpackWheelUpdatePrefix(BackpackWheel __instance)
|
||||
{
|
||||
if (!__instance.backpack.exists || __instance.backpack.locationTransform == null)
|
||||
{
|
||||
GUIManager.instance.CloseBackpackWheel();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isBackPackOpen = EasyBackpackModule.Instance?._isBackpackOpen ?? false;
|
||||
|
||||
if (!Character.localCharacter.input.interactIsPressed && !isBackPackOpen)
|
||||
@@ -18,13 +24,17 @@ class EasyBackpackPatch
|
||||
return false;
|
||||
}
|
||||
|
||||
if (__instance.backpack.locationTransform != null && Vector3.Distance(__instance.backpack.locationTransform.position, Character.localCharacter.Center) > 6f)
|
||||
if (Vector3.Distance(__instance.backpack.locationTransform.position, Character.localCharacter.Center) > 6f)
|
||||
{
|
||||
GUIManager.instance.CloseBackpackWheel();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (__instance.chosenSlice.IsSome && !__instance.chosenSlice.Value.isBackpackWear && !__instance.slices[__instance.chosenSlice.Value.slotID + 1].image.enabled)
|
||||
if (__instance.chosenSlice.IsSome && __instance.chosenSlice.Value.isJetpackFuelSlice)
|
||||
{
|
||||
__instance.currentlyHeldItem.transform.position = Vector3.Lerp(__instance.currentlyHeldItem.transform.position, __instance.jetpackSlice.transform.GetChild(0).GetChild(0).position, Time.deltaTime * 20f);
|
||||
}
|
||||
else if (__instance.chosenSlice.IsSome && !__instance.chosenSlice.Value.isBackpackWear && !__instance.slices[__instance.chosenSlice.Value.slotID + 1].image.enabled)
|
||||
{
|
||||
__instance.currentlyHeldItem.transform.position = Vector3.Lerp(__instance.currentlyHeldItem.transform.position, __instance.slices[__instance.chosenSlice.Value.slotID + 1].transform.GetChild(0).GetChild(0).position, Time.deltaTime * 20f);
|
||||
}
|
||||
@@ -32,7 +42,7 @@ class EasyBackpackPatch
|
||||
{
|
||||
__instance.currentlyHeldItem.transform.localPosition = Vector3.Lerp(__instance.currentlyHeldItem.transform.localPosition, Vector3.zero, Time.deltaTime * 20f);
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class AudioSyncService
|
||||
if (File.Exists(filePath)) File.Delete(filePath);
|
||||
|
||||
string url = $"{API_BASE_URL}/audio/{Id}/download?hash={Hash}";
|
||||
Debug.LogError($"Downloading audio from URL: {url}");
|
||||
Debug.Log($"Downloading audio from URL: {url}");
|
||||
|
||||
using UnityWebRequest www = UnityWebRequest.Get(url);
|
||||
var operation = www.SendWebRequest();
|
||||
@@ -244,48 +244,58 @@ class AudioSyncWorker
|
||||
{
|
||||
if (IsLoading || IsSyncing) return;
|
||||
IsSyncing = true;
|
||||
Dictionary<AudioSyncService.APIAudioFormat, Song?> toDownload = new();
|
||||
|
||||
string[] existingSongNames = [.. Song.Sounds.Keys];
|
||||
AudioSyncService.APIAudioFormat[] existingAPIFormats = [.. AudioSyncService.GetAudioClips()];
|
||||
string[] apiExistingNames = [.. existingAPIFormats.Select(apiAudio => apiAudio.Filename)];
|
||||
|
||||
var songsToRemove = existingSongNames.Except(apiExistingNames).ToArray();
|
||||
foreach (var songName in songsToRemove)
|
||||
try
|
||||
{
|
||||
if (Song.Sounds.TryGetValue(songName, out var songToDispose))
|
||||
Dictionary<AudioSyncService.APIAudioFormat, Song?> toDownload = new();
|
||||
|
||||
string[] existingSongNames = [.. Song.Sounds.Keys];
|
||||
AudioSyncService.APIAudioFormat[] existingAPIFormats = [.. AudioSyncService.GetAudioClips()];
|
||||
string[] apiExistingNames = [.. existingAPIFormats.Select(apiAudio => apiAudio.Filename)];
|
||||
|
||||
var songsToRemove = existingSongNames.Except(apiExistingNames).ToArray();
|
||||
foreach (var songName in songsToRemove)
|
||||
{
|
||||
songToDispose.Dispose();
|
||||
songToDispose.DeleteFile();
|
||||
if (Song.Sounds.TryGetValue(songName, out var songToDispose))
|
||||
{
|
||||
songToDispose.Dispose();
|
||||
songToDispose.DeleteFile();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (AudioSyncService.APIAudioFormat apiAudio in existingAPIFormats)
|
||||
{
|
||||
Song? existingSong = Song.SoundsByHash.GetValueOrDefault(apiAudio.Hash);
|
||||
if (existingSong == null || existingSong.Hash != apiAudio.Hash)
|
||||
{
|
||||
toDownload.Add(apiAudio, existingSong);
|
||||
}
|
||||
}
|
||||
|
||||
BetterBugleUI.Instance?.ShowActionbar($"Syncing audio bank... {toDownload.Count} changed/new files found.");
|
||||
|
||||
string[] filesToOverload = [];
|
||||
|
||||
foreach (AudioSyncService.APIAudioFormat apiAudio in toDownload.Keys)
|
||||
{
|
||||
bool success = await AudioSyncService.DownloadAPIAudio(apiAudio, SoundsDirectory, toDownload[apiAudio]);
|
||||
if (success)
|
||||
{
|
||||
Debug.Log($"Successfully downloaded audio: {apiAudio.Filename}.{apiAudio.Extension}, adding to forceload");
|
||||
filesToOverload = [.. filesToOverload, $"{apiAudio.Filename}.{apiAudio.Extension}"];
|
||||
}
|
||||
}
|
||||
IsSyncing = false;
|
||||
IsLoading = true;
|
||||
// StartCoroutine is a Unity API - must run on the main thread, not on this Task.Run background thread.
|
||||
Plugin.RunOnMainThread(() => Plugin.Instance.StartCoroutine(LoadAllAudioClipsCoroutine(SoundsDirectory, filesToOverload)));
|
||||
}
|
||||
|
||||
|
||||
foreach (AudioSyncService.APIAudioFormat apiAudio in existingAPIFormats)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Song? existingSong = Song.SoundsByHash.GetValueOrDefault(apiAudio.Hash);
|
||||
if (existingSong == null || existingSong.Hash != apiAudio.Hash)
|
||||
{
|
||||
toDownload.Add(apiAudio, existingSong);
|
||||
}
|
||||
Debug.LogError($"Audio sync failed: {ex}");
|
||||
IsSyncing = false;
|
||||
IsLoading = false;
|
||||
}
|
||||
|
||||
BetterBugleUI.Instance?.ShowActionbar($"Syncing audio bank... {toDownload.Count} changed/new files found.");
|
||||
|
||||
string[] filesToOverload = [];
|
||||
|
||||
foreach (AudioSyncService.APIAudioFormat apiAudio in toDownload.Keys)
|
||||
{
|
||||
bool success = await AudioSyncService.DownloadAPIAudio(apiAudio, SoundsDirectory, toDownload[apiAudio]);
|
||||
if (success)
|
||||
{
|
||||
Debug.Log($"Successfully downloaded audio: {apiAudio.Filename}.{apiAudio.Extension}, adding to forceload");
|
||||
filesToOverload = [.. filesToOverload, $"{apiAudio.Filename}.{apiAudio.Extension}"];
|
||||
}
|
||||
}
|
||||
IsSyncing = false;
|
||||
IsLoading = true;
|
||||
Plugin.Instance.StartCoroutine(LoadAllAudioClipsCoroutine(SoundsDirectory, filesToOverload));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user