mirror of
https://github.com/Luzifer/sii.git
synced 2024-10-18 05:14:19 +00:00
Add placement reading
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
5aa424fa3d
commit
a9607ba090
3 changed files with 155 additions and 6 deletions
59
datatypes.go
59
datatypes.go
|
@ -1,6 +1,12 @@
|
||||||
package sii
|
package sii
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
// See https://modding.scssoft.com/wiki/Documentation/Engine/Units
|
// See https://modding.scssoft.com/wiki/Documentation/Engine/Units
|
||||||
|
|
||||||
|
@ -10,12 +16,50 @@ import "strings"
|
||||||
|
|
||||||
// float2-4 => [2]float - [4]float
|
// float2-4 => [2]float - [4]float
|
||||||
|
|
||||||
type Placement struct {
|
var placementRegexp = regexp.MustCompile(`^\(([0-9.]+|&[0-9a-f]+), ([0-9.]+|&[0-9a-f]+), ([0-9.]+|&[0-9a-f]+)\) \(([0-9.]+|&[0-9a-f]+); ([0-9.]+|&[0-9a-f]+), ([0-9.]+|&[0-9a-f]+), ([0-9.]+|&[0-9a-f]+)\)$`)
|
||||||
X, Y, Z float64
|
|
||||||
W, X2, Y2, Z2 float64
|
// Placement contains 7 floats: (x, y, z) (w; x, y, z)
|
||||||
|
type Placement [7]float32
|
||||||
|
|
||||||
|
func (p Placement) MarshalSII() ([]byte, error) {
|
||||||
|
var siiFloats = [][]byte{}
|
||||||
|
|
||||||
|
for _, f := range p {
|
||||||
|
b, err := float2sii(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Unable to encode float")
|
||||||
|
}
|
||||||
|
siiFloats = append(siiFloats, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf = new(bytes.Buffer)
|
||||||
|
|
||||||
|
buf.Write([]byte("("))
|
||||||
|
bytes.Join(siiFloats[0:3], []byte(", "))
|
||||||
|
buf.Write([]byte(") ("))
|
||||||
|
buf.Write(siiFloats[3])
|
||||||
|
buf.Write([]byte("; "))
|
||||||
|
bytes.Join(siiFloats[4:7], []byte(", "))
|
||||||
|
buf.Write([]byte(")"))
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement marshalling for Placement
|
func (p *Placement) UnmarshalSII(in []byte) error {
|
||||||
|
if !placementRegexp.Match(in) {
|
||||||
|
return errors.New("Input data does not match expected format")
|
||||||
|
}
|
||||||
|
|
||||||
|
grps := placementRegexp.FindSubmatch(in)
|
||||||
|
var err error
|
||||||
|
for i := 0; i < 7; i++ {
|
||||||
|
if p[i], err = sii2float(grps[i+1]); err != nil {
|
||||||
|
return errors.Wrap(err, "Unable to decode float")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// fixed => native type int
|
// fixed => native type int
|
||||||
|
|
||||||
|
@ -38,8 +82,10 @@ type Ptr struct {
|
||||||
unit *Unit
|
unit *Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Ptr) CanResolve() bool { return strings.HasPrefix(p.Target, ".") }
|
func (p Ptr) CanResolve() bool { return strings.HasPrefix(p.Target, ".") }
|
||||||
|
|
||||||
func (p Ptr) MarshalSII() []byte { return []byte(p.Target) }
|
func (p Ptr) MarshalSII() []byte { return []byte(p.Target) }
|
||||||
|
|
||||||
func (p Ptr) Resolve() Block {
|
func (p Ptr) Resolve() Block {
|
||||||
if p.Target == "null" {
|
if p.Target == "null" {
|
||||||
return nil
|
return nil
|
||||||
|
@ -52,6 +98,7 @@ func (p Ptr) Resolve() Block {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Ptr) UnmarshalSII(in []byte) error {
|
func (p *Ptr) UnmarshalSII(in []byte) error {
|
||||||
p.Target = string(in)
|
p.Target = string(in)
|
||||||
return nil
|
return nil
|
||||||
|
|
51
helpers.go
Normal file
51
helpers.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package sii
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func float2sii(f float32) ([]byte, error) {
|
||||||
|
var (
|
||||||
|
buf = new(bytes.Buffer)
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
err = binary.Write(buf, binary.BigEndian, f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "Unable to encode float")
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := make([]byte, hex.EncodedLen(buf.Len()))
|
||||||
|
hex.Encode(dst, buf.Bytes())
|
||||||
|
|
||||||
|
return append([]byte("&"), dst...), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sii2float(f []byte) (float32, error) {
|
||||||
|
if f[0] != '&' {
|
||||||
|
out, err := strconv.ParseFloat(string(f), 32)
|
||||||
|
return float32(out), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip leading '&'
|
||||||
|
f = f[1:]
|
||||||
|
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
out float32
|
||||||
|
)
|
||||||
|
|
||||||
|
dst := make([]byte, hex.DecodedLen(len(f)))
|
||||||
|
_, err = hex.Decode(dst, f)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.Wrap(err, "Unable to read hex format")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = binary.Read(bytes.NewReader(dst), binary.BigEndian, &out)
|
||||||
|
return out, errors.Wrap(err, "Unable to decode hex notation")
|
||||||
|
}
|
51
helpers_test.go
Normal file
51
helpers_test.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package sii
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestSii2FloatConversion(t *testing.T) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
f float32
|
||||||
|
)
|
||||||
|
|
||||||
|
for b, exp := range map[string]float32{
|
||||||
|
"0.00250711967": 0.00250711967,
|
||||||
|
"1.0": 1.0,
|
||||||
|
"&3b244e7d": 0.00250711967,
|
||||||
|
"&3f46da61": 0.7767697,
|
||||||
|
"&47135818": 37720.0938,
|
||||||
|
} {
|
||||||
|
f, err = sii2float([]byte(b))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Conversion of %q failed: %s", b, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if f != exp {
|
||||||
|
t.Errorf("Conversion of %q has unxpected result: %f != %f", b, f, exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFloat2SiiConversion(t *testing.T) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
f []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
for b, exp := range map[float32]string{
|
||||||
|
0.00250711967: "&3b244e7d",
|
||||||
|
0.7767697: "&3f46da61",
|
||||||
|
37720.0938: "&47135818",
|
||||||
|
} {
|
||||||
|
f, err = float2sii(b)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Conversion of %f failed: %s", b, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(f) != exp {
|
||||||
|
t.Errorf("Conversion of %f has unxpected result: %s != %s", b, f, exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue