예제 #1
0
        public McpeBatch GetBatch()
        {
            lock (_cacheSync)
            {
                if (_cache != null && _cachedBatch != null)
                {
                    return(_cachedBatch);
                }

                McpeFullChunkData fullChunkData = McpeFullChunkData.CreateObject();
                fullChunkData.chunkX          = x;
                fullChunkData.chunkZ          = z;
                fullChunkData.order           = 0;
                fullChunkData.chunkData       = GetBytes();
                fullChunkData.chunkDataLength = fullChunkData.chunkData.Length;
                byte[] bytes = fullChunkData.Encode();
                fullChunkData.PutPool();

                MemoryStream memStream = new MemoryStream();
                memStream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4);
                memStream.Write(bytes, 0, bytes.Length);

                McpeBatch batch  = McpeBatch.CreateObject();
                byte[]    buffer = Player.CompressBytes(memStream.ToArray(), CompressionLevel.Optimal);
                batch.payloadSize = buffer.Length;
                batch.payload     = buffer;
                batch.Encode();
                batch.MarkPermanent();

                _cachedBatch = batch;

                return(batch);
            }
        }
예제 #2
0
        public McpeBatch GetBatch()
        {
            if (_cache != null && _cachedBatch != null)
            {
                return(_cachedBatch);
            }

            McpeFullChunkData fullChunkData = McpeFullChunkData.CreateObject();

            fullChunkData.chunkX          = x;
            fullChunkData.chunkZ          = z;
            fullChunkData.chunkData       = GetBytes();
            fullChunkData.chunkDataLength = fullChunkData.chunkData.Length;
            byte[] bytes = fullChunkData.Encode();
            fullChunkData.PutPool();

            McpeBatch batch = McpeBatch.CreateObject();

            byte[] buffer = Player.CompressBytes(bytes, CompressionLevel.Optimal);
            batch.payloadSize = buffer.Length;
            batch.payload     = buffer;
            batch.Encode();
            batch.MarkPermanent();

            _cachedBatch = batch;

            return(batch);
        }
예제 #3
0
        public object Clone()
        {
            ChunkColumn cc = (ChunkColumn)MemberwiseClone();

            //public int x;
            //public int z;
            //public bool isDirty;

            //public byte[] biomeId = ArrayOf<byte>.Create(256, 2);
            cc.biomeId = (byte[])biomeId.Clone();

            //public int[] biomeColor = ArrayOf<int>.Create(256, 1);
            cc.biomeColor = (int[])biomeColor.Clone();

            //public byte[] height = ArrayOf<byte>.Create(256, 0);
            cc.height = (byte[])height.Clone();

            //public byte[] blocks = new byte[16 * 16 * 128];
            cc.blocks = (byte[])blocks.Clone();

            //public NibbleArray metadata = new NibbleArray(16 * 16 * 128);
            cc.metadata = (NibbleArray)metadata.Clone();

            //public NibbleArray blocklight = new NibbleArray(16 * 16 * 128);
            cc.blocklight = (NibbleArray)blocklight.Clone();

            //public NibbleArray skylight = new NibbleArray(16 * 16 * 128);
            cc.skylight = (NibbleArray)skylight.Clone();

            //public IDictionary<BlockCoordinates, NbtCompound> BlockEntities = new Dictionary<BlockCoordinates, NbtCompound>();
            cc.BlockEntities = new Dictionary <BlockCoordinates, NbtCompound>();
            foreach (KeyValuePair <BlockCoordinates, NbtCompound> blockEntityPair in BlockEntities)
            {
                cc.BlockEntities.Add(blockEntityPair.Key, (NbtCompound)blockEntityPair.Value.Clone());
            }

            //private byte[] _cache;
            if (_cache != null)
            {
                cc._cache = (byte[])_cache.Clone();
            }

            //private McpeBatch _cachedBatch = null;
            McpeBatch batch = McpeBatch.CreateObject();

            batch.payloadSize = _cachedBatch.payloadSize;
            batch.payload     = _cachedBatch.payload;
            batch.Encode();
            batch.MarkPermanent();

            cc._cachedBatch = batch;

            //private object _cacheSync = new object();
            _cacheSync = new object();

            return(cc);
        }
