166 lines
4.1 KiB
Go
166 lines
4.1 KiB
Go
package world
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/Tnze/go-mc/bot/world/entity"
|
|
e "github.com/Tnze/go-mc/data/entity"
|
|
pk "github.com/Tnze/go-mc/net/packet"
|
|
"github.com/Tnze/go-mc/net/ptypes"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// PlayerEntities returns a list of players on the server within viewing range.
|
|
func (w *World) PlayerEntities() []entity.Entity {
|
|
w.entityLock.RLock()
|
|
defer w.entityLock.RUnlock()
|
|
out := make([]entity.Entity, 0, 12)
|
|
for _, ent := range w.Entities {
|
|
if ent.Base.ID == e.Player.ID {
|
|
out = append(out, *ent)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// OnSpawnEntity should be called when a SpawnEntity packet
|
|
// is received.
|
|
func (w *World) OnSpawnEntity(pkt ptypes.SpawnEntity) error {
|
|
w.entityLock.Lock()
|
|
defer w.entityLock.Unlock()
|
|
|
|
base, ok := e.ByID[e.ID(pkt.Type)]
|
|
if !ok {
|
|
return fmt.Errorf("unknown entity ID %v", pkt.Type)
|
|
}
|
|
|
|
w.Entities[int32(pkt.ID)] = &entity.Entity{
|
|
ID: int32(pkt.ID),
|
|
Base: base,
|
|
Data: int32(pkt.Data),
|
|
UUID: uuid.UUID(pkt.UUID),
|
|
X: float64(pkt.X),
|
|
Y: float64(pkt.Y),
|
|
Z: float64(pkt.Z),
|
|
Pitch: int8(pkt.Pitch),
|
|
Yaw: int8(pkt.Yaw),
|
|
VelX: int16(pkt.VelX),
|
|
VelY: int16(pkt.VelY),
|
|
VelZ: int16(pkt.VelZ),
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// OnSpawnLivingEntity should be called when a SpawnLivingEntity packet
|
|
// is received.
|
|
func (w *World) OnSpawnLivingEntity(pkt ptypes.SpawnLivingEntity) error {
|
|
w.entityLock.Lock()
|
|
defer w.entityLock.Unlock()
|
|
|
|
base, ok := e.ByID[e.ID(pkt.Type)]
|
|
if !ok {
|
|
return fmt.Errorf("unknown entity ID %v", pkt.Type)
|
|
}
|
|
|
|
w.Entities[int32(pkt.ID)] = &entity.Entity{
|
|
ID: int32(pkt.ID),
|
|
Base: base,
|
|
UUID: uuid.UUID(pkt.UUID),
|
|
X: float64(pkt.X),
|
|
Y: float64(pkt.Y),
|
|
Z: float64(pkt.Z),
|
|
Pitch: int8(pkt.Pitch),
|
|
Yaw: int8(pkt.Yaw),
|
|
VelX: int16(pkt.VelX),
|
|
VelY: int16(pkt.VelY),
|
|
VelZ: int16(pkt.VelZ),
|
|
HeadPitch: int8(pkt.HeadPitch),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// OnSpawnPlayer should be called when a SpawnPlayer packet
|
|
// is received.
|
|
func (w *World) OnSpawnPlayer(pkt ptypes.SpawnPlayer) error {
|
|
w.entityLock.Lock()
|
|
defer w.entityLock.Unlock()
|
|
|
|
w.Entities[int32(pkt.ID)] = &entity.Entity{
|
|
ID: int32(pkt.ID),
|
|
Base: &e.Player,
|
|
UUID: uuid.UUID(pkt.UUID),
|
|
X: float64(pkt.X),
|
|
Y: float64(pkt.Y),
|
|
Z: float64(pkt.Z),
|
|
Pitch: int8(pkt.Pitch),
|
|
Yaw: int8(pkt.Yaw),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// OnEntityPosUpdate should be called when an EntityPosition packet
|
|
// is received.
|
|
func (w *World) OnEntityPosUpdate(pkt ptypes.EntityPosition) error {
|
|
w.entityLock.Lock()
|
|
defer w.entityLock.Unlock()
|
|
|
|
ent, ok := w.Entities[int32(pkt.ID)]
|
|
if !ok {
|
|
return fmt.Errorf("cannot handle position update for unknown entity %d", pkt.ID)
|
|
}
|
|
|
|
ent.X += float64(pkt.X) / (128 * 32)
|
|
ent.Y += float64(pkt.Y) / (128 * 32)
|
|
ent.Z += float64(pkt.Z) / (128 * 32)
|
|
ent.OnGround = bool(pkt.OnGround)
|
|
return nil
|
|
}
|
|
|
|
// OnEntityPosLookUpdate should be called when an EntityPositionLook packet
|
|
// is received.
|
|
func (w *World) OnEntityPosLookUpdate(pkt ptypes.EntityPositionLook) error {
|
|
w.entityLock.Lock()
|
|
defer w.entityLock.Unlock()
|
|
|
|
ent, ok := w.Entities[int32(pkt.ID)]
|
|
if !ok {
|
|
return fmt.Errorf("cannot handle position look update for unknown entity %d", pkt.ID)
|
|
}
|
|
|
|
ent.X += float64(pkt.X) / (128 * 32)
|
|
ent.Y += float64(pkt.Y) / (128 * 32)
|
|
ent.Z += float64(pkt.Z) / (128 * 32)
|
|
ent.OnGround = bool(pkt.OnGround)
|
|
ent.Pitch, ent.Yaw = int8(pkt.Pitch), int8(pkt.Yaw)
|
|
return nil
|
|
}
|
|
|
|
// OnEntityLookUpdate should be called when an EntityRotation packet
|
|
// is received.
|
|
func (w *World) OnEntityLookUpdate(pkt ptypes.EntityRotation) error {
|
|
w.entityLock.Lock()
|
|
defer w.entityLock.Unlock()
|
|
|
|
ent, ok := w.Entities[int32(pkt.ID)]
|
|
if !ok {
|
|
return fmt.Errorf("cannot handle look update for unknown entity %d", pkt.ID)
|
|
}
|
|
|
|
ent.Pitch, ent.Yaw = int8(pkt.Pitch), int8(pkt.Yaw)
|
|
ent.OnGround = bool(pkt.OnGround)
|
|
return nil
|
|
}
|
|
|
|
// OnEntityDestroy should be called when a DestroyEntities packet
|
|
// is received.
|
|
func (w *World) OnEntityDestroy(eIDs []pk.VarInt) error {
|
|
w.entityLock.Lock()
|
|
defer w.entityLock.Unlock()
|
|
|
|
for _, eID := range eIDs {
|
|
delete(w.Entities, int32(eID))
|
|
}
|
|
return nil
|
|
}
|