/// <summary> /// Adds a worldBlockChangedr's list of worlds. /// </summary> public void AddLevel(Level level) { level.World.BlockChanged += HandleOnBlockChanged; level.World.SpawnEntity += (sender, args) => EntityManager.SpawnEntity(sender as World, args.Entity); level.World.DestroyEntity += (sender, args) => EntityManager.DespawnEntity(sender as World, args.Entity); WeatherManagers.Add(new WeatherManager(level.World, this)); Levels.Add(level); }
private void NetworkWorker() { while (true) // TODO: Consider refactoring { lock (NetworkLock) { for (int i = 0; i < Clients.Count; i++) { var client = Clients[i]; if (client.IsLoggedIn) { DoClientUpdates(client); } bool disconnect = false; while (client.SendQueue.Count != 0) { IPacket packet; if (client.SendQueue.TryDequeue(out packet)) { try { packet.WritePacket(client.Stream); #if DEBUG LogProvider.Log(packet, false); #endif client.Stream.Flush(); } catch { // TODO: Consider more detail disconnect = true; break; } if (packet is DisconnectPacket) { disconnect = true; break; } if (packet is EncryptionKeyResponsePacket) { // Set up crypto stream #if DEBUG LogProvider.Log("Encryption enabled with " + client.Username, LogImportance.Low); #endif client.Stream = new MinecraftStream(new BufferedStream(new AesStream(client.NetworkStream, client.SharedKey))); client.EncryptionEnabled = true; } } } if (disconnect) { Clients.Remove(client); i--; EntityManager.DespawnEntity(client.Entity); if (client.IsLoggedIn) { OnPlayerLoggedOut(new PlayerLogInEventArgs(client)); } continue; } // Each client has a maximum of 10 milliseconds per iteration for reads DateTime readTimeout = DateTime.Now.AddMilliseconds(10); while (client.NetworkStream.DataAvailable && DateTime.Now < readTimeout) { try { var packet = PacketReader.ReadPacket(client.Stream); #if DEBUG LogProvider.Log(packet, true); #endif if (packet is DisconnectPacket) // TODO: Should we have a disconnect packet handler? { Clients.Remove(client); i--; EntityManager.DespawnEntity(client.Entity); if (client.IsLoggedIn) { OnPlayerLoggedOut(new PlayerLogInEventArgs(client)); } continue; } HandlePacket(client, packet); if (client.DisconnectPending) { break; } } catch (InvalidOperationException e) { new DisconnectPacket(e.Message).WritePacket(client.Stream); client.Stream.Flush(); Clients.Remove(client); i--; EntityManager.DespawnEntity(client.Entity); if (client.IsLoggedIn) { OnPlayerLoggedOut(new PlayerLogInEventArgs(client)); } } catch (SocketException e) { Clients.Remove(client); i--; EntityManager.DespawnEntity(client.Entity); if (client.IsLoggedIn) { OnPlayerLoggedOut(new PlayerLogInEventArgs(client)); } } catch (Exception e) { new DisconnectPacket("A network exception occured: " + e.GetType().Name).WritePacket(client.Stream); client.Stream.Flush(); Clients.Remove(client); i--; EntityManager.DespawnEntity(client.Entity); if (client.IsLoggedIn) { OnPlayerLoggedOut(new PlayerLogInEventArgs(client)); } } } } } if (DefaultLevel.Time % 5 == 0) { foreach (var level in Levels) { level.World.DoScheduledUpdates(); } } Thread.Sleep(1); } }