Ejemplo n.º 1
0
    public void MinecraftPacketReadVarInt64Test(long expectedValue, byte[] packetContent)
    {
        using var packet = new MinecraftPacket(0, packetContent);

        long value = packet.ReadVarInt64();

        Assert.Equal(expectedValue, value);
    }
Ejemplo n.º 2
0
 public void SendPacketViewers(MinecraftPacket packet)
 {
     Player[] players = this.Viewers;
     for (int i = 0; i < players.Length; ++i)
     {
         players[i].SendPacket(packet);
     }
 }
Ejemplo n.º 3
0
    public void MinecraftPacketWriteVarInt64Test(long valueToWrite, byte[] expectedContent)
    {
        using var packet = new MinecraftPacket(0);

        packet.WriteVarInt64(valueToWrite);

        Assert.Equal(expectedContent, packet.BaseBuffer);
    }
Ejemplo n.º 4
0
    private void SendLoginSucess(IMinecraftUser user)
    {
        using var p = new MinecraftPacket(ClientLoginPacketType.LoginSuccess);

        p.WriteUUID(user.Id);
        p.WriteString(user.Username);

        user.Send(p);
    }
Ejemplo n.º 5
0
        public void SendPacket(MinecraftPacket packet, int reliability = RakNetPacketReliability.RELIABLE, int flag = RakNetProtocol.FlagNormal)
        {
            NetworkSession session = this.GetSession();

            if (session == null)
            {
                return;
            }

            session.AddPacketBatchQueue(packet, reliability, flag);
        }
Ejemplo n.º 6
0
        public void BroadcastSendPacket(MinecraftPacket packet, Player[] players = null)
        {
            if (players == null)
            {
                players = Instance.GetPlayers();
            }

            for (int i = 0; i < players.Length; ++i)
            {
                players[i].SendPacket(packet);
            }
        }
Ejemplo n.º 7
0
    public override void AddVisibleEntity(IEntity entity)
    {
        base.AddVisibleEntity(entity);

        using MinecraftPacket packet = entity switch
              {
                  IPlayer playerEntity => new SpawnPlayerPacket(playerEntity),
                  // TODO: add other entity types
                  _ => throw new NotImplementedException()
              };
        SendPacket(packet);
    }
Ejemplo n.º 8
0
    public void Serialize(IMinecraftPacket packet, bool fullChunk = false)
    {
        packet.WriteInt32(X);
        packet.WriteInt32(Z);
        packet.WriteBoolean(fullChunk);

        int mask = 0;

        // if full chunk
        using var chunkStream = new MinecraftPacket();
        for (int i = 0; i < Sections.Count(); i++)
        {
            IChunkSection section = Sections.ElementAt(i);

            if (fullChunk || section.IsDirty)
            {
                mask |= 1 << i;
                section.Serialize(chunkStream);
            }
        }

        packet.WriteVarInt32(mask);

        // Heightmap serialization
        var heightmapCompound = new NbtCompound("")
        {
            new NbtLongArray("MOTION_BLOCKING", Heightmap.ToArray()),
            new NbtLongArray("WORLD_SURFACE", WorldSurfaceHeightmap.ToArray())
        };
        var nbtFile = new NbtFile(heightmapCompound);

        packet.WriteBytes(nbtFile.GetBuffer());

        // Biomes
        if (fullChunk)
        {
            packet.WriteVarInt32(1024);

            for (int i = 0; i < 1024; i++)
            {
                packet.WriteVarInt32(0);
            }
        }

        chunkStream.Position = 0;

        packet.WriteVarInt32((int)chunkStream.Length);
        packet.WriteBytes(chunkStream.BaseBuffer);

        packet.WriteVarInt32(0); // block count
        // TODO: foreach block in blocks in chunk as NBT
    }
Ejemplo n.º 9
0
    public void MinecraftPacketWriteJsonTest()
    {
        const string json = "{\"text\":\"Hello world!\"}";

        byte[] jsonBytes  = Encoding.UTF8.GetBytes(json);
        var    jsonObject = new JsonPacketClass("Hello world!");

        using var packet = new MinecraftPacket(0);

        packet.WriteJson(jsonObject);

        byte[] packetBytes = packet.BaseBuffer.Skip(1).ToArray();
        Assert.Equal(jsonBytes, packetBytes);
    }
