Exemple #1
0
    public void OnPlayerDigging(IMinecraftUser user, IMinecraftPacket packet)
    {
        var status   = (DiggingType)packet.ReadVarInt32();
        var position = packet.ReadPosition();
        var face     = (BlockFaceType)packet.ReadByte();

        _logger.LogTrace($"Status={status};Position={position};Face={face}");

        if (user.Player.GameMode is ServerGameModeType.Creative)
        {
            IBlock previousBlock = user.Player.Map.GetBlock(position);

            if (previousBlock.IsAir)
            {
                throw new InvalidOperationException($"Cannot dig air blocks ({position})");
            }

            using var playerDiggingAck = new AcknowledgePlayerDiggingPacket(position, previousBlock, DiggingType.Started);
            user.Player.SendPacketToVisibleEntities(playerDiggingAck);

            using var blockChange = new BlockChangePacket(BlockType.Air, position);
            user.Player.SendPacketToVisibleEntities(blockChange);

            IBlock block = user.Player.Map.SetBlock(BlockType.Air, position);

            using var chunkPacket = new ChunkDataPacket(block.Chunk);
            user.Player.SendPacketToVisibleEntities(chunkPacket, includeEntity: true);
        }
        else
        {
            // TODO: other modes
        }
    }
    public void OnPlayerBlockPlacement(IMinecraftUser user, IMinecraftPacket packet)
    {
        var      handType      = (HandType)packet.ReadVarInt32();
        Position blockPosition = packet.ReadPosition();
        var      blockFace     = (BlockFaceType)packet.ReadVarInt32();
        float    cursorX       = packet.ReadSingle();
        float    cursorY       = packet.ReadSingle();
        float    cursorZ       = packet.ReadSingle();
        bool     isInsideBlock = packet.ReadBoolean();

        // TODO: check if the current player is interacting with an interactable object.
        // Like: Chest, anvil, crafting table.

        IItemSlot currentHeldItem = user.Player.HotBar.SelectedSlot;

        if (currentHeldItem.HasItem)
        {
            BlockData block        = _registry.Blocks.FirstOrDefault(x => x.ItemId == currentHeldItem.ItemId);
            BlockType blockToPlace = block.Type;

            if (blockToPlace is not BlockType.Air)
            {
                Position realBlockPosition = blockFace switch
                {
                    BlockFaceType.Bottom => new Position(blockPosition.X, blockPosition.Y - 1, blockPosition.Z),
                    BlockFaceType.Top => new Position(blockPosition.X, blockPosition.Y + 1, blockPosition.Z),
                    BlockFaceType.North => new Position(blockPosition.X, blockPosition.Y, blockPosition.Z - 1),
                    BlockFaceType.South => new Position(blockPosition.X, blockPosition.Y, blockPosition.Z + 1),
                    BlockFaceType.West => new Position(blockPosition.X - 1, blockPosition.Y, blockPosition.Z),
                    BlockFaceType.East => new Position(blockPosition.X + 1, blockPosition.Y, blockPosition.Z),
                    _ => throw new InvalidOperationException("Invalid block face type.")
                };

                _logger.LogDebug($"Placing block '{blockToPlace}' at position {realBlockPosition}");

                user.Player.Map.SetBlock(blockToPlace, (int)realBlockPosition.X, (int)realBlockPosition.Y, (int)realBlockPosition.Z);

                using var blockChangePacket = new BlockChangePacket(blockToPlace, blockPosition);
                user.Player.SendPacketToVisibleEntities(blockChangePacket);

                using var chunkDataPacket = new ChunkDataPacket(user.Player.Chunk);
                user.Player.SendPacketToVisibleEntities(chunkDataPacket);
            }
        }
    }
}