network stuff

This commit is contained in:
Aaro Varis
2025-03-02 11:45:15 +02:00
parent 055ee44da5
commit fc744fd1ab
12 changed files with 162 additions and 19 deletions

View File

@@ -85,11 +85,13 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Networking\Messages\DiscardSyncableMessage.cs" />
<Compile Include="Networking\Messages\ObjectAttributeMessage.cs" />
<Compile Include="Networking\Messages\ObjectDamageMessage.cs" />
<Compile Include="Networking\Messages\ObjectSyncMessage.cs" />
<Compile Include="Networking\Messages\OwnershipTransferMessage.cs" />
<Compile Include="Networking\Messages\RegisterSyncableMessage.cs" />
<Compile Include="Patching\CallPatchedMethod.cs" />
<Compile Include="Patching\GripPatches.cs" />
<Compile Include="Patching\InteractableHostPatches.cs" />
<Compile Include="Patching\ObjectHealthPatches.cs" />
<Compile Include="Sync\Components\SyncableBase.cs" />

View File

@@ -8,6 +8,40 @@ using System.Threading.Tasks;
namespace BoneSync.Networking
{
public static class BitPacking
{
public static byte[] PackBits(bool[] bits)
{
int byteCount = bits.Length / 8;
if (bits.Length % 8 != 0)
{
byteCount++;
}
byte[] bytes = new byte[byteCount];
for (int i = 0; i < bits.Length; i++)
{
int byteIndex = i / 8;
int bitIndex = i % 8;
if (bits[i])
{
bytes[byteIndex] |= (byte)(1 << bitIndex);
}
}
return bytes;
}
public static bool[] UnpackBits(byte[] bytes, int bitCount)
{
bool[] bits = new bool[bitCount];
for (int i = 0; i < bitCount; i++)
{
int byteIndex = i / 8;
int bitIndex = i % 8;
bits[i] = (bytes[byteIndex] & (1 << bitIndex)) != 0;
}
return bits;
}
}
internal class ByteEncoder
{
public List<byte> Data;
@@ -203,5 +237,19 @@ namespace BoneSync.Networking
}
return matrix;
}
public void WriteBoolArray(bool[] array)
{
byte[] bytes = BitPacking.PackBits(array);
WriteByte((byte)bytes.Length);
WriteBytes(bytes);
}
public bool[] ReadBoolArray()
{
byte length = ReadByte();
byte[] bytes = ReadBytes(length);
return BitPacking.UnpackBits(bytes, length);
}
}
}

View File

