예제 #1
0
 public static void SpawnPlayers([NotNull] Player player)
 {
     if (player == null)
     {
         throw new ArgumentNullException("player");
     }
     lock ( PlayerListLock ) {
         foreach (Player other in PlayerIndex)
         {
             if (other != player)
             {
                 player.Send(Packet.MakeAddEntity(other.Id, other.Name, other.Position));
             }
         }
     }
 }
예제 #2
0
 static void SetSpawnHandler([NotNull] Player player)
 {
     if (!player.CheckIfOp())
     {
         return;
     }
     if (player == Player.Console)
     {
         player.Message("Can't set spawn from console!");
         return;
     }
     player.Map.Spawn            = player.Position;
     player.Map.ChangedSinceSave = true;
     player.Send(Packet.MakeAddEntity(255, player.Name, player.Map.Spawn.GetFixed()));
     player.Send(Packet.MakeSelfTeleport(player.Map.Spawn));
     Server.Players.Message("Player {0} set a new spawn point.", player.Name);
 }
예제 #3
0
        void SendMap()
        {
            // write MapBegin
            //Logger.Log( "Send: MapBegin()" );
            writer.Write(OpCode.MapBegin);

            // grab a compressed copy of the map
            byte[] blockData;
            Map    map = Server.Map;

            using (MemoryStream mapStream = new MemoryStream()) {
                using (GZipStream compressor = new GZipStream(mapStream, CompressionMode.Compress)) {
                    int convertedBlockCount = IPAddress.HostToNetworkOrder(map.Volume);
                    compressor.Write(BitConverter.GetBytes(convertedBlockCount), 0, 4);
                    byte[] rawData = (UsesCustomBlocks ? map.Blocks : map.GetFallbackMap());
                    compressor.Write(rawData, 0, rawData.Length);
                }
                blockData = mapStream.ToArray();
            }

            // Transfer the map copy
            byte[] buffer       = new byte[1024];
            int    mapBytesSent = 0;

            while (mapBytesSent < blockData.Length)
            {
                int chunkSize = blockData.Length - mapBytesSent;
                if (chunkSize > 1024)
                {
                    chunkSize = 1024;
                }
                else
                {
                    // CRC fix for ManicDigger
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        buffer[i] = 0;
                    }
                }
                Buffer.BlockCopy(blockData, mapBytesSent, buffer, 0, chunkSize);
                byte progress = (byte)(100 * mapBytesSent / blockData.Length);

                // write in chunks of 1024 bytes or less
                //Logger.Log( "Send: MapChunk({0},{1})", chunkSize, progress );
                writer.Write(OpCode.MapChunk);
                writer.Write((short)chunkSize);
                writer.Write(buffer, 0, 1024);
                writer.Write(progress);
                mapBytesSent += chunkSize;
            }

            // write MapEnd
            writer.Write(OpCode.MapEnd);
            writer.Write((short)map.Width);
            writer.Write((short)map.Height);
            writer.Write((short)map.Length);

            // write spawn point
            writer.Write(Packet.MakeAddEntity(255, Name, map.Spawn).Bytes);
            writer.Write(Packet.MakeTeleport(255, map.Spawn).Bytes);

            lastValidPosition = map.Spawn;
        }
예제 #4
0
        public static bool RegisterPlayer([NotNull] Player player)
        {
            if (player == null)
            {
                throw new ArgumentNullException("player");
            }
            lock ( PlayerListLock ) {
                // Kick other sessions with same player name
                Player ghost = PlayerIndex.FirstOrDefault(p => p.Name.Equals(player.Name,
                                                                             StringComparison.OrdinalIgnoreCase));
                if (ghost != null)
                {
                    // Wait for other session to exit/unregister
                    Logger.Log("Kicked a duplicate connection from {0} for player {1}.",
                               ghost.IP, ghost.Name);
                    ghost.KickSynchronously("Connected from elsewhere!");
                }

                // check the number of connections from this IP.
                if (!player.IP.Equals(IPAddress.Loopback) &&
                    (!player.IsOp && Config.MaxConnections > 0 || player.IsOp && Config.OpMaxConnections > 0))
                {
                    int connections    = PlayerIndex.Count(p => p.IP.Equals(player.IP));
                    int maxConnections = (player.IsOp ? Config.OpMaxConnections : Config.MaxConnections);
                    if (connections >= maxConnections)
                    {
                        player.Kick("Too many connections from your IP address!");
                        Logger.LogWarning(
                            "Player {0} was not allowed to join: connection limit of {1} reached for {2}.",
                            player.Name, maxConnections, player.IP);
                        return(false);
                    }
                }

                // check if server is full
                if (PlayerIndex.Count >= Config.MaxPlayers)
                {
                    if (Config.AdminSlot && player.IsOp)
                    {
                        // if player has a reserved slot, kick someone to make room
                        Player playerToKick = Players.OrderBy(p => p.LastActiveTime)
                                              .FirstOrDefault(p => p.IsOp);
                        if (playerToKick != null)
                        {
                            Logger.Log("Kicked player {0} to make room for player {1} from {2}.",
                                       playerToKick.Name, player.Name, player.IP);
                            playerToKick.KickSynchronously("Making room for an op.");
                        }
                        else
                        {
                            Logger.Log("Player {0} from {1} was not allowed to join (server is full and no one to kick).",
                                       player.Name, player.IP);
                            player.Kick("Server is full of ops!");
                            return(false);
                        }
                    }
                    else
                    {
                        Logger.Log("Player {0} from {1} was not allowed to join (server is full).",
                                   player.Name, player.IP);
                        player.Kick("Server is full!");
                        return(false);
                    }
                }

                // Assign index and spawn player
                player.Id = FreePlayerIDs.Pop();
                if (Config.RevealOps && player.IsOp)
                {
                    PlayerIndex.Send(null, Packet.MakeAddEntity(player.Id, Config.OpColor + player.Name, Map.Spawn));
                }
                else
                {
                    PlayerIndex.Send(null, Packet.MakeAddEntity(player.Id, player.Name, Map.Spawn));
                }
                player.HasRegistered = true;
                player.Map           = Map;
                player.ChangeMap(Map);

                // Add player to index
                SpawnPlayers(player);
                PlayerIndex.Add(player);
                Logger.Log("Player {0} connected from {1}", player.Name, player.IP);
                UpdatePlayerList();
            }
            return(true);
        }