Added World Restriction Checks

This commit is contained in:
SketchFoxsky 2024-09-20 18:10:40 -04:00 committed by GitHub
parent 5f6a85984d
commit 71d780248f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 344 additions and 313 deletions

View file

@ -1,124 +1,151 @@
using ABI_RC.Core.IO; using ABI_RC.Core.IO;
using ABI_RC.Core.Networking.IO.Instancing; using ABI_RC.Core.Networking.IO.Instancing;
using ABI_RC.Core.UI; using ABI_RC.Core.UI;
using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.GameEventSystem;
using NAK.Stickers.Networking; using JetBrains.Annotations;
using NAK.Stickers.Utilities; using NAK.Stickers.Networking;
using NAK.Stickers.Utilities;
namespace NAK.Stickers; using System.EnterpriseServices;
using UnityEngine;
public partial class StickerSystem using MelonLoader;
{ using UnityEngine.ProBuilder.MeshOperations;
#region Singleton using NAK.Stickers.Integrations;
public static StickerSystem Instance { get; private set; } namespace NAK.Stickers;
public static void Initialize() public partial class StickerSystem
{ {
if (Instance != null) #region Singleton
return;
public static bool RestrictedInstance = false;
Instance = new StickerSystem();
public static StickerSystem Instance { get; private set; }
// configure decalery
DecalManager.SetPreferredMode(DecalUtils.Mode.GPU, false, 0); public static void Initialize()
{
// ensure cache folder exists if (Instance != null)
EnsureStickersFolderExists(); return;
// listen for game events Instance = new StickerSystem();
CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(Instance.OnPlayerSetupStart);
} // configure decalery
DecalManager.SetPreferredMode(DecalUtils.Mode.GPU, false, 0);
#endregion Singleton
// ensure cache folder exists
#region Callback Registration EnsureStickersFolderExists();
private void OnPlayerSetupStart() // listen for game events
{ CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(Instance.OnPlayerSetupStart);
CVRGameEventSystem.World.OnUnload.AddListener(_ => OnWorldUnload());
CVRGameEventSystem.Instance.OnConnected.AddListener((_) => { if (!Instances.IsReconnecting) OnInitialConnection(); }); }
CVRGameEventSystem.Player.OnJoinEntity.AddListener(Instance.OnPlayerJoined); #endregion Singleton
CVRGameEventSystem.Player.OnLeaveEntity.AddListener(Instance.OnPlayerLeft);
SchedulerSystem.AddJob(Instance.OnUpdate, 10f, -1); #region Callback Registration
LoadAllImagesAtStartup();
} private void OnPlayerSetupStart()
{
#endregion Callback Registration CVRGameEventSystem.World.OnUnload.AddListener(_ => OnWorldUnload());
CVRGameEventSystem.World.OnLoad.AddListener(_ => OnWorldLoad());
#region Game Events CVRGameEventSystem.Instance.OnConnected.AddListener((_) => { if (!Instances.IsReconnecting) OnInitialConnection(); });
private void OnInitialConnection() CVRGameEventSystem.Player.OnJoinEntity.AddListener(Instance.OnPlayerJoined);
{ CVRGameEventSystem.Player.OnLeaveEntity.AddListener(Instance.OnPlayerLeft);
ClearStickersSelf(); // clear stickers on remotes just in case we rejoined SchedulerSystem.AddJob(Instance.OnUpdate, 10f, -1);
ModNetwork.Reset(); // reset network buffers and metadata LoadAllImagesAtStartup();
} }
private void OnWorldUnload() #endregion Callback Registration
{
CleanupAllButSelf(); // release all stickers except for self #region Game Events
}
private void OnInitialConnection()
#endregion Game Events {
OnWorldLoad(); //Checks the world again in case the bundle updated.
#region Data ClearStickersSelf(); // clear stickers on remotes just in case we rejoined
ModNetwork.Reset(); // reset network buffers and metadata
// private bool _isEnabled = true; }
//
// public bool IsEnabled private void OnWorldLoad()
// { {
// get => _isEnabled; GameObject StickerWorldRestriction = GameObject.Find("[DisableStickers]");
// set if (StickerWorldRestriction != null)
// { {
// if (_isEnabled == value) RestrictedInstance = true;
// return; MelonLogger.Msg("This is a Restricted Instance");
// }
// _isEnabled = value; else
// if (!_isEnabled) ClearAllStickers(); {
// ModNetwork.IsEnabled = _isEnabled; MelonLogger.Msg("This is NOT a Restricted Instance");
// } }
// } BTKUIAddon.UpdateStickerMenu();
}
private string SelectedStickerName => ModSettings.Hidden_SelectedStickerNames.Value[_selectedStickerSlot];
private void OnWorldUnload()
private const float StickerKillTime = 30f; {
private const float StickerCooldown = 0.2f; RestrictedInstance = false;
private readonly Dictionary<string, StickerData> _playerStickers = new(); CleanupAllButSelf(); // release all stickers except for self
internal const string PlayerLocalId = "_PLAYERLOCAL"; }
private int _selectedStickerSlot; #endregion Game Events
public int SelectedStickerSlot
{ #region Data
get => _selectedStickerSlot;
set // private bool _isEnabled = true;
{ //
_selectedStickerSlot = value < 0 ? ModSettings.MaxStickerSlots - 1 : value % ModSettings.MaxStickerSlots; // public bool IsEnabled
IsInStickerMode = IsInStickerMode; // refresh sticker mode // {
} // get => _isEnabled;
} // set
// {
private bool _isInStickerMode; // if (_isEnabled == value)
public bool IsInStickerMode // return;
{ //
get => _isInStickerMode; // _isEnabled = value;
set // if (!_isEnabled) ClearAllStickers();
{ // ModNetwork.IsEnabled = _isEnabled;
_isInStickerMode = value; // }
if (_isInStickerMode) // }
{
CohtmlHud.Instance.SelectPropToSpawn( private string SelectedStickerName => ModSettings.Hidden_SelectedStickerNames.Value[_selectedStickerSlot];
StickerCache.GetCohtmlResourcesPath(SelectedStickerName),
Path.GetFileNameWithoutExtension(SelectedStickerName), private const float StickerKillTime = 30f;
"Sticker selected for stickering:"); private const float StickerCooldown = 0.2f;
} private readonly Dictionary<string, StickerData> _playerStickers = new();
else internal const string PlayerLocalId = "_PLAYERLOCAL";
{
CohtmlHud.Instance.ClearPropToSpawn(); private int _selectedStickerSlot;
ClearStickerPreview(); public int SelectedStickerSlot
} {
} get => _selectedStickerSlot;
} set
{
#endregion Data _selectedStickerSlot = value < 0 ? ModSettings.MaxStickerSlots - 1 : value % ModSettings.MaxStickerSlots;
IsInStickerMode = IsInStickerMode; // refresh sticker mode
}
}
private bool _isInStickerMode;
public bool IsInStickerMode
{
get => _isInStickerMode;
set
{
_isInStickerMode = value;
if (_isInStickerMode)
{
CohtmlHud.Instance.SelectPropToSpawn(
StickerCache.GetCohtmlResourcesPath(SelectedStickerName),
Path.GetFileNameWithoutExtension(SelectedStickerName),
"Sticker selected for stickering:");
}
else
{
CohtmlHud.Instance.ClearPropToSpawn();
ClearStickerPreview();
}
}
}
#endregion Data
} }

