diff --git a/bit/decode.go b/bit/decode.go index 5c8795f..bdf49c4 100644 --- a/bit/decode.go +++ b/bit/decode.go @@ -4,6 +4,11 @@ import ( "bytes" ) +// normalized values are represented with 11 significant bits. we pre-compute a +// divisor so that we can use a multiply instruction and avoid using +// floating-point division during the lifecycle of the program. +var normal_divisor = float32(1.0) / float32(2047) + // ReadUbitVar reads a prefixed uint value. A prefix is 2 bits wide, followed // by the 4 least-significant bits, then a variable number of most-significant // bits based on the prefix. @@ -109,3 +114,16 @@ func ReadZigZag32(r Reader) int32 { } return int32(u >> 1) } + +// reads a 12-bit normalized float. The first bit represents a sign bit, the +// next sequence of 11 bits represents some normalized value between 0 and +// 2047, allowing up to 4096 positions between -1.0 and 1.0. the resulting +// float will always be between -1.0 and 1.0 (that's why it's normal) +func ReadNormal(r Reader) float32 { + // sign bit + if ReadBool(r) { + return float32(r.ReadBits(11)) * normal_divisor + } else { + return -float32(r.ReadBits(11)) * normal_divisor + } +} diff --git a/ent/decoders.go b/ent/decoders.go new file mode 100644 index 0000000..1e631ff --- /dev/null +++ b/ent/decoders.go @@ -0,0 +1,102 @@ +package ent + +import ( + "math" + "strings" + + "github.com/jordanorelli/hyperstone/bit" +) + +// a decoder decodes an entity value off of a bit reader +type decoder func(bit.Reader) interface{} + +// creates a new field decoder for the field f. +func newFieldDecoder(n *Namespace, f *Field) decoder { + Debug.Printf("new decoder: type: %s name: %s sendNode: %s\n\tbits: %d low: %v high: %v\n\tflags: %d serializer: %v serializerVersion: %v\n\tclass: %v encoder: %v", f._type, f.name, f.sendNode, f.bits, f.low, f.high, f.flags, f.serializer, f.serializerVersion, f.class, f.encoder) + + switch f._type.String() { + case "bool": + return decodeBool + case "float32": + return floatDecoder(f) + case "uint8", "uint16", "uint32", "uint64", "Color": + return decodeVarInt64 + case "Vector": + return vectorDecoder(f) + } + + // the field is itself an entity contained within the outer entity. + if f.class != nil { + return entityDecoder(f.class) + } + + switch { + case strings.HasPrefix(f._type.String(), "CHandle"): + return decodeVarInt32 + } + return nil +} + +func decodeBool(br bit.Reader) interface{} { return bit.ReadBool(br) } +func decodeVarInt32(br bit.Reader) interface{} { return bit.ReadVarInt32(br) } +func decodeVarInt64(br bit.Reader) interface{} { return bit.ReadVarInt(br) } + +func floatDecoder(f *Field) decoder { + if f.bits <= 0 || f.bits >= 32 { + return ieeeFloat32Decoder + } + return nil +} + +// reads an IEEE 754 binary float value off of the stream +func ieeeFloat32Decoder(br bit.Reader) interface{} { + return math.Float32frombits(uint32(br.ReadBits(32))) +} + +func entityDecoder(c *Class) decoder { + return func(br bit.Reader) interface{} { + // I have no idea what this bit means. + return bit.ReadBool(br) + } +} + +func vectorDecoder(f *Field) decoder { + if f.encoder != nil { + switch f.encoder.String() { + case "normal": + return decodeNormalVector + default: + return nil + } + } + + fn := floatDecoder(f) + if fn == nil { + return nil + } + return func(br bit.Reader) interface{} { + return vector{fn(br).(float32), fn(br).(float32), fn(br).(float32)} + } +} + +type vector [3]float32 + +func decodeNormalVector(br bit.Reader) interface{} { + var v vector + x, y := bit.ReadBool(br), bit.ReadBool(br) + if x { + v[0] = bit.ReadNormal(br) + } + if y { + v[1] = bit.ReadNormal(br) + } + // yoooooo what in the good fuck is going on here + p := v[0]*v[0] + v[1]*v[1] + if p < 1.0 { + v[2] = float32(math.Sqrt(float64(1.0 - p))) + } + if bit.ReadBool(br) { + v[2] = -v[2] + } + return v +} diff --git a/ent/entity.go b/ent/entity.go index 70ac47f..658646c 100644 --- a/ent/entity.go +++ b/ent/entity.go @@ -8,6 +8,7 @@ import ( type Entity struct { *Class + slots []interface{} } func (e *Entity) Read(br bit.Reader, sr *selectionReader) error { @@ -23,9 +24,20 @@ func (e *Entity) Read(br bit.Reader, sr *selectionReader) error { for _, s := range sr.selections() { switch s.count { case 0: - Debug.Printf("FUCK!") + panic("field selection makes no sense") case 1: Debug.Printf("direct selection: %v", s.path()) + field := e.Class.Fields[s.vals[0]] + Debug.Printf("field: %v", e.Class.Fields[s.vals[0]]) + fn := field.decoder + if fn == nil { + Info.Fatalf("field has no decoder: %v", field) + } + v, err := fn(br), br.Err() + Debug.Printf("value: %v err: %v", v, err) + if err != nil { + Info.Fatalf("field decode error: %v", err) + } default: Debug.Printf("child selection: %v", s.path()) } diff --git a/ent/field.go b/ent/field.go index b5d3f48..c24159d 100644 --- a/ent/field.go +++ b/ent/field.go @@ -11,21 +11,25 @@ type Field struct { _type Symbol // type of data held by the field name Symbol // name of the field sendNode Symbol // not sure what this is - bits *int // number of bits used to encode field? + bits int // number of bits used to encode field? low *float32 // lower limit of field values high *float32 // upper limit of field values - flags *int32 // dunno what these flags do + flags int // dunno what these flags do serializer *Symbol // class on which the field was defined serializerVersion *int32 // version of the class on which the field was defined class *Class // source class on which the field was originally defined - encoder *Symbol // binary reader + encoder *Symbol // binary encoder, named explicitly in protobuf + decoder // decodes field values from a bit stream } func (f Field) String() string { var buf bytes.Buffer fmt.Fprintf(&buf, "{type: %s name: %s send: %s", f._type, f.name, f.sendNode) - if f.bits != nil { - fmt.Fprintf(&buf, " bits: %d", *f.bits) + if f.bits > 0 { + fmt.Fprintf(&buf, " bits: %d", f.bits) + } + if f.flags > 0 { + fmt.Fprintf(&buf, " flags: %d", f.flags) } if f.low != nil { fmt.Fprintf(&buf, " low: %f", *f.low) @@ -33,9 +37,6 @@ func (f Field) String() string { if f.high != nil { fmt.Fprintf(&buf, " high: %f", *f.high) } - if f.flags != nil { - fmt.Fprintf(&buf, " flags: %d", *f.flags) - } if f.serializer != nil { fmt.Fprintf(&buf, " serializer: %s", *f.serializer) } @@ -52,15 +53,10 @@ func (f Field) String() string { func (f *Field) fromProto(flat *dota.ProtoFlattenedSerializerFieldT, t *SymbolTable) { f._type = t.Symbol(int(flat.GetVarTypeSym())) f.name = t.Symbol(int(flat.GetVarNameSym())) - if flat.BitCount == nil { - f.bits = nil - } else { - f.bits = new(int) - *f.bits = int(flat.GetBitCount()) - } + f.bits = int(flat.GetBitCount()) + f.flags = int(flat.GetEncodeFlags()) f.low = flat.LowValue f.high = flat.HighValue - f.flags = flat.EncodeFlags if flat.FieldSerializerNameSym == nil { f.serializer = nil diff --git a/ent/namespace.go b/ent/namespace.go index efa4f48..9fe2579 100644 --- a/ent/namespace.go +++ b/ent/namespace.go @@ -106,6 +106,11 @@ func (n *Namespace) mergeSendTables(st *dota.CDemoSendTables) error { f.class = n.NewestClass(f.serializer.String()) } } + + // we also wait until after we've discovered all of the classes to + // build the field decoder functions, because some fields are + // themselves entities. + f.decoder = newFieldDecoder(n, f) } return br.Err() @@ -140,3 +145,8 @@ func (n *Namespace) ClassByNetId(id int) *Class { } return n.NewestClass(name) } + +func (n *Namespace) HasClass(name string) bool { + _, ok := n.classesByName[name] + return ok +} diff --git a/ent/selection.go b/ent/selection.go index 4c7cb3c..cd20dc0 100644 --- a/ent/selection.go +++ b/ent/selection.go @@ -42,9 +42,11 @@ func (r *selectionReader) read(br bit.Reader, n node) error { return fmt.Errorf("unable to read selection: bit reader error: %v", err) } fn(r, br) - Debug.Printf("selection: %v", r.cur.path()) r.keep() } + if err := br.Err(); err != nil { + return fmt.Errorf("unable to read selection: bit reader error: %v", err) + } return nil }