mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 06:19:22 +00:00
Don't send AAS while switching avatar. This should mean I am less likely to load into the wrong states while switching if others load me faster. This does mean though that it is more likely that remote users will apply null buffers forcing all 0/false instead of garbage aas, but its at least kind of a mitigation. There is a possibility syncing garbage data is better than syncing nothing at all, as that does give the chance to apply settings that don't immediatly load in naked. This just requires testing...
134 lines
No EOL
5.3 KiB
C#
134 lines
No EOL
5.3 KiB
C#
using ABI.CCK.Components;
|
|
using ABI_RC.Core.Player;
|
|
using UnityEngine;
|
|
|
|
namespace NAK.Melons.AASBufferFix
|
|
{
|
|
public class AASBufferHelper : MonoBehaviour
|
|
{
|
|
///public bool DebuggingFlag = false;
|
|
|
|
//public stuff
|
|
public bool GameHandlesAAS { get; private set; }
|
|
|
|
//internal references
|
|
private PuppetMaster _puppetMaster;
|
|
|
|
//outside aas buffers
|
|
private float[] _aasBufferFloat = new float[0];
|
|
private int[] _aasBufferInt = new int[0];
|
|
private byte[] _aasBufferByte = new byte[0];
|
|
|
|
//calculated footprints
|
|
private int _aasFootprint = -1;
|
|
private int _avatarFootprint = 0;
|
|
|
|
private void Start() => _puppetMaster = GetComponent<PuppetMaster>();
|
|
|
|
public void OnAvatarInstantiated(Animator animator)
|
|
{
|
|
//check if avatar uses Avatar Advanced Settings
|
|
///SendDebug("[OnInit] Remote avatar initialized. Checking for AAS...");
|
|
CVRAvatar avatar = animator.GetComponent<CVRAvatar>();
|
|
if (avatar != null && !avatar.avatarUsesAdvancedSettings)
|
|
{
|
|
GameHandlesAAS = true;
|
|
return;
|
|
}
|
|
|
|
//check if AAS footprint is valid
|
|
///SendDebug("[OnInit] Avatar uses AAS. Generating AAS footprint...");
|
|
_avatarFootprint = Utils.GenerateAnimatorAASFootprint(animator);
|
|
if (_avatarFootprint == 1)
|
|
{
|
|
// we will let the game handle this by setting GameHandlesAAS to true
|
|
///SendDebug("[OnInit] Avatar does not contain valid AAS. It is likely hidden or blocked.");
|
|
GameHandlesAAS = true;
|
|
return;
|
|
}
|
|
|
|
///SendDebug($"[OnInit] Avatar footprint is : {_avatarFootprint}");
|
|
|
|
//check if we received expected AAS while we loaded the avatar, and if so, apply it now
|
|
if (SyncDataMatchesExpected())
|
|
{
|
|
///SendDebug("[OnInit] Valid buffered AAS found. Applying buffer...");
|
|
ApplyExternalAASBuffer();
|
|
return;
|
|
}
|
|
|
|
//we loaded avatar faster than wearer
|
|
///SendDebug("[OnInit] Remote avatar initialized faster than wearer. Waiting on valid AAS...");
|
|
}
|
|
|
|
public void OnAvatarDestroyed()
|
|
{
|
|
GameHandlesAAS = false;
|
|
_aasFootprint = -1;
|
|
_avatarFootprint = 0;
|
|
}
|
|
|
|
public void OnReceiveAAS(float[] settingsFloat, int[] settingsInt, byte[] settingsByte)
|
|
{
|
|
// Calculate AAS footprint to compare against.
|
|
_aasFootprint = (settingsFloat.Length + 1) * (settingsInt.Length + 1) * (settingsByte.Length + 1);
|
|
|
|
//if it matches, apply the settings and let game take over
|
|
if (SyncDataMatchesExpected())
|
|
{
|
|
///SendDebug("[OnSync] Avatar values matched and have been applied.");
|
|
ApplyExternalAAS(settingsFloat, settingsInt, settingsByte);
|
|
return;
|
|
}
|
|
|
|
//avatar is still loading on our side, we must assume AAS data is correct and store it until we load
|
|
//there is also a chance it errored
|
|
//if (_avatarFootprint == 0)
|
|
//{
|
|
// ///SendDebug("[OnSync] Avatar is still loading on our end.");
|
|
// StoreExternalAASBuffer(settingsFloat, settingsInt, settingsByte);
|
|
// return;
|
|
//}
|
|
|
|
//avatar is loaded on our end, and is not blocked by filter
|
|
//this does run if it is manually hidden or distance hidden
|
|
|
|
///SendDebug("[OnSync] Avatar is loaded on our side and is not blocked. Comparing for expected values.");
|
|
///SendDebug($"[OnSync] Avatar Footprint is : {_avatarFootprint}");
|
|
|
|
//if it did not match, that means the avatar we see on our side is different than what the remote user is wearing and syncing
|
|
///SendDebug("[OnSync] Avatar loaded is different than wearer. The wearer is likely still loading the avatar!");
|
|
StoreExternalAASBuffer(settingsFloat, settingsInt, settingsByte);
|
|
}
|
|
|
|
private void ApplyExternalAASBuffer()
|
|
{
|
|
GameHandlesAAS = true;
|
|
_puppetMaster?.ApplyAdvancedAvatarSettings(_aasBufferFloat, _aasBufferInt, _aasBufferByte);
|
|
}
|
|
|
|
private void ApplyExternalAAS(float[] settingsFloat, int[] settingsInt, byte[] settingsByte)
|
|
{
|
|
GameHandlesAAS = true;
|
|
_puppetMaster?.ApplyAdvancedAvatarSettings(settingsFloat, settingsInt, settingsByte);
|
|
}
|
|
|
|
private void StoreExternalAASBuffer(float[] settingsFloat, int[] settingsInt, byte[] settingsByte)
|
|
{
|
|
Array.Resize(ref _aasBufferFloat, settingsFloat.Length);
|
|
Array.Resize(ref _aasBufferInt, settingsInt.Length);
|
|
Array.Resize(ref _aasBufferByte, settingsByte.Length);
|
|
Array.Copy(settingsFloat, _aasBufferFloat, settingsFloat.Length);
|
|
Array.Copy(settingsInt, _aasBufferInt, settingsInt.Length);
|
|
Array.Copy(settingsByte, _aasBufferByte, settingsByte.Length);
|
|
}
|
|
|
|
private bool SyncDataMatchesExpected() => _aasFootprint == _avatarFootprint;
|
|
|
|
///private void SendDebug(string message)
|
|
///{
|
|
/// if (!DebuggingFlag) return;
|
|
/// AASBufferFix.Logger.Msg(message);
|
|
///}
|
|
}
|
|
} |