예제 #4
0
 public static McpeBatch CreateBatchPacket(byte[] input, int offset, int length, CompressionLevel compressionLevel, bool writeLen)
 {
     using (var stream = CompressIntoStream(input, offset, length, compressionLevel, writeLen))
     {
         var batch = McpeBatch.CreateObject();
         batch.payload = stream.ToArray();
         batch.Encode();
         return(batch);
     }
 }
예제 #5
0
        internal static McpeBatch CreateMcpeBatch(byte[] bytes)
        {
            MemoryStream memStream = MiNetServer.MemoryStreamManager.GetStream();

            memStream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4);
            memStream.Write(bytes, 0, bytes.Length);

            McpeBatch batch = McpeBatch.CreateObject();

            byte[] buffer = Player.CompressBytes(memStream.ToArray(), CompressionLevel.Optimal);
            batch.payloadSize = buffer.Length;
            batch.payload     = buffer;
            batch.Encode(true);
            return(batch);
        }
예제 #6
0
파일: Level.cs 프로젝트: Eros/MiNET
        public void DespawnFromAll(Player player)
        {
            lock (_playerWriteLock)
            {
                List <Player> spawnedPlayers = GetSpawnedPlayers().ToList();

                McpePlayerList playerListMessage = McpePlayerList.CreateObject();
                playerListMessage.records = new PlayerRemoveRecords(spawnedPlayers);
                var bytes = playerListMessage.Encode();
                playerListMessage.records = null;

                MemoryStream memStream = new MemoryStream();
                memStream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4);
                memStream.Write(bytes, 0, bytes.Length);

                McpeBatch batch  = McpeBatch.CreateObject();
                byte[]    buffer = Player.CompressBytes(memStream.ToArray(), CompressionLevel.Optimal);
                batch.payloadSize = buffer.Length;
                batch.payload     = buffer;
                batch.Encode();
                player.SendPackage(batch);

                foreach (Player spawnedPlayer in spawnedPlayers)
                {
                    SendRemoveForPlayer(player, spawnedPlayer, false);
                }

                McpePlayerList playerList = McpePlayerList.CreateObject();
                playerList.records = new PlayerRemoveRecords {
                    player
                };
                playerList.Encode();
                playerList.records = null;
                RelayBroadcast(player, playerList);

                McpeRemovePlayer removePlayerMessage = McpeRemovePlayer.CreateObject();
                removePlayerMessage.clientUuid = player.ClientUuid;
                removePlayerMessage.entityId   = player.EntityId;
                RelayBroadcast(player, removePlayerMessage);
            }
        }
예제 #7
0
        public void SendMoveList(List <McpeMovePlayer> movePlayerPackages)
        {
            if (!IsConnected)
            {
                return;
            }

            //if (Level.TickTime%4 != 0) return;

            int messageCount = 0;

            MemoryStream stream = new MemoryStream();

            foreach (var movePlayer in movePlayerPackages)
            {
                if (movePlayer.entityId != EntityId)
                {
                    messageCount++;
                    byte[] bytes = movePlayer.Encode();
                    stream.Write(bytes, 0, bytes.Length);
                }

                movePlayer.PutPool();
            }

            if (messageCount > 0)
            {
                McpeBatch batch  = McpeBatch.CreateObject();
                byte[]    buffer = CompressBytes(stream.ToArray());
                batch.payloadSize = buffer.Length;
                batch.payload     = buffer;
                batch.Encode();

                Server.SendPackage(this, new List <Package> {
                    batch
                }, _mtuSize, ref _reliableMessageNumber);
                //Server.SendPackage(EndPoint, messages, _mtuSize, ref _reliableMessageNumber);
            }
        }
