diff --git a/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs b/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs index 86ce8b3..b4cd62e 100644 --- a/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs +++ b/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs @@ -32,7 +32,9 @@ public enum EngineNetworkVersionHistory HISTORY_REPMOVE_SERVERFRAME_AND_HANDLE = 25, // Bump version to support serialization changes to RepMove so we can get the serverframe and physics handle associated with the object HISTORY_21_AND_VIEWPITCH_ONLY_DO_NOT_USE = 26, // Bump version to support up to history 21 + HISTORY_PAWN_REMOTEVIEWPITCH. DO NOT USE!!! HISTORY_PLACEHOLDER = 27, // Bump version to a placeholder. This version is the same as HISTORY_REPMOVE_SERVERFRAME_AND_HANDLE - HISTORY_RUNTIME_FEATURES_COMPATIBILITY = 28, // Bump version to add network runtime feature compatibility test to handshake (hello/upgrade) control messages + HISTORY_RUNTIME_FEATURES_COMPATIBILITY = 28, // Bump version to add network runtime feature compatibility test to handshake (hello/upgrade) control messages + HISTORY_SOFTOBJECTPTR_NETGUIDS = 29, // Bump version to support replicating SoftObjectPtrs by NetGuid instead of raw strings. + HISTORY_SUBOBJECT_DESTROY_FLAG = 30, // Bump version to support subobject destruction message flags HISTORY_ENGINENETVERSION_PLUS_ONE, LATEST = HISTORY_ENGINENETVERSION_PLUS_ONE - 1, diff --git a/src/Unreal.Core/ReplayReader.cs b/src/Unreal.Core/ReplayReader.cs index 0ef0233..4e257ae 100644 --- a/src/Unreal.Core/ReplayReader.cs +++ b/src/Unreal.Core/ReplayReader.cs @@ -359,7 +359,7 @@ public virtual void ReadReplayData(FArchive archive, int fallbackChunkSize) { info.Start = archive.ReadUInt32(); info.End = archive.ReadUInt32(); - info.Length = (int)archive.ReadUInt32(); + info.Length = (int) archive.ReadUInt32(); } else { @@ -816,7 +816,7 @@ public virtual void ReadDemoFrameIntoPlaybackPackets(FArchive archive) if (skipExternalOffset > 0) { // ignore it for now - archive.SkipBytes((int)skipExternalOffset); + archive.SkipBytes((int) skipExternalOffset); } // else skip externalOffset } @@ -1247,7 +1247,7 @@ public virtual void ProcessBunch(DataBunch bunch) continue; } - bunch.Archive.SetTempEnd((int)payload, FBitArchiveEndIndex.CONTENT_BLOCK_PAYLOAD); + bunch.Archive.SetTempEnd((int) payload, FBitArchiveEndIndex.CONTENT_BLOCK_PAYLOAD); try { @@ -1325,7 +1325,7 @@ public virtual bool ReceivedReplicatorBunch(DataBunch bunch, FBitArchive archive continue; } - archive.SetTempEnd((int)payload, FBitArchiveEndIndex.FIELD_HEADER_PAYLOAD); + archive.SetTempEnd((int) payload, FBitArchiveEndIndex.FIELD_HEADER_PAYLOAD); try { if (fieldCache == null) @@ -1691,7 +1691,7 @@ public virtual bool ReceiveProperties(FBitArchive archive, NetFieldExportGroup g hasdata = true; try { - _cmdReader.FillBuffer(archive.ReadBits(numBits), (int)numBits); + _cmdReader.FillBuffer(archive.ReadBits(numBits), (int) numBits); if (!_netFieldParser.ReadField(exportGroup, export, handle, group, _cmdReader)) { // Set field incompatible since we couldnt (or didnt want to) parse it. @@ -1706,7 +1706,7 @@ public virtual bool ReceiveProperties(FBitArchive archive, NetFieldExportGroup g #if DEBUG Debug("failed-properties", $"Property {export.Name} (handle: {handle}, path: {group.PathName}) caused error when reading (bits: {numBits}, group: {group.PathName})"); _cmdReader.Reset(); - Debug($"cmd-{export.Name}-{numBits}", "cmds", _cmdReader.ReadBytes(Math.Max((int)Math.Ceiling(_cmdReader.GetBitsLeft() / 8.0), 1))); + Debug($"cmd-{export.Name}-{numBits}", "cmds", _cmdReader.ReadBytes(Math.Max((int) Math.Ceiling(_cmdReader.GetBitsLeft() / 8.0), 1))); #endif continue; } @@ -1719,7 +1719,7 @@ public virtual bool ReceiveProperties(FBitArchive archive, NetFieldExportGroup g #if DEBUG Debug("failed-properties", $"Property {export.Name} (handle: {handle}, path: {group.PathName}) didnt read proper number of bits: {(_cmdReader.LastBit - _cmdReader.GetBitsLeft())} out of {numBits}"); _cmdReader.Reset(); - Debug($"cmd-{export.Name}-{numBits}", "cmds", _cmdReader.ReadBytes(Math.Max((int)Math.Ceiling(_cmdReader.GetBitsLeft() / 8.0), 1))); + Debug($"cmd-{export.Name}-{numBits}", "cmds", _cmdReader.ReadBytes(Math.Max((int) Math.Ceiling(_cmdReader.GetBitsLeft() / 8.0), 1))); #endif continue; } @@ -1759,7 +1759,7 @@ public virtual bool ReadFieldHeaderAndPayload(FBitArchive archive, NetFieldExpor } // const int32 NetFieldExportHandle = Bunch.ReadInt(FMath::Max(NetFieldExportGroup->NetFieldExports.Num(), 2)); - var netFieldExportHandle = archive.ReadSerializedInt(Math.Max((int)group.NetFieldExportsLength, 2)); + var netFieldExportHandle = archive.ReadSerializedInt(Math.Max((int) group.NetFieldExportsLength, 2)); if (archive.IsError) { payload = null; @@ -1769,7 +1769,7 @@ public virtual bool ReadFieldHeaderAndPayload(FBitArchive archive, NetFieldExpor } // const FNetFieldExport& NetFieldExport = NetFieldExportGroup->NetFieldExports[NetFieldExportHandle]; - outField = group.NetFieldExports[(int)netFieldExportHandle]; + outField = group.NetFieldExports[(int) netFieldExportHandle]; payload = archive.ReadIntPacked(); if (archive.IsError) @@ -1780,7 +1780,7 @@ public virtual bool ReadFieldHeaderAndPayload(FBitArchive archive, NetFieldExpor return false; } - if (!archive.CanRead((int)payload)) + if (!archive.CanRead((int) payload)) { payload = null; return false; @@ -1834,10 +1834,35 @@ public virtual bool ReadFieldHeaderAndPayload(FBitArchive archive, NetFieldExpor return netGuid.Value; } - // Serialize the class in case we have to spawn it. - var classNetGUID = InternalLoadObject(bunch.Archive, false); + var bDeleteSubObject = false; + var bSerializeClass = true; - if (!classNetGUID.IsValid()) + if (bunch.Archive.EngineNetworkVersion >= EngineNetworkVersionHistory.HISTORY_SUBOBJECT_DESTROY_FLAG) + { + var bIsDestroyMessage = bunch.Archive.ReadBit(); + if (bIsDestroyMessage) + { + bDeleteSubObject = true; + bSerializeClass = false; + + var destroyFlags = bunch.Archive.ReadByte(); + } + } + //else + //{ + // bSerializeClass = true; + //} + + var classNetGUID = new NetworkGUID(); + if (bSerializeClass) + { + // Serialize the class in case we have to spawn it. + classNetGUID = InternalLoadObject(bunch.Archive, false); + + bDeleteSubObject = !classNetGUID.IsValid(); + } + + if (bDeleteSubObject) { bObjectDeleted = true; return null; @@ -1853,7 +1878,7 @@ public virtual bool ReadFieldHeaderAndPayload(FBitArchive archive, NetFieldExpor } } - return classNetGUID.Value; + return classNetGUID?.Value; } /// @@ -1930,7 +1955,7 @@ public virtual void ReceivedPacket(FBitArchive bitReader) } else { - bunch.CloseReason = bunch.bClose ? (ChannelCloseReason)bitReader.ReadSerializedInt((int)ChannelCloseReason.MAX) : ChannelCloseReason.Destroyed; + bunch.CloseReason = bunch.bClose ? (ChannelCloseReason) bitReader.ReadSerializedInt((int) ChannelCloseReason.MAX) : ChannelCloseReason.Destroyed; bunch.bDormant = bunch.CloseReason == ChannelCloseReason.Dormancy; } @@ -1973,7 +1998,7 @@ public virtual void ReceivedPacket(FBitArchive bitReader) if (bitReader.EngineNetworkVersion < EngineNetworkVersionHistory.HISTORY_CHANNEL_NAMES) { - var type = bitReader.ReadSerializedInt((int)ChannelType.MAX); + var type = bitReader.ReadSerializedInt((int) ChannelType.MAX); // chType = (bunch.bReliable || bunch.bOpen) ? (ChannelType)type : ChannelType.None; // chName = chType switch @@ -2008,7 +2033,7 @@ public virtual void ReceivedPacket(FBitArchive bitReader) // If there's an existing channel and the bunch specified it's channel type, make sure they match. // Channel && (Bunch.ChName != NAME_None) && (Bunch.ChName != Channel->ChName) - var bunchDataBits = (int)bitReader.ReadSerializedInt(MaxPacketSizeInBits); + var bunchDataBits = (int) bitReader.ReadSerializedInt(MaxPacketSizeInBits); if (bunch.bPartial) {