@@ -10,7 +10,7 @@ namespace BoneSync.Networking.Messages
{
public struct DiscardSyncableMessageData
{
public ushort syncableId;
public ushort syncId;
}
[PacketType(PacketType.DiscardSyncable), PacketReliability(PacketReliability.ReliableFast)]
internal class DiscardSyncableMessage : NetworkMessage
@@ -20,18 +20,18 @@ namespace BoneSync.Networking.Messages
public DiscardSyncableMessage(DiscardSyncableMessageData discardSyncableMessageData)
{
_data = discardSyncableMessageData;
byteEncoder.WriteUShort(_data.syncableId);
byteEncoder.WriteUShort(_data.syncId);
}
public DiscardSyncableMessage(Packet packet)
{
byteEncoder.WriteBytes(packet.Data);
_data.syncableId = byteEncoder.ReadUShort();
_data.syncId = byteEncoder.ReadUShort();
}
public override void Execute()
{
Syncable syncable = ObjectSyncCache.GetSyncable(_data.syncableId);
Syncable syncable = ObjectSyncCache.GetSyncable(_data.syncId);
if (syncable != null)
{
syncable.DiscardSyncable(true);

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BoneSync.Networking.Messages
{
public struct ObjectMagazineData
{
public byte ammoCount;
}
public struct ObjectAttributeMessageData
{
public ushort syncId;
public bool[] _attributes;
public ObjectMagazineData? magazineData;
}
internal class ObjectAttributeMessage : NetworkMessage
{
private ObjectAttributeMessageData _data;
public ObjectAttributeMessage(ObjectAttributeMessageData objectAttributeMessageData)
{
List<bool> attributes = new List<bool>();
_data = objectAttributeMessageData;
byteEncoder.WriteUShort(_data.syncId);
attributes.Add(_data.magazineData != null);
if (_data.magazineData != null)
{
byteEncoder.WriteByte(_data.magazineData.Value.ammoCount);
}
_data._attributes = attributes.ToArray();
}
public ObjectAttributeMessage(Packet packet)
{
byteEncoder.WriteBytes(packet.Data);
_data.syncId = byteEncoder.ReadUShort();
_data._attributes = byteEncoder.ReadBoolArray();
if (_data._attributes[0])
{
_data.magazineData = new ObjectMagazineData()
{
ammoCount = byteEncoder.ReadByte(),
};
}
}
}
}

View File

@@ -41,7 +41,7 @@ namespace BoneSync.Networking.Messages
public ObjectHealthInfo objectHealthInfo;
}
[PacketType(PacketType.ObjectEvent), PacketReliability(PacketReliability.Unreliable)]
[PacketType(PacketType.ObjectEvent), PacketReliability(PacketReliability.Unreliable), PacketCatchup(4)]
public class ObjectDamageMessage : NetworkMessage
{
public ObjectDamageInfo objectEventInfo => _objectEventInfo;

View File

@@ -9,19 +9,19 @@ namespace BoneSync.Networking.Messages
{
public struct OwnershipTransferMessageData
{
public ushort SyncId;
public ushort syncId;
public bool force;
public ulong NewOwnerId;
}
[PacketType(PacketType.ObjectOwnership), PacketReliability(PacketReliability.ReliableFast)]
[PacketType(PacketType.ObjectOwnership), PacketReliability(PacketReliability.ReliableFast), PacketCatchup(2)]
internal class OwnershipTransferMessage : NetworkMessage
{
private OwnershipTransferMessageData Data;
public OwnershipTransferMessage(OwnershipTransferMessageData data)
{
Data = data;
byteEncoder.WriteUShort(Data.SyncId);
byteEncoder.WriteUShort(Data.syncId);
byteEncoder.WriteULong(Data.NewOwnerId);
byteEncoder.WriteBool(Data.force);
}
@@ -29,14 +29,14 @@ namespace BoneSync.Networking.Messages
public OwnershipTransferMessage(Packet packet)
{
byteEncoder.WriteBytes(packet.Data);
Data.SyncId = byteEncoder.ReadUShort();
Data.syncId = byteEncoder.ReadUShort();
Data.NewOwnerId = byteEncoder.ReadULong();
Data.force = byteEncoder.ReadBool();
}
override public void Execute()
{
ObjectSync.OnOwnershipChangeMessage(Data.SyncId, Data.NewOwnerId, Data.force);
ObjectSync.OnOwnershipChangeMessage(Data.syncId, Data.NewOwnerId, Data.force);
}
}

View File

@@ -29,7 +29,7 @@ namespace BoneSync.Networking.Messages
public SpawnPoolableInfo? spawnInfo;
}
[PacketType(PacketType.RegisterSyncable), PacketReliability(PacketReliability.ReliableFast)]
[PacketType(PacketType.RegisterSyncable), PacketReliability(PacketReliability.ReliableFast), PacketCatchup(0)]
internal class RegisterSyncableMessage : NetworkMessage
{
private RegisterSyncableInfo _info;

View File

@@ -33,6 +33,15 @@ namespace BoneSync.Networking
public PacketReliability reliability { get; }
}
public class PacketCatchupAttribute : Attribute
{
public int order { get; }
public PacketCatchupAttribute(int order = 1)
{
this.order = order;
}
}
public abstract class NetworkMessage
{
public ulong senderId

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoneSync.Sync;
using HarmonyLib;
using StressLevelZero.Interaction;
namespace BoneSync.Patching
{
[HarmonyPatch(typeof(ForcePullGrip))]
internal class ForcePullGripPatches
{
[HarmonyPatch(nameof(ForcePullGrip.Pull)), HarmonyPostfix]
public static void OnEnablePatch(ForcePullGrip __instance)
{
MelonLoader.MelonLogger.Msg("ForcePullGrip.Pull: " + __instance.name);
ObjectSync.MakeOrGetSyncable(__instance.gameObject);
}
}
}

View File

@@ -23,12 +23,13 @@ namespace BoneSync.Patching
private static bool TakeDamagePatch(ObjectDestructable __instance, ref Vector3 normal, ref float damage, ref bool crit, ref AttackType attackType)
{
if (CallPatchedMethods.allowPatchedMethodCall) return true;
if (damage < 0.05f) return true; // ignore small damage (e.g. a little bit of fall damage)
MelonLoader.MelonLogger.Msg("ObjectDestructable.TakeDamage: " + damage);
Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance.gameObject);
if (syncable != null)
{
if (damage > 0.5f) syncable.RegisterSyncable();
if (!syncable.isOwner) return true;
if (damage > 0.5f) syncable.RegisterSyncable(); // register syncable if damage is very significant, e.g. a bullet hit
if (!syncable.isOwner) return false;
MelonLoader.MelonLogger.Msg("Patch: ObjectDestructable.TakeDamage: " + damage + " " + syncable.gameObject.name);
ObjectHealthInfo objectHealthInfo = new ObjectHealthInfo(__instance._health, __instance._hits, normal, damage, crit, attackType);

View File

@@ -60,7 +60,7 @@ namespace BoneSync.Sync.Components
{
DiscardSyncableMessageData discardSyncableMessageData = new DiscardSyncableMessageData()
{
syncableId = _syncId
syncId = _syncId
};
DiscardSyncableMessage discardSyncableMessage = new DiscardSyncableMessage(discardSyncableMessageData);
discardSyncableMessage.Broadcast();
@@ -73,7 +73,7 @@ namespace BoneSync.Sync.Components
MelonLogger.Msg("Sending ownership transfer for " + _syncId + " to " + newOwnerId);
OwnershipTransferMessageData data = new OwnershipTransferMessageData()
{
SyncId = _syncId,
syncId = _syncId,
NewOwnerId = newOwnerId,
force = true
};
@@ -90,7 +90,7 @@ namespace BoneSync.Sync.Components
MelonLogger.Msg("Attempting to become owner of " + _syncId);
OwnershipTransferMessageData data = new OwnershipTransferMessageData()
{
SyncId = _syncId,
syncId = _syncId,
NewOwnerId = BoneSync.lobby.GetLocalId(),
force = false
};

View File

@@ -105,6 +105,11 @@ namespace BoneSync.Sync
//Scene scene = gameObject.scene;
//MelonLogger.Msg("Making or getting syncable for: " + gameObject.name + " in scene: " + scene.name);
Syncable parentSyncable = gameObject.transform.parent.GetComponentInParent<Syncable>();
if (parentSyncable != null)
{
return parentSyncable;
}
Syncable syncable = gameObject.GetComponent<Syncable>();
@@ -128,7 +133,7 @@ namespace BoneSync.Sync
return syncable;
}
public static Syncable GetSyncableFromCache(GameObject gameObject)
private static Syncable _GetSyncableFromCache(GameObject gameObject)
{
bool success = Syncable.syncablesCache.TryGetValue(gameObject, out Syncable syncable);
if (!success)
@@ -140,7 +145,7 @@ namespace BoneSync.Sync
public static Syncable MakeOrGetSyncable(GameObject gameObject)
{
Syncable syncable = GetSyncableFromCache(gameObject);
Syncable syncable = _GetSyncableFromCache(gameObject);
if (syncable == null)
{
syncable = _MakeOrGetSyncable(gameObject);