예제 #8
0
        public static McpeBatch CreateBatchPacket(byte[] input, int offset, int length, CompressionLevel compressionLevel, bool writeLen)
        {
            var batch = McpeBatch.CreateObject();

            //using (var stream = CompressIntoStream(input, offset, length, compressionLevel, writeLen))

            if (writeLen)
            {
                var stream = MiNetServer.MemoryStreamManager.GetStream();
                WriteLength(stream, length);
                stream.Write(input, offset, length);
                batch.payload = stream.ToArray();
            }
            else
            {
                byte[] target = new byte[length];
                Buffer.BlockCopy(input, offset, target, 0, length);
                batch.payload = target;
            }

            batch.Encode();
            return(batch);
        }
예제 #9
0
파일: ChunkColumn.cs 프로젝트: oizma/MiNET
        public object Clone()
        {
            ChunkColumn cc = (ChunkColumn)MemberwiseClone();

            cc.chunks = new Chunk[16];
            for (int i = 0; i < chunks.Length; i++)
            {
                cc.chunks[i] = (Chunk)chunks[i].Clone();
            }

            cc.biomeId    = (byte[])biomeId.Clone();
            cc.biomeColor = (int[])biomeColor.Clone();
            cc.height     = (byte[])height.Clone();

            cc.BlockEntities = new Dictionary <BlockCoordinates, NbtCompound>();
            foreach (KeyValuePair <BlockCoordinates, NbtCompound> blockEntityPair in BlockEntities)
            {
                cc.BlockEntities.Add(blockEntityPair.Key, (NbtCompound)blockEntityPair.Value.Clone());
            }

            if (_cache != null)
            {
                cc._cache = (byte[])_cache.Clone();
            }

            McpeBatch batch = McpeBatch.CreateObject();

            batch.payload = _cachedBatch.payload;
            batch.Encode();
            batch.MarkPermanent();

            cc._cachedBatch = batch;

            _cacheSync = new object();

            return(cc);
        }
예제 #10
0
        protected virtual void BroadCastMovement(Player[] players, Entity[] entities)
        {
            if (players.Length == 0)
            {
                return;
            }

            DateTime tickTime = _lastSendTime;

            _lastSendTime = DateTime.UtcNow;
            DateTime now = DateTime.UtcNow;

            MemoryStream stream = MiNetServer.MemoryStreamManager.GetStream();

            int            count = 0;
            McpeMovePlayer move  = McpeMovePlayer.CreateObject();

            foreach (var player in players)
            {
                if (((now - player.LastUpdatedTime) <= now - tickTime))
                {
                    PlayerLocation knownPosition = player.KnownPosition;

                    move.entityId = player.EntityId;
                    move.x        = knownPosition.X;
                    move.y        = knownPosition.Y + 1.62f;
                    move.z        = knownPosition.Z;
                    move.yaw      = knownPosition.Yaw;
                    move.pitch    = knownPosition.Pitch;
                    move.headYaw  = knownPosition.HeadYaw;
                    move.mode     = 0;
                    byte[] bytes = move.Encode();
                    stream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4);
                    stream.Write(bytes, 0, bytes.Length);
                    move.Reset();
                    count++;
                }
            }
            move.PutPool();

            McpeMoveEntity moveEntity = McpeMoveEntity.CreateObject();

            moveEntity.entities = new EntityLocations();

            McpeSetEntityMotion entityMotion = McpeSetEntityMotion.CreateObject();

            entityMotion.entities = new EntityMotions();

            foreach (var entity in entities)
            {
                if (((now - entity.LastUpdatedTime) <= now - tickTime))
                {
                    moveEntity.entities.Add(entity.EntityId, entity.KnownPosition);
                    entityMotion.entities.Add(entity.EntityId, entity.Velocity);
                    count++;
                }
            }

            if (moveEntity.entities.Count > 0)
            {
                byte[] bytes = moveEntity.Encode();
                stream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4);
                stream.Write(bytes, 0, bytes.Length);
            }
            moveEntity.PutPool();

            if (moveEntity.entities.Count > 0)
            {
                byte[] bytes = entityMotion.Encode();
                stream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4);
                stream.Write(bytes, 0, bytes.Length);
            }
            entityMotion.PutPool();

            if (count == 0)
            {
                return;
            }

            McpeBatch batch = McpeBatch.CreateObject(players.Length);

            byte[] buffer = Player.CompressBytes(stream.ToArray(), CompressionLevel.Optimal);
            batch.payloadSize = buffer.Length;
            batch.payload     = buffer;
            batch.Encode(true);

            foreach (var player in players)
            {
                Task sendTask = new Task(obj => ((Player)obj).SendMoveList(batch, now), player);
                sendTask.Start();
            }
        }
