This commit is contained in:
adman
2026-05-14 10:42:38 +02:00
parent d43ff7f83d
commit 764cfd8c4d
6 changed files with 352 additions and 16 deletions
+113
View File
@@ -4,6 +4,7 @@ import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"io" "io"
"math"
) )
var ( var (
@@ -284,3 +285,115 @@ func Bool2uint64(b bool) uint64 {
} }
return 0 return 0
} }
type LpVec3d struct {
X, Y, Z float64
}
func (v *LpVec3d) Encode(w io.Writer) error {
return writeVelocity(w, *v)
}
func (v *LpVec3d) Decode(r io.ReadSeeker) error {
v3, err := readVelocity(r)
if err != nil {
return err
}
v.X = v3.X
v.Y = v3.Y
v.Z = v3.Z
return nil
}
func readVelocity(r io.Reader) (LpVec3d, error) {
var marker, second uint8
if err := binary.Read(r, binary.BigEndian, &marker); err != nil {
return LpVec3d{}, err
}
if marker == 0 {
return LpVec3d{}, nil
}
if err := binary.Read(r, binary.BigEndian, &second); err != nil {
return LpVec3d{}, err
}
var packed uint32
if err := binary.Read(r, binary.BigEndian, &packed); err != nil {
return LpVec3d{}, err
}
m := (uint64(packed) << 16) | (uint64(second) << 8) | uint64(marker)
n := int64(marker & 3)
if (marker & 4) != 0 {
// fast marker bit set, read varint for extended scale
scale, err := DecodeVarInt(r)
if err != nil {
return LpVec3d{}, err
}
n |= (int64(scale) & 0xFFFFFFFF) << 2
}
x := fromLong(int64(m>>3), n)
y := fromLong(int64(m>>18), n)
z := fromLong(int64(m>>33), n)
return LpVec3d{X: x, Y: y, Z: z}, nil
}
func writeVelocity(w io.Writer, v LpVec3d) error {
const maxVal = 1.7179869183e10
const scaleMax = 32766.0
x := clamp(v.X, maxVal)
y := clamp(v.Y, maxVal)
z := clamp(v.Z, maxVal)
g := absMax(absMax(x, y), z)
if g < 3.051944088384301e-5 {
_, err := w.Write([]byte{0})
return err
}
l := int64(math.Ceil(g))
bl := (l & 3) != l
m := l
if bl {
m = (l & 3) | 4
}
lf := float64(l)
n := toLong(x/lf) << 3
o := toLong(y/lf) << 18
p := toLong(z/lf) << 33
q := m | n | o | p
var buf [7]byte
buf[0] = byte(q)
buf[1] = byte(q >> 8)
binary.BigEndian.PutUint32(buf[2:6], uint32(q>>16))
if _, err := w.Write(buf[:6]); err != nil {
return err
}
if bl {
if err := EncodeVarInt(w, int32(l>>2)); err != nil {
return err
}
}
return nil
}
func clamp(v, max float64) float64 {
if math.IsNaN(v) {
return 0
}
if v > max {
return max
}
if v < -max {
return -max
}
return v
}
func absMax(a, b float64) float64 {
if math.Abs(a) > math.Abs(b) {
return a
}
return b
}
func toLong(v float64) int64 {
return int64(math.Round((v*0.5 + 0.5) * 32766.0))
}
func fromLong(bits int64, scale int64) float64 {
v := bits & 0x7FFF
if v > 32766 {
v = 32766
}
return (float64(v)*2.0/32766.0 - 1.0) * float64(scale)
}
+119 -7
View File
@@ -2,10 +2,11 @@ package v1_21_11
import ( import (
"encoding/binary" "encoding/binary"
"io"
"github.com/admin-else/strom/nbt" "github.com/admin-else/strom/nbt"
"github.com/admin-else/strom/proto_base" "github.com/admin-else/strom/proto_base"
"github.com/google/uuid" "github.com/google/uuid"
"io"
) )
type ArmorTrimMaterial struct { type ArmorTrimMaterial struct {
@@ -16668,15 +16669,30 @@ func (ret *PlayToClientPacketEntityUpdateAttributes) Encode(w io.Writer) (err er
} }
type PlayToClientPacketEntityVelocity struct { type PlayToClientPacketEntityVelocity struct {
Val proto_base.ToDo EntityId int32
Velocity proto_base.LpVec3d
} }
func (ret *PlayToClientPacketEntityVelocity) Decode(r io.ReadSeeker) (err error) { func (ret *PlayToClientPacketEntityVelocity) Decode(r io.ReadSeeker) (err error) {
err = proto_base.ToDoError ret.EntityId, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
err = ret.Velocity.Decode(r)
if err != nil {
return
}
return return
} }
func (ret *PlayToClientPacketEntityVelocity) Encode(w io.Writer) (err error) { func (ret *PlayToClientPacketEntityVelocity) Encode(w io.Writer) (err error) {
err = proto_base.ToDoError err = proto_base.EncodeVarInt(w, ret.EntityId)
if err != nil {
return
}
err = ret.Velocity.Encode(w)
if err != nil {
return
}
return return
} }
@@ -20453,15 +20469,111 @@ func (ret *PlayToClientPacketSoundEffect) Encode(w io.Writer) (err error) {
} }
type PlayToClientPacketSpawnEntity struct { type PlayToClientPacketSpawnEntity struct {
Val proto_base.ToDo EntityId int32
ObjectUUID uuid.UUID
Type int32
X float64
Y float64
Z float64
Velocity proto_base.LpVec3d
Pitch int8
Yaw int8
HeadPitch int8
ObjectData int32
} }
func (ret *PlayToClientPacketSpawnEntity) Decode(r io.ReadSeeker) (err error) { func (ret *PlayToClientPacketSpawnEntity) Decode(r io.ReadSeeker) (err error) {
err = proto_base.ToDoError ret.EntityId, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
_, err = io.ReadFull(r, ret.ObjectUUID[:])
if err != nil {
return
}
ret.Type, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.X)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Y)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Z)
if err != nil {
return
}
err = ret.Velocity.Decode(r)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Pitch)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Yaw)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.HeadPitch)
if err != nil {
return
}
ret.ObjectData, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
return return
} }
func (ret *PlayToClientPacketSpawnEntity) Encode(w io.Writer) (err error) { func (ret *PlayToClientPacketSpawnEntity) Encode(w io.Writer) (err error) {
err = proto_base.ToDoError err = proto_base.EncodeVarInt(w, ret.EntityId)
if err != nil {
return
}
_, err = w.Write(ret.ObjectUUID[:])
if err != nil {
return
}
err = proto_base.EncodeVarInt(w, ret.Type)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.X)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Y)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Z)
if err != nil {
return
}
err = ret.Velocity.Encode(w)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Pitch)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Yaw)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.HeadPitch)
if err != nil {
return
}
err = proto_base.EncodeVarInt(w, ret.ObjectData)
if err != nil {
return
}
return return
} }
+117 -6
View File
@@ -16491,15 +16491,30 @@ func (ret *PlayToClientPacketEntityUpdateAttributes) Encode(w io.Writer) (err er
} }
type PlayToClientPacketEntityVelocity struct { type PlayToClientPacketEntityVelocity struct {
Val proto_base.ToDo EntityId int32
Velocity proto_base.LpVec3d
} }
func (ret *PlayToClientPacketEntityVelocity) Decode(r io.ReadSeeker) (err error) { func (ret *PlayToClientPacketEntityVelocity) Decode(r io.ReadSeeker) (err error) {
err = proto_base.ToDoError ret.EntityId, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
err = ret.Velocity.Decode(r)
if err != nil {
return
}
return return
} }
func (ret *PlayToClientPacketEntityVelocity) Encode(w io.Writer) (err error) { func (ret *PlayToClientPacketEntityVelocity) Encode(w io.Writer) (err error) {
err = proto_base.ToDoError err = proto_base.EncodeVarInt(w, ret.EntityId)
if err != nil {
return
}
err = ret.Velocity.Encode(w)
if err != nil {
return
}
return return
} }
@@ -20276,15 +20291,111 @@ func (ret *PlayToClientPacketSoundEffect) Encode(w io.Writer) (err error) {
} }
type PlayToClientPacketSpawnEntity struct { type PlayToClientPacketSpawnEntity struct {
Val proto_base.ToDo EntityId int32
ObjectUUID uuid.UUID
Type int32
X float64
Y float64
Z float64
Velocity proto_base.LpVec3d
Pitch int8
Yaw int8
HeadPitch int8
ObjectData int32
} }
func (ret *PlayToClientPacketSpawnEntity) Decode(r io.ReadSeeker) (err error) { func (ret *PlayToClientPacketSpawnEntity) Decode(r io.ReadSeeker) (err error) {
err = proto_base.ToDoError ret.EntityId, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
_, err = io.ReadFull(r, ret.ObjectUUID[:])
if err != nil {
return
}
ret.Type, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.X)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Y)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Z)
if err != nil {
return
}
err = ret.Velocity.Decode(r)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Pitch)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.Yaw)
if err != nil {
return
}
err = binary.Read(r, binary.BigEndian, &ret.HeadPitch)
if err != nil {
return
}
ret.ObjectData, err = proto_base.DecodeVarInt(r)
if err != nil {
return
}
return return
} }
func (ret *PlayToClientPacketSpawnEntity) Encode(w io.Writer) (err error) { func (ret *PlayToClientPacketSpawnEntity) Encode(w io.Writer) (err error) {
err = proto_base.ToDoError err = proto_base.EncodeVarInt(w, ret.EntityId)
if err != nil {
return
}
_, err = w.Write(ret.ObjectUUID[:])
if err != nil {
return
}
err = proto_base.EncodeVarInt(w, ret.Type)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.X)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Y)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Z)
if err != nil {
return
}
err = ret.Velocity.Encode(w)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Pitch)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.Yaw)
if err != nil {
return
}
err = binary.Write(w, binary.BigEndian, ret.HeadPitch)
if err != nil {
return
}
err = proto_base.EncodeVarInt(w, ret.ObjectData)
if err != nil {
return
}
return return
} }
+1 -1
View File
@@ -634,7 +634,7 @@ func (g *Generator) RegisterDecoderNatives() {
"varlong": VarLongDecoder, "varlong": VarLongDecoder,
"anonymousNbt": DefaultDecoder, "anonymousNbt": DefaultDecoder,
"anonOptionalNbt": DefaultDecoder, // I have no idea what the difference is between these two "anonOptionalNbt": DefaultDecoder, // I have no idea what the difference is between these two
"lpVec3": ToDoDecoder, "lpVec3": DefaultDecoder,
"UUID": UUIDDecoder, "UUID": UUIDDecoder,
"restBuffer": DefaultDecoder, "restBuffer": DefaultDecoder,
+1 -1
View File
@@ -414,7 +414,7 @@ func (g *Generator) RegisterEncoderNatives() {
"anonOptionalNbt": DefaultEncoder, // I have no idea what the difference is between these two "anonOptionalNbt": DefaultEncoder, // I have no idea what the difference is between these two
"UUID": UUIDEncoder, "UUID": UUIDEncoder,
"restBuffer": DefaultEncoder, "restBuffer": DefaultEncoder,
"lpVec3": ToDoEncoder, "lpVec3": DefaultEncoder,
"string": StringEncoder, "string": StringEncoder,
"f32": SimpleTypeEncoder, "f32": SimpleTypeEncoder,
+1 -1
View File
@@ -225,6 +225,6 @@ func (g *Generator) RegisterNatives() {
"bitflags": VisitBitFlagsType, "bitflags": VisitBitFlagsType,
"topBitSetTerminatedArray": VisitToDoType, "topBitSetTerminatedArray": VisitToDoType,
"todo": VisitToDoType, "todo": VisitToDoType,
"lpVec3": VisitToDoType, "lpVec3": MakeSelectorVisitor("proto_base", "LpVec3d"),
} }
} }