Ejemplo n.º 10
0
        public MinecraftPacket GetMinecraftPacket(int msgId, byte[] buffer = null)
        {
            MinecraftPacket pk = null;

            MineNET_Registries.MinecraftPacket.TryGetValue(msgId, out pk);
            pk = pk?.Clone();

            if (pk != null && buffer != null)
            {
                pk.SetBuffer(buffer);
                pk.Decode();
            }

            return(pk);
        }
Ejemplo n.º 11
0
        public void AddPacketBatchQueue(MinecraftPacket packet, int reliability, int flags = RakNetProtocol.FlagNormal)
        {
            packet.Encode();

            byte[] buffer = packet.ToArray();

            BinaryStream st = new BinaryStream();

            st.WriteVarInt((int)buffer.Length);
            st.WriteBytes(buffer);

            if (Server.Instance.Config.PacketDebug)
            {
                Logger.Debug("%server.network.minecraft.sendPacket", packet.PacketID.ToString("X"), packet.Length);
            }

            BatchPacket pk = new BatchPacket();

            if (packet is FullChunkDataPacket)
            {
                pk.CompressionLevel = CompressionLevel.Optimal;
            }

            pk.Payload = st.ToArray();

            string endPointStr = this.EndPoint.ToString();
            Player player      = null;

            Server.Instance.Network.Players.TryGetValue(endPointStr, out player);
            if (player == null)
            {
                return;
            }

            RakNetBatchPacketSendEventArgs ev = new RakNetBatchPacketSendEventArgs(this, player, pk);

            Server.Instance.Event.Network.OnRakNetBatchPacketSend(this, ev);

            if (ev.IsCancel)
            {
                return;
            }

            pk = ev.Packet;

            this.QueueConnectedPacket(pk, reliability, packet.OrderChannel, flags);
        }
Ejemplo n.º 12
0
    public void MinecraftPacketReadUUIDTest(Guid expectedValue, byte[] packetContent)
    {
        // FIX: little/big Endian
        if (BitConverter.IsLittleEndian)
        {
            byte[] firstLong  = packetContent.Take(8).Reverse().ToArray();
            byte[] secondLong = packetContent.Skip(8).Reverse().ToArray();

            packetContent = firstLong.Concat(secondLong).ToArray();
        }

        using var packet = new MinecraftPacket(0, packetContent);

        Guid value = packet.ReadUUID();

        Assert.Equal(expectedValue, value);
    }
Ejemplo n.º 13
0
    public void MinecraftPacketWriteUUIDTest(Guid valueToWrite, byte[] expectedContent)
    {
        using var packet = new MinecraftPacket(0);

        packet.WriteUUID(valueToWrite);

        // FIX: little/big Endian
        if (BitConverter.IsLittleEndian)
        {
            byte[] firstLong  = expectedContent.Take(8).Reverse().ToArray();
            byte[] secondLong = expectedContent.Skip(8).Reverse().ToArray();

            expectedContent = firstLong.Concat(secondLong).ToArray();
        }

        Assert.Equal(expectedContent, packet.BaseBuffer);
    }
Ejemplo n.º 14
0
        public void Write(MinecraftPacket stream)
        {
            stream.WriteSVarInt(this.ID);

            stream.WriteUVarInt((uint)this.RecipeItems.Length);
            for (int i = 0; i < this.RecipeItems.Length; ++i)
            {
                stream.WriteItem(this.RecipeItems[i]);
            }

            stream.WriteUVarInt((uint)this.Output.Length);
            for (int i = 0; i < this.Output.Length; ++i)
            {
                stream.WriteItem(this.Output[i]);
            }

            stream.WriteUUID(this.UUID);
        }
