up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,306 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/entity"
|
||||
"github.com/df-mc/dragonfly/server/entity/effect"
|
||||
"github.com/df-mc/dragonfly/server/internal/nbtconv"
|
||||
"github.com/df-mc/dragonfly/server/item"
|
||||
"github.com/df-mc/dragonfly/server/item/potion"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
"github.com/google/uuid"
|
||||
"github.com/sandertv/gophertunnel/minecraft/protocol"
|
||||
)
|
||||
|
||||
// parseEntityMetadata returns an entity metadata object with default values. It is equivalent to setting
|
||||
// all properties to their default values and disabling all flags.
|
||||
func (s *Session) parseEntityMetadata(e world.Entity) protocol.EntityMetadata {
|
||||
bb := e.H().Type().BBox(e)
|
||||
m := protocol.NewEntityMetadata()
|
||||
|
||||
m[protocol.EntityDataKeyWidth] = float32(bb.Width())
|
||||
m[protocol.EntityDataKeyHeight] = float32(bb.Height())
|
||||
m[protocol.EntityDataKeyEffectColor] = int32(0)
|
||||
m[protocol.EntityDataKeyEffectAmbience] = byte(0)
|
||||
m[protocol.EntityDataKeyColorIndex] = byte(0)
|
||||
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagHasGravity)
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagClimb)
|
||||
if g, ok := e.H().Type().(glint); ok && g.Glint() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagEnchanted)
|
||||
}
|
||||
if e.H().Type() == entity.LingeringPotionType {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagLingering)
|
||||
}
|
||||
s.addSpecificMetadata(e, m)
|
||||
if ent, ok := e.(*entity.Ent); ok {
|
||||
s.addSpecificMetadata(ent.Behaviour(), m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (s *Session) addSpecificMetadata(e any, m protocol.EntityMetadata) {
|
||||
if sn, ok := e.(sneaker); ok && sn.Sneaking() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagSneaking)
|
||||
}
|
||||
if sp, ok := e.(sprinter); ok && sp.Sprinting() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagSprinting)
|
||||
}
|
||||
if sw, ok := e.(swimmer); ok && sw.Swimming() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagSwimming)
|
||||
}
|
||||
if cr, ok := e.(crawler); ok && cr.Crawling() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlagsTwo, protocol.EntityDataFlagCrawling&63)
|
||||
}
|
||||
if gl, ok := e.(glider); ok && gl.Gliding() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagGliding)
|
||||
}
|
||||
if bb, ok := e.(baby); ok && bb.Baby() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagBaby)
|
||||
}
|
||||
if b, ok := e.(breather); ok {
|
||||
m[protocol.EntityDataKeyAirSupply] = int16(b.AirSupply().Milliseconds() / 50)
|
||||
m[protocol.EntityDataKeyAirSupplyMax] = int16(b.MaxAirSupply().Milliseconds() / 50)
|
||||
if b.Breathing() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagBreathing)
|
||||
}
|
||||
}
|
||||
if i, ok := e.(invisible); ok && i.Invisible() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagInvisible)
|
||||
}
|
||||
if i, ok := e.(immobile); ok && i.Immobile() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagNoAI)
|
||||
}
|
||||
if o, ok := e.(onFire); ok && o.OnFireDuration() > 0 {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagOnFire)
|
||||
}
|
||||
if u, ok := e.(using); ok && u.UsingItem() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagUsingItem)
|
||||
}
|
||||
if c, ok := e.(arrow); ok && c.Critical() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagCritical)
|
||||
}
|
||||
if g, ok := e.(gameMode); ok {
|
||||
if g.GameMode().HasCollision() {
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagHasCollision)
|
||||
}
|
||||
}
|
||||
if o, ok := e.(orb); ok {
|
||||
m[protocol.EntityDataKeyValue] = int32(o.Experience())
|
||||
}
|
||||
if f, ok := e.(firework); ok {
|
||||
m[protocol.EntityDataKeyDisplayTileRuntimeID] = nbtconv.WriteItem(item.NewStack(f.Firework(), 1), false)
|
||||
if o, ok := e.(owned); ok && f.Attached() && o.Owner() != nil {
|
||||
m[protocol.EntityDataKeyCustomDisplay] = int64(s.handleRuntimeID(o.Owner()))
|
||||
}
|
||||
} else if o, ok := e.(owned); ok && o.Owner() != nil {
|
||||
m[protocol.EntityDataKeyOwner] = int64(s.handleRuntimeID(o.Owner()))
|
||||
}
|
||||
if sc, ok := e.(scaled); ok {
|
||||
m[protocol.EntityDataKeyScale] = float32(sc.Scale())
|
||||
}
|
||||
if t, ok := e.(tnt); ok {
|
||||
m[protocol.EntityDataKeyFuseTime] = int32(t.Fuse().Milliseconds() / 50)
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagIgnited)
|
||||
}
|
||||
if n, ok := e.(named); ok {
|
||||
name := n.NameTag()
|
||||
m[protocol.EntityDataKeyName] = name
|
||||
if name == "" {
|
||||
m[protocol.EntityDataKeyAlwaysShowNameTag] = uint8(0)
|
||||
m.UnsetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagAlwaysShowName)
|
||||
m.UnsetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagShowName)
|
||||
} else {
|
||||
m[protocol.EntityDataKeyAlwaysShowNameTag] = uint8(1)
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagAlwaysShowName)
|
||||
m.SetFlag(protocol.EntityDataKeyFlags, protocol.EntityDataFlagShowName)
|
||||
}
|
||||
}
|
||||
if sc, ok := e.(scoreTag); ok {
|
||||
m[protocol.EntityDataKeyScore] = sc.ScoreTag()
|
||||
}
|
||||
if sl, ok := e.(sleeper); ok {
|
||||
if pos, ok := sl.Sleeping(); ok {
|
||||
m[protocol.EntityDataKeyBedPosition] = protocol.BlockPos{int32(pos[0]), int32(pos[1]), int32(pos[2])}
|
||||
|
||||
// For some reason there is no such flag in gophertunnel.
|
||||
m.SetFlag(protocol.EntityDataKeyPlayerFlags, 1)
|
||||
}
|
||||
}
|
||||
if c, ok := e.(areaEffectCloud); ok {
|
||||
m[protocol.EntityDataKeyDataRadius] = float32(c.Radius())
|
||||
|
||||
// We purposely fill these in with invalid values to disable the client-sided shrinking of the cloud.
|
||||
m[protocol.EntityDataKeyDataDuration] = int32(math.MaxInt32)
|
||||
m[protocol.EntityDataKeyDataChangeOnPickup] = float32(math.SmallestNonzeroFloat32)
|
||||
m[protocol.EntityDataKeyDataChangeRate] = float32(math.SmallestNonzeroFloat32)
|
||||
|
||||
colour, am := effect.ResultingColour(c.Effects())
|
||||
m[protocol.EntityDataKeyEffectColor] = nbtconv.Int32FromRGBA(colour)
|
||||
if am {
|
||||
m[protocol.EntityDataKeyEffectAmbience] = byte(1)
|
||||
} else {
|
||||
m[protocol.EntityDataKeyEffectAmbience] = byte(0)
|
||||
}
|
||||
}
|
||||
|
||||
if l, ok := e.(living); ok && s.ent != nil && s.ent.UUID() == l.UUID() {
|
||||
deathPos, deathDimension, died := l.DeathPosition()
|
||||
if died {
|
||||
dim, _ := world.DimensionID(deathDimension)
|
||||
m[protocol.EntityDataKeyPlayerLastDeathPosition] = vec64To32(deathPos)
|
||||
m[protocol.EntityDataKeyPlayerLastDeathDimension] = int32(dim)
|
||||
}
|
||||
m[protocol.EntityDataKeyPlayerHasDied] = boolByte(died)
|
||||
}
|
||||
if p, ok := e.(splash); ok {
|
||||
m[protocol.EntityDataKeyAuxValueData] = int16(p.Potion().Uint8())
|
||||
if tip := p.Potion().Uint8(); tip > 4 {
|
||||
m[protocol.EntityDataKeyCustomDisplay] = tip + 1
|
||||
}
|
||||
}
|
||||
if eff, ok := e.(effectBearer); ok {
|
||||
var packedEffects int64
|
||||
|
||||
for _, ef := range eff.Effects() {
|
||||
if !ef.ParticlesHidden() {
|
||||
id, found := effect.ID(ef.Type())
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
packedEffects = (packedEffects << 7) | int64(id<<1)
|
||||
if ef.Ambient() {
|
||||
packedEffects |= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
m[protocol.EntityDataKeyVisibleMobEffects] = packedEffects
|
||||
}
|
||||
if v, ok := e.(variable); ok {
|
||||
m[protocol.EntityDataKeyVariant] = v.Variant()
|
||||
}
|
||||
if mv, ok := e.(markVariable); ok {
|
||||
m[protocol.EntityDataKeyMarkVariant] = mv.MarkVariant()
|
||||
}
|
||||
}
|
||||
|
||||
type sneaker interface {
|
||||
Sneaking() bool
|
||||
}
|
||||
|
||||
type sprinter interface {
|
||||
Sprinting() bool
|
||||
}
|
||||
|
||||
type swimmer interface {
|
||||
Swimming() bool
|
||||
}
|
||||
|
||||
type crawler interface {
|
||||
Crawling() bool
|
||||
}
|
||||
|
||||
type glider interface {
|
||||
Gliding() bool
|
||||
}
|
||||
|
||||
type baby interface {
|
||||
Baby() bool
|
||||
}
|
||||
|
||||
type breather interface {
|
||||
Breathing() bool
|
||||
AirSupply() time.Duration
|
||||
MaxAirSupply() time.Duration
|
||||
}
|
||||
|
||||
type immobile interface {
|
||||
Immobile() bool
|
||||
}
|
||||
|
||||
type invisible interface {
|
||||
Invisible() bool
|
||||
}
|
||||
|
||||
type scaled interface {
|
||||
Scale() float64
|
||||
}
|
||||
|
||||
type owned interface {
|
||||
Owner() *world.EntityHandle
|
||||
}
|
||||
|
||||
type named interface {
|
||||
NameTag() string
|
||||
}
|
||||
|
||||
type scoreTag interface {
|
||||
ScoreTag() string
|
||||
}
|
||||
|
||||
type splash interface {
|
||||
Potion() potion.Potion
|
||||
}
|
||||
|
||||
type glint interface {
|
||||
Glint() bool
|
||||
}
|
||||
|
||||
type areaEffectCloud interface {
|
||||
effectBearer
|
||||
Radius() float64
|
||||
}
|
||||
|
||||
type onFire interface {
|
||||
OnFireDuration() time.Duration
|
||||
}
|
||||
|
||||
type effectBearer interface {
|
||||
Effects() []effect.Effect
|
||||
}
|
||||
|
||||
type using interface {
|
||||
UsingItem() bool
|
||||
}
|
||||
|
||||
type arrow interface {
|
||||
Critical() bool
|
||||
}
|
||||
|
||||
type orb interface {
|
||||
Experience() int
|
||||
}
|
||||
|
||||
type firework interface {
|
||||
Firework() item.Firework
|
||||
Attached() bool
|
||||
}
|
||||
|
||||
type gameMode interface {
|
||||
GameMode() world.GameMode
|
||||
}
|
||||
|
||||
type sleeper interface {
|
||||
Sleeping() (cube.Pos, bool)
|
||||
}
|
||||
|
||||
type tnt interface {
|
||||
Fuse() time.Duration
|
||||
}
|
||||
|
||||
type living interface {
|
||||
UUID() uuid.UUID
|
||||
DeathPosition() (mgl64.Vec3, world.Dimension, bool)
|
||||
}
|
||||
|
||||
type variable interface {
|
||||
Variant() int32
|
||||
}
|
||||
|
||||
type markVariable interface {
|
||||
MarkVariant() int32
|
||||
}
|
||||
Reference in New Issue
Block a user