예제 #11
0
파일: Level.cs 프로젝트: Eros/MiNET
        public void SpawnToAll(Player newPlayer)
        {
            lock (_playerWriteLock)
            {
                List <Player> spawnedPlayers = GetSpawnedPlayers().ToList();
                spawnedPlayers.Add(newPlayer);

                Player[] sendList = spawnedPlayers.ToArray();

                McpePlayerList playerListMessage = McpePlayerList.CreateObject();
                playerListMessage.records = new PlayerAddRecords(spawnedPlayers);
                var bytes = playerListMessage.Encode();
                playerListMessage.records = null;

                MemoryStream memStream = new MemoryStream();
                memStream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4);
                memStream.Write(bytes, 0, bytes.Length);

                McpeBatch batch  = McpeBatch.CreateObject();
                byte[]    buffer = Player.CompressBytes(memStream.ToArray(), CompressionLevel.Optimal);
                batch.payloadSize = buffer.Length;
                batch.payload     = buffer;
                batch.Encode();

                newPlayer.SendPackage(batch);

                McpePlayerList playerList = McpePlayerList.CreateObject();
                playerList.records = new PlayerAddRecords {
                    newPlayer
                };
                playerList.Encode();
                playerList.records = null;
                RelayBroadcast(newPlayer, sendList, playerList);

                McpeAddPlayer mcpeAddPlayer = McpeAddPlayer.CreateObject();
                mcpeAddPlayer.uuid     = newPlayer.ClientUuid;
                mcpeAddPlayer.username = newPlayer.Username;
                mcpeAddPlayer.entityId = newPlayer.EntityId;
                mcpeAddPlayer.x        = newPlayer.KnownPosition.X;
                mcpeAddPlayer.y        = newPlayer.KnownPosition.Y;
                mcpeAddPlayer.z        = newPlayer.KnownPosition.Z;
                mcpeAddPlayer.yaw      = newPlayer.KnownPosition.Yaw;
                mcpeAddPlayer.headYaw  = newPlayer.KnownPosition.HeadYaw;
                mcpeAddPlayer.pitch    = newPlayer.KnownPosition.Pitch;
                mcpeAddPlayer.metadata = newPlayer.GetMetadata();
                RelayBroadcast(newPlayer, sendList, mcpeAddPlayer);

                McpePlayerEquipment mcpePlayerEquipment = McpePlayerEquipment.CreateObject();
                mcpePlayerEquipment.entityId = newPlayer.EntityId;
                mcpePlayerEquipment.item     = new MetadataSlot(newPlayer.Inventory.GetItemInHand());
                mcpePlayerEquipment.slot     = 0;
                RelayBroadcast(newPlayer, sendList, mcpePlayerEquipment);

                McpePlayerArmorEquipment mcpePlayerArmorEquipment = McpePlayerArmorEquipment.CreateObject();
                mcpePlayerArmorEquipment.entityId   = newPlayer.EntityId;
                mcpePlayerArmorEquipment.helmet     = new MetadataSlot(new ItemStack(newPlayer.Inventory.Helmet, 0));
                mcpePlayerArmorEquipment.chestplate = new MetadataSlot(new ItemStack(newPlayer.Inventory.Chest, 0));
                mcpePlayerArmorEquipment.leggings   = new MetadataSlot(new ItemStack(newPlayer.Inventory.Leggings, 0));
                mcpePlayerArmorEquipment.boots      = new MetadataSlot(new ItemStack(newPlayer.Inventory.Boots, 0));
                RelayBroadcast(newPlayer, sendList, mcpePlayerArmorEquipment);

                foreach (Player spawnedPlayer in spawnedPlayers)
                {
                    SendAddForPlayer(newPlayer, spawnedPlayer, false);
                }
            }
        }
