// placeBlock attempts to place a block. This is called by PlayerBlockInteract // in the situation where the player interacts with an attachable block // (potentially in a different chunk to the one where the block gets placed). func (chunk *Chunk) reqPlaceItem(player gamerules.IPlayerClient, target *BlockXyz, slot *gamerules.Slot) { // TODO defer a check for remaining items in slot, and do something with them // (send to player or drop on the ground). // TODO more flexible item checking for block placement (e.g placing seed // items on farmland doesn't fit this current simplistic model). The block // type for the block being placed against should probably contain this logic // (i.e farmland block should know about the seed item). heldBlockType, ok := slot.ItemTypeId.ToBlockId() if !ok || slot.Count < 1 { // Not a placeable item. return } index, subLoc, ok := chunk.getBlockIndexByBlockXyz(target) if !ok { return } // Blocks can only replace certain blocks. blockTypeId := index.BlockId(chunk.blocks) blockType, ok := gamerules.Blocks.Get(blockTypeId) if !ok || !blockType.Replaceable { return } // Safe to replace block. chunk.setBlock(target, subLoc, index, heldBlockType, byte(slot.Data)) // Allow this block to tick once chunk.AddActiveBlockIndex(index) slot.Decrement() }
// Implementing IInventorySubscriber - relays inventory changes to the viewer // of the window. func (iv *inventoryView) SlotUpdate(slot *gamerules.Slot, slotId SlotId) { buf := new(bytes.Buffer) slot.SendUpdate(buf, iv.window.windowId, iv.startSlot+slotId) iv.window.viewer.TransmitPacket(buf.Bytes()) }