Ejemplo n.º 15
0
        public void MulticastAsync(MinecraftPacket packet, TcpSession excludeSession = null, params TcpSession[] sessions)
        {
            Task.Run(() => {
                if (!IsStarted)
                {
                    return;
                }

                if (packet == null)
                {
                    return;
                }

                foreach (TcpSession session in sessions)
                {
                    if (session is MinecraftClient client)
                    {
                        if (client.GameState != MinecraftClient.State.Playing)
                        {
                            continue;
                        }

                        if (excludeSession != null)
                        {
                            if (session != excludeSession)
                            {
                                client.Send(new MinecraftPacket(client, packet));
                            }
                        }
                        else
                        {
                            client.Send(new MinecraftPacket(client, packet));
                        }
                    }
                }

                packet.Dispose();
            });
        }
Ejemplo n.º 16
0
        public void HandleInventoryAction(MinecraftPacket packet)
        {
            switch (packet)
            {
            case CP25HeldItemChange heldItemChange:
                Inventory.HeldSlot = heldItemChange.Slot + 36;     // mojang moment
                break;

            case CP28CreativeInventoryAction creativeInventoryAction:
                if (creativeInventoryAction.Slot == -1)
                {
                    // TODO spawn item entity here
                }
                else
                {
                    Inventory.Slots[creativeInventoryAction.Slot]
                        = creativeInventoryAction.ClickedItem.IsEmpty() ?
                          Inventories.Inventory.Slot.Empty : creativeInventoryAction.ClickedItem;
                }
                break;
            }
        }
Ejemplo n.º 17
0
        public void HandleMinecraftPacket(BatchPacket pk, Player player)
        {
            using (BinaryStream stream = new BinaryStream(pk.Payload))
            {
                while (!stream.EndOfStream)
                {
                    int             len    = stream.ReadVarInt();
                    byte[]          buffer = stream.ReadBytes(len);
                    MinecraftPacket packet = this.Manager.GetMinecraftPacket(buffer[0], buffer);
                    if (packet != null)
                    {
                        /*DataPacketReceiveArgs args = new DataPacketReceiveArgs(player, pk);
                         * ServerEvents.OnPacketReceive(args);
                         *
                         * if (args.IsCancel)
                         * {
                         *  return;
                         * }*/

                        if (Server.Instance.Config.PacketDebug)
                        {
                            Logger.Debug("%server.network.minecraft.receivePacket", buffer[0].ToString("X"),
                                         buffer.Length);
                        }


                        Server.Instance.Invoke(() => player.OnPacketHandle(packet.Clone()));
                    }
                    else
                    {
                        if (Server.Instance.Config.PacketDebug)
                        {
                            Logger.Debug("%server.network.minecraft.notHandle", buffer[0].ToString("X"));
                        }
                    }
                }
            }
        }
Ejemplo n.º 18
0
        public static void Run(string[] args)
        {
            Directory.CreateDirectory(WORLDS_DIRECTORY);

            Logger.Out = Console.Out;

#if DEBUG
            Logger.MinimumLevel = LogLevel.Debug;
#else
            Logger.MinimumLevel = LogLevel.Info;
#endif

            AppDomain.CurrentDomain.UnhandledException += ShutdownHook;
            AppDomain.CurrentDomain.ProcessExit        += ShutdownHook;

            MinecraftPacket.Initialize();
            BaseEntity.Initialize();
            BlockRepository.Initialize();
            ItemRepository.Initialize();
            Tag.Initialize();

            Server = new MinecraftServer(IPAddress.Any, args.Length > 0 ? int.Parse(args[0]) : 25565);
            Server.Start();
        }
