back to this thing again

types
Jordan Orelli 8 years ago
parent 6b2371a940
commit 79200cae38

@ -16,21 +16,47 @@ func (c class) String() string {
} }
func (c *class) read(r bit.Reader) (value, error) { func (c *class) read(r bit.Reader) (value, error) {
return nil, fmt.Errorf("fart") bit.ReadBool(r) // ???
return c.nü(), nil
} }
type classHistory map[int]*class func (c *class) nü() entity {
return entity{class: c, slots: make([]value, len(c.fields))}
}
type classHistory struct {
versions map[int]*class
oldest *class
newest *class
}
func (h *classHistory) add(c *class) {
if h.oldest == nil || c.version < h.oldest.version {
h.oldest = c
}
if h.newest == nil || c.version > h.newest.version {
h.newest = c
}
if h.versions == nil {
h.versions = make(map[int]*class)
}
h.versions[c.version] = c
}
func (h *classHistory) version(v int) *class {
if h.versions == nil {
return nil
}
return h.versions[v]
}
func classType(spec *typeSpec, env *Env) tÿpe { func classType(spec *typeSpec, env *Env) tÿpe {
if spec.serializer != "" { if spec.serializer != "" {
h := env.classes[spec.serializer] c := env.classVersion(spec.serializer, spec.serializerV)
if h != nil { if c != nil {
class := h[spec.serializerV] return c
if class != nil {
return class
}
return typeError("class %s exists for spec serializer but can't find version %d", spec.serializer, spec.serializerV)
} }
return typeError("unable to find class named %s with version %d", spec.serializer, spec.serializerV)
} }
return nil return nil
} }

@ -0,0 +1,36 @@
package ent
import (
"github.com/jordanorelli/hyperstone/bit"
)
type entity struct {
class *class
slots []value
}
func (e *entity) read(r bit.Reader) error {
Debug.Printf("entity %s read", e.className())
sr := new(selectionReader)
selections, err := sr.readSelections(r, htree)
if err != nil {
return wrap(err, "entity of type %s failed to read selections", e.className())
}
for _, s := range selections {
if err := s.fillSlots(e, r); err != nil {
return err
}
}
return nil
}
func (e *entity) className() string {
if e.class != nil {
return e.class.name
}
return "<None>"
}
func (e *entity) slotType(i int) tÿpe { return e.class.fields[i].tÿpe }
func (e *entity) setSlotValue(i int, v value) { e.slots[i] = v }
func (e *entity) getSlotValue(i int) value { return e.slots[i] }

