241 lines
8.6 KiB
C#
241 lines
8.6 KiB
C#
using BoneSync.Data;
|
|
using BoneSync.Networking;
|
|
using BoneSync.Networking.Messages;
|
|
using BoneSync.Patching;
|
|
using Facepunch.Steamworks;
|
|
using MelonLoader;
|
|
using StressLevelZero.Interaction;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
namespace BoneSync.Sync.Components
|
|
{
|
|
public partial class Syncable : MonoBehaviour
|
|
{
|
|
private HashSet<int> patchedButtonToggles = new HashSet<int>();
|
|
private bool pullDevicePatched = false;
|
|
|
|
bool ButtonOnPress(ButtonToggle toggle)
|
|
{
|
|
SyncLogger.Msg("ButtonToggle:OnPress " + toggle.transform.GetPath());
|
|
byte index = (byte)Array.IndexOf(buttonToggles, toggle);
|
|
RegisterSyncable();
|
|
if (!Registered) return false;
|
|
if (!isOwner) return false;
|
|
_SendSimpleEvent(SimpleEventType.OnButtonPress, index);
|
|
return true;
|
|
}
|
|
bool ButtonOnRelease(ButtonToggle toggle)
|
|
{
|
|
SyncLogger.Msg("ButtonToggle:OnRelease " + toggle.transform.GetPath());
|
|
byte index = (byte)Array.IndexOf(buttonToggles, toggle);
|
|
RegisterSyncable();
|
|
if (!Registered) return false;
|
|
if (!isOwner) return false;
|
|
_SendSimpleEvent(SimpleEventType.OnButtonRelease, index);
|
|
return true;
|
|
}
|
|
|
|
void DeviceOnPull()
|
|
{
|
|
if (!isOwner) { return; }
|
|
_SendSimpleEvent(SimpleEventType.OnDevicePull);
|
|
}
|
|
void DeviceOnRelease()
|
|
{
|
|
if (!isOwner) { return; }
|
|
_SendSimpleEvent(SimpleEventType.OnDeviceRelease);
|
|
}
|
|
|
|
private void TryPatchUnityEvents()
|
|
{
|
|
try
|
|
{
|
|
_TryPatchPullDevice();
|
|
foreach (ButtonToggle buttonToggle in GetComponentsInChildren<ButtonToggle>())
|
|
{
|
|
_TryPatchButtonToggle(buttonToggle);
|
|
}
|
|
} catch (Exception e)
|
|
{
|
|
SyncLogger.Error("Failed to patch UnityEvents: " + e);
|
|
}
|
|
}
|
|
|
|
private void _TryPatchPullDevice()
|
|
{
|
|
if (pullDevicePatched) return;
|
|
if (!pullDevice) return;
|
|
//pullDevice.OnHandlePull.AddListener((UnityAction)DeviceOnPull);
|
|
//pullDevice.OnHandleReturn.AddListener((UnityAction)DeviceOnRelease);
|
|
|
|
pullDevicePatched = true;
|
|
}
|
|
|
|
private void _TryPatchButtonToggle(ButtonToggle buttonToggle)
|
|
{
|
|
if (patchedButtonToggles.Contains(buttonToggle.GetHashCode())) return;
|
|
SyncLogger.Msg("Patching ButtonToggle: " + buttonToggle.transform.GetPath());
|
|
//buttonToggle.onPress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnPress(btn), buttonToggle);
|
|
//buttonToggle.onDepress.AddListenerWithArgs<ButtonToggle>((btn, args) => ButtonOnRelease(btn), buttonToggle);
|
|
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onPress, ButtonOnPress);
|
|
UnityEventPatch<ButtonToggle>.Patch(buttonToggle, buttonToggle.onDepress, ButtonOnRelease);
|
|
|
|
patchedButtonToggles.Add(buttonToggle.GetHashCode());
|
|
}
|
|
|
|
public bool AllRigidbodiesSleeping()
|
|
{
|
|
if (rigidbodies.Length == 0) return false;
|
|
foreach (Rigidbody rb in rigidbodies)
|
|
{
|
|
try
|
|
{
|
|
if (!rb.IsSleeping()) return false;
|
|
}
|
|
catch { } // ignore null rigidbodies
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void _SetKinematic(bool kinematic)
|
|
{
|
|
if (rigidbodies.Length == 0) return;
|
|
foreach (Rigidbody rb in rigidbodies)
|
|
{
|
|
try
|
|
{
|
|
rb.isKinematic = kinematic;
|
|
}
|
|
catch { } // ignore null rigidbodies
|
|
}
|
|
}
|
|
private void SetKinematic(bool kinematic)
|
|
{
|
|
if (!this) return;
|
|
try
|
|
{
|
|
_SetKinematic(kinematic);
|
|
}
|
|
catch {
|
|
SyncLogger.Warning("Failed to set kinematic");
|
|
}
|
|
}
|
|
|
|
public ObjectSyncTransform[] GetObjectSyncTransforms()
|
|
{
|
|
ObjectSyncTransform[] objectSyncTransforms = new ObjectSyncTransform[rigidbodies.Length];
|
|
for (int i = 0; i < _transforms.Length; i++)
|
|
{
|
|
objectSyncTransforms[i] = new ObjectSyncTransform()
|
|
{
|
|
transform = new SimpleSyncTransform(_transforms[i]),
|
|
velocity = Vector3.zero
|
|
};
|
|
}
|
|
return objectSyncTransforms;
|
|
}
|
|
|
|
public void ApplyObjectSyncTransforms(ObjectSyncTransform[] objectSyncTransforms)
|
|
{
|
|
if (IsPlugged()) { return; }
|
|
if (objectSyncTransforms.Length != rigidbodies.Length)
|
|
{
|
|
SyncLogger.Warning("ObjectSyncTransforms length mismatch: " + objectSyncTransforms.Length + " != " + _transforms.Length);
|
|
return;
|
|
}
|
|
for (int i = 0; i < objectSyncTransforms.Length; i++)
|
|
{
|
|
ObjectSyncTransform objectSyncTransform = objectSyncTransforms[i];
|
|
rigidbodies[i].angularVelocity = objectSyncTransform.angularVelocity;
|
|
rigidbodies[i].velocity = objectSyncTransform.velocity;
|
|
rigidbodies[i].position = objectSyncTransform.transform.position;
|
|
rigidbodies[i].rotation = objectSyncTransform.transform.rotation;
|
|
_transforms[i].localScale = objectSyncTransform.transform.scale;
|
|
//_transforms[i].ApplySimpleTransform(objectSyncTransform.transform);
|
|
}
|
|
}
|
|
|
|
private Syncable GetRigidbodySyncable(Rigidbody rigidbody)
|
|
{
|
|
if (rigidbody == null) return null;
|
|
return rigidbody.GetComponentInParent<Syncable>();
|
|
}
|
|
|
|
private bool RigidbodyBelongsToSyncable(Rigidbody rigidbody)
|
|
{
|
|
return GetRigidbodySyncable(rigidbody) == this;
|
|
}
|
|
|
|
private Rigidbody[] GetRigidbodies()
|
|
{
|
|
if (interactableManager)
|
|
{
|
|
return interactableManager.hosts.Select(host => host.rb).ToArray();
|
|
}
|
|
if (interactableHost)
|
|
{
|
|
return new Rigidbody[] { interactableHost.rb };
|
|
}
|
|
if (poolee)
|
|
{
|
|
return new Rigidbody[] { poolee.GetComponentInChildren<Rigidbody>(true) };
|
|
}
|
|
|
|
return new Rigidbody[0];
|
|
}
|
|
|
|
private void UpdateTransformList()
|
|
{
|
|
// get non-null rigidbodies
|
|
Rigidbody[] rbs = GetRigidbodies().Where(rb => rb != null).ToArray();
|
|
rigidbodies = rbs;
|
|
_transforms = rbs.Select(rb => rb.transform).ToArray();
|
|
}
|
|
|
|
private void UpdateKinematic()
|
|
{
|
|
//SetKinematic(false);
|
|
SetKinematic(_ownerId != BoneSync.lobby.GetLocalId() && Registered && !IsPlugged());
|
|
}
|
|
|
|
internal void OnSimpleSyncableEvent(SimpleSyncableEvent eventData)
|
|
{
|
|
SyncLogger.Msg("OnSimpleSyncableEvent: " + eventData.eventType);
|
|
SimpleEventType eType = eventData.eventType;
|
|
byte index = eventData.index;
|
|
byte len = eventData.length;
|
|
switch (eType) {
|
|
case SimpleEventType.OnDevicePull:
|
|
pullDevice?.OnHandlePull?.BypassPatchInvoke();
|
|
break;
|
|
case SimpleEventType.OnDeviceRelease:
|
|
pullDevice?.OnHandleReturn?.BypassPatchInvoke();
|
|
break;
|
|
case SimpleEventType.OnButtonPress:
|
|
if (len != eventData.length) { SyncLogger.Warning("ButtonPress length mismatch: " + len + " != " + eventData.length); }
|
|
if (index < buttonToggles.Length)
|
|
{
|
|
buttonToggles[index]?.onPress.BypassPatchInvoke();
|
|
}
|
|
break;
|
|
case SimpleEventType.OnButtonRelease:
|
|
if (len != eventData.length) { SyncLogger.Warning("ButtonPress length mismatch: " + len + " != " + eventData.length); }
|
|
if (index < buttonToggles.Length)
|
|
{
|
|
buttonToggles[index]?.onDepress.BypassPatchInvoke();
|
|
}
|
|
break;
|
|
|
|
|
|
}
|
|
}
|
|
// on collision
|
|
}
|
|
}
|