示例#1
0
func (player *Player) PacketWindowClick(windowId WindowId, slotId SlotId, rightClick bool, txId TxId, shiftClick bool, expectedSlot *proto.WindowSlot) {
	player.lock.Lock()
	defer player.lock.Unlock()

	// Note that the expectedSlot parameter is currently ignored. The item(s)
	// involved are worked out from the server-side data.
	// TODO use the expectedSlot as a conditions for the click, and base the
	// transaction result on that.

	// Determine which inventory window is involved.
	// TODO support for more windows

	var clickedWindow window.IWindow
	if windowId == WindowIdInventory {
		clickedWindow = &player.inventory
	} else if player.curWindow != nil && player.curWindow.WindowId() == windowId {
		clickedWindow = player.curWindow
	} else {
		log.Printf(
			"Warning: ignored window click on unknown window ID %d",
			windowId)
	}

	expectedSlotContent := &gamerules.Slot{
		ItemTypeId: expectedSlot.ItemTypeId,
		Count:      expectedSlot.Count,
		Data:       expectedSlot.Data,
	}
	// The client tends to send item IDs even when the count is zero.
	expectedSlotContent.Normalize()

	txState := TxStateRejected

	click := gamerules.Click{
		SlotId:     slotId,
		Cursor:     player.cursor,
		RightClick: rightClick,
		ShiftClick: shiftClick,
		TxId:       txId,
	}
	click.ExpectedSlot.SetWindowSlot(expectedSlot)

	if clickedWindow != nil {
		txState = clickedWindow.Click(&click)
	}

	switch txState {
	case TxStateAccepted, TxStateRejected:
		// Inform client of operation status.
		buf := new(bytes.Buffer)
		proto.WriteWindowTransaction(buf, windowId, txId, txState == TxStateAccepted)
		player.cursor = click.Cursor
		player.cursor.SendUpdate(buf, WindowIdCursor, SlotIdCursor)
		player.TransmitPacket(buf.Bytes())
	case TxStateDeferred:
		// The remote inventory should send the transaction outcome.
	}
}
示例#2
0
func (player *Player) handlePacketWindowClick(pkt *proto.PacketWindowClick) {

	// Note that the expectedSlot parameter is currently ignored. The item(s)
	// involved are worked out from the server-side data.
	// TODO use the expectedSlot as a conditions for the click, and base the
	// transaction result on that.

	// Determine which inventory window is involved.
	// TODO support for more windows

	var clickedWindow window.IWindow
	if pkt.WindowId == WindowIdInventory {
		clickedWindow = &player.inventory
	} else if player.curWindow != nil && player.curWindow.WindowId() == pkt.WindowId {
		clickedWindow = player.curWindow
	} else {
		log.Printf(
			"Warning: ignored window click on unknown window ID %d",
			pkt.WindowId)
	}

	txState := TxStateRejected

	click := gamerules.Click{
		SlotId:     pkt.Slot,
		Cursor:     player.cursor,
		RightClick: pkt.RightClick == 1,
		ShiftClick: pkt.Mode == 1,
		TxId:       pkt.TxId,
	}
	//click.ExpectedSlot.SetItemSlot(&pkt.ExpectedSlot) @TODO 1.5.1

	if clickedWindow != nil {
		txState = clickedWindow.Click(&click)
	}

	switch txState {
	case TxStateAccepted, TxStateRejected:
		// Inform client of operation status.
		data := player.txPktSerial.SerializePackets(&proto.PacketWindowTransaction{pkt.WindowId, pkt.TxId, txState == TxStateAccepted})
		player.TransmitPacket(data)
	case TxStateDeferred:
		// The remote inventory should send the transaction outcome.
	}
}