예제 #12
0
        internal void HandlePackage(Package message, PlayerNetworkSession playerSession)
        {
            try
            {
                if (message == null)
                {
                    return;
                }

                if (typeof(McpeWrapper) == message.GetType())
                {
                    McpeWrapper wrapper = (McpeWrapper)message;

                    // Get bytes
                    byte[] payload = wrapper.payload;
                    //if (Log.IsDebugEnabled) Log.Debug($"Received package 0x{message.Id:X2}\n{Package.HexDump(payload)}");

                    if (playerSession.CryptoContext != null && playerSession.CryptoContext.UseEncryption)
                    {
                        payload = CryptoUtils.Decrypt(payload, playerSession.CryptoContext);
                    }

                    McpeBatch batch = McpeBatch.CreateObject();
                    batch.payload = payload;

                    HandlePackage(batch, playerSession);

                    //if (Log.IsDebugEnabled)
                    //	Log.Debug($"0x{payload[0]:x2}\n{Package.HexDump(payload)}");

                    //var msg = PackageFactory.CreatePackage(payload[0], payload, "mcpe") ?? new UnknownPackage(payload[0], payload);
                    //msg.DatagramSequenceNumber = wrapper.DatagramSequenceNumber;
                    //msg.Reliability = wrapper.Reliability;
                    //msg.ReliableMessageNumber = wrapper.ReliableMessageNumber;
                    //msg.OrderingChannel = wrapper.OrderingChannel;
                    //msg.OrderingIndex = wrapper.OrderingIndex;
                    //HandlePackage(msg, playerSession);

                    message.PutPool();
                    return;
                }

                if (typeof(UnknownPackage) == message.GetType())
                {
                    UnknownPackage packet = (UnknownPackage)message;
                    if (Log.IsDebugEnabled)
                    {
                        Log.Warn($"Received unknown package 0x{message.Id:X2}\n{Package.HexDump(packet.Message)}");
                    }

                    message.PutPool();
                    return;
                }

                if (typeof(McpeBatch) == message.GetType())
                {
                    McpeBatch batch = (McpeBatch)message;

                    var messages = new List <Package>();

                    // Get bytes
                    byte[] payload = batch.payload;
                    // Decompress bytes

                    MemoryStream stream = new MemoryStream(payload);
                    if (stream.ReadByte() != 0x78)
                    {
                        throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
                    }
                    stream.ReadByte();
                    using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false))
                    {
                        // Get actual package out of bytes
                        using (MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream())
                        {
                            defStream2.CopyTo(destination);
                            destination.Position = 0;
                            NbtBinaryReader reader = new NbtBinaryReader(destination, true);

                            while (destination.Position < destination.Length)
                            {
                                //int len = reader.ReadInt32();
                                int    len            = BatchUtils.ReadLength(destination);
                                byte[] internalBuffer = reader.ReadBytes(len);

                                //if (Log.IsDebugEnabled)
                                //	Log.Debug($"0x{internalBuffer[0]:x2}\n{Package.HexDump(internalBuffer)}");

                                messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer, "mcpe") ??
                                             new UnknownPackage(internalBuffer[0], internalBuffer));
                            }

                            if (destination.Length > destination.Position)
                            {
                                throw new Exception("Have more data");
                            }
                        }
                    }
                    foreach (var msg in messages)
                    {
                        msg.DatagramSequenceNumber = batch.DatagramSequenceNumber;
                        msg.Reliability            = batch.Reliability;
                        msg.ReliableMessageNumber  = batch.ReliableMessageNumber;
                        msg.OrderingChannel        = batch.OrderingChannel;
                        msg.OrderingIndex          = batch.OrderingIndex;
                        HandlePackage(msg, playerSession);
                    }

                    message.PutPool();
                    return;
                }

                MiNetServer.TraceReceive(message);

                if (CryptoContext != null && CryptoContext.UseEncryption)
                {
                    MiNetServer.FastThreadPool.QueueUserWorkItem(delegate()
                    {
                        HandlePackage(MessageHandler, message as Package);
                        message.PutPool();
                    });
                }
                else
                {
                    HandlePackage(MessageHandler, message);
                    message.PutPool();
                }
            }
            catch (Exception e)
            {
                Log.Error("Package handling", e);
                throw;
            }
        }