View file

@ -1,190 +1,194 @@
using ABI_RC.Core; using ABI_RC.Core;
using ABI_RC.Core.Player; using ABI_RC.Core.Player;
using ABI_RC.Systems.InputManagement; using ABI_RC.Systems.InputManagement;
using NAK.Stickers.Networking; using NAK.Stickers.Networking;
using UnityEngine; using UnityEngine;
namespace NAK.Stickers; namespace NAK.Stickers;
public partial class StickerSystem public partial class StickerSystem
{ {
#region Sticker Lifecycle #region Sticker Lifecycle
private StickerData GetOrCreateStickerData(string playerId) private StickerData GetOrCreateStickerData(string playerId)
{ {
if (_playerStickers.TryGetValue(playerId, out StickerData stickerData)) if (_playerStickers.TryGetValue(playerId, out StickerData stickerData))
return stickerData; return stickerData;
stickerData = new StickerData(playerId, ModSettings.MaxStickerSlots); stickerData = new StickerData(playerId, ModSettings.MaxStickerSlots);
_playerStickers[playerId] = stickerData; _playerStickers[playerId] = stickerData;
return stickerData; return stickerData;
} }
public void PlaceStickerFromControllerRay(Transform transform, CVRHand hand = CVRHand.Left, bool isPreview = false) public void PlaceStickerFromControllerRay(Transform transform, CVRHand hand = CVRHand.Left, bool isPreview = false)
{ {
Vector3 controllerForward = transform.forward; Vector3 controllerForward = transform.forward;
Vector3 controllerUp = transform.up; Vector3 controllerUp = transform.up;
Vector3 playerUp = PlayerSetup.Instance.transform.up; Vector3 playerUp = PlayerSetup.Instance.transform.up;
// extracting angle of controller ray on forward axis // extracting angle of controller ray on forward axis
Vector3 projectedControllerUp = Vector3.ProjectOnPlane(controllerUp, controllerForward).normalized; Vector3 projectedControllerUp = Vector3.ProjectOnPlane(controllerUp, controllerForward).normalized;
Vector3 projectedPlayerUp = Vector3.ProjectOnPlane(playerUp, controllerForward).normalized; Vector3 projectedPlayerUp = Vector3.ProjectOnPlane(playerUp, controllerForward).normalized;
float angle = Vector3.Angle(projectedControllerUp, projectedPlayerUp); float angle = Vector3.Angle(projectedControllerUp, projectedPlayerUp);
float angleThreshold = ModSettings.Entry_PlayerUpAlignmentThreshold.Value; float angleThreshold = ModSettings.Entry_PlayerUpAlignmentThreshold.Value;
Vector3 targetUp = (angleThreshold != 0f && angle <= angleThreshold) Vector3 targetUp = (angleThreshold != 0f && angle <= angleThreshold)
// leave 0.01% of the controller up vector to prevent issues with alignment on floor & ceiling in Desktop // leave 0.01% of the controller up vector to prevent issues with alignment on floor & ceiling in Desktop
? Vector3.Slerp(controllerUp, playerUp, 0.99f) ? Vector3.Slerp(controllerUp, playerUp, 0.99f)
: controllerUp; : controllerUp;
if (isPreview) if (isPreview)
{ {
PlaceStickerPreview(transform.position, controllerForward, targetUp); PlaceStickerPreview(transform.position, controllerForward, targetUp);
return; return;
} }
if (!PlaceStickerSelf(transform.position, transform.forward, targetUp)) if (!PlaceStickerSelf(transform.position, transform.forward, targetUp))
return; return;
CVRInputManager.Instance.Vibrate(0f, 0.1f, 10f, 0.1f, hand); CVRInputManager.Instance.Vibrate(0f, 0.1f, 10f, 0.1f, hand);
} }
private bool PlaceStickerSelf(Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true) private bool PlaceStickerSelf(Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true)
{ {
if (!AttemptPlaceSticker(PlayerLocalId, position, forward, up, alignWithNormal, SelectedStickerSlot)) if (!AttemptPlaceSticker(PlayerLocalId, position, forward, up, alignWithNormal, SelectedStickerSlot, RestrictedInstance))
return false; // failed return false; // failed
// placed, now network // placed, now network
ModNetwork.SendPlaceSticker(SelectedStickerSlot, position, forward, up); ModNetwork.SendPlaceSticker(SelectedStickerSlot, position, forward, up);
return true; return true;
} }
private bool AttemptPlaceSticker(string playerId, Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true, int stickerSlot = 0, bool isPreview = false) private bool AttemptPlaceSticker(string playerId, Vector3 position, Vector3 forward, Vector3 up, bool alignWithNormal = true, int stickerSlot = 0, bool RestrictedInstance = false, bool isPreview = false)
{ {
StickerData stickerData = GetOrCreateStickerData(playerId); StickerData stickerData = GetOrCreateStickerData(playerId);
if (Time.time - stickerData.LastPlacedTime < StickerCooldown) if (Time.time - stickerData.LastPlacedTime < StickerCooldown)
return false; return false;
// Every layer other than IgnoreRaycast, PlayerLocal, PlayerClone, PlayerNetwork, and UI Internal // Every layer other than IgnoreRaycast, PlayerLocal, PlayerClone, PlayerNetwork, and UI Internal
const int LayerMask = ~((1 << 2) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 15)); const int LayerMask = ~((1 << 2) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 15));
if (!Physics.Raycast(position, forward, out RaycastHit hit, if (!Physics.Raycast(position, forward, out RaycastHit hit,
10f, LayerMask, QueryTriggerInteraction.Ignore)) 10f, LayerMask, QueryTriggerInteraction.Ignore))
return false; return false;
// if gameobject name starts with [NoSticker] then don't place sticker // if gameobject name starts with [NoSticker] then don't place sticker
if (hit.transform.gameObject.name.StartsWith("[NoSticker]")) if (hit.transform.gameObject.name.StartsWith("[NoSticker]"))
return false; return false;
if (isPreview) // if the world contained a gameobject with the [DisableStickers] name and restricted the instance disable stickers!
{ if (RestrictedInstance == true)
stickerData.PlacePreview(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot); return false;
return true;
} if (isPreview)
{
stickerData.Place(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot); stickerData.PlacePreview(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot);
stickerData.PlayAudio(); return true;
return true; }
}
stickerData.Place(hit, alignWithNormal ? -hit.normal : forward, up, stickerSlot);
public void ClearStickersSelf() stickerData.PlayAudio();
{ return true;
ClearStickersForPlayer(PlayerLocalId); }
ModNetwork.SendClearAllStickers();
} public void ClearStickersSelf()
{
public void ClearStickerSelf(int stickerSlot) ClearStickersForPlayer(PlayerLocalId);
{ ModNetwork.SendClearAllStickers();
ClearStickersForPlayer(PlayerLocalId, stickerSlot); }
ModNetwork.SendClearSticker(stickerSlot);
} public void ClearStickerSelf(int stickerSlot)
{
private void ClearStickersForPlayer(string playerId) ClearStickersForPlayer(PlayerLocalId, stickerSlot);
{ ModNetwork.SendClearSticker(stickerSlot);
if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData)) }
return;
private void ClearStickersForPlayer(string playerId)
stickerData.Clear(); {
} if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData))
return;
private void ClearStickersForPlayer(string playerId, int stickerSlot)
{ stickerData.Clear();
if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData)) }
return;
private void ClearStickersForPlayer(string playerId, int stickerSlot)
stickerData.Clear(stickerSlot); {
} if (!_playerStickers.TryGetValue(playerId, out StickerData stickerData))
return;
private void SetTextureSelf(byte[] imageBytes, int stickerSlot = 0)
{ stickerData.Clear(stickerSlot);
Texture2D texture = new(1, 1); // placeholder }
texture.LoadImage(imageBytes);
texture.Compress(true); // noachi said to do private void SetTextureSelf(byte[] imageBytes, int stickerSlot = 0)
{
ClearStickerSelf(stickerSlot); // clear placed stickers in-scene so we can't replace an entire wall at once Texture2D texture = new(1, 1); // placeholder
OnPlayerStickerTextureReceived(PlayerLocalId, Guid.Empty, texture, stickerSlot); texture.LoadImage(imageBytes);
ModNetwork.SetTexture(stickerSlot, imageBytes); texture.Compress(true); // noachi said to do
}
ClearStickerSelf(stickerSlot); // clear placed stickers in-scene so we can't replace an entire wall at once
public void ClearAllStickers() OnPlayerStickerTextureReceived(PlayerLocalId, Guid.Empty, texture, stickerSlot);
{ ModNetwork.SetTexture(stickerSlot, imageBytes);
foreach (StickerData stickerData in _playerStickers.Values) }
stickerData.Clear();
public void ClearAllStickers()
ModNetwork.SendClearAllStickers(); {
} foreach (StickerData stickerData in _playerStickers.Values)
stickerData.Clear();
public void OnPlayerStickerTextureReceived(string playerId, Guid textureHash, Texture2D texture, int stickerSlot = 0)
{ ModNetwork.SendClearAllStickers();
StickerData stickerData = GetOrCreateStickerData(playerId); }
stickerData.SetTexture(textureHash, texture, stickerSlot);
} public void OnPlayerStickerTextureReceived(string playerId, Guid textureHash, Texture2D texture, int stickerSlot = 0)
{
public bool HasTextureHash(string playerId, Guid textureHash) StickerData stickerData = GetOrCreateStickerData(playerId);
{ stickerData.SetTexture(textureHash, texture, stickerSlot);
StickerData stickerData = GetOrCreateStickerData(playerId); }
return stickerData.CheckHasTextureHash(textureHash);
} public bool HasTextureHash(string playerId, Guid textureHash)
{
public void CleanupAll() StickerData stickerData = GetOrCreateStickerData(playerId);
{ return stickerData.CheckHasTextureHash(textureHash);
foreach ((_, StickerData data) in _playerStickers) }
data.Cleanup();
public void CleanupAll()
_playerStickers.Clear(); {
} foreach ((_, StickerData data) in _playerStickers)
data.Cleanup();
public void CleanupAllButSelf()
{ _playerStickers.Clear();
StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); }
foreach ((_, StickerData data) in _playerStickers) public void CleanupAllButSelf()
{ {
if (data == localStickerData) data.Clear(); StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId);
else data.Cleanup();
} foreach ((_, StickerData data) in _playerStickers)
{
_playerStickers.Clear(); if (data == localStickerData) data.Clear();
_playerStickers[PlayerLocalId] = localStickerData; else data.Cleanup();
} }
public void PlaceStickerPreview(Vector3 position, Vector3 forward, Vector3 up) _playerStickers.Clear();
{ _playerStickers[PlayerLocalId] = localStickerData;
AttemptPlaceSticker(PlayerLocalId, position, forward, up, true, SelectedStickerSlot, true); }
}
public void PlaceStickerPreview(Vector3 position, Vector3 forward, Vector3 up)
public void UpdateStickerPreview() {
{ AttemptPlaceSticker(PlayerLocalId, position, forward, up, true, SelectedStickerSlot, true);
if (!IsInStickerMode) return; }
StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); public void UpdateStickerPreview()
localStickerData.UpdatePreview(SelectedStickerSlot); {
} if (!IsInStickerMode) return;
public void ClearStickerPreview() StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId);
{ localStickerData.UpdatePreview(SelectedStickerSlot);
StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId); }
localStickerData.ClearPreview();
} public void ClearStickerPreview()
{
#endregion Sticker Lifecycle StickerData localStickerData = GetOrCreateStickerData(PlayerLocalId);
} localStickerData.ClearPreview();
}
#endregion Sticker Lifecycle
}