network stuff
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
56
BoneSync/Networking/Messages/ObjectAttributeMessage.cs
Normal file
56
BoneSync/Networking/Messages/ObjectAttributeMessage.cs
Normal 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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
22
BoneSync/Patching/GripPatches.cs
Normal file
22
BoneSync/Patching/GripPatches.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -105,7 +105,12 @@ 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>();
|
||||
|
||||
// delete all sub syncables
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user