From 1f7f770d92ec008d77b22e0cb9f212b3d8ea9742 Mon Sep 17 00:00:00 2001 From: JustTal Date: Wed, 20 Jul 2022 13:22:53 -0500 Subject: [PATCH] session/player.go: Ensure the player is not currently changing slots to prevent desync. --- server/session/handler_inventory_transaction.go | 6 ++++++ server/session/handler_mob_equipment.go | 2 ++ server/session/player.go | 3 +++ server/session/session.go | 1 + 4 files changed, 12 insertions(+) diff --git a/server/session/handler_inventory_transaction.go b/server/session/handler_inventory_transaction.go index ec0aa10d3..4f9c154bc 100644 --- a/server/session/handler_inventory_transaction.go +++ b/server/session/handler_inventory_transaction.go @@ -29,16 +29,22 @@ func (h *InventoryTransactionHandler) Handle(p packet.Packet, s *Session) error h.resendInventories(s) return nil case *protocol.UseItemOnEntityTransactionData: + s.changingSlot.Store(true) + defer s.changingSlot.Store(false) if err := s.c.SetHeldSlot(int(data.HotBarSlot)); err != nil { return err } return h.handleUseItemOnEntityTransaction(data, s) case *protocol.UseItemTransactionData: + s.changingSlot.Store(true) + defer s.changingSlot.Store(false) if err := s.c.SetHeldSlot(int(data.HotBarSlot)); err != nil { return err } return h.handleUseItemTransaction(data, s) case *protocol.ReleaseItemTransactionData: + s.changingSlot.Store(true) + defer s.changingSlot.Store(false) if err := s.c.SetHeldSlot(int(data.HotBarSlot)); err != nil { return err } diff --git a/server/session/handler_mob_equipment.go b/server/session/handler_mob_equipment.go index f0ad40020..4438aa4e1 100644 --- a/server/session/handler_mob_equipment.go +++ b/server/session/handler_mob_equipment.go @@ -29,6 +29,8 @@ func (*MobEquipmentHandler) Handle(p packet.Packet, s *Session) error { // out of sync. s.log.Debugf("failed processing packet from %v (%v): *packet.MobEquipment: client-side item must be identical to server-side item, but got differences: client: %v vs server: %v", s.conn.RemoteAddr(), s.c.Name(), clientSide, actual) } + s.changingSlot.Store(true) + defer s.changingSlot.Store(false) return s.c.SetHeldSlot(int(pk.InventorySlot)) default: return fmt.Errorf("only main inventory should be involved in slot chnage, got window ID %v", pk.WindowID) diff --git a/server/session/player.go b/server/session/player.go index 0f457aebe..355997b5a 100644 --- a/server/session/player.go +++ b/server/session/player.go @@ -569,6 +569,9 @@ func (s *Session) SetHeldSlot(slot int) error { if slot < 0 || slot > 8 { return fmt.Errorf("slot exceeds hotbar range 0-8: slot is %v", slot) } + if s.changingSlot.Load() { + return nil + } s.heldSlot.Store(uint32(slot)) diff --git a/server/session/session.go b/server/session/session.go index 82f216c15..36e0d676d 100644 --- a/server/session/session.go +++ b/server/session/session.go @@ -71,6 +71,7 @@ type Session struct { openedWindow atomic.Value[*inventory.Inventory] openedPos atomic.Value[cube.Pos] swingingArm atomic.Bool + changingSlot atomic.Bool recipes map[uint32]recipe.Recipe