Implement packet decoding for entities
This commit is contained in:
177
bot/ingame.go
177
bot/ingame.go
@ -132,36 +132,60 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
}
|
}
|
||||||
case data.AbilitiesClientbound:
|
case data.AbilitiesClientbound:
|
||||||
err = handlePlayerAbilitiesPacket(c, p)
|
err = handlePlayerAbilitiesPacket(c, p)
|
||||||
|
case data.UpdateHealth:
|
||||||
|
err = handleUpdateHealthPacket(c, p)
|
||||||
|
case data.ChatClientbound:
|
||||||
|
err = handleChatMessagePacket(c, p)
|
||||||
|
|
||||||
case data.HeldItemSlotClientbound:
|
case data.HeldItemSlotClientbound:
|
||||||
err = handleHeldItemPacket(c, p)
|
err = handleHeldItemPacket(c, p)
|
||||||
|
case data.WindowItems:
|
||||||
|
err = handleWindowItemsPacket(c, p)
|
||||||
|
|
||||||
|
case data.DeclareRecipes:
|
||||||
|
// handleDeclareRecipesPacket(g, reader)
|
||||||
|
case data.KeepAliveClientbound:
|
||||||
|
err = handleKeepAlivePacket(c, p)
|
||||||
|
|
||||||
|
case data.SpawnEntity:
|
||||||
|
err = handleSpawnEntityPacket(c, p)
|
||||||
|
case data.NamedEntitySpawn:
|
||||||
|
err = handleSpawnPlayerPacket(c, p)
|
||||||
|
case data.SpawnEntityLiving:
|
||||||
|
err = handleSpawnLivingEntityPacket(c, p)
|
||||||
|
case data.Animation:
|
||||||
|
err = handleEntityAnimationPacket(c, p)
|
||||||
|
case data.EntityStatus:
|
||||||
|
err = handleEntityStatusPacket(c, p)
|
||||||
|
case data.EntityDestroy:
|
||||||
|
err = handleDestroyEntitiesPacket(c, p)
|
||||||
|
case data.RelEntityMove:
|
||||||
|
err = handleEntityPositionPacket(c, p)
|
||||||
|
case data.EntityMoveLook:
|
||||||
|
err = handleEntityPositionLookPacket(c, p)
|
||||||
|
case data.EntityLook:
|
||||||
|
err = handleEntityLookPacket(c, p)
|
||||||
|
case data.Entity:
|
||||||
|
err = handleEntityMovePacket(c, p)
|
||||||
|
|
||||||
case data.UpdateLight:
|
case data.UpdateLight:
|
||||||
err = c.Events.updateSeenPackets(seenUpdateLight)
|
err = c.Events.updateSeenPackets(seenUpdateLight)
|
||||||
case data.MapChunk:
|
case data.MapChunk:
|
||||||
err = handleChunkDataPacket(c, p)
|
err = handleChunkDataPacket(c, p)
|
||||||
|
case data.BlockChange:
|
||||||
|
err = handleBlockChangePacket(c, p)
|
||||||
|
case data.MultiBlockChange:
|
||||||
|
err = handleMultiBlockChangePacket(c, p)
|
||||||
|
case data.UnloadChunk:
|
||||||
|
err = handleUnloadChunkPacket(c, p)
|
||||||
|
|
||||||
case data.PositionClientbound:
|
case data.PositionClientbound:
|
||||||
err = handlePlayerPositionAndLookPacket(c, p)
|
err = handlePlayerPositionAndLookPacket(c, p)
|
||||||
sendPlayerPositionAndLookPacket(c) // to confirm the position
|
sendPlayerPositionAndLookPacket(c) // to confirm the position
|
||||||
if err2 := c.Events.updateSeenPackets(seenPlayerPositionAndLook); err == nil {
|
if err2 := c.Events.updateSeenPackets(seenPlayerPositionAndLook); err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
case data.DeclareRecipes:
|
|
||||||
// handleDeclareRecipesPacket(g, reader)
|
|
||||||
case data.KeepAliveClientbound:
|
|
||||||
err = handleKeepAlivePacket(c, p)
|
|
||||||
case data.Entity:
|
|
||||||
//handleEntityPacket(g, reader)
|
|
||||||
case data.NamedEntitySpawn:
|
|
||||||
// err = handleSpawnPlayerPacket(g, reader)
|
|
||||||
case data.WindowItems:
|
|
||||||
err = handleWindowItemsPacket(c, p)
|
|
||||||
case data.UpdateHealth:
|
|
||||||
err = handleUpdateHealthPacket(c, p)
|
|
||||||
case data.ChatClientbound:
|
|
||||||
err = handleChatMessagePacket(c, p)
|
|
||||||
case data.BlockChange:
|
|
||||||
err = handleBlockChangePacket(c, p)
|
|
||||||
case data.MultiBlockChange:
|
|
||||||
err = handleMultiBlockChangePacket(c, p)
|
|
||||||
case data.KickDisconnect:
|
case data.KickDisconnect:
|
||||||
err = handleDisconnectPacket(c, p)
|
err = handleDisconnectPacket(c, p)
|
||||||
disconnect = true
|
disconnect = true
|
||||||
@ -179,6 +203,110 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleSpawnEntityPacket(c *Client, p pk.Packet) error {
|
||||||
|
var se ptypes.SpawnEntity
|
||||||
|
if err := se.Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("SpawnEntity: %+v\n", se)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSpawnLivingEntityPacket(c *Client, p pk.Packet) error {
|
||||||
|
var se ptypes.SpawnLivingEntity
|
||||||
|
if err := se.Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("SpawnLivingEntity: %+v\n", se)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSpawnPlayerPacket(c *Client, p pk.Packet) error {
|
||||||
|
var se ptypes.SpawnPlayer
|
||||||
|
if err := se.Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("SpawnPlayer: %+v\n", se)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleEntityPositionPacket(c *Client, p pk.Packet) error {
|
||||||
|
var se ptypes.EntityPosition
|
||||||
|
if err := se.Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("EntityPosition: %+v\n", se)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleEntityPositionLookPacket(c *Client, p pk.Packet) error {
|
||||||
|
var se ptypes.EntityPositionLook
|
||||||
|
if err := se.Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("EntityPositionLook: %+v\n", se)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleEntityLookPacket(c *Client, p pk.Packet) error {
|
||||||
|
var se ptypes.EntityRotation
|
||||||
|
if err := se.Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("EntityRotation: %+v\n", se)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleEntityMovePacket(c *Client, p pk.Packet) error {
|
||||||
|
var id pk.VarInt
|
||||||
|
if err := p.Scan(&id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("EntityMove (probs didnt for players): %+v\n", id)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleEntityAnimationPacket(c *Client, p pk.Packet) error {
|
||||||
|
var se ptypes.EntityAnimationClientbound
|
||||||
|
if err := se.Decode(p); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("EntityAnimationClientbound: %+v\n", se)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleEntityStatusPacket(c *Client, p pk.Packet) error {
|
||||||
|
var (
|
||||||
|
id pk.Int
|
||||||
|
status pk.Byte
|
||||||
|
)
|
||||||
|
if err := p.Scan(&id, &status); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("EntityStatus: %v, %v\n", id, status)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleDestroyEntitiesPacket(c *Client, p pk.Packet) error {
|
||||||
|
var (
|
||||||
|
count pk.VarInt
|
||||||
|
r = bytes.NewReader(p.Data)
|
||||||
|
)
|
||||||
|
if err := count.Decode(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
entities := make([]pk.VarInt, int(count))
|
||||||
|
for i := 0; i < int(count); i++ {
|
||||||
|
if err := entities[i].Decode(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("DestroyEntities: %v\n", entities)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func handleSoundEffect(c *Client, p pk.Packet) error {
|
func handleSoundEffect(c *Client, p pk.Packet) error {
|
||||||
var s ptypes.SoundEffect
|
var s ptypes.SoundEffect
|
||||||
if err := s.Decode(p); err != nil {
|
if err := s.Decode(p); err != nil {
|
||||||
@ -463,6 +591,19 @@ func handleHeldItemPacket(c *Client, p pk.Packet) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleUnloadChunkPacket(c *Client, p pk.Packet) error {
|
||||||
|
if !c.settings.ReceiveMap {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var x, z pk.Int
|
||||||
|
if err := p.Scan(&x, &z); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.Wd.UnloadChunk(world.ChunkLoc{X: int(x) >> 4, Z: int(z) >> 4})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func handleChunkDataPacket(c *Client, p pk.Packet) error {
|
func handleChunkDataPacket(c *Client, p pk.Packet) error {
|
||||||
if err := c.Events.updateSeenPackets(seenChunkData); err != nil {
|
if err := c.Events.updateSeenPackets(seenChunkData); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -68,6 +68,10 @@ func (w *World) GetBlockStatus(x, y, z int) BlockStatus {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *World) UnloadChunk(loc ChunkLoc) {
|
||||||
|
delete(w.Chunks, loc)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *World) UnaryBlockUpdate(pos pk.Position, bStateID BlockStatus) bool {
|
func (w *World) UnaryBlockUpdate(pos pk.Position, bStateID BlockStatus) bool {
|
||||||
c := w.Chunks[ChunkLoc{X: pos.X >> 4, Z: pos.Z >> 4}]
|
c := w.Chunks[ChunkLoc{X: pos.X >> 4, Z: pos.Z >> 4}]
|
||||||
if c == nil {
|
if c == nil {
|
||||||
|
@ -2,10 +2,11 @@ package packet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/google/uuid"
|
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/nbt"
|
"github.com/Tnze/go-mc/nbt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -364,6 +365,16 @@ func (p *Position) Decode(r DecodeReader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Decodes an Angle
|
||||||
|
func (b *Angle) Decode(r DecodeReader) error {
|
||||||
|
v, err := r.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*b = Angle(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//Encode a Float
|
//Encode a Float
|
||||||
func (f Float) Encode() []byte {
|
func (f Float) Encode() []byte {
|
||||||
return Int(math.Float32bits(float32(f))).Encode()
|
return Int(math.Float32bits(float32(f))).Encode()
|
||||||
|
95
net/ptypes/entities.go
Normal file
95
net/ptypes/entities.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package ptypes
|
||||||
|
|
||||||
|
import pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
|
||||||
|
// SpawnEntity is a clientbound packet used to spawn a non-mob entity.
|
||||||
|
type SpawnEntity struct {
|
||||||
|
ID pk.VarInt
|
||||||
|
UUID pk.UUID
|
||||||
|
Type pk.VarInt
|
||||||
|
X, Y, Z pk.Int
|
||||||
|
Pitch, Yaw pk.Angle
|
||||||
|
Data pk.Int
|
||||||
|
VelX, VelY, VelZ pk.Short
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SpawnEntity) Decode(pkt pk.Packet) error {
|
||||||
|
return pkt.Scan(&p.ID, &p.UUID, &p.Type,
|
||||||
|
&p.X, &p.Y, &p.Z, &p.Pitch, &p.Yaw,
|
||||||
|
&p.Data, &p.VelX, &p.VelY, &p.VelZ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpawnPlayer is a clientbound packet used to describe a player entering
|
||||||
|
// visible range.
|
||||||
|
type SpawnPlayer struct {
|
||||||
|
ID pk.VarInt
|
||||||
|
UUID pk.UUID
|
||||||
|
X, Y, Z pk.Double
|
||||||
|
Yaw, Pitch pk.Angle
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SpawnPlayer) Decode(pkt pk.Packet) error {
|
||||||
|
return pkt.Scan(&p.ID, &p.UUID, &p.X, &p.Y, &p.Z, &p.Yaw, &p.Pitch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpawnLivingEntity is a clientbound packet used to spawn a mob.
|
||||||
|
type SpawnLivingEntity struct {
|
||||||
|
ID pk.VarInt
|
||||||
|
UUID pk.UUID
|
||||||
|
Type pk.VarInt
|
||||||
|
X, Y, Z pk.Double
|
||||||
|
Yaw, Pitch pk.Angle
|
||||||
|
HeadPitch pk.Angle
|
||||||
|
VelX, VelY, VelZ pk.Short
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SpawnLivingEntity) Decode(pkt pk.Packet) error {
|
||||||
|
return pkt.Scan(&p.ID, &p.UUID, &p.Type,
|
||||||
|
&p.X, &p.Y, &p.Z, &p.Yaw, &p.Pitch,
|
||||||
|
&p.HeadPitch, &p.VelX, &p.VelY, &p.VelZ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntityAnimationClientbound updates the animationf state of an entity.
|
||||||
|
type EntityAnimationClientbound struct {
|
||||||
|
ID pk.VarInt
|
||||||
|
Animation pk.UnsignedByte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EntityAnimationClientbound) Decode(pkt pk.Packet) error {
|
||||||
|
return pkt.Scan(&p.ID, &p.Animation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntityPosition is a clientbound packet used to update an entities position.
|
||||||
|
type EntityPosition struct {
|
||||||
|
ID pk.VarInt
|
||||||
|
X, Y, Z pk.Short // Deltas
|
||||||
|
OnGround pk.Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EntityPosition) Decode(pkt pk.Packet) error {
|
||||||
|
return pkt.Scan(&p.ID, &p.X, &p.Y, &p.Z, &p.OnGround)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntityPosition is a clientbound packet used to update an entities position
|
||||||
|
// and its rotation.
|
||||||
|
type EntityPositionLook struct {
|
||||||
|
ID pk.VarInt
|
||||||
|
X, Y, Z pk.Short // Deltas
|
||||||
|
Yaw, Pitch pk.Angle
|
||||||
|
OnGround pk.Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EntityPositionLook) Decode(pkt pk.Packet) error {
|
||||||
|
return pkt.Scan(&p.ID, &p.X, &p.Y, &p.Z, &p.Yaw, &p.Pitch, &p.OnGround)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntityRotation is a clientbound packet used to update an entities rotation.
|
||||||
|
type EntityRotation struct {
|
||||||
|
ID pk.VarInt
|
||||||
|
Yaw, Pitch pk.Angle
|
||||||
|
OnGround pk.Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *EntityRotation) Decode(pkt pk.Packet) error {
|
||||||
|
return pkt.Scan(&p.ID, &p.Yaw, &p.Pitch, &p.OnGround)
|
||||||
|
}
|
Reference in New Issue
Block a user