Client LuaCsForBarotrauma
EosServerProvider.cs
1 #nullable enable
2 using System;
3 using System.Collections.Generic;
4 using System.Collections.Immutable;
5 using System.Linq;
6 using System.Threading.Tasks;
7 using System.Xml.Linq;
9 
10 namespace Barotrauma;
11 
12 sealed class EosServerProvider : ServerProvider
13 {
14  public sealed class DataSource : ServerInfo.DataSource
15  {
16  public readonly string SteamPingLocation;
17 
18  public DataSource(string steamPingLocation)
19  {
20  SteamPingLocation = steamPingLocation;
21  }
22 
23  public override void Write(XElement element) { /* do nothing */ }
24  }
25 
26  protected override void RetrieveServersImpl(Action<ServerInfo, ServerProvider> onServerDataReceived, Action onQueryCompleted)
27  {
28  if (EosInterface.IdQueries.GetLoggedInPuids() is not { Length: > 0 } loggedInPuids) { return; }
29 
30  int finishedTaskCount = 0;
31  int totalTaskCount = EosInterface.Sessions.MaxBucketIndex + 1 - EosInterface.Sessions.MinBucketIndex;
32 
33  void countTaskFinished()
34  {
35  finishedTaskCount++;
36  if (finishedTaskCount == totalTaskCount)
37  {
38  onQueryCompleted();
39  }
40  }
41 
42  void onTaskFinished(Task t)
43  {
44  using var janitor = Janitor.Start();
45  janitor.AddAction(countTaskFinished);
46 
47  if (!t.TryGetResult(
48  out Result<ImmutableArray<EosInterface.Sessions.RemoteSession>, EosInterface.Sessions.RemoteSession.Query.Error>? result))
49  {
50  return;
51  }
52 
53  if (!result.TryUnwrapSuccess(out var sessions))
54  {
55  return;
56  }
57 
58  var addedEndpoints = new HashSet<Endpoint>();
59  foreach (var session in sessions)
60  {
61  if (!session.Attributes.TryGetValue("ServerName".ToIdentifier(), out var serverName))
62  {
63  continue;
64  }
65 
66  var endpointOption = Endpoint.Parse(session.HostAddress);
67  if (!endpointOption.TryUnwrap(out var primaryEndpoint))
68  {
69  continue;
70  }
71 
72  var endpoints = new List<Endpoint> { primaryEndpoint };
73  if (primaryEndpoint is EosP2PEndpoint
74  && session.Attributes.TryGetValue("SteamP2PEndpoint".ToIdentifier(), out var steamIdStr)
75  && SteamP2PEndpoint.Parse(steamIdStr).TryUnwrap(out var steamP2PEndpoint))
76  {
77  endpoints.Add(steamP2PEndpoint);
78  }
79  else if (primaryEndpoint is LidgrenEndpoint
80  {
81  Address: LidgrenAddress address, Port: NetConfig.DefaultPort
82  }
83  && session.Attributes.TryGetValue("Port".ToIdentifier(), out var portStr)
84  && ushort.TryParse(portStr, out var port))
85  {
86  // Port isn't included as part of the host address
87  // because it's filled in by EOS automatically,
88  // so extract the port from a separate attribute and
89  // fix up the endpoint here
90  primaryEndpoint = new LidgrenEndpoint(address.NetAddress, port);
91  endpoints[0] = primaryEndpoint;
92  }
93 
94  // Prevent duplicate entries
95  if (endpoints.Intersect(addedEndpoints).Any())
96  {
97  continue;
98  }
99 
100  addedEndpoints.UnionWith(endpoints);
101 
102  var serverInfo = new ServerInfo(endpoints.ToImmutableArray())
103  {
104  ServerName = serverName
105  };
106  serverInfo.UpdateInfo(key =>
107  session.Attributes.TryGetValue(key.ToIdentifier(), out var value) ? value : string.Empty);
108  serverInfo.EosCrossplay = true;
109  serverInfo.Checked = true;
110 
111  if (session.Attributes.TryGetValue("steampinglocation".ToIdentifier(), out var steamPingLocation))
112  {
113  serverInfo.MetadataSource = Option.Some((ServerInfo.DataSource)new DataSource(steamPingLocation));
114  }
115 
116  onServerDataReceived(serverInfo, this);
117  }
118  };
119 
120  for (int bucketIndex = EosInterface.Sessions.MinBucketIndex; bucketIndex <= EosInterface.Sessions.MaxBucketIndex; bucketIndex++)
121  {
122  var query = new EosInterface.Sessions.RemoteSession.Query(
123  BucketIndex: bucketIndex,
124  LocalUserId: loggedInPuids.First(),
125  MaxResults: 200,
126  Attributes: ImmutableDictionary<Identifier, string>.Empty);
127 
128  TaskPool.Add(
129  $"{nameof(EosServerProvider)}.{nameof(RetrieveServersImpl)}",
130  query.Run(),
131  onTaskFinished);
132  }
133  }
134 
135  public override void Cancel()
136  {
137 
138  }
139 }
static Option< Endpoint > Parse(string str)
void UpdateInfo(Func< string, string?> valueGetter)
Definition: ServerInfo.cs:438
static new Option< SteamP2PEndpoint > Parse(string endpointStr)
DataSource(string steamPingLocation)
override void Write(XElement element)
override void Cancel()
override void RetrieveServersImpl(Action< ServerInfo, ServerProvider > onServerDataReceived, Action onQueryCompleted)