private static void OnLevelReady(ref LevelReady p) { Player player; if (players.TryGetValue(p.SenderConnection, out player)) { if (player.Index != p.Index) { throw new InvalidOperationException(); } player.IsReady = true; foreach (var to in players) { if (to.Key == p.SenderConnection || !to.Value.IsReady) { continue; } Send(new CreateRemotePlayer { Index = player.Index, Type = Actors.PlayerType.Spaz, Pos = Vector3.Zero }, 2 + 1 + 3 * 4, to.Key, NetDeliveryMethod.ReliableSequenced, NetworkChannels.PlayerGeneral); } foreach (var other in players) { if (other.Key == p.SenderConnection || !other.Value.IsReady) { continue; } Send(new CreateRemotePlayer { Index = other.Value.Index, Type = Actors.PlayerType.Spaz, Pos = other.Value.Pos }, 2 + 1 + 3 * 4, p.SenderConnection, NetDeliveryMethod.ReliableSequenced, NetworkChannels.PlayerGeneral); } } }
/// <summary> /// Player finished loading of a level and is ready to play /// </summary> private void OnPacketLevelReady(ref LevelReady p) { PlayerClient player = playersByIndex[p.Index]; if (player == null) { return; } if (player.Connection != p.SenderConnection) { throw new InvalidOperationException(); } // TODO: Allow player type change player.PlayerType = p.PlayerType; lock (sync) { if (player.State >= PlayerState.HasLevelLoaded) { // Player has already loaded level, he might want to only change player type return; } // Add connection to list, so it will start to receive gameplay events from server if (!playerConnections.Contains(p.SenderConnection)) { playerConnections.Add(p.SenderConnection); } if (!playerSpawningEnabled) { // If spawning is not enabled, postpone spawning of the player, // but send command to create all already spawned players player.State = PlayerState.HasLevelLoaded; foreach (KeyValuePair <NetConnection, PlayerClient> pair in players) { if (pair.Key == p.SenderConnection) { continue; } if (pair.Value.State == PlayerState.Spawned && pair.Value.ProxyActor != null) { string metadataPath; switch (pair.Value.PlayerType) { default: case PlayerType.Jazz: metadataPath = "Interactive/PlayerJazz"; break; case PlayerType.Spaz: metadataPath = "Interactive/PlayerSpaz"; break; case PlayerType.Lori: metadataPath = "Interactive/PlayerLori"; break; case PlayerType.Frog: metadataPath = "Interactive/PlayerFrog"; break; } Send(new CreateRemoteActor { Index = pair.Value.Index, CollisionFlags = CollisionFlags.ApplyGravitation, MetadataPath = metadataPath, Pos = pair.Value.ProxyActor.Transform.Pos }, 64, p.SenderConnection, NetDeliveryMethod.ReliableOrdered, PacketChannels.Main); } } } else { Vector3 pos = new Vector3(levelHandler.EventMap.GetSpawnPositionForMultiplayer(), LevelHandler.PlayerZ); if (player.ProxyActor == null) { player.ProxyActor = new Player(); player.ProxyActor.Index = player.Index; player.ProxyActor.OnActivated(new ActorActivationDetails { LevelHandler = levelHandler, Pos = pos, Params = new[] { (ushort)player.PlayerType, (ushort)0 } }); levelHandler.AddPlayer(player.ProxyActor); } else { player.ProxyActor.Transform.Pos = pos; } player.State = PlayerState.Spawned; Send(new CreateControllablePlayer { Index = player.Index, Type = player.PlayerType, Pos = pos, Health = playerHealth, Controllable = levelStarted }, 11, p.SenderConnection, NetDeliveryMethod.ReliableOrdered, PacketChannels.Main); // Send command to create all already spawned players string metadataPath; List <NetConnection> playersWithLoadedLevel = new List <NetConnection>(); foreach (KeyValuePair <NetConnection, PlayerClient> pair in players) { if (pair.Key == p.SenderConnection) { continue; } if (pair.Value.State == PlayerState.HasLevelLoaded || pair.Value.State == PlayerState.Spawned || pair.Value.State == PlayerState.Dead) { playersWithLoadedLevel.Add(pair.Key); if (pair.Value.State == PlayerState.Spawned) { switch (pair.Value.PlayerType) { default: case PlayerType.Jazz: metadataPath = "Interactive/PlayerJazz"; break; case PlayerType.Spaz: metadataPath = "Interactive/PlayerSpaz"; break; case PlayerType.Lori: metadataPath = "Interactive/PlayerLori"; break; case PlayerType.Frog: metadataPath = "Interactive/PlayerFrog"; break; } Send(new CreateRemoteActor { Index = pair.Value.Index, CollisionFlags = CollisionFlags.ApplyGravitation, MetadataPath = metadataPath, Pos = pair.Value.ProxyActor.Transform.Pos }, 64, p.SenderConnection, NetDeliveryMethod.ReliableOrdered, PacketChannels.Main); } } } switch (player.PlayerType) { default: case PlayerType.Jazz: metadataPath = "Interactive/PlayerJazz"; break; case PlayerType.Spaz: metadataPath = "Interactive/PlayerSpaz"; break; case PlayerType.Lori: metadataPath = "Interactive/PlayerLori"; break; case PlayerType.Frog: metadataPath = "Interactive/PlayerFrog"; break; } // Send command to all active players to create this new player Send(new CreateRemoteActor { Index = player.Index, CollisionFlags = CollisionFlags.ApplyGravitation, MetadataPath = metadataPath, Pos = pos }, 64, playersWithLoadedLevel, NetDeliveryMethod.ReliableOrdered, PacketChannels.Main); } // Send command to create all remotable actors /*foreach (KeyValuePair<int, RemotableActor> pair in remotableActors) { * RemotableActor remotableActor = pair.Value; * * Send(new CreateRemoteObject { * Index = remotableActor.Index, * EventType = remotableActor.EventType, * EventParams = remotableActor.EventParams, * Pos = remotableActor.Pos, * }, 35, p.SenderConnection, NetDeliveryMethod.ReliableOrdered, PacketChannels.Main); * }*/ levelHandler.SendAllSpawnedActors(p.SenderConnection); if (!levelStarted) { bool allLoaded = true; if (playerSpawningEnabled) { // If spawning is not enabled, don't wait anymore, because another player cannot be spawned anyway foreach (var pair in players) { if (pair.Value.State == PlayerState.NotReady) { allLoaded = false; break; } } } if (allLoaded) { // All players are ready to player, start game in 15 seconds countdown = 15f; countdownNotify = int.MaxValue; } } if (currentLevelType == MultiplayerLevelType.Race) { SendToActivePlayers(new PlayerSetLaps { Index = (byte)0, Laps = 0, LapsTotal = raceTotalLaps }, 4, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); } else if (CurrentLevelType == MultiplayerLevelType.TreasureHunt) { SendToActivePlayers(new PlayerSetLaps { Index = (byte)0, Laps = 0, LapsTotal = treasureHuntTotalGems }, 4, NetDeliveryMethod.ReliableUnordered, PacketChannels.UnorderedUpdates); } } #if DEBUG Log.Write(LogType.Verbose, "Player #" + player.Index + " is ready to play"); #endif }
private void OnLevelReady(ref LevelReady p) { Player player; if (players.TryGetValue(p.SenderConnection, out player)) { if (player.Index != p.Index) { throw new InvalidOperationException(); } lock (sync) { playerConnections.Add(p.SenderConnection); if (!playerSpawningEnabled) { player.State = PlayerState.HasLevelLoaded; foreach (KeyValuePair <NetConnection, Player> pair in players) { if (pair.Key == p.SenderConnection) { continue; } if (pair.Value.State == PlayerState.Spawned) { Send(new CreateRemotePlayer { Index = pair.Value.Index, Type = pair.Value.PlayerType, Pos = pair.Value.Pos }, 9, p.SenderConnection, NetDeliveryMethod.ReliableUnordered, PacketChannels.Main); } } return; } // ToDo: Set character requested by the player player.PlayerType = MathF.Rnd.OneOf(new[] { PlayerType.Jazz, PlayerType.Spaz, PlayerType.Lori }); player.Pos = new Vector3(eventMap.GetRandomSpawnPosition(), LevelHandler.PlayerZ); player.State = PlayerState.Spawned; player.AABB = new AABB(player.Pos.Xy, 20, 30); collisions.AddProxy(player); Send(new CreateControllablePlayer { Index = player.Index, Type = player.PlayerType, Pos = player.Pos, Health = playerHealth }, 9, p.SenderConnection, NetDeliveryMethod.ReliableUnordered, PacketChannels.Main); List <NetConnection> playersWithLoadedLevel = new List <NetConnection>(); foreach (KeyValuePair <NetConnection, Player> pair in players) { if (pair.Key == p.SenderConnection) { continue; } if (pair.Value.State == PlayerState.HasLevelLoaded || pair.Value.State == PlayerState.Spawned || pair.Value.State == PlayerState.Dead) { playersWithLoadedLevel.Add(pair.Key); if (pair.Value.State == PlayerState.Spawned) { Send(new CreateRemotePlayer { Index = pair.Value.Index, Type = pair.Value.PlayerType, Pos = pair.Value.Pos }, 9, p.SenderConnection, NetDeliveryMethod.ReliableUnordered, PacketChannels.Main); } } } Send(new CreateRemotePlayer { Index = player.Index, Type = player.PlayerType, Pos = player.Pos }, 9, playersWithLoadedLevel, NetDeliveryMethod.ReliableUnordered, PacketChannels.Main); } } }
public void SendLevelReady() { LevelReady?.Invoke(); }