3 using System.Collections.Immutable;
10 internal struct PeerPacketHeaders : INetSerializableStruct
12 public DeliveryMethod DeliveryMethod;
13 public PacketHeader PacketHeader;
14 public ConnectionInitialization? Initialization;
16 public readonly
void Deconstruct(
17 out DeliveryMethod deliveryMethod,
18 out PacketHeader packetHeader,
19 out ConnectionInitialization? initialization)
21 deliveryMethod = DeliveryMethod;
22 packetHeader = PacketHeader;
23 initialization = Initialization;
27 [NetworkSerialize(ArrayMaxSize = ushort.MaxValue)]
28 internal struct ClientAuthTicketAndVersionPacket : INetSerializableStruct
31 public Option<int> OwnerKey;
32 public Option<AccountId> AccountId;
33 public Option<AuthenticationTicket> AuthTicket;
34 public string GameVersion;
35 public Identifier Language;
39 internal readonly record
struct P2POwnerToServerHeader
40 (string? EndpointStr, AccountInfo AccountInfo) : INetSerializableStruct
46 internal readonly record
struct P2PServerToOwnerHeader
47 (string? EndpointStr) : INetSerializableStruct
53 internal struct P2PInitializationRelayPacket : INetSerializableStruct
56 public PeerPacketMessage Message;
60 internal readonly record
struct P2PInitializationOwnerPacket(
63 : INetSerializableStruct;
66 [NetworkSerialize(ArrayMaxSize = ushort.MaxValue)]
67 internal struct ServerPeerContentPackageOrderPacket : INetSerializableStruct
69 public string ServerName;
70 public ImmutableArray<ServerContentPackage> ContentPackages;
71 public bool AllowModDownloads;
74 [NetworkSerialize(ArrayMaxSize = ushort.MaxValue)]
75 internal struct PeerPacketMessage : INetSerializableStruct
78 public readonly
int Length => Buffer.Length;
80 public readonly IReadMessage GetReadMessageUncompressed() =>
new ReadWriteMessage(Buffer, 0, Length * 8, copyBuf:
false);
81 public readonly IReadMessage GetReadMessage(
bool isCompressed, NetworkConnection conn) =>
new ReadOnlyMessage(Buffer, isCompressed, 0, Length, conn);
84 [NetworkSerialize(ArrayMaxSize =
byte.MaxValue)]
85 internal struct ClientPeerPasswordPacket : INetSerializableStruct
87 public byte[] Password;
91 internal struct ServerPeerPasswordPacket : INetSerializableStruct
93 public Option<int> Salt;
94 public Option<int> RetriesLeft;
98 internal readonly
struct PeerDisconnectPacket : INetSerializableStruct
100 public readonly DisconnectReason DisconnectReason;
102 public readonly
string AdditionalInformation;
104 private PeerDisconnectPacket(
105 DisconnectReason disconnectReason,
106 string additionalInformation =
"")
108 DisconnectReason = disconnectReason;
109 AdditionalInformation = additionalInformation;
114 LocalizedString message = DisconnectReason
switch
116 DisconnectReason.Disconnected => TextManager.GetWithVariable(
"ServerMessage.ClientLeftServer",
118 DisconnectReason.Banned => TextManager.GetWithVariable(
"servermessage.bannedfromserver",
"[client]", c.Name),
119 DisconnectReason.Kicked => TextManager.GetWithVariable(
"servermessage.kickedfromserver",
"[client]", c.Name),
120 _ => TextManager.GetWithVariables(
"ChatMsg.DisconnectedWithReason",
121 (
"[client]", c.Name),
122 (
"[reason]", TextManager.Get($
"ChatMsg.DisconnectReason.{DisconnectReason}")))
124 if (!
string.IsNullOrEmpty(AdditionalInformation) &&
125 DisconnectReason is DisconnectReason.Banned or DisconnectReason.Kicked)
127 message +=
" "+ TextManager.Get(
"banreason") +
" " + TextManager.GetServerMessage(AdditionalInformation);
133 private LocalizedString MsgWithReason
134 => TextManager.Get($
"DisconnectReason.{DisconnectReason}")
136 + TextManager.Get(
"banreason") +
" " + TextManager.GetServerMessage(AdditionalInformation);
138 private LocalizedString ServerMessage
139 => TextManager.Get($
"ServerMessage.{DisconnectReason}");
141 public LocalizedString PopupMessage
142 => DisconnectReason
switch
144 DisconnectReason.Banned => MsgWithReason,
145 DisconnectReason.Kicked => MsgWithReason,
146 DisconnectReason.InvalidVersion => TextManager.GetWithVariables(
"DisconnectMessage.InvalidVersion",
147 (
"[version]", AdditionalInformation),
148 (
"[clientversion]", GameMain.Version.ToString())),
149 DisconnectReason.ExcessiveDesyncOldEvent => ServerMessage,
150 DisconnectReason.ExcessiveDesyncRemovedEvent => ServerMessage,
151 DisconnectReason.SyncTimeout => ServerMessage,
152 DisconnectReason.AuthenticationFailed => TextManager.Get($
"DisconnectReason.{DisconnectReason}").Fallback(TextManager.Get(
"ChatMsg.DisconnectReason.AuthenticationRequired")),
153 _ => TextManager.Get($
"DisconnectReason.{DisconnectReason}").Fallback($
"{TextManager.Get("ConnectionLost
")} ({DisconnectReason})")
156 public LocalizedString ReconnectMessage
157 => PopupMessage +
"\n\n" + TextManager.Get(
"ConnectionLostReconnecting");
160 => DisconnectReason
switch
167 public bool ShouldAttemptReconnect
169 is DisconnectReason.ExcessiveDesyncOldEvent
170 or DisconnectReason.ExcessiveDesyncRemovedEvent
171 or DisconnectReason.Timeout
172 or DisconnectReason.SyncTimeout
173 or DisconnectReason.SteamP2PTimeOut;
175 public bool IsEventSyncError
177 is DisconnectReason.ExcessiveDesyncOldEvent
178 or DisconnectReason.ExcessiveDesyncRemovedEvent
179 or DisconnectReason.SyncTimeout;
181 public bool ShouldCreateAnalyticsEvent
182 => DisconnectReason is not (
183 DisconnectReason.Disconnected
184 or DisconnectReason.ServerShutdown
185 or DisconnectReason.ServerFull
186 or DisconnectReason.Banned
187 or DisconnectReason.Kicked
188 or DisconnectReason.TooManyFailedLogins
189 or DisconnectReason.InvalidVersion);
198 public string ToLidgrenStringRepresentation()
200 static string strToBase64(
string str)
201 => Convert.ToBase64String(Encoding.UTF8.GetBytes(str));
203 return DisconnectReason
204 + NetworkMagicStrings.LidgrenDisconnectSeparator
205 + strToBase64(AdditionalInformation);
208 public static Option<PeerDisconnectPacket> FromLidgrenStringRepresentation(
string str)
216 case Lidgren.Network.NetConnection.NoResponseMessage:
217 case "Connection timed out":
219 return Option.Some(WithReason(DisconnectReason.Timeout));
222 static string base64ToStr(
string base64)
223 => Encoding.UTF8.GetString(Convert.FromBase64String(base64));
225 string[] split = str.Split(NetworkMagicStrings.LidgrenDisconnectSeparator);
226 if (split.Length != 2) {
return Option.None; }
227 if (!Enum.TryParse(split[0], out DisconnectReason disconnectReason)) {
return Option.None; }
228 return Option.Some(
new PeerDisconnectPacket(disconnectReason, base64ToStr(split[1])));
231 public static PeerDisconnectPacket Custom(
string customMessage)
232 =>
new PeerDisconnectPacket(
233 DisconnectReason.Unknown,
236 public static PeerDisconnectPacket WithReason(DisconnectReason disconnectReason)
237 =>
new PeerDisconnectPacket(disconnectReason);
239 public static PeerDisconnectPacket
Kicked(
string? msg)
240 =>
new PeerDisconnectPacket(DisconnectReason.Kicked, msg ??
"");
242 public static PeerDisconnectPacket
Banned(
string? msg)
243 =>
new PeerDisconnectPacket(DisconnectReason.Banned, msg ??
"");
245 public static PeerDisconnectPacket InvalidVersion()
246 =>
new PeerDisconnectPacket(
247 DisconnectReason.InvalidVersion,
248 GameMain.Version.ToString());
250 public static PeerDisconnectPacket SteamP2PError(Steamworks.P2PSessionError error)
251 =>
new PeerDisconnectPacket(
252 DisconnectReason.SteamP2PError,
255 public static PeerDisconnectPacket SteamAuthError(Steamworks.BeginAuthResult error)
256 =>
new PeerDisconnectPacket(
257 DisconnectReason.AuthenticationFailed,
258 $
"{nameof(Steamworks.BeginAuthResult)}.{error}");
260 public static PeerDisconnectPacket SteamAuthError(Steamworks.AuthResponse error)
261 =>
new PeerDisconnectPacket(
262 DisconnectReason.AuthenticationFailed,
263 $
"{nameof(Steamworks.AuthResponse)}.{error}");
288 private DateTime? cachedDateTime;
302 ContentPackageManager.RegularPackages.FirstOrDefault(p => p.Name.Equals(
Name) && p.Hash.Equals(
Hash)) ??
303 ContentPackageManager.RegularPackages.FirstOrDefault(p => p.Hash.Equals(
Hash));
306 ContentPackageManager.CorePackages.FirstOrDefault(p => p.Name.Equals(
Name) && p.Hash.Equals(
Hash)) ??
307 ContentPackageManager.CorePackages.FirstOrDefault(p => p.Hash.Equals(
Hash));
316 UgcId = contentPackage.
UgcId.TryUnwrap(out var ugcId)
317 ? ugcId.StringRepresentation
320 IsVanilla = contentPackage == ContentPackageManager.VanillaCorePackage;
322 contentPackage.
InstallTime.TryUnwrap(out var installTime)
323 ? (uint)(installTime - referenceTime).TotalSeconds
327 public string GetPackageStr() => $
"\"{Name}\" (hash {Hash.ShortRepresentation})";
ImmutableArray< ContentFile > Files
readonly Option< ContentPackageId > UgcId
readonly Option< SerializableDateTime > InstallTime
static Md5Hash BytesAsHash(byte[] bytes)
Marks fields and properties as to be serialized and deserialized by INetSerializableStruct....
uint InstallTimeDiffInSeconds
ServerContentPackage(ContentPackage contentPackage, SerializableDateTime referenceTime)
static new Option< P2PEndpoint > Parse(string str)
PlayerConnectionChangeType
DateTime wrapper that tries to offer a reliable string representation that's also human-friendly