github.com/df-mc/dragonfly@v0.9.13/server/session/handler_player_auth_input.go (about) 1 package session 2 3 import ( 4 "fmt" 5 "github.com/df-mc/dragonfly/server/block/cube" 6 "github.com/go-gl/mathgl/mgl32" 7 "github.com/go-gl/mathgl/mgl64" 8 "github.com/sandertv/gophertunnel/minecraft/protocol" 9 "github.com/sandertv/gophertunnel/minecraft/protocol/packet" 10 "math" 11 ) 12 13 // PlayerAuthInputHandler handles the PlayerAuthInput packet. 14 type PlayerAuthInputHandler struct{} 15 16 // Handle ... 17 func (h PlayerAuthInputHandler) Handle(p packet.Packet, s *Session) error { 18 pk := p.(*packet.PlayerAuthInput) 19 if err := h.handleMovement(pk, s); err != nil { 20 return err 21 } 22 return h.handleActions(pk, s) 23 } 24 25 // handleMovement handles the movement part of the packet.PlayerAuthInput. 26 func (h PlayerAuthInputHandler) handleMovement(pk *packet.PlayerAuthInput, s *Session) error { 27 yaw, pitch := s.c.Rotation().Elem() 28 pos := s.c.Position() 29 30 reference := []float64{pitch, yaw, yaw, pos[0], pos[1], pos[2]} 31 for i, v := range [...]*float32{&pk.Pitch, &pk.Yaw, &pk.HeadYaw, &pk.Position[0], &pk.Position[1], &pk.Position[2]} { 32 f := float64(*v) 33 if math.IsNaN(f) || math.IsInf(f, 1) || math.IsInf(f, 0) { 34 // Sometimes, the PlayerAuthInput packet is in fact sent with NaN/INF after being teleported (to another 35 // world), see #425. For this reason, we don't actually return an error if this happens, because this will 36 // result in the player being kicked. Just log it and replace the NaN value with the one we have tracked 37 // server-side. 38 s.log.Debugf("failed processing packet from %v (%v): %T: must not have nan/inf values, but got %v (%v, %v, %v). assuming server-side values\n", s.conn.RemoteAddr(), s.c.Name(), pk, pk.Position, pk.Pitch, pk.Yaw, pk.HeadYaw) 39 *v = float32(reference[i]) 40 } 41 } 42 43 pk.Position = pk.Position.Sub(mgl32.Vec3{0, 1.62}) // Sub the base offset of players from the pos. 44 45 newPos := vec32To64(pk.Position) 46 deltaPos, deltaYaw, deltaPitch := newPos.Sub(pos), float64(pk.Yaw)-yaw, float64(pk.Pitch)-pitch 47 if mgl64.FloatEqual(deltaPos.Len(), 0) && mgl64.FloatEqual(deltaYaw, 0) && mgl64.FloatEqual(deltaPitch, 0) { 48 // The PlayerAuthInput packet is sent every tick, so don't do anything if the position and rotation 49 // were unchanged. 50 return nil 51 } 52 53 if expected := s.teleportPos.Load(); expected != nil { 54 if newPos.Sub(*expected).Len() > 1 { 55 // The player has moved before it received the teleport packet. Ignore this movement entirely and 56 // wait for the client to sync itself back to the server. Once we get a movement that is close 57 // enough to the teleport position, we'll allow the player to move around again. 58 return nil 59 } 60 s.teleportPos.Store(nil) 61 } 62 63 s.c.Move(deltaPos, deltaYaw, deltaPitch) 64 return nil 65 } 66 67 // handleActions handles the actions with the world that are present in the PlayerAuthInput packet. 68 func (h PlayerAuthInputHandler) handleActions(pk *packet.PlayerAuthInput, s *Session) error { 69 if pk.InputData&packet.InputFlagPerformItemInteraction != 0 { 70 if err := h.handleUseItemData(pk.ItemInteractionData, s); err != nil { 71 return err 72 } 73 } 74 if pk.InputData&packet.InputFlagPerformBlockActions != 0 { 75 if err := h.handleBlockActions(pk.BlockActions, s); err != nil { 76 return err 77 } 78 } 79 h.handleInputFlags(pk.InputData, s) 80 81 if pk.InputData&packet.InputFlagPerformItemStackRequest != 0 { 82 s.inTransaction.Store(true) 83 defer s.inTransaction.Store(false) 84 85 // As of 1.18 this is now used for sending item stack requests such as when mining a block. 86 sh := s.handlers[packet.IDItemStackRequest].(*ItemStackRequestHandler) 87 if err := sh.handleRequest(pk.ItemStackRequest, s); err != nil { 88 // Item stacks being out of sync isn't uncommon, so don't error. Just debug the error and let the 89 // revert do its work. 90 s.log.Debugf("failed processing packet from %v (%v): PlayerAuthInput: error resolving item stack request: %v", s.conn.RemoteAddr(), s.c.Name(), err) 91 } 92 } 93 return nil 94 } 95 96 // handleInputFlags handles the toggleable input flags set in a PlayerAuthInput packet. 97 func (h PlayerAuthInputHandler) handleInputFlags(flags uint64, s *Session) { 98 if flags&packet.InputFlagStartSprinting != 0 { 99 s.c.StartSprinting() 100 } 101 if flags&packet.InputFlagStopSprinting != 0 { 102 s.c.StopSprinting() 103 } 104 if flags&packet.InputFlagStartSneaking != 0 { 105 s.c.StartSneaking() 106 } 107 if flags&packet.InputFlagStopSneaking != 0 { 108 s.c.StopSneaking() 109 } 110 if flags&packet.InputFlagStartSwimming != 0 { 111 s.c.StartSwimming() 112 } 113 if flags&packet.InputFlagStopSwimming != 0 { 114 s.c.StopSwimming() 115 } 116 if flags&packet.InputFlagStartGliding != 0 { 117 s.c.StartGliding() 118 } 119 if flags&packet.InputFlagStopGliding != 0 { 120 s.c.StopGliding() 121 } 122 if flags&packet.InputFlagStartJumping != 0 { 123 s.c.Jump() 124 } 125 if flags&packet.InputFlagMissedSwing != 0 { 126 s.swingingArm.Store(true) 127 defer s.swingingArm.Store(false) 128 s.c.PunchAir() 129 } 130 } 131 132 // handleUseItemData handles the protocol.UseItemTransactionData found in a packet.PlayerAuthInput. 133 func (h PlayerAuthInputHandler) handleUseItemData(data protocol.UseItemTransactionData, s *Session) error { 134 s.swingingArm.Store(true) 135 defer s.swingingArm.Store(false) 136 137 held, _ := s.c.HeldItems() 138 if !held.Equal(stackToItem(data.HeldItem.Stack)) { 139 s.log.Debugf("failed processing item interaction from %v (%v): PlayerAuthInput: actual held and client held item mismatch", s.conn.RemoteAddr(), s.c.Name()) 140 return nil 141 } 142 pos := cube.Pos{int(data.BlockPosition[0]), int(data.BlockPosition[1]), int(data.BlockPosition[2])} 143 144 // Seems like this is only used for breaking blocks at the moment. 145 switch data.ActionType { 146 case protocol.UseItemActionBreakBlock: 147 s.c.BreakBlock(pos) 148 default: 149 return fmt.Errorf("unhandled UseItem ActionType for PlayerAuthInput packet %v", data.ActionType) 150 } 151 return nil 152 } 153 154 // handleBlockActions handles a slice of protocol.PlayerBlockAction present in a PlayerAuthInput packet. 155 func (h PlayerAuthInputHandler) handleBlockActions(a []protocol.PlayerBlockAction, s *Session) error { 156 for _, action := range a { 157 if err := handlePlayerAction(action.Action, action.Face, action.BlockPos, selfEntityRuntimeID, s); err != nil { 158 return err 159 } 160 } 161 return nil 162 }