Ejemplo n.º 19
0
        private void WriteChunkSection(ChunkSection section, ref MemoryStream stream)
        {
            #region Section
            byte bitsPerBlock = FULL_SIZE_BITS_PER_BLOCK;

            MinecraftPacket.WriteToStream(stream, bitsPerBlock);
            //0: disabled?
            //MinecraftPacket.WriteToStream(stream, (VarInt)0);   //up to 4: Blocks are encoded as 4 bits. The palette is used and sent.
            //5 to 8: Blocks are encoded with the given number of bits.The palette is used and sent.
            //9 and above: The palette is not sent. Blocks are encoded by their whole ID in the global palette, with bits per block being set as the base 2 logarithm of the number of block states, rounded up. For the current vanilla release, this is 14 bits per block.

            // A bitmask that contains bitsPerBlock set bits
            uint individualValueMask = (uint)((1 << bitsPerBlock) - 1);

            int      dataLength = (Constants.SECTION_HEIGHT * Constants.SECTION_WIDTH * Constants.SECTION_DEPTH) * bitsPerBlock / 64;
            UInt64[] DataArray  = new UInt64[dataLength];

            for (int y = 0; y < Constants.SECTION_HEIGHT; y++)
            {
                for (int z = 0; z < Constants.SECTION_WIDTH; z++)
                {
                    for (int x = 0; x < Constants.SECTION_WIDTH; x++)
                    {
                        var blockPos = new Vector3(x, y, z);

                        int blockNumber = ((((int)blockPos.Y * Constants.SECTION_HEIGHT) + (int)blockPos.Z) * Constants.SECTION_WIDTH) + (int)blockPos.X;
                        int startLong   = (blockNumber * bitsPerBlock) / 64;
                        int startOffset = (blockNumber * bitsPerBlock) % 64;
                        int endLong     = ((blockNumber + 1) * bitsPerBlock - 1) / 64;

                        Block state = section.blocks[blockPos];

                        //C# Still limits the Byte Size to uint if this is a uint,
                        //even after byteshifting into a ulong
                        ulong value = (ulong)state.GetGlobalPaletteIDFromState();
                        value &= individualValueMask;

                        DataArray[startLong] |= (value << startOffset);

                        if (startLong != endLong)
                        {
                            DataArray[endLong] = (value >> (64 - startOffset));
                        }
                    }
                }
            }

            Console.WriteLine($"Data Array was {DataArray.Length} long");
            MinecraftPacket.WriteToStream(stream, (VarInt)dataLength);
            MinecraftPacket.WriteArrayToStream(stream, DataArray);

            List <byte> BlockLightData = new List <byte>();
            for (int y = 0; y < Constants.SECTION_HEIGHT; y++)
            {
                for (int z = 0; z < Constants.SECTION_WIDTH; z++)
                {
                    for (int x = 0; x < Constants.SECTION_WIDTH; x += 2)
                    {
                        // Note: x += 2 above; we read 2 values along x each time
                        byte blocklight1 = (byte)(section.blocks[new Vector3(x, y, z)].BlockLight);
                        //this only works because 16 is even
                        byte blocklight2 = (byte)(section.blocks[new Vector3(x + 1, y, z)].BlockLight << 4);
                        byte value       = (byte)(blocklight1 | blocklight2);
                        BlockLightData.Add(value);
                    }
                }
            }
            Console.WriteLine($"BlockLight was {BlockLightData.Count} Long");
            MinecraftPacket.WriteArrayToStream(stream, BlockLightData.ToArray());

            List <byte> SkyLightData = new List <byte>();
            if (section.HasSkylight)
            { // => current dimension is overworld / 0
                for (int y = 0; y < Constants.SECTION_HEIGHT; y++)
                {
                    for (int z = 0; z < Constants.SECTION_WIDTH; z++)
                    {
                        for (int x = 0; x < Constants.SECTION_WIDTH; x += 2)
                        {
                            // Note: x += 2 above; we read 2 values along x each time
                            byte blocklight1 = (byte)(section.blocks[new Vector3(x, y, z)].SkyLight);
                            //this only works because 16 is even
                            byte blocklight2 = (byte)(section.blocks[new Vector3(x + 1, y, z)].SkyLight << 4);
                            byte value       = (byte)(blocklight1 | blocklight2);
                            SkyLightData.Add(value);
                        }
                    }
                }
            }
            Console.WriteLine($"SkyLight was {SkyLightData.Count} Long");
            MinecraftPacket.WriteArrayToStream(stream, SkyLightData.ToArray());
            #endregion
        }
