@@ -15,14 +15,8 @@ public class Router
1515 public static readonly MessageBuffer [ ] globalMsgBuffers = new MessageBuffer [ 257 ] ;
1616 public readonly ServerContext [ ] clientCurrentlyServers = new ServerContext [ 256 ] ;
1717 static Router ( ) {
18- const int maxTilesX = 8400 ;
19- const int maxTilesY = 2400 ;
20- var tmp = new RootContext ( "tmp" ) ;
21- tmp . Main . maxTilesX = maxTilesX ;
22- tmp . Main . maxTilesY = maxTilesY ;
23-
2418 for ( int i = 0 ; i < 256 ; i ++ ) {
25- globalClients [ i ] = new RemoteClient ( tmp ) {
19+ globalClients [ i ] = new RemoteClient ( ) {
2620 Id = i ,
2721 ReadBuffer = new byte [ 1024 ]
2822 } ;
@@ -39,11 +33,14 @@ public Router(int listenPort, ServerContext main, params ServerContext[] allServ
3933
4034 On . Terraria . NetMessageSystemContext . mfwh_CheckBytes += ProcessBytes ;
4135 On . Terraria . NetplaySystemContext . mfwh_UpdateServerInMainThread += UpdateServerInMainThread ;
36+ On . Terraria . NetMessageSystemContext . CheckCanSend += NetMessageSystemContext_CheckCanSend ;
4237
4338 this . main = main ;
4439 this . servers = allServers ;
4540
4641 listener = new TcpListener ( IPAddress . Any , listenPort ) ;
42+ broadcastClient = new UdpClient ( ) ;
43+ broadcastClient . EnableBroadcast = true ;
4744
4845 var listenThread = new Thread ( ServerLoop ) {
4946 IsBackground = true ,
@@ -52,6 +49,10 @@ public Router(int listenPort, ServerContext main, params ServerContext[] allServ
5249 listenThread . Start ( ) ;
5350 }
5451
52+ private bool NetMessageSystemContext_CheckCanSend ( On . Terraria . NetMessageSystemContext . orig_CheckCanSend orig , NetMessageSystemContext self , int clientIndex ) {
53+ return clientCurrentlyServers [ clientIndex ] == self . root && globalClients [ clientIndex ] . IsConnected ( ) ;
54+ }
55+
5556 private void UpdateServerInMainThread ( On . Terraria . NetplaySystemContext . orig_mfwh_UpdateServerInMainThread orig , NetplaySystemContext self ) {
5657 var server = self . root ;
5758 for ( int i = 0 ; i < 256 ; i ++ ) {
@@ -132,6 +133,8 @@ private void ProcessBytes(On.Terraria.NetMessageSystemContext.orig_mfwh_CheckByt
132133
133134 readonly TcpListener listener ;
134135 volatile bool isListening ;
136+ readonly UdpClient broadcastClient ;
137+ volatile bool keepBroadcasting ;
135138
136139 public event Func < TcpClient , ISocket > ? CreateSocket ;
137140 public event Action ? Started ;
@@ -152,38 +155,43 @@ void ServerLoop() {
152155 }
153156
154157 private void UpdateConnectedClients ( ) {
155- for ( int i = 0 ; i < 256 ; i ++ ) {
156- var client = globalClients [ i ] ;
157- var server = clientCurrentlyServers [ i ] ;
158-
159- if ( client . PendingTermination ) {
160- if ( client . PendingTerminationApproved ) {
161- client . Reset ( main ) ;
162- server . NetMessage . SyncDisconnectedPlayer ( i ) ;
163-
164- bool active = server . Main . player [ i ] . active ;
165- server . Main . player [ i ] . active = false ;
166- if ( active ) {
167- server . Player . Hooks . PlayerDisconnect ( i ) ;
168- }
158+ try {
159+ for ( int i = 0 ; i < 256 ; i ++ ) {
160+ var client = globalClients [ i ] ;
161+ var server = clientCurrentlyServers [ i ] ;
162+
163+ if ( client . PendingTermination ) {
164+ if ( client . PendingTerminationApproved ) {
165+ client . Reset ( main ) ;
166+ server . NetMessage . SyncDisconnectedPlayer ( i ) ;
167+
168+ bool active = server . Main . player [ i ] . active ;
169+ server . Main . player [ i ] . active = false ;
170+ if ( active ) {
171+ server . Player . Hooks . PlayerDisconnect ( i ) ;
172+ }
169173
170- clientCurrentlyServers [ i ] = main ;
174+ clientCurrentlyServers [ i ] = main ;
175+ }
176+ continue ;
171177 }
172- continue ;
173- }
174- if ( client . IsConnected ( ) ) {
175- lock ( client ) {
176- client . Update ( server ) ;
177- server . Netplay . HasClients = true ;
178+ if ( client . IsConnected ( ) ) {
179+ lock ( client ) {
180+ client . Update ( server ) ;
181+ server . Netplay . HasClients = true ;
182+ }
183+ continue ;
178184 }
179- continue ;
180- }
181- if ( client . IsActive ) {
182- client . PendingTermination = true ;
183- client . PendingTerminationApproved = true ;
184- continue ;
185+ if ( client . IsActive ) {
186+ client . PendingTermination = true ;
187+ client . PendingTerminationApproved = true ;
188+ continue ;
189+ }
190+ client . StatusText2 = "" ;
185191 }
186- client . StatusText2 = "" ;
192+ }
193+ catch ( Exception ex ) {
194+
187195 }
188196 }
189197
@@ -196,6 +204,15 @@ static int GetClientSpace() {
196204 }
197205 return space ;
198206 }
207+ static int GetActiveClientCount ( ) {
208+ int count = 0 ;
209+ for ( int i = 0 ; i < 255 ; i ++ ) {
210+ if ( globalClients [ i ] . IsActive ) {
211+ count += 1 ;
212+ }
213+ }
214+ return count ;
215+ }
199216
200217 void StartListeningIfNeeded ( ) {
201218 if ( isListening || ! main . IsRunning || GetClientSpace ( ) <= 0 ) {
@@ -204,6 +221,7 @@ void StartListeningIfNeeded() {
204221 isListening = true ;
205222 listener . Start ( ) ;
206223 Task . Run ( ListenLoop ) ;
224+ Task . Run ( LaunchBroadcast ) ;
207225 }
208226 void ListenLoop ( ) {
209227 while ( main . IsRunning && GetClientSpace ( ) > 0 ) {
@@ -217,6 +235,49 @@ void ListenLoop() {
217235 }
218236 listener . Stop ( ) ;
219237 isListening = false ;
238+ keepBroadcasting = false ;
239+ }
240+ void LaunchBroadcast ( ) {
241+ try {
242+ keepBroadcasting = true ;
243+ int playerCountPosInStream = 0 ;
244+ byte [ ] data ;
245+ using ( MemoryStream memoryStream = new MemoryStream ( ) ) {
246+ using ( BinaryWriter bw = new BinaryWriter ( memoryStream ) ) {
247+ int value = 1010 ;
248+ bw . Write ( value ) ;
249+ bw . Write ( ListenPort ) ;
250+ bw . Write ( "Unified-Server-Process" ) ;
251+ string text = Dns . GetHostName ( ) ;
252+ if ( text == "localhost" ) {
253+ text = Environment . MachineName ;
254+ }
255+ bw . Write ( text ) ;
256+ bw . Write ( ( ushort ) main . Main . maxTilesX ) ;
257+ bw . Write ( main . Main . ActiveWorldFileData . HasCrimson ) ;
258+ bw . Write ( main . Main . ActiveWorldFileData . GameMode ) ;
259+ bw . Write ( 255 ) ;
260+ playerCountPosInStream = ( int ) memoryStream . Position ;
261+ bw . Write ( ( byte ) 0 ) ;
262+ bw . Write ( main . Main . ActiveWorldFileData . IsHardMode ) ;
263+ bw . Flush ( ) ;
264+ data = memoryStream . ToArray ( ) ;
265+ }
266+ }
267+ do {
268+ data [ ( int ) playerCountPosInStream ] = ( byte ) GetActiveClientCount ( ) ;
269+ try {
270+ broadcastClient . Send ( data , data . Length , new IPEndPoint ( IPAddress . Broadcast , 8888 ) ) ;
271+ }
272+ catch {
273+ }
274+ Thread . Sleep ( 1000 ) ;
275+ }
276+ while ( keepBroadcasting ) ;
277+ }
278+ catch {
279+ keepBroadcasting = false ;
280+ }
220281 }
221282
222283 void OnConnectionAccepted ( ISocket client ) {
0 commit comments