예제 #13
0
        private void SendQueue(object sender)
        {
            if (!IsConnected)
            {
                return;
            }

            Queue <Package> queue = _sendQueueNotConcurrent;

            int messageCount = 0;

            int          lenght = queue.Count;
            MemoryStream stream = new MemoryStream();

            for (int i = 0; i < lenght; i++)
            {
                Package package = null;
                lock (_queueSync)
                {
                    if (queue.Count == 0)
                    {
                        break;
                    }
                    try
                    {
                        package = queue.Dequeue();
                    }
                    catch (Exception e)
                    {
                    }
                }

                if (package == null)
                {
                    continue;
                }

                byte[] bytes = package.Encode();
                if (bytes != null)
                {
                    messageCount++;
                    stream.Write(bytes, 0, bytes.Length);
                    package.PutPool();
                }
            }

            if (messageCount == 0)
            {
                return;
            }

            McpeBatch batch = McpeBatch.CreateObject();

            byte[] buffer = CompressBytes(stream.ToArray());
            batch.payloadSize = buffer.Length;
            batch.payload     = buffer;
            batch.Encode();

            Server.SendPackage(this, new List <Package> {
                batch
            }, _mtuSize, ref _reliableMessageNumber);
            //Server.SendPackage(EndPoint, messages, _mtuSize, ref _reliableMessageNumber);
        }
예제 #14
0
        /// <summary>
        ///     Sends the chunks for known position.
        /// </summary>
        private void SendChunksForKnownPosition()
        {
            var chunkPosition = new ChunkCoordinates(KnownPosition);

            if (IsSpawned && _currentChunkPosition == chunkPosition)
            {
                return;
            }

            _currentChunkPosition = chunkPosition;

            ThreadPool.QueueUserWorkItem(delegate(object state)
            {
                int packetCount = 0;

                if (!IsBot)
                {
                    while (Rtt < 0)
                    {
                        Thread.Yield();
                    }
                }

                MemoryStream stream = new MemoryStream();
                foreach (var chunk in Level.GenerateChunks(_currentChunkPosition, _chunksUsed))
                {
                    McpeFullChunkData fullChunkData = McpeFullChunkData.CreateObject();
                    fullChunkData.chunkX            = chunk.x;
                    fullChunkData.chunkZ            = chunk.z;
                    fullChunkData.chunkData         = chunk.GetBytes();
                    fullChunkData.chunkDataLength   = fullChunkData.chunkData.Length;


                    McpeBatch batch   = McpeBatch.CreateObject();
                    byte[] buffer     = CompressBytes(fullChunkData.Encode());
                    batch.payloadSize = buffer.Length;
                    batch.payload     = buffer;
                    fullChunkData.PutPool();

                    // This is to slow down chunk-sending not to overrun old devices.
                    // The timeout should be configurable and enable/disable.
                    if (Math.Floor(Rtt / 10d) > 0)
                    {
                        Thread.Sleep(Math.Min(Math.Max((int)Math.Floor(Rtt / 10d), 12) + 10, 40));
                    }

                    SendPackage(batch, sendDirect: true);
                    //var bytes = fullChunkData.Encode();
                    //stream.Write(bytes, 0, bytes.Length);
                    if (!IsSpawned)
                    {
                        if (packetCount++ == 56)
                        {
                            InitializePlayer();
                        }
                    }
                }

                //McpeBatch batch = new McpeBatch();
                //byte[] buffer = CompressBytes(stream.ToArray());
                //batch.payloadSize = buffer.Length;
                //batch.payload = buffer;
                //batch.Encode();

                //SendPackage(batch);
            });
        }