@ -2,6 +2,7 @@ package ent
import ( import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"strconv"
"github.com/jordanorelli/hyperstone/bit" "github.com/jordanorelli/hyperstone/bit"
"github.com/jordanorelli/hyperstone/dota" "github.com/jordanorelli/hyperstone/dota"
@ -11,14 +12,17 @@ import (
type Env struct { type Env struct {
symbols symbolTable symbols symbolTable
source bit.BufReader source bit.BufReader
classes map[string]classHistory classes map[string]*classHistory
netIds map[int]string netIds map[int]string
fields []field fields []field
strings *stbl.Dict strings *stbl.Dict
} }
func NewEnv() *Env { func NewEnv() *Env {
e := &Env{strings: stbl.NewDict()} e := &Env{
classes: make(map[string]*classHistory),
strings: stbl.NewDict(),
}
e.strings.WatchTable("instancebaseline", e.syncBaselineTable) e.strings.WatchTable("instancebaseline", e.syncBaselineTable)
return e return e
} }
@ -36,10 +40,10 @@ func (e *Env) Handle(m proto.Message) error {
if err := e.mergeSendTables(v); err != nil { if err := e.mergeSendTables(v); err != nil {
return err return err
} }
e.syncBaseline()
case *dota.CDemoClassInfo: case *dota.CDemoClassInfo:
e.mergeClassInfo(v) e.mergeClassInfo(v)
e.syncBaseline()
} }
return nil return nil
} }
@ -71,16 +75,17 @@ func (e *Env) mergeSendTables(m *dota.CDemoSendTables) error {
// structs that fields may point to. // structs that fields may point to.
func (e *Env) stubClasses(flat *dota.CSVCMsg_FlattenedSerializer) { func (e *Env) stubClasses(flat *dota.CSVCMsg_FlattenedSerializer) {
serializers := flat.GetSerializers() serializers := flat.GetSerializers()
if e.classes == nil {
e.classes = make(map[string]classHistory, len(serializers))
}
for _, s := range serializers { for _, s := range serializers {
name := e.symbol(int(s.GetSerializerNameSym())) name := e.symbol(int(s.GetSerializerNameSym()))
v := int(s.GetSerializerVersion()) v := int(s.GetSerializerVersion())
if e.classes[name] == nil { c := &class{name: name, version: v}
e.classes[name] = make(classHistory, 4) Debug.Printf("new class: %s", c)
h := e.classes[name]
if h == nil {
h = new(classHistory)
e.classes[name] = h
} }
e.classes[name][v] = &class{name: name, version: v} h.add(c)
} }
} }
@ -104,7 +109,7 @@ func (e *Env) fillClasses(flat *dota.CSVCMsg_FlattenedSerializer) {
for _, s := range flat.GetSerializers() { for _, s := range flat.GetSerializers() {
name := e.symbol(int(s.GetSerializerNameSym())) name := e.symbol(int(s.GetSerializerNameSym()))
v := int(s.GetSerializerVersion()) v := int(s.GetSerializerVersion())
class := e.classes[name][v] class := e.classes[name].version(v)
class.fields = make([]field, len(s.GetFieldsIndex())) class.fields = make([]field, len(s.GetFieldsIndex()))
for i, id := range s.GetFieldsIndex() { for i, id := range s.GetFieldsIndex() {
@ -136,7 +141,48 @@ func (e *Env) syncBaseline() {
} }
func (e *Env) syncBaselineTable(t *stbl.Table) { func (e *Env) syncBaselineTable(t *stbl.Table) {
if e.classes == nil { if e.netIds == nil || len(e.netIds) == 0 {
Debug.Printf("syncBaselines skipped: net ids are nil")
}
if e.classes == nil || len(e.classes) == 0 {
Debug.Printf("syncBaselines skipped: classes are nil") Debug.Printf("syncBaselines skipped: classes are nil")
} }
r := new(bit.BufReader)
for _, entry := range t.Entries() {
netId, err := strconv.Atoi(entry.Key)
if err != nil {
Debug.Printf("syncBaselines ignored bad key %s: %v", err)
continue
}
className := e.netIds[netId]
if className == "" {
Debug.Printf("syncBaselines couldn't find class with net id %d", netId)
continue
}
c := e.class(className)
if c == nil {
Debug.Printf("syncBaselines couldn't find class named %s", className)
continue
}
Debug.Printf("syncBaselines key: %s className: %s", entry.Key, c.name)
ent := c.nü()
r.SetSource(entry.Value)
if err := ent.read(r); err != nil {
Debug.Printf("syncBaselines failed to fill an entity: %v", err)
}
}
}
func (e *Env) class(name string) *class {
h := e.classes[name]
if h == nil {
return nil
}
return h.newest
}
func (e *Env) classVersion(name string, version int) *class {
h := e.classes[name]
return h.version(version)
} }

@ -19,6 +19,35 @@ type selection struct {
func (s selection) String() string { return fmt.Sprint(s.path()) } func (s selection) String() string { return fmt.Sprint(s.path()) }
func (s selection) path() []int { return s.vals[:s.count] } func (s selection) path() []int { return s.vals[:s.count] }
func (s selection) fillSlots(v slotted, r bit.Reader) error {
Debug.Printf("%v fill slots into %v", s, v)
return s.fillSlotsIter(0, v, r)
}
func (s selection) fillSlotsIter(offset int, dest slotted, r bit.Reader) error {
slot := s.vals[offset]
if s.count-offset <= 0 {
return fmt.Errorf("unable to fill selection %v having count %d at offset %d", s, s.count, offset)
}
switch s.count - offset {
case 1:
t := dest.slotType(slot)
v, err := t.read(r)
if err != nil {
return fmt.Errorf("unable to fill selection: %v", err)
}
dest.setSlotValue(slot, v)
return nil
default:
v := dest.getSlotValue(slot)
vs, ok := v.(slotted)
if !ok {
return fmt.Errorf("destination is not slotted")
}
return s.fillSlotsIter(offset+1, vs, r)
}
}
// selectionReader reads a set of field selections off of the wire. the // selectionReader reads a set of field selections off of the wire. the
// selections are represented as arrays of slot positions to be traversed in // selections are represented as arrays of slot positions to be traversed in
// order to select an entity slot. // order to select an entity slot.

@ -0,0 +1,7 @@
package ent
type slotted interface {
slotType(int) tÿpe
setSlotValue(int, value)
getSlotValue(int) value
}

@ -34,7 +34,14 @@ func parseTypeSpec(spec *typeSpec, env *Env) tÿpe {
return nil return nil
} }
return coalesce(arrayType, atomType, floatType, handleType, qAngleType, return coalesce(arrayType, atomType, floatType, handleType, qAngleType,
hSeqType, genericType, vectorType, classType) hSeqType, genericType, vectorType, classType, unknownType)
}
func unknownType(spec *typeSpec, env *Env) tÿpe {
Debug.Printf("Unknown Type: %v", spec)
return typeFn(func(r bit.Reader) (value, error) {
return bit.ReadVarInt(r), r.Err()
})
} }
// a type error is both an error and a type. It represents a type that we were // a type error is both an error and a type. It represents a type that we were

@ -10,7 +10,14 @@ func vectorType(spec *typeSpec, env *Env) tÿpe {
if spec.encoder != "" { if spec.encoder != "" {
return nil return nil
} }
return vector_t{elem: floatType(spec, env)} t := floatType(spec, env)
if _, ok := t.(error); ok {
return t
}
if t == nil {
return nil
}
return vector_t{elem: t}
} }
type vector_t struct { type vector_t struct {

Loading…
Cancel
Save