Ejemplo n.º 20
0
        public void HandleWorldAction(MinecraftPacket packet)
        {
            switch (packet)
            {
            case CP1BPlayerDigging digging:
                bool IsLegal(double x1, double y1, double z1, double x2, double y2, double z2)
                {
                    return(Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2) + Math.Pow(z2 - z1, 2)) <= 6.0);
                }

                BlockBase block = Parent.GetBlock(digging.Location.X, digging.Location.Y, digging.Location.Z);
                SP07AcknowledgePlayerDigging acknowledgePlayerDigging;

                if (block == null)
                {
                    acknowledgePlayerDigging = new SP07AcknowledgePlayerDigging(Client, digging.Location, 0,
                                                                                (SP07AcknowledgePlayerDigging.ActionType)digging.Status, false);
                    Client.Send(acknowledgePlayerDigging);
                    break;
                }

                if (!IsLegal(X, Y + 1.5, Z, digging.Location.X, digging.Location.Y, digging.Location.Z))
                {
                    acknowledgePlayerDigging = new SP07AcknowledgePlayerDigging(Client, digging.Location, block.State,
                                                                                (SP07AcknowledgePlayerDigging.ActionType)digging.Status, false);
                    Client.Send(acknowledgePlayerDigging);
                    break;
                }

                acknowledgePlayerDigging = new SP07AcknowledgePlayerDigging(Client, digging.Location, block.State,
                                                                            (SP07AcknowledgePlayerDigging.ActionType)digging.Status, true);
                Client.Send(acknowledgePlayerDigging);

                // TODO block break animation

                CP1BPlayerDigging.ActionType requiredAction;

                if (Gamemode == Gamemode.Creative)
                {
                    requiredAction = CP1BPlayerDigging.ActionType.StartedDigging;
                }
                else
                {
                    requiredAction = CP1BPlayerDigging.ActionType.FinishedDigging;
                }

                if (digging.Status == requiredAction)
                {
                    BlockBase air = new BlockAir();

                    Parent.SetBlock(air, digging.Location.X, digging.Location.Y, digging.Location.Z);

                    SP0BBlockChange blockChange = new(null, digging.Location, air.State);
                    Client.Server.MulticastAsync(blockChange, Client, Parent.GetClientsWithChunkLoaded(
                                                     (int)Math.Floor((double)digging.Location.X / Chunk.X_SIZE),
                                                     (int)Math.Floor((double)digging.Location.Z / Chunk.Z_SIZE)).ToArray());
                }
                break;

            case CP2EPlayerBlockPlacement playerBlockPlacement:
                Position.Int pos = new(playerBlockPlacement.Location);

                switch (playerBlockPlacement.Face)
                {
                case Face.Top:
                    pos.Y++;
                    break;

                case Face.Bottom:
                    pos.Y--;
                    break;

                case Face.North:
                    pos.Z--;
                    break;

                case Face.East:
                    pos.X++;
                    break;

                case Face.South:
                    pos.Z++;
                    break;

                case Face.West:
                    pos.X--;
                    break;
                }

                // TODO check for collisions here

                if (Parent.GetBlock(pos.X, pos.Y, pos.Z) == null)
                {
                    Inventory.Slot held = Inventory.Slots[Inventory.HeldSlot];

                    if (!held.IsEmpty() && held.Item is BlockItem item)
                    {
                        block = BlockRepository.Create(item.BlockProtocolId);

                        if (block == null || block.State == 0)
                        {
                            break;
                        }

                        if (pos.Y < 0 || pos.Y >= Chunk.Y_SIZE)
                        {
                            return;
                        }

                        Parent.SetBlock(block, pos.X, pos.Y, pos.Z);

                        SP0BBlockChange _blockChange = new(null, pos, block.State);
                        Client.Server.MulticastAsync(_blockChange, Client, Parent.GetClientsWithChunkLoaded(
                                                         (int)Math.Floor((double)pos.X / Chunk.X_SIZE),
                                                         (int)Math.Floor((double)pos.Z / Chunk.Z_SIZE)).ToArray());
                    }
                }
                break;

            case CP1CEntityAction:
                break;
            }
        }
