diff --git a/ent/float.go b/ent/float.go index c7fd834..b1e8a1e 100644 --- a/ent/float.go +++ b/ent/float.go @@ -1,7 +1,7 @@ package ent import ( - "fmt" + "math" "github.com/jordanorelli/hyperstone/bit" "github.com/jordanorelli/hyperstone/dota" @@ -13,10 +13,25 @@ const ( f_center ) -func qFloatType(flat *dota.ProtoFlattenedSerializerFieldT, env *Env) tÿpe { - if env.symbol(int(flat.GetVarTypeSym())) != "CNetworkedQuantizedFloat" { +func floatType(flat *dota.ProtoFlattenedSerializerFieldT, env *Env) tÿpe { + if env.symbol(int(flat.GetVarTypeSym())) == "CNetworkedQuantizedFloat" { + return qFloatType(flat, env) + } + if env.symbol(int(flat.GetVarEncoderSym())) == "coord" { + return nil + } + if env.symbol(int(flat.GetFieldSerializerNameSym())) == "simulationtime" { + return nil + } + switch flat.GetBitCount() { + case 0, 32: + return typeFn(float_t) + default: return nil } +} + +func qFloatType(flat *dota.ProtoFlattenedSerializerFieldT, env *Env) tÿpe { if flat.GetBitCount() < 0 { return typeError("quantized float has invalid negative bit count specifier") } @@ -63,5 +78,10 @@ func (t qfloat_t) read(r bit.Reader) (value, error) { if t.special != nil && bit.ReadBool(r) { return *t.special, nil } - return nil, fmt.Errorf("I'll get there") + return t.low + float32(r.ReadBits(t.bits))*t.interval, r.Err() +} + +func float_t(r bit.Reader) (value, error) { + // TODO: check uint32 overflow here? + return math.Float32frombits(uint32(r.ReadBits(32))), r.Err() } diff --git a/ent/handle.go b/ent/handle.go index 19cef53..eafd01e 100644 --- a/ent/handle.go +++ b/ent/handle.go @@ -5,19 +5,16 @@ import ( "github.com/jordanorelli/hyperstone/dota" ) -func handleType(flat *dota.ProtoFlattenedSerializerFieldT, env *Env) tÿpe { - if env.symbol(int(flat.GetVarTypeSym())) != "CGameSceneNodeHandle" { - return nil - } - return handle_t{} -} - // a handle represents a soft pointer to an entity. handles are represented by // IDs and can cross the client-server divide. type handle int -type handle_t struct{} +func handleType(flat *dota.ProtoFlattenedSerializerFieldT, env *Env) tÿpe { + if env.symbol(int(flat.GetVarTypeSym())) != "CGameSceneNodeHandle" { + return nil + } -func (t handle_t) read(r bit.Reader) (value, error) { - return handle(bit.ReadVarInt(r)), nil + return typeFn(func(r bit.Reader) (value, error) { + return handle(bit.ReadVarInt(r)), r.Err() + }) } diff --git a/ent/qangle.go b/ent/qangle.go new file mode 100644 index 0000000..d030ca1 --- /dev/null +++ b/ent/qangle.go @@ -0,0 +1,33 @@ +package ent + +import ( + "github.com/jordanorelli/hyperstone/bit" + "github.com/jordanorelli/hyperstone/dota" +) + +func qAngleType(flat *dota.ProtoFlattenedSerializerFieldT, env *Env) tÿpe { + if env.symbol(int(flat.GetVarTypeSym())) != "QAngle" { + return nil + } + switch flat.GetBitCount() { + case 0: + return typeFn(func(r bit.Reader) (value, error) { + x, y, z := bit.ReadBool(r), bit.ReadBool(r), bit.ReadBool(r) + var v vector + if x { + v.x = bit.ReadCoord(r) + } + if y { + v.y = bit.ReadCoord(r) + } + if z { + v.z = bit.ReadCoord(r) + } + return v, nil + }) + case 32: + return nil + default: + return nil + } +} diff --git a/ent/type.go b/ent/type.go index d73f43c..23b45b7 100644 --- a/ent/type.go +++ b/ent/type.go @@ -26,7 +26,7 @@ func parseType(flat *dota.ProtoFlattenedSerializerFieldT, env *Env) tÿpe { } return nil } - return coalesce(atomType, qFloatType, handleType) + return coalesce(atomType, floatType, handleType, qAngleType) } // a type error is both an error and a type. It represents a type that we were diff --git a/ent/vector.go b/ent/vector.go new file mode 100644 index 0000000..5dcd82e --- /dev/null +++ b/ent/vector.go @@ -0,0 +1,3 @@ +package ent + +type vector struct{ x, y, z float32 }