mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 14:29:25 +00:00
Stickers: minor changes
This commit is contained in:
parent
c206d98a97
commit
2f65634031
16 changed files with 204 additions and 140 deletions
|
@ -1,13 +0,0 @@
|
||||||
using BTKUILib.UIObjects;
|
|
||||||
|
|
||||||
namespace NAK.Stickers.Integrations;
|
|
||||||
|
|
||||||
public static partial class BTKUIAddon
|
|
||||||
{
|
|
||||||
private static void Setup_DebugOptionsCategory()
|
|
||||||
{
|
|
||||||
Category debugCategory = _rootPage.AddMelonCategory(ModSettings.Hidden_Foldout_DebugCategory);
|
|
||||||
debugCategory.AddMelonToggle(ModSettings.Debug_NetworkInbound);
|
|
||||||
debugCategory.AddMelonToggle(ModSettings.Debug_NetworkOutbound);
|
|
||||||
}
|
|
||||||
}
|
|
24
Stickers/Integrations/BTKUI/UIAddon.Category.MiscOptions.cs
Normal file
24
Stickers/Integrations/BTKUI/UIAddon.Category.MiscOptions.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using BTKUILib;
|
||||||
|
using BTKUILib.UIObjects;
|
||||||
|
using BTKUILib.UIObjects.Components;
|
||||||
|
using NAK.Stickers.Utilities;
|
||||||
|
|
||||||
|
namespace NAK.Stickers.Integrations;
|
||||||
|
|
||||||
|
public static partial class BTKUIAddon
|
||||||
|
{
|
||||||
|
private static void Setup_OtherOptionsCategory()
|
||||||
|
{
|
||||||
|
Category debugCategory = _rootPage.AddMelonCategory(ModSettings.Hidden_Foldout_MiscCategory);
|
||||||
|
debugCategory.AddMelonToggle(ModSettings.Debug_NetworkInbound);
|
||||||
|
debugCategory.AddMelonToggle(ModSettings.Debug_NetworkOutbound);
|
||||||
|
debugCategory.AddMelonToggle(ModSettings.Entry_FriendsOnly);
|
||||||
|
debugCategory.AddButton("Clear Thumbnail Cache", "Stickers-rubbish-bin", "Clear the cache of all loaded stickers.", ButtonStyle.TextWithIcon)
|
||||||
|
.OnPress += () => QuickMenuAPI.ShowConfirm("Clear Thumbnail Cache", "Are you sure you want to clear the Cohtml thumbnail cache for all stickers?",
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
StickerCache.ClearCache();
|
||||||
|
QuickMenuAPI.ShowAlertToast("Thumbnail cache cleared.", 2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,8 +36,8 @@ public static partial class BTKUIAddon
|
||||||
Button openStickersFolderButton = _ourCategory.AddButton("Open Stickers Folder", "Stickers-folder", "Open UserData/Stickers folder in explorer. If above 256kb your image will automatically be downscaled for networking reasons.", ButtonStyle.TextWithIcon);
|
Button openStickersFolderButton = _ourCategory.AddButton("Open Stickers Folder", "Stickers-folder", "Open UserData/Stickers folder in explorer. If above 256kb your image will automatically be downscaled for networking reasons.", ButtonStyle.TextWithIcon);
|
||||||
openStickersFolderButton.OnPress += OnOpenStickersFolderButtonClick;
|
openStickersFolderButton.OnPress += OnOpenStickersFolderButtonClick;
|
||||||
|
|
||||||
Button openMultiSelectionButton = _ourCategory.AddButton("Sticker SFX", "Stickers-headset", "Choose the SFX used when a sticker is placed.", ButtonStyle.TextWithIcon);
|
Button openStickerSFXButton = _ourCategory.AddButton("Sticker SFX", "Stickers-headset", "Choose the SFX used when a sticker is placed.", ButtonStyle.TextWithIcon);
|
||||||
openMultiSelectionButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_sfxSelection);
|
openStickerSFXButton.OnPress += () => QuickMenuAPI.OpenMultiSelect(_sfxSelection);
|
||||||
|
|
||||||
ToggleButton toggleDesktopKeybindButton = _ourCategory.AddToggle("Use Desktop Keybind", "Should the Desktop keybind be active.", ModSettings.Entry_UsePlaceBinding.Value);
|
ToggleButton toggleDesktopKeybindButton = _ourCategory.AddToggle("Use Desktop Keybind", "Should the Desktop keybind be active.", ModSettings.Entry_UsePlaceBinding.Value);
|
||||||
Button openDesktopKeybindButton = _ourCategory.AddButton("Desktop Keybind", "Stickers-alphabet", "Choose the key binding to place stickers.", ButtonStyle.TextWithIcon);
|
Button openDesktopKeybindButton = _ourCategory.AddButton("Desktop Keybind", "Stickers-alphabet", "Choose the key binding to place stickers.", ButtonStyle.TextWithIcon);
|
||||||
|
|
|
@ -66,7 +66,7 @@ public static partial class BTKUIAddon
|
||||||
|
|
||||||
Setup_StickersModCategory();
|
Setup_StickersModCategory();
|
||||||
Setup_StickerSelectionCategory();
|
Setup_StickerSelectionCategory();
|
||||||
Setup_DebugOptionsCategory();
|
Setup_OtherOptionsCategory();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Setup
|
#endregion Setup
|
||||||
|
|
|
@ -18,6 +18,7 @@ public static partial class BTKUIAddon
|
||||||
|
|
||||||
private static Category _fileCategory;
|
private static Category _fileCategory;
|
||||||
private static Category _folderCategory;
|
private static Category _folderCategory;
|
||||||
|
private static TextBlock _noFilesTextBlock;
|
||||||
|
|
||||||
private const int MAX_BUTTONS = 512; // cohtml literally will start to explode
|
private const int MAX_BUTTONS = 512; // cohtml literally will start to explode
|
||||||
private static Button[] _fileButtons = new Button[80]; // 100 files, will resize if needed
|
private static Button[] _fileButtons = new Button[80]; // 100 files, will resize if needed
|
||||||
|
@ -53,6 +54,8 @@ public static partial class BTKUIAddon
|
||||||
// Setup categories
|
// Setup categories
|
||||||
_folderCategory = _ourDirectoryBrowserPage.AddCategory("Subdirectories");
|
_folderCategory = _ourDirectoryBrowserPage.AddCategory("Subdirectories");
|
||||||
_fileCategory = _ourDirectoryBrowserPage.AddCategory("Images");
|
_fileCategory = _ourDirectoryBrowserPage.AddCategory("Images");
|
||||||
|
_noFilesTextBlock = _fileCategory.AddTextBlock("No images found in this directory. You can add your own images and subfolders to the `UserData/Stickers/` folder.");
|
||||||
|
_noFilesTextBlock.Hidden = true;
|
||||||
|
|
||||||
SetupFolderButtons();
|
SetupFolderButtons();
|
||||||
SetupFileButtons();
|
SetupFileButtons();
|
||||||
|
@ -88,6 +91,7 @@ public static partial class BTKUIAddon
|
||||||
string absolutePath = Path.Combine(_curDirectoryInfo.FullName, button.ButtonTooltip[5..]);
|
string absolutePath = Path.Combine(_curDirectoryInfo.FullName, button.ButtonTooltip[5..]);
|
||||||
string relativePath = Path.GetRelativePath(_initialDirectory, absolutePath);
|
string relativePath = Path.GetRelativePath(_initialDirectory, absolutePath);
|
||||||
StickerSystem.Instance.LoadImage(relativePath, _curSelectedSticker);
|
StickerSystem.Instance.LoadImage(relativePath, _curSelectedSticker);
|
||||||
|
_rootPage.OpenPage(true); // close the directory browser to artificially limit loading speed
|
||||||
};
|
};
|
||||||
_fileButtons[i] = button;
|
_fileButtons[i] = button;
|
||||||
}
|
}
|
||||||
|
@ -162,12 +166,16 @@ public static partial class BTKUIAddon
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_stickerSelectionButtonDoubleClickTime = Time.time;
|
_stickerSelectionButtonDoubleClickTime = Time.time;
|
||||||
|
|
||||||
|
// quick menu notification
|
||||||
|
QuickMenuAPI.ShowAlertToast($"Selected sticker slot {index + 1}", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OpenStickerSelectionForSlot(int index)
|
private static void OpenStickerSelectionForSlot(int index)
|
||||||
{
|
{
|
||||||
if (IsPopulatingPage) return;
|
if (IsPopulatingPage) return;
|
||||||
_curSelectedSticker = index;
|
_curSelectedSticker = index;
|
||||||
|
_initialDirectory = StickerSystem.GetStickersFolderPath(); // creates folder if needed (lazy fix)
|
||||||
_curDirectoryInfo = new DirectoryInfo(_initialDirectory);
|
_curDirectoryInfo = new DirectoryInfo(_initialDirectory);
|
||||||
_ourDirectoryBrowserPage.OpenPage(false, true);
|
_ourDirectoryBrowserPage.OpenPage(false, true);
|
||||||
}
|
}
|
||||||
|
@ -203,8 +211,9 @@ public static partial class BTKUIAddon
|
||||||
|
|
||||||
_folderCategory.Hidden = foldersCount == 0;
|
_folderCategory.Hidden = foldersCount == 0;
|
||||||
_folderCategory.CategoryName = $"Subdirectories ({foldersCount})";
|
_folderCategory.CategoryName = $"Subdirectories ({foldersCount})";
|
||||||
_fileCategory.Hidden = filesCount == 0;
|
//_fileCategory.Hidden = filesCount == 0;
|
||||||
_fileCategory.CategoryName = $"Images ({filesCount})";
|
_fileCategory.CategoryName = $"Images ({filesCount})";
|
||||||
|
_noFilesTextBlock.Hidden = filesCount > 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
PopulateFolders(directories);
|
PopulateFolders(directories);
|
||||||
|
|
|
@ -11,7 +11,7 @@ public static class ModSettings
|
||||||
|
|
||||||
internal const string SM_SettingsCategory = "Stickers Mod";
|
internal const string SM_SettingsCategory = "Stickers Mod";
|
||||||
private const string SM_SelectionCategory = "Sticker Selection";
|
private const string SM_SelectionCategory = "Sticker Selection";
|
||||||
private const string DEBUG_SettingsCategory = "Debug Options";
|
private const string MISC_SettingsCategory = "Miscellaneous Options";
|
||||||
|
|
||||||
internal const int MaxStickerSlots = 4;
|
internal const int MaxStickerSlots = 4;
|
||||||
|
|
||||||
|
@ -28,16 +28,13 @@ public static class ModSettings
|
||||||
internal static readonly MelonPreferences_Entry<bool> Hidden_Foldout_SelectionCategory =
|
internal static readonly MelonPreferences_Entry<bool> Hidden_Foldout_SelectionCategory =
|
||||||
Category.CreateEntry("hidden_foldout_selection", true, is_hidden: true, display_name: SM_SelectionCategory, description: "Foldout state for Sticker selection.");
|
Category.CreateEntry("hidden_foldout_selection", true, is_hidden: true, display_name: SM_SelectionCategory, description: "Foldout state for Sticker selection.");
|
||||||
|
|
||||||
internal static readonly MelonPreferences_Entry<bool> Hidden_Foldout_DebugCategory =
|
internal static readonly MelonPreferences_Entry<bool> Hidden_Foldout_MiscCategory =
|
||||||
Category.CreateEntry("hidden_foldout_debug", false, is_hidden: true, display_name: DEBUG_SettingsCategory, description: "Foldout state for Debug settings.");
|
Category.CreateEntry("hidden_foldout_miscellaneous", false, is_hidden: true, display_name: MISC_SettingsCategory, description: "Foldout state for Miscellaneous settings.");
|
||||||
|
|
||||||
#endregion Hidden Foldout Entries
|
#endregion Hidden Foldout Entries
|
||||||
|
|
||||||
#region Stickers Mod Settings
|
#region Stickers Mod Settings
|
||||||
|
|
||||||
internal static readonly MelonPreferences_Entry<bool> Entry_HapticsOnPlace =
|
|
||||||
Category.CreateEntry("haptics_on_place", true, "Haptics On Place", "Enable haptic feedback when placing stickers.");
|
|
||||||
|
|
||||||
internal static readonly MelonPreferences_Entry<float> Entry_PlayerUpAlignmentThreshold =
|
internal static readonly MelonPreferences_Entry<float> Entry_PlayerUpAlignmentThreshold =
|
||||||
Category.CreateEntry("player_up_alignment_threshold", 20f, "Player Up Alignment Threshold", "The threshold the controller roll can be within to align perfectly with the player up vector. Set to 0f to always align to controller up.");
|
Category.CreateEntry("player_up_alignment_threshold", 20f, "Player Up Alignment Threshold", "The threshold the controller roll can be within to align perfectly with the player up vector. Set to 0f to always align to controller up.");
|
||||||
|
|
||||||
|
@ -59,6 +56,9 @@ public static class ModSettings
|
||||||
description: "The name of the sticker selected for stickering.",
|
description: "The name of the sticker selected for stickering.",
|
||||||
is_hidden: true);
|
is_hidden: true);
|
||||||
|
|
||||||
|
internal static readonly MelonPreferences_Entry<bool> Entry_FriendsOnly =
|
||||||
|
Category.CreateEntry("friends_only", false, "Friends Only", "Only allow friends to use stickers.");
|
||||||
|
|
||||||
#endregion Stickers Mod Settings
|
#endregion Stickers Mod Settings
|
||||||
|
|
||||||
#region Debug Settings
|
#region Debug Settings
|
||||||
|
|
|
@ -27,6 +27,6 @@ using System.Reflection;
|
||||||
namespace NAK.Stickers.Properties;
|
namespace NAK.Stickers.Properties;
|
||||||
internal static class AssemblyInfoParams
|
internal static class AssemblyInfoParams
|
||||||
{
|
{
|
||||||
public const string Version = "1.0.4";
|
public const string Version = "1.0.5";
|
||||||
public const string Author = "NotAKidoS";
|
public const string Author = "NotAKidoS";
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
<TargetFramework>net48</TargetFramework>
|
<TargetFramework>net48</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
<DefineConstants>TRACE;TRACE;UNITY_2017_1_OR_NEWER;UNITY_2018_1_OR_NEWER;UNITY_2019_3_OR_NEWER;USE_BURST;USE_NEWMATHS;USE_BURST_REALLY;</DefineConstants>
|
<DefineConstants>TRACE;TRACE;UNITY_2017_1_OR_NEWER;UNITY_2018_1_OR_NEWER;UNITY_2019_3_OR_NEWER;USE_BURST;USE_NEWMATHS;USE_BURST_REALLY;USEDFORSTICKERMOD;</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="ThirdParty\" />
|
<Folder Include="ThirdParty\" />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using NAK.Stickers.Properties;
|
using ABI_RC.Core.Util.AnimatorManager;
|
||||||
|
using NAK.Stickers.Properties;
|
||||||
|
|
||||||
namespace NAK.Stickers.Networking;
|
namespace NAK.Stickers.Networking;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using ABI_RC.Core.Savior;
|
using ABI_RC.Core.Networking.IO.Social;
|
||||||
|
using ABI_RC.Core.Savior;
|
||||||
using ABI_RC.Systems.ModNetwork;
|
using ABI_RC.Systems.ModNetwork;
|
||||||
using NAK.Stickers.Utilities;
|
using NAK.Stickers.Utilities;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -16,57 +17,90 @@ public static partial class ModNetwork
|
||||||
|
|
||||||
#endregion Inbound Buffers
|
#endregion Inbound Buffers
|
||||||
|
|
||||||
|
#region Reset Method
|
||||||
|
|
||||||
|
public static void Reset()
|
||||||
|
{
|
||||||
|
_textureChunkBuffers.Clear();
|
||||||
|
_receivedChunkCounts.Clear();
|
||||||
|
_expectedChunkCounts.Clear();
|
||||||
|
_textureMetadata.Clear();
|
||||||
|
|
||||||
|
LoggerInbound("ModNetwork inbound buffers and metadata have been reset.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Reset Method
|
||||||
|
|
||||||
#region Inbound Methods
|
#region Inbound Methods
|
||||||
|
|
||||||
|
private static bool ShouldReceiveFromSender(string sender)
|
||||||
|
{
|
||||||
|
if (_disallowedForSession.Contains(sender))
|
||||||
|
return false; // ignore messages from disallowed users
|
||||||
|
|
||||||
|
if (MetaPort.Instance.blockedUserIds.Contains(sender))
|
||||||
|
return false; // ignore messages from blocked users
|
||||||
|
|
||||||
|
if (ModSettings.Entry_FriendsOnly.Value && !Friends.FriendsWith(sender))
|
||||||
|
return false; // ignore messages from non-friends if friends only is enabled
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static void HandleMessageReceived(ModNetworkMessage msg)
|
private static void HandleMessageReceived(ModNetworkMessage msg)
|
||||||
{
|
{
|
||||||
string sender = msg.Sender;
|
try
|
||||||
msg.Read(out byte msgTypeRaw);
|
|
||||||
|
|
||||||
if (!Enum.IsDefined(typeof(MessageType), msgTypeRaw))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_disallowedForSession.Contains(sender))
|
|
||||||
return; // ignore messages from disallowed users
|
|
||||||
|
|
||||||
if (MetaPort.Instance.blockedUserIds.Contains(sender))
|
|
||||||
return; // ignore messages from blocked users
|
|
||||||
|
|
||||||
LoggerInbound($"Received message from {msg.Sender}, Type: {(MessageType)msgTypeRaw}");
|
|
||||||
|
|
||||||
switch ((MessageType)msgTypeRaw)
|
|
||||||
{
|
{
|
||||||
case MessageType.PlaceSticker:
|
string sender = msg.Sender;
|
||||||
HandlePlaceSticker(msg);
|
msg.Read(out byte msgTypeRaw);
|
||||||
break;
|
|
||||||
|
|
||||||
case MessageType.ClearSticker:
|
if (!Enum.IsDefined(typeof(MessageType), msgTypeRaw))
|
||||||
HandleClearSticker(msg);
|
return;
|
||||||
break;
|
|
||||||
|
|
||||||
case MessageType.ClearAllStickers:
|
if (!ShouldReceiveFromSender(sender))
|
||||||
HandleClearAllStickers(msg);
|
return;
|
||||||
break;
|
|
||||||
|
|
||||||
case MessageType.StartTexture:
|
LoggerInbound($"Received message from {msg.Sender}, Type: {(MessageType)msgTypeRaw}");
|
||||||
HandleStartTexture(msg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MessageType.SendTexture:
|
switch ((MessageType)msgTypeRaw)
|
||||||
HandleSendTexture(msg);
|
{
|
||||||
break;
|
case MessageType.PlaceSticker:
|
||||||
|
HandlePlaceSticker(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
case MessageType.EndTexture:
|
case MessageType.ClearSticker:
|
||||||
HandleEndTexture(msg);
|
HandleClearSticker(msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageType.RequestTexture:
|
case MessageType.ClearAllStickers:
|
||||||
HandleRequestTexture(msg);
|
HandleClearAllStickers(msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case MessageType.StartTexture:
|
||||||
LoggerInbound($"Invalid message type received: {msgTypeRaw}");
|
HandleStartTexture(msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MessageType.SendTexture:
|
||||||
|
HandleSendTexture(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MessageType.EndTexture:
|
||||||
|
HandleEndTexture(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MessageType.RequestTexture:
|
||||||
|
HandleRequestTexture(msg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LoggerInbound($"Invalid message type received: {msgTypeRaw}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LoggerInbound($"Error handling message from {msg.Sender}: {e.Message}", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,12 @@ namespace NAK.Stickers
|
||||||
{
|
{
|
||||||
private const float DECAL_SIZE = 0.25f;
|
private const float DECAL_SIZE = 0.25f;
|
||||||
|
|
||||||
private static readonly int s_EmissionStrengthID = Shader.PropertyToID("_EmissionStrength");
|
public readonly string PlayerId;
|
||||||
|
|
||||||
public float DeathTime; // when a remote player leaves, we need to kill their stickers
|
|
||||||
public float LastPlacedTime;
|
public float LastPlacedTime;
|
||||||
|
public float DeathTime = -1f;
|
||||||
|
|
||||||
private Vector3 _lastPlacedPosition = Vector3.zero;
|
private Vector3 _lastPlacedPosition = Vector3.zero;
|
||||||
|
|
||||||
public readonly bool IsLocal;
|
|
||||||
private readonly DecalType _decal;
|
private readonly DecalType _decal;
|
||||||
private readonly DecalSpawner[] _decalSpawners;
|
private readonly DecalSpawner[] _decalSpawners;
|
||||||
|
|
||||||
|
@ -23,9 +22,9 @@ namespace NAK.Stickers
|
||||||
private readonly Material[] _materials;
|
private readonly Material[] _materials;
|
||||||
private readonly AudioSource _audioSource;
|
private readonly AudioSource _audioSource;
|
||||||
|
|
||||||
public StickerData(bool isLocal, int decalSpawnersCount)
|
public StickerData(string playerId, int decalSpawnersCount)
|
||||||
{
|
{
|
||||||
IsLocal = isLocal;
|
PlayerId = playerId;
|
||||||
|
|
||||||
_decal = ScriptableObject.CreateInstance<DecalType>();
|
_decal = ScriptableObject.CreateInstance<DecalType>();
|
||||||
_decalSpawners = new DecalSpawner[decalSpawnersCount];
|
_decalSpawners = new DecalSpawner[decalSpawnersCount];
|
||||||
|
@ -54,7 +53,7 @@ namespace NAK.Stickers
|
||||||
_audioSource.maxDistance = 5f;
|
_audioSource.maxDistance = 5f;
|
||||||
_audioSource.minDistance = 1f;
|
_audioSource.minDistance = 1f;
|
||||||
_audioSource.outputAudioMixerGroup = RootLogic.Instance.propSfx; // props are close enough to stickers
|
_audioSource.outputAudioMixerGroup = RootLogic.Instance.propSfx; // props are close enough to stickers
|
||||||
if (isLocal) Object.DontDestroyOnLoad(_audioSource.gameObject); // keep audio source through world transitions
|
if (PlayerId == StickerSystem.PlayerLocalId) Object.DontDestroyOnLoad(_audioSource.gameObject); // keep audio source through world transitions
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid GetTextureHash(int spawnerIndex = 0)
|
public Guid GetTextureHash(int spawnerIndex = 0)
|
||||||
|
@ -95,8 +94,6 @@ namespace NAK.Stickers
|
||||||
? FilterMode.Bilinear // smear it cause its fat
|
? FilterMode.Bilinear // smear it cause its fat
|
||||||
: FilterMode.Point; // my minecraft skin looked shit
|
: FilterMode.Point; // my minecraft skin looked shit
|
||||||
|
|
||||||
if (IsLocal) StickerMod.Logger.Msg($"Set texture filter mode to: {texture.filterMode}");
|
|
||||||
|
|
||||||
Material material = _materials[spawnerIndex];
|
Material material = _materials[spawnerIndex];
|
||||||
|
|
||||||
// Destroy the previous texture to avoid memory leaks
|
// Destroy the previous texture to avoid memory leaks
|
||||||
|
@ -117,9 +114,9 @@ namespace NAK.Stickers
|
||||||
|
|
||||||
Transform rootObject = null;
|
Transform rootObject = null;
|
||||||
GameObject hitGO = hit.transform.gameObject;
|
GameObject hitGO = hit.transform.gameObject;
|
||||||
if (hitGO.TryGetComponent(out Rigidbody _)
|
if (hitGO.scene.buildIndex == 4 // additive (dynamic) content
|
||||||
|| hitGO.TryGetComponent(out Animator _)
|
|| hitGO.TryGetComponent(out Animator _) // potentially movable
|
||||||
|| hitGO.scene.buildIndex == 4) // additive (dynamic) content
|
|| hitGO.GetComponentInParent<Rigidbody>() != null) // movable
|
||||||
rootObject = hitGO.transform;
|
rootObject = hitGO.transform;
|
||||||
|
|
||||||
_lastPlacedPosition = hit.point;
|
_lastPlacedPosition = hit.point;
|
||||||
|
@ -128,7 +125,7 @@ namespace NAK.Stickers
|
||||||
// Add decal to the specified spawner
|
// Add decal to the specified spawner
|
||||||
_decalSpawners[spawnerIndex].AddDecal(
|
_decalSpawners[spawnerIndex].AddDecal(
|
||||||
_lastPlacedPosition, Quaternion.LookRotation(forwardDirection, upDirection),
|
_lastPlacedPosition, Quaternion.LookRotation(forwardDirection, upDirection),
|
||||||
hit.collider.gameObject,
|
hitGO,
|
||||||
DECAL_SIZE, DECAL_SIZE, 1f, 1f, 0f, rootObject);
|
DECAL_SIZE, DECAL_SIZE, 1f, 1f, 0f, rootObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +161,7 @@ namespace NAK.Stickers
|
||||||
_decalSpawners[i].movableGroups.Clear();
|
_decalSpawners[i].movableGroups.Clear();
|
||||||
|
|
||||||
// Clean up textures and materials
|
// Clean up textures and materials
|
||||||
|
if (_materials[i] == null) continue;
|
||||||
if (_materials[i].mainTexture != null) Object.Destroy(_materials[i].mainTexture);
|
if (_materials[i].mainTexture != null) Object.Destroy(_materials[i].mainTexture);
|
||||||
Object.Destroy(_materials[i]);
|
Object.Destroy(_materials[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,5 +150,10 @@ public partial class StickerSystem
|
||||||
return s_StickersFolderPath;
|
return s_StickersFolderPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EnsureStickersFolderExists()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(s_StickersFolderPath)) Directory.CreateDirectory(s_StickersFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Image Loading
|
#endregion Image Loading
|
||||||
}
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
using ABI_RC.Core.UI;
|
using ABI_RC.Core.IO;
|
||||||
|
using ABI_RC.Core.Networking.IO.Instancing;
|
||||||
|
using ABI_RC.Core.UI;
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
using ABI_RC.Systems.GameEventSystem;
|
||||||
|
using NAK.Stickers.Networking;
|
||||||
using NAK.Stickers.Utilities;
|
using NAK.Stickers.Utilities;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
@ -22,7 +25,7 @@ public partial class StickerSystem
|
||||||
DecalManager.SetPreferredMode(DecalUtils.Mode.GPU, false, 0);
|
DecalManager.SetPreferredMode(DecalUtils.Mode.GPU, false, 0);
|
||||||
|
|
||||||
// ensure cache folder exists
|
// ensure cache folder exists
|
||||||
if (!Directory.Exists(s_StickersFolderPath)) Directory.CreateDirectory(s_StickersFolderPath);
|
EnsureStickersFolderExists();
|
||||||
|
|
||||||
// listen for game events
|
// listen for game events
|
||||||
CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(Instance.OnPlayerSetupStart);
|
CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(Instance.OnPlayerSetupStart);
|
||||||
|
@ -30,6 +33,36 @@ public partial class StickerSystem
|
||||||
|
|
||||||
#endregion Singleton
|
#endregion Singleton
|
||||||
|
|
||||||
|
#region Callback Registration
|
||||||
|
|
||||||
|
private void OnPlayerSetupStart()
|
||||||
|
{
|
||||||
|
CVRGameEventSystem.World.OnUnload.AddListener(_ => OnWorldUnload());
|
||||||
|
CVRGameEventSystem.Instance.OnConnected.AddListener((_) => { if (!Instances.IsReconnecting) OnInitialConnection(); });
|
||||||
|
|
||||||
|
CVRGameEventSystem.Player.OnJoinEntity.AddListener(Instance.OnPlayerJoined);
|
||||||
|
CVRGameEventSystem.Player.OnLeaveEntity.AddListener(Instance.OnPlayerLeft);
|
||||||
|
SchedulerSystem.AddJob(Instance.OnOccasionalUpdate, 10f, 1f);
|
||||||
|
LoadAllImagesAtStartup();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Callback Registration
|
||||||
|
|
||||||
|
#region Game Events
|
||||||
|
|
||||||
|
private void OnInitialConnection()
|
||||||
|
{
|
||||||
|
ClearStickersSelf(); // clear stickers on remotes just in case we rejoined
|
||||||
|
ModNetwork.Reset(); // reset network buffers and metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWorldUnload()
|
||||||
|
{
|
||||||
|
CleanupAllButSelf(); // release all stickers except for self
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Game Events
|
||||||
|
|
||||||
#region Data
|
#region Data
|
||||||
|
|
||||||
private int _selectedStickerSlot;
|
private int _selectedStickerSlot;
|
||||||
|
@ -63,9 +96,7 @@ public partial class StickerSystem
|
||||||
private const float StickerKillTime = 30f;
|
private const float StickerKillTime = 30f;
|
||||||
private const float StickerCooldown = 0.2f;
|
private const float StickerCooldown = 0.2f;
|
||||||
private readonly Dictionary<string, StickerData> _playerStickers = new();
|
private readonly Dictionary<string, StickerData> _playerStickers = new();
|
||||||
private const string PlayerLocalId = "_PLAYERLOCAL";
|
internal const string PlayerLocalId = "_PLAYERLOCAL";
|
||||||
|
|
||||||
private readonly List<StickerData> _deadStickerPool = new(); // for cleanup on player leave
|
|
||||||
|
|
||||||
#endregion Data
|
#endregion Data
|
||||||
}
|
}
|
|
@ -1,7 +1,4 @@
|
||||||
using ABI_RC.Core.IO;
|
using ABI_RC.Core.Player;
|
||||||
using ABI_RC.Core.Networking.IO.Instancing;
|
|
||||||
using ABI_RC.Core.Player;
|
|
||||||
using ABI_RC.Systems.GameEventSystem;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace NAK.Stickers;
|
namespace NAK.Stickers;
|
||||||
|
@ -10,17 +7,6 @@ public partial class StickerSystem
|
||||||
{
|
{
|
||||||
#region Player Callbacks
|
#region Player Callbacks
|
||||||
|
|
||||||
private void OnPlayerSetupStart()
|
|
||||||
{
|
|
||||||
CVRGameEventSystem.World.OnUnload.AddListener(_ => Instance.CleanupAllButSelf());
|
|
||||||
CVRGameEventSystem.Instance.OnConnected.AddListener((_) => { if (!Instances.IsReconnecting) Instance.ClearStickersSelf(); });
|
|
||||||
|
|
||||||
CVRGameEventSystem.Player.OnJoinEntity.AddListener(Instance.OnPlayerJoined);
|
|
||||||
CVRGameEventSystem.Player.OnLeaveEntity.AddListener(Instance.OnPlayerLeft);
|
|
||||||
SchedulerSystem.AddJob(Instance.OnOccasionalUpdate, 10f, 1f);
|
|
||||||
LoadAllImagesAtStartup();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPlayerJoined(CVRPlayerEntity playerEntity)
|
private void OnPlayerJoined(CVRPlayerEntity playerEntity)
|
||||||
{
|
{
|
||||||
if (!_playerStickers.TryGetValue(playerEntity.Uuid, out StickerData stickerData))
|
if (!_playerStickers.TryGetValue(playerEntity.Uuid, out StickerData stickerData))
|
||||||
|
@ -28,7 +14,6 @@ public partial class StickerSystem
|
||||||
|
|
||||||
stickerData.DeathTime = -1f;
|
stickerData.DeathTime = -1f;
|
||||||
stickerData.SetAlpha(1f);
|
stickerData.SetAlpha(1f);
|
||||||
_deadStickerPool.Remove(stickerData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlayerLeft(CVRPlayerEntity playerEntity)
|
private void OnPlayerLeft(CVRPlayerEntity playerEntity)
|
||||||
|
@ -38,23 +23,14 @@ public partial class StickerSystem
|
||||||
|
|
||||||
stickerData.DeathTime = Time.time + StickerKillTime;
|
stickerData.DeathTime = Time.time + StickerKillTime;
|
||||||
stickerData.SetAlpha(1f);
|
stickerData.SetAlpha(1f);
|
||||||
_deadStickerPool.Add(stickerData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOccasionalUpdate()
|
private void OnOccasionalUpdate()
|
||||||
{
|
{
|
||||||
if (_deadStickerPool.Count == 0)
|
float currentTime = Time.time;
|
||||||
return;
|
for (int i = 0; i < _playerStickers.Values.Count; i++)
|
||||||
|
|
||||||
for (var i = _deadStickerPool.Count - 1; i >= 0; i--)
|
|
||||||
{
|
{
|
||||||
float currentTime = Time.time;
|
StickerData stickerData = _playerStickers.Values.ElementAt(i);
|
||||||
StickerData stickerData = _deadStickerPool[i];
|
|
||||||
if (stickerData == null)
|
|
||||||
{
|
|
||||||
_deadStickerPool.RemoveAt(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stickerData.DeathTime < 0f)
|
if (stickerData.DeathTime < 0f)
|
||||||
continue;
|
continue;
|
||||||
|
@ -65,15 +41,8 @@ public partial class StickerSystem
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < _playerStickers.Values.Count; j++)
|
|
||||||
{
|
|
||||||
if (_playerStickers.Values.ElementAt(j) != stickerData) continue;
|
|
||||||
_playerStickers.Remove(_playerStickers.Keys.ElementAt(j));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_deadStickerPool.RemoveAt(i);
|
|
||||||
stickerData.Cleanup();
|
stickerData.Cleanup();
|
||||||
|
_playerStickers.Remove(stickerData.PlayerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ public partial class StickerSystem
|
||||||
if (_playerStickers.TryGetValue(playerId, out StickerData stickerData))
|
if (_playerStickers.TryGetValue(playerId, out StickerData stickerData))
|
||||||
return stickerData;
|
return stickerData;
|
||||||
|
|
||||||
stickerData = new StickerData(playerId == PlayerLocalId, ModSettings.MaxStickerSlots);
|
stickerData = new StickerData(playerId, ModSettings.MaxStickerSlots);
|
||||||
_playerStickers[playerId] = stickerData;
|
_playerStickers[playerId] = stickerData;
|
||||||
return stickerData;
|
return stickerData;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,6 @@ public partial class StickerSystem
|
||||||
if (!PlaceStickerSelf(transform.position, transform.forward, targetUp))
|
if (!PlaceStickerSelf(transform.position, transform.forward, targetUp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// do haptic if not lame
|
|
||||||
if (!ModSettings.Entry_HapticsOnPlace.Value) return;
|
|
||||||
CVRInputManager.Instance.Vibrate(0f, 0.1f, 10f, 0.1f, hand);
|
CVRInputManager.Instance.Vibrate(0f, 0.1f, 10f, 0.1f, hand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +65,10 @@ public partial class StickerSystem
|
||||||
10f, LayerMask, QueryTriggerInteraction.Ignore))
|
10f, LayerMask, QueryTriggerInteraction.Ignore))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// if gameobject name starts with [NoSticker] then don't place sticker
|
||||||
|
if (hit.transform.gameObject.name.StartsWith("[NoSticker]"))
|
||||||
|
return false;
|
||||||
|
|
||||||
stickerData.Place(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot);
|
stickerData.Place(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot);
|
||||||
stickerData.PlayAudio();
|
stickerData.PlayAudio();
|
||||||
return true;
|
return true;
|
||||||
|
@ -78,6 +80,12 @@ public partial class StickerSystem
|
||||||
ModNetwork.SendClearAllStickers();
|
ModNetwork.SendClearAllStickers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearStickerSelf(int stickerSlot)
|
||||||
|
{
|
||||||
|
ClearStickersForPlayer(PlayerLocalId, stickerSlot);
|
||||||
|
ModNetwork.SendClearSticker(stickerSlot);
|
||||||
|
}
|
||||||
|
|
||||||
private void ClearStickersForPlayer(string playerId)
|
private void ClearStickersForPlayer(string playerId)
|
||||||
{
|
{
|
||||||
if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData))
|
if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData))
|
||||||
|
@ -100,6 +108,7 @@ public partial class StickerSystem
|
||||||
texture.LoadImage(imageBytes);
|
texture.LoadImage(imageBytes);
|
||||||
texture.Compress(true); // noachi said to do
|
texture.Compress(true); // noachi said to do
|
||||||
|
|
||||||
|
ClearStickerSelf(stickerSlot); // clear placed stickers in-scene so we can't replace an entire wall at once
|
||||||
OnPlayerStickerTextureReceived(PlayerLocalId, Guid.Empty, texture, stickerSlot);
|
OnPlayerStickerTextureReceived(PlayerLocalId, Guid.Empty, texture, stickerSlot);
|
||||||
ModNetwork.SetTexture(stickerSlot, imageBytes);
|
ModNetwork.SetTexture(stickerSlot, imageBytes);
|
||||||
}
|
}
|
||||||
|
@ -138,7 +147,7 @@ public partial class StickerSystem
|
||||||
|
|
||||||
foreach ((_, StickerData data) in _playerStickers)
|
foreach ((_, StickerData data) in _playerStickers)
|
||||||
{
|
{
|
||||||
if (data.IsLocal) data.Clear();
|
if (data == localStickerData) data.Clear();
|
||||||
else data.Cleanup();
|
else data.Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,15 +155,5 @@ public partial class StickerSystem
|
||||||
_playerStickers[PlayerLocalId] = localStickerData;
|
_playerStickers[PlayerLocalId] = localStickerData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectStickerSlot(int stickerSlot)
|
|
||||||
{
|
|
||||||
SelectedStickerSlot = Mathf.Clamp(stickerSlot, 0, ModSettings.MaxStickerSlots - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetCurrentStickerSlot()
|
|
||||||
{
|
|
||||||
return SelectedStickerSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Sticker Lifecycle
|
#endregion Sticker Lifecycle
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,13 @@ public static class StickerCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ClearCache()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(ThumbnailPath)) return;
|
||||||
|
Directory.Delete(ThumbnailPath, true);
|
||||||
|
StickerMod.Logger.Msg("Cleared thumbnail cache.");
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Public Methods
|
#endregion Public Methods
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue