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);*/ }
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); } }