Beispiel #1
0
        public static void DestroyBlock(NetState from, int x, int y, int z, int face)
        {
            // Get the chunk the player is digging in
            Chunk chunk = CXMineServer.Server.World.GetChunkAt(x, z);

            // Get a new EID for the spawn
            int eid = Server.getEID();
            // Get relative X and Z coordinate in the chunk
            int _x = x & 15, _z = z & 15;

            // Get the block data in the chunk
            BlockType block = chunk.GetBlock(_x, y, _z);
            // Update the chunk with the new block
            chunk.SetBlock(_x, y, _z, BlockType.Air);
            // Manage special spawn case where the destroyed block isn't the one to spawn
            if (block == BlockType.Grass)
                block = BlockType.Dirt;
            if (block == BlockType.Rock)
                block = BlockType.Cobblestone;

            int itemX = x * 32 + 16;
            int itemZ = z * 32 + 16;
            int itemY = y * 32;

            int prevDistance = Utility.DistanceBetweenEntities(from.Owner, itemX, itemZ); // It's the power of 2 distance
            Player picksUp = null;

            from.BlockChange(x, (byte)y, z, (byte)BlockType.Air, 0);
            from.PickupSpawn(eid, (short)block, 1, 0, itemX, itemY, itemZ, 0, 0, 0);

            foreach (Player p in CXMineServer.Server.PlayerList)
            {
                if (p == from.Owner)
                    continue;

                int chunkX = PlayerToChunkPosition(p.X);
                int chunkZ = PlayerToChunkPosition(p.Z);

                if (DistanceBetweenChunks(chunk, CXMineServer.Server.World.GetChunkAt(chunkX, chunkZ)) <= (Map.visibleChunks * Map.visibleChunks))
                    p.State.BlockChange(x, (byte)y, z, (byte)BlockType.Air, 0);

                if (DistanceBetweenChunks(chunk, CXMineServer.Server.World.GetChunkAt(chunkX, chunkZ)) <= 1)
                    p.State.PickupSpawn(eid, (short)block, 1, 0, itemX, itemY, itemZ, 0, 0, 0);

                int distance;
                if (Utility.IsInRange(p, itemX, itemZ, 40, out distance) && p.CanPick(itemY))
                {
                    if (distance < prevDistance)
                    {
                        prevDistance = distance;
                        picksUp = p;
                    }
                }
            }

            Item newItem = null;

            if (picksUp != null)
                picksUp.State.CollectItem(eid, picksUp.EntityID, (short)block, 1, 0);
            else if (prevDistance <= 1600 && from.Owner.CanPick(itemY))
                from.CollectItem(eid, from.Owner.EntityID, (short)block, 1, 0);
            else
            {
                newItem = new Item(chunk);
                newItem.Type = (int)block;
                newItem.X = itemX;
                newItem.Y = itemY;
                newItem.Z = itemZ;
                newItem.Yaw = 0.0f;
                newItem.Pitch = 0.0f;
                newItem.EId = eid;
                newItem.Uses = 0;
                newItem.Count = 1;

                chunk.Items.Add(newItem);
            }

            // Spawn a new object to collect
            /*Transmit(PacketType.PickupSpawn, eid, (short)block, (byte)1, (int)packet[2] * 32 + 16, (int)((byte)packet[3]) * 32, (int)packet[4] * 32 + 16, (byte)0, (byte)0, (byte)0);
            // Collect the block instantly (TODO: Collect the block if near the player)
            Transmit(PacketType.CollectItem, eid, _Player.EntityID);
            // Destroy the entity beacuse it's collected
            Transmit(PacketType.DestroyEntity, eid);
            // Update the inventory coherently
            int slot = _Player.inventory.Add((short)block);
            CXMineServer.Log("Sent to slot " + slot.ToString());
            Transmit(PacketType.SetSlot, (byte)0, slot, (short)block, (byte)_Player.inventory.GetItem(slot).Count, (byte)0);*/
        }
Beispiel #2
0
        public static void PlaceBlock(NetState from, int id, int x, int y, int z, int direction)
        {
            int meta = MetaHtN(direction);

            switch (direction)
            { // Direction
                case 0:
                    { // -Y
                        CXMineServer.Log("-Y");
                        y -= 1;
                        break;
                    }
                case 1:
                    { // +Y
                        CXMineServer.Log("+Y");
                        y += 1;
                        break;
                    }
                case 2:
                    { // -Z
                        CXMineServer.Log("-Z");
                        z -= 1;
                        break;
                    }
                case 3:
                    { // +Z
                        CXMineServer.Log("+Z");
                        z += 1;
                        break;
                    }
                case 4:
                    { // -X
                        CXMineServer.Log("-X");
                        x -= 1;
                        break;
                    }
                case 5:
                    { // +X
                        CXMineServer.Log("+X");
                        x += 1;
                        break;
                    }
            }

            int _x = x & 15, _z = z & 15;

            if (!Utility.IsInRange(from.Owner, x*32+16, z*32+16, 128) || !from.Owner.CanPlace(y) || (id == (int)BlockType.Torch && direction == 0))
            {
                // No need to rollback, no block exist here
                if(y > 127 || y < -128)
                    return;
                // Rollback to the precedent situation if the placement is invalid
                BlockType block = CXMineServer.Server.World.GetChunkAt(x, z).GetBlock(_x, y, _z);
                byte data = (byte)MetaHtN((int)CXMineServer.Server.World.GetChunkAt(x, z).GetData(_x, y, _z));
                from.BlockChange(x, (byte)y, z, (byte)block, data);

                Inventory.Slot slot = from.Owner.inventory.GetItem(from.Owner.inventory.HoldingPos + 36);
                from.SetSlot(0, (short)slot.Position, slot.Id, (byte)slot.Count, slot.Uses);
                return;
            }

            // Get the current chunk
            Chunk chunk = CXMineServer.Server.World.GetChunkAt(x, z);
            from.BlockChange(x, (byte)y, z, (byte)id, (byte)meta);
            // For each player using that chunk, update the block data
            foreach (Player p in CXMineServer.Server.PlayerList)
            {
                if (p == from.Owner)
                    continue;

                int chunkX = PlayerToChunkPosition(p.X);
                int chunkZ = PlayerToChunkPosition(p.Z);

                if (DistanceBetweenChunks(chunk, CXMineServer.Server.World.GetChunkAt(chunkX, chunkZ)) <= Map.visibleChunks)
                    from.BlockChange(x, (byte)y, z, (byte)id, (byte)meta);
            }

            // Update the chunk's data on the server
            try
            {
                chunk.SetBlock(_x, y, _z, (BlockType)id);
            }
            catch (System.Exception ex)
            {
                CXMineServer.Log("Exception: " + ex.Message + "\n\nXYZ: " + _x + " " + y + " " + _z);
            }

            // Decrement the inventory counter
            int pos = from.Owner.inventory.HoldingPos;
            from.Owner.inventory.Remove(pos + 36);

            // Handle Count == 0 and so ID == -1 (Needed by the different packet format)
            if (from.Owner.inventory.GetItem(pos).Id == -1)
                from.SetSlot(0, (short)pos, (short)-1);
            else
            {
                Inventory.Slot slot = from.Owner.inventory.GetItem(pos);
                from.SetSlot(0, (short)pos, slot.Id, (byte)slot.Count, slot.Uses);
            }
        }