Implement proper FName / FNamePool
This commit is contained in:
@@ -8,7 +8,7 @@ public class UActorChannel : UChannel
|
||||
public UActorChannel()
|
||||
{
|
||||
ChType = EChannelType.CHTYPE_Actor;
|
||||
ChName = UnrealNames.FNames[UnrealNameKey.Actor];
|
||||
ChName = EName.Actor;
|
||||
// bClearRecentActorRefs = true;
|
||||
// bHoldQueuedExportBunchesAndGUIDs = false;
|
||||
// QueuedCloseReason = EChannelCloseReason::Destroyed;
|
||||
|
||||
@@ -12,7 +12,7 @@ public class UControlChannel : UChannel
|
||||
public UControlChannel()
|
||||
{
|
||||
ChType = EChannelType.CHTYPE_Control;
|
||||
ChName = UnrealNames.FNames[UnrealNameKey.Control];
|
||||
ChName = EName.Control;
|
||||
}
|
||||
|
||||
protected override void ReceivedBunch(FInBunch bunch)
|
||||
|
||||
@@ -8,7 +8,7 @@ public class UVoiceChannel : UChannel
|
||||
public UVoiceChannel()
|
||||
{
|
||||
ChType = EChannelType.CHTYPE_Voice;
|
||||
ChName = UnrealNames.FNames[UnrealNameKey.Control];
|
||||
ChName = EName.Voice;
|
||||
}
|
||||
|
||||
protected override void ReceivedBunch(FInBunch bunch)
|
||||
|
||||
@@ -71,12 +71,7 @@ public class FUniqueNetIdRepl
|
||||
{
|
||||
var typeString = ar.ReadString();
|
||||
var type = new FName(typeString);
|
||||
// TODO: Add FName into FNamePool
|
||||
throw new NotImplementedException();
|
||||
if (ar.IsError() || type.Number == (int)UnrealNameKey.None)
|
||||
{
|
||||
bValidTypeHash = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -110,7 +105,7 @@ public class FUniqueNetIdRepl
|
||||
}
|
||||
else
|
||||
{
|
||||
type = UnrealNames.FNames[UnrealNameKey.None];
|
||||
type = new FName(EName.None);
|
||||
// TODO: Type = UOnlineEngineInterface::Get()->GetSubsystemFromReplicationHash(TypeHash);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Prospect.Unreal.Net.Packets.Bunch
|
||||
Connection = inConnection;
|
||||
ChIndex = 0;
|
||||
ChType = EChannelType.CHTYPE_None;
|
||||
ChName = UnrealNames.FNames[UnrealNameKey.None];
|
||||
ChName = EName.None;
|
||||
ChSequence = 0;
|
||||
bOpen = false;
|
||||
bClose = false;
|
||||
|
||||
@@ -8,7 +8,7 @@ public class FOutBunch : FNetBitWriter
|
||||
{
|
||||
public FOutBunch() : base(0)
|
||||
{
|
||||
ChName = UnrealNames.FNames[UnrealNameKey.None];
|
||||
ChName = EName.None;
|
||||
}
|
||||
|
||||
public FOutBunch(UChannel inChannel, bool bInClose) : base(
|
||||
@@ -53,7 +53,7 @@ public class FOutBunch : FNetBitWriter
|
||||
Time = 0;
|
||||
ChIndex = 0;
|
||||
ChType = EChannelType.CHTYPE_None;
|
||||
ChName = UnrealNames.FNames[UnrealNameKey.None];
|
||||
ChName = EName.None;
|
||||
ChSequence = 0;
|
||||
PacketId = 0;
|
||||
ReceivedAck = false;
|
||||
|
||||
@@ -90,7 +90,7 @@ public abstract class UNetConnection : UPlayer
|
||||
public UNetConnection()
|
||||
{
|
||||
_channelsToTick = new HashSet<UChannel>();
|
||||
_playerOnlinePlatformName = UnrealNames.FNames[UnrealNameKey.None];
|
||||
_playerOnlinePlatformName = EName.None;
|
||||
_packetOrderCache = null;
|
||||
_packetOrderCacheStartIdx = 0;
|
||||
_packetOrderCacheCount = 0;
|
||||
@@ -649,13 +649,13 @@ public abstract class UNetConnection : UPlayer
|
||||
switch (bunch.ChType)
|
||||
{
|
||||
case EChannelType.CHTYPE_Control:
|
||||
bunch.ChName = UnrealNames.FNames[UnrealNameKey.Control];
|
||||
bunch.ChName = EName.Control;
|
||||
break;
|
||||
case EChannelType.CHTYPE_Voice:
|
||||
bunch.ChName = UnrealNames.FNames[UnrealNameKey.Voice];
|
||||
bunch.ChName = EName.Voice;
|
||||
break;
|
||||
case EChannelType.CHTYPE_Actor:
|
||||
bunch.ChName = UnrealNames.FNames[UnrealNameKey.Actor];
|
||||
bunch.ChName = EName.Actor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -667,32 +667,30 @@ public abstract class UNetConnection : UPlayer
|
||||
|
||||
if (!UPackageMap.StaticSerializeName(reader, ref chName) || reader.IsError())
|
||||
{
|
||||
// TODO: Close connection
|
||||
Close();
|
||||
Logger.Fatal("Channel name serialization failed");
|
||||
return;
|
||||
}
|
||||
|
||||
bunch.ChName = chName;
|
||||
|
||||
switch ((UnrealNameKey) bunch.ChName.Number)
|
||||
bunch.ChName = chName!.Value;
|
||||
|
||||
if (bunch.ChName == EName.Control)
|
||||
{
|
||||
case UnrealNameKey.Control:
|
||||
bunch.ChType = EChannelType.CHTYPE_Control;
|
||||
break;
|
||||
|
||||
case UnrealNameKey.Voice:
|
||||
bunch.ChType = EChannelType.CHTYPE_Voice;
|
||||
break;
|
||||
|
||||
case UnrealNameKey.Actor:
|
||||
bunch.ChType = EChannelType.CHTYPE_Actor;
|
||||
break;
|
||||
bunch.ChType = EChannelType.CHTYPE_Control;
|
||||
}
|
||||
else if (bunch.ChName == EName.Voice)
|
||||
{
|
||||
bunch.ChType = EChannelType.CHTYPE_Voice;
|
||||
}
|
||||
else if (bunch.ChName == EName.Actor)
|
||||
{
|
||||
bunch.ChType = EChannelType.CHTYPE_Actor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bunch.ChType = EChannelType.CHTYPE_None;
|
||||
bunch.ChName = UnrealNames.FNames[UnrealNameKey.None];
|
||||
bunch.ChName = EName.None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,12 +698,11 @@ public abstract class UNetConnection : UPlayer
|
||||
|
||||
// If there's an existing channel and the bunch specified it's channel type, make sure they match.
|
||||
if (channel != null &&
|
||||
(bunch.ChName.Number != (int)UnrealNameKey.None) &&
|
||||
(bunch.ChName.Number != channel.ChName.Number))
|
||||
(bunch.ChName != EName.None) &&
|
||||
(bunch.ChName != channel.ChName))
|
||||
{
|
||||
Logger.Error("Existing channel at index {ChIndex} with type \"{ChName}\" differs from the incoming bunch's expected channel type, \"{BunchChName}\"",
|
||||
bunch.ChIndex, channel.ChName.Str, bunch.ChName.Str);
|
||||
// TODO: Close();
|
||||
Logger.Error("Existing channel at index {ChIndex} with type \"{ChName}\" differs from the incoming bunch's expected channel type, \"{BunchChName}\"", bunch.ChIndex, channel.ChName, bunch.ChName);
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -714,7 +711,7 @@ public abstract class UNetConnection : UPlayer
|
||||
if (reader.IsError())
|
||||
{
|
||||
Logger.Error("Bunch header overflow");
|
||||
// TODO: Close();
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -746,27 +743,27 @@ public abstract class UNetConnection : UPlayer
|
||||
Logger.Verbose(" bOpen Bunch, Channel {Ch} Sequence {Seq}: Size {A:###.0}+{B:###.0}", bunch.ChIndex, bunch.ChSequence, (headerPos - incomingStartPos)/8.0f, (reader.GetPosBits()-headerPos)/8.0f);
|
||||
}
|
||||
|
||||
if (Channels[bunch.ChIndex] == null && (bunch.ChIndex != 0 || bunch.ChName != UnrealNames.FNames[UnrealNameKey.Control]))
|
||||
if (Channels[bunch.ChIndex] == null && (bunch.ChIndex != 0 || bunch.ChName != EName.Control))
|
||||
{
|
||||
if (Channels[0] == null)
|
||||
{
|
||||
Logger.Fatal(" Received non-control bunch before control channel was created. ChIndex: {Ch}, ChName: {Name}", bunch.ChIndex, bunch.ChName);
|
||||
// TODO: Close();
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
else if (PlayerController == null && Driver.ClientConnections.Contains(this))
|
||||
{
|
||||
Logger.Fatal(" Received non-control bunch before player controller was assigned. ChIndex: {Ch}, ChName: {Name}", bunch.ChIndex, bunch.ChName);
|
||||
// TODO: Close();
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore control channel close if it hasn't been opened yet
|
||||
if (bunch.ChIndex == 0 && Channels[0] == null && bunch.bClose && bunch.ChName == UnrealNames.FNames[UnrealNameKey.Control])
|
||||
if (bunch.ChIndex == 0 && Channels[0] == null && bunch.bClose && bunch.ChName == EName.Control)
|
||||
{
|
||||
Logger.Fatal("Received control channel close before open");
|
||||
// Close();
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -827,7 +824,7 @@ public abstract class UNetConnection : UPlayer
|
||||
{
|
||||
// Unknown type.
|
||||
Logger.Fatal("Connection unknown channel type ({Name})", bunch.ChName);
|
||||
// TODO: Close()
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -883,7 +880,7 @@ public abstract class UNetConnection : UPlayer
|
||||
if (Driver.IsServer() && (bunch.IsCriticalError() || bunch.IsError()))
|
||||
{
|
||||
Logger.Error("Received corrupted packet data from client {RemoteAddress}. Disconnecting", LowLevelGetRemoteAddress());
|
||||
// TODO: Close()
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1218,7 +1215,7 @@ public abstract class UNetConnection : UPlayer
|
||||
|
||||
if (bIsOpenOrReliable)
|
||||
{
|
||||
var name = bunch.ChName;
|
||||
var name = (FName?) bunch.ChName;
|
||||
UPackageMap.StaticSerializeName(sendBunchHeader, ref name);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ public abstract class UNetDriver : IAsyncDisposable
|
||||
ChannelDefinitionMap = new Dictionary<FName, FChannelDefinition>();
|
||||
ChannelDefinitions = new List<FChannelDefinition>
|
||||
{
|
||||
new FChannelDefinition(UnrealNames.FNames[UnrealNameKey.Control], typeof(string), 0, true, false, true, false, true),
|
||||
new FChannelDefinition(UnrealNames.FNames[UnrealNameKey.Voice], typeof(string), 1, true, true, true, true, true),
|
||||
new FChannelDefinition(UnrealNames.FNames[UnrealNameKey.Actor], typeof(string), -1, false, true, false, false, false)
|
||||
new FChannelDefinition(EName.Control, typeof(string), 0, true, false, true, false, true),
|
||||
new FChannelDefinition(EName.Voice, typeof(string), 1, true, true, true, true, true),
|
||||
new FChannelDefinition(EName.Actor, typeof(string), -1, false, true, false, false, false)
|
||||
};
|
||||
ClientConnections = new List<UNetConnection>();
|
||||
MappedClientConnections = new ConcurrentDictionary<IPEndPoint, UNetConnection>();
|
||||
@@ -179,11 +179,17 @@ public abstract class UNetDriver : IAsyncDisposable
|
||||
{
|
||||
// TODO: Pool actor channels (?)
|
||||
|
||||
return (UnrealNameKey)chName.Number switch
|
||||
var name = chName.ToEName();
|
||||
if (name == null)
|
||||
{
|
||||
UnrealNameKey.Actor => new UActorChannel(),
|
||||
UnrealNameKey.Control => new UControlChannel(),
|
||||
UnrealNameKey.Voice => new UVoiceChannel(),
|
||||
throw new UnrealNetException($"Unsupported channel name specified {chName}");
|
||||
}
|
||||
|
||||
return name switch
|
||||
{
|
||||
EName.Actor => new UActorChannel(),
|
||||
EName.Control => new UControlChannel(),
|
||||
EName.Voice => new UVoiceChannel(),
|
||||
_ => throw new UnrealNetException($"Attempted to create unknown channel {chName}")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Prospect.Unreal.Core;
|
||||
using Prospect.Unreal.Core.Names;
|
||||
using Prospect.Unreal.Exceptions;
|
||||
using Prospect.Unreal.Net.Packets.Bunch;
|
||||
using Prospect.Unreal.Serialization;
|
||||
|
||||
@@ -8,7 +9,7 @@ namespace Prospect.Unreal.Net;
|
||||
|
||||
public class UPackageMap
|
||||
{
|
||||
public static unsafe bool StaticSerializeName(FArchive ar, [MaybeNullWhen(false)] ref FName name)
|
||||
public static unsafe bool StaticSerializeName(FArchive ar, ref FName? name)
|
||||
{
|
||||
if (ar.IsLoading())
|
||||
{
|
||||
@@ -34,7 +35,7 @@ public class UPackageMap
|
||||
if (nameIndex < UnrealNames.MaxHardcodedNameIndex)
|
||||
{
|
||||
// hardcoded names never have a Number
|
||||
name = UnrealNames.FNames[(UnrealNameKey) nameIndex];
|
||||
name = new FName((EName) nameIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -51,17 +52,23 @@ public class UPackageMap
|
||||
}
|
||||
else
|
||||
{
|
||||
var bHardcoded = (byte)(ShouldReplicateAsInteger(name) ? 1 : 0);
|
||||
if (name == null)
|
||||
{
|
||||
throw new UnrealException("Name should not be null when saving");
|
||||
}
|
||||
|
||||
var inEName = name.Value.ToEName();
|
||||
var bHardcoded = inEName.HasValue && ShouldReplicateAsInteger(inEName.Value) ? 1 : 0;
|
||||
ar.SerializeBits(&bHardcoded, 1); // 25
|
||||
if (bHardcoded != 0)
|
||||
{
|
||||
ar.SerializeIntPacked((uint)name.Number);
|
||||
ar.SerializeIntPacked((uint)inEName!.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// send by string
|
||||
var outString = name.Str;
|
||||
var outNumber = name.Number;
|
||||
var outString = name.Value.GetPlainNameString();
|
||||
var outNumber = name.Value.GetNumber();
|
||||
|
||||
ar.WriteString(outString);
|
||||
ar.WriteInt32(outNumber);
|
||||
@@ -71,9 +78,9 @@ public class UPackageMap
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool ShouldReplicateAsInteger(FName name)
|
||||
private static bool ShouldReplicateAsInteger(EName name)
|
||||
{
|
||||
return name.Number <= UnrealNames.MaxNetworkedHardcodedName;
|
||||
return (int)name <= UnrealNames.MaxNetworkedHardcodedName;
|
||||
}
|
||||
|
||||
public void NotifyBunchCommit(int bunchPacketId, FOutBunch bunch)
|
||||
|
||||
Reference in New Issue
Block a user