Ejemplo n.º 21
0
        public void HandleMovement(MinecraftPacket packet)
        {
            LastX        = X;
            LastY        = Y;
            LastZ        = Z;
            LastOnGround = OnGround;

            double newX        = X;
            double newY        = Y;
            double newZ        = Z;
            float  newYaw      = Yaw;
            float  newPitch    = Pitch;
            bool   newOnGround = OnGround;

            switch (packet)
            {
            case CP12PlayerPosition p:
                newX        = p.X;
                newY        = p.FeetY;
                newZ        = p.Z;
                newOnGround = p.OnGround;
                break;

            case CP13PlayerPositionAndRotation _p:
                newX        = _p.X;
                newY        = _p.FeetY;
                newZ        = _p.Z;
                newYaw      = _p.Yaw;
                newPitch    = _p.Pitch;
                newOnGround = _p.OnGround;
                break;

            case CP14PlayerRotation __p:
                newYaw      = __p.Yaw;
                newPitch    = __p.Pitch;
                newOnGround = __p.OnGround;
                break;

            case CP15PlayerMovement:
                SP2AEntityMovement entityMovement = new(Client, EntityId);
                Client.Server.MulticastAsync(entityMovement, Client);
                return;
            }

            if (newX != LastX || newY != LastY || newZ != LastZ)
            {
                if (double.IsInfinity(newX) || double.IsInfinity(newY) || double.IsInfinity(newZ) ||
                    newX > 3.2 * Math.Pow(10, 7) || newZ > 3.2 * Math.Pow(10, 7))
                {
                    SP19Disconnect disconnect = new(Client, new {
                        text = "Invalid move packet received"
                    });
                    Client.Send(disconnect);
                    Client.Disconnect();
                }

                double deltaX = newX - LastX;
                double deltaY = newY - LastY;
                double deltaZ = newZ - LastZ;

                double total    = Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2) + Math.Pow(deltaZ, 2);
                double expected = Math.Pow(LastX, 2) + Math.Pow(LastY, 2) + Math.Pow(LastZ, 2);

                // TODO               300 if elytra
                if (total - expected > 100)
                {
                    Logger.Info($"Player [{Username}] moved too fast!");

                    SP56EntityTeleport teleport = new(Client, EntityId, LastX, LastY, LastZ,
                                                      Yaw, Pitch, LastOnGround);
                    Client.Send(teleport);
                }

                X        = newX;
                Y        = newY;
                Z        = newZ;
                OnGround = newOnGround;

                SP27EntityPosition entityPosition = new(Client, EntityId,
                                                        (short)(((X * 32) - (LastX * 32)) * 128),
                                                        (short)(((Y * 32) - (LastY * 32)) * 128),
                                                        (short)(((Z * 32) - (LastZ * 32)) * 128),
                                                        OnGround);
                Client.Server.MulticastAsync(entityPosition, Client);

                // player changed chunk
                if (ChunkX != (int)Math.Floor(LastX / Chunk.X_SIZE) ||
                    ChunkZ != (int)Math.Floor(LastZ / Chunk.Z_SIZE))
                {
                    SP40UpdateViewPosition updateViewPosition = new(Client, ChunkX, ChunkZ);
                    Client.Send(updateViewPosition);

                    Chunk[] chunks = Parent.GetChunksInViewDistance(ChunkX, ChunkZ, Client.Configuration.ViewDistance);

                    IEnumerable <Chunk> toUnload = Client.LoadedChunks.Except(chunks);
                    IEnumerable <Chunk> toLoad   = chunks.Except(Client.LoadedChunks);

                    Client.UnloadChunks(toUnload.ToArray());
                    Client.LoadChunks(toLoad.ToArray());
                }
            }

            // TODO fix this somehow
            if (newYaw != Yaw || newPitch != Pitch)
            {
                double x = -Math.Cos(newPitch) * Math.Sin(newYaw);
                double y = -Math.Sin(newPitch);
                double z = Math.Cos(newPitch) * Math.Cos(newYaw);

                double dx = x - X;
                double dy = y - Y;
                double dz = z - Z;

                double r   = Math.Sqrt((dx * dx) + (dy * dy) + (dz * dz));
                double yaw = (-Math.Atan2(dx, dz) / Math.PI) * 180;

                if (yaw < 0)
                {
                    yaw = 360 + yaw;
                }

                double pitch = (-Math.Asin(dy / r) / Math.PI) * 180;

                Yaw   = (float)yaw;
                Pitch = (float)pitch;

                OnGround = newOnGround;

                SP29EntityRotation entityRotation = new(Client, EntityId, Yaw, Pitch, OnGround);
                Client.Server.MulticastAsync(entityRotation, Client);
            }
        }
Ejemplo n.º 22
0
 public void Write(MinecraftPacket stream)
 {
     throw new System.NotImplementedException();
 }