lpvec3d
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"math"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -284,3 +285,115 @@ func Bool2uint64(b bool) uint64 {
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package v1_21_11
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/admin-else/strom/nbt"
|
||||
"github.com/admin-else/strom/proto_base"
|
||||
"github.com/google/uuid"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ArmorTrimMaterial struct {
|
||||
@@ -16668,15 +16669,30 @@ func (ret *PlayToClientPacketEntityUpdateAttributes) Encode(w io.Writer) (err er
|
||||
}
|
||||
|
||||
type PlayToClientPacketEntityVelocity struct {
|
||||
Val proto_base.ToDo
|
||||
EntityId int32
|
||||
Velocity proto_base.LpVec3d
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -20453,15 +20469,111 @@ func (ret *PlayToClientPacketSoundEffect) Encode(w io.Writer) (err error) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -16491,15 +16491,30 @@ func (ret *PlayToClientPacketEntityUpdateAttributes) Encode(w io.Writer) (err er
|
||||
}
|
||||
|
||||
type PlayToClientPacketEntityVelocity struct {
|
||||
Val proto_base.ToDo
|
||||
EntityId int32
|
||||
Velocity proto_base.LpVec3d
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -20276,15 +20291,111 @@ func (ret *PlayToClientPacketSoundEffect) Encode(w io.Writer) (err error) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -634,7 +634,7 @@ func (g *Generator) RegisterDecoderNatives() {
|
||||
"varlong": VarLongDecoder,
|
||||
"anonymousNbt": DefaultDecoder,
|
||||
"anonOptionalNbt": DefaultDecoder, // I have no idea what the difference is between these two
|
||||
"lpVec3": ToDoDecoder,
|
||||
"lpVec3": DefaultDecoder,
|
||||
"UUID": UUIDDecoder,
|
||||
"restBuffer": DefaultDecoder,
|
||||
|
||||
|
||||
@@ -414,7 +414,7 @@ func (g *Generator) RegisterEncoderNatives() {
|
||||
"anonOptionalNbt": DefaultEncoder, // I have no idea what the difference is between these two
|
||||
"UUID": UUIDEncoder,
|
||||
"restBuffer": DefaultEncoder,
|
||||
"lpVec3": ToDoEncoder,
|
||||
"lpVec3": DefaultEncoder,
|
||||
"string": StringEncoder,
|
||||
|
||||
"f32": SimpleTypeEncoder,
|
||||
|
||||
@@ -225,6 +225,6 @@ func (g *Generator) RegisterNatives() {
|
||||
"bitflags": VisitBitFlagsType,
|
||||
"topBitSetTerminatedArray": VisitToDoType,
|
||||
"todo": VisitToDoType,
|
||||
"lpVec3": VisitToDoType,
|
||||
"lpVec3": MakeSelectorVisitor("proto_base", "LpVec3d"),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user