let's export less stuff

master
Jordan Orelli 8 years ago
parent b6df19139f
commit bd3387b605

@ -1,6 +1,7 @@
package ent package ent
import ( import (
"fmt"
"github.com/jordanorelli/hyperstone/dota" "github.com/jordanorelli/hyperstone/dota"
) )
@ -15,6 +16,10 @@ func (c *Class) New() *Entity {
return &Entity{Class: c} return &Entity{Class: c}
} }
func (c Class) String() string {
return fmt.Sprintf("{%s %d}", c.Name, c.Version)
}
type classId struct { type classId struct {
name Symbol name Symbol
version int version int

@ -2,44 +2,114 @@ package ent
import ( import (
"fmt" "fmt"
"github.com/golang/protobuf/proto"
"github.com/jordanorelli/hyperstone/bit" "github.com/jordanorelli/hyperstone/bit"
"github.com/jordanorelli/hyperstone/dota"
) )
type Context struct { // Dict corresponds to the edict_t in Valve's documentation for the Source
// engine. See here: https://developer.valvesoftware.com/wiki/Edict_t
//
// From the Valve docs:
// edict_t ("entity dictionary") is an interface struct that allows entities
// to cross the client/server divide: with one attached, an entity has the
// same index at both ends. The edict also manages the state of the entity's
// DataTable and provides a common representation across all DLLs. It cannot
// be used on the client.
type Dict struct {
*Namespace *Namespace
entities map[int]Entity entities map[int]Entity
br *bit.BufReader
} }
func NewContext() *Context { func NewDict() *Dict {
return &Context{Namespace: new(Namespace), entities: make(map[int]Entity)} return &Dict{
Namespace: new(Namespace),
entities: make(map[int]Entity),
br: new(bit.BufReader),
}
} }
func (c *Context) CreateEntity(id int, r bit.Reader) error { // creates an entity with the provided id. the entity's contents data are read
classId := int(c.readClassId(r)) // off of the Dict's internal bit stream br
if len(c.Namespace.classes) == 0 { func (d *Dict) createEntity(id int) error {
classId := int(d.readClassId(d.br))
if len(d.Namespace.classes) == 0 {
return fmt.Errorf("unable to create entity %d: namespace has no classes", id) return fmt.Errorf("unable to create entity %d: namespace has no classes", id)
} }
r.ReadBits(17) // ??? d.br.ReadBits(17) // ???
classV := int(bit.ReadVarInt(r)) classV := int(bit.ReadVarInt(d.br))
className := c.classIds[classId] className := d.classIds[classId]
class := c.Class(className, classV) class := d.Class(className, classV)
if class == nil { if class == nil {
return fmt.Errorf("unable to create entity %d: no class found for class name %s, version %d", className, classV) return fmt.Errorf("unable to create entity %d: no class found for class name %s, version %d", className, classV)
} }
Debug.Printf("create entity id: %d classId: %d className: %v class: %v\n", id, classId, className, class) Debug.Printf("create entity id: %d classId: %d className: %v class: %v\n", id, classId, className, class)
e := class.New() e := class.New()
e.Read(r) e.Read(d.br)
return nil return nil
} }
func (c *Context) UpdateEntity(id int, r bit.Reader) { func (d *Dict) updateEntity(id int) error {
Debug.Printf("update entity id: %d\n", id) Debug.Printf("update entity id: %d\n", id)
return nil
} }
func (c *Context) DeleteEntity(id int) { func (d *Dict) deleteEntity(id int) error {
Debug.Printf("delete entity id: %d\n", id) Debug.Printf("delete entity id: %d\n", id)
return nil
} }
func (c *Context) LeaveEntity(id int) { func (d *Dict) leaveEntity(id int) error {
Debug.Printf("leave entity id: %d\n", id) Debug.Printf("leave entity id: %d\n", id)
return nil
}
func (d *Dict) Handle(m proto.Message) {
switch v := m.(type) {
case *dota.CDemoSendTables:
d.mergeSendTables(v)
case *dota.CDemoClassInfo:
d.mergeClassInfo(v)
case *dota.CSVCMsg_PacketEntities:
d.mergeEntities(v)
}
}
func (d *Dict) mergeEntities(m *dota.CSVCMsg_PacketEntities) error {
data := m.GetEntityData()
Debug.Printf("packet header MaxEntries: %d UpdatedEntries: %v IsDelta: %t UpdateBaseline: %t Baseline: %d DeltaFrom: %d PendingFullFrame: %t ActiveSpawngroupHandle: %d", m.GetMaxEntries(), m.GetUpdatedEntries(), m.GetIsDelta(), m.GetUpdateBaseline(), m.GetBaseline(), m.GetDeltaFrom(), m.GetPendingFullFrame(), m.GetActiveSpawngroupHandle())
d.br.SetSource(data)
id := -1
// for i := 0; i < int(m.GetUpdatedEntries()); i++ {
for i := 0; i < 1; i++ {
id++
// there may be a jump indicator, indicating how many id positions
// to skip.
id += int(bit.ReadUBitVar(d.br))
// next two bits encode one of four entity mutate operations
var fn func(int) error
switch d.br.ReadBits(2) {
case 0:
fn = d.updateEntity
case 1:
fn = d.leaveEntity
case 2:
fn = d.createEntity
case 3:
fn = d.deleteEntity
}
if err := fn(id); err != nil {
return fmt.Errorf("entity merge error: %v", err)
}
}
return nil
} }

@ -27,7 +27,7 @@ type Namespace struct {
} }
// Merges in the ClassInfo data found in the replay protobufs // Merges in the ClassInfo data found in the replay protobufs
func (n *Namespace) MergeClassInfo(ci *dota.CDemoClassInfo) { func (n *Namespace) mergeClassInfo(ci *dota.CDemoClassInfo) {
if n.classIds == nil { if n.classIds == nil {
n.classIds = make(map[int]string, len(ci.GetClasses())) n.classIds = make(map[int]string, len(ci.GetClasses()))
} }
@ -37,7 +37,9 @@ func (n *Namespace) MergeClassInfo(ci *dota.CDemoClassInfo) {
n.idBits = int(math.Floor(math.Log2(float64(len(n.classIds))))) + 1 n.idBits = int(math.Floor(math.Log2(float64(len(n.classIds))))) + 1
} }
func (n *Namespace) MergeSendTables(st *dota.CDemoSendTables) { // merges the send table data found in the replay protobufs. The send table
// data contains a specification for an entity type system.
func (n *Namespace) mergeSendTables(st *dota.CDemoSendTables) {
// sendtables only has one field, a binary data field. // sendtables only has one field, a binary data field.
data := st.GetData() data := st.GetData()
br := bit.NewBytesReader(data) br := bit.NewBytesReader(data)

@ -1,67 +0,0 @@
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
"github.com/jordanorelli/hyperstone/bit"
"github.com/jordanorelli/hyperstone/dota"
"github.com/jordanorelli/hyperstone/ent"
)
// type CSVCMsg_PacketEntities struct {
// MaxEntries *int32
// UpdatedEntries *int32
// IsDelta *bool
// UpdateBaseline *bool
// Baseline *int32
// DeltaFrom *int32
// EntityData []byte
// PendingFullFrame *bool
// ActiveSpawngroupHandle *uint32
// MaxSpawngroupCreationsequence *uint32
// }
var ctx = ent.NewContext()
func dumpEntities(m proto.Message) {
switch v := m.(type) {
case *dota.CDemoSendTables:
ctx.MergeSendTables(v)
case *dota.CDemoClassInfo:
ctx.MergeClassInfo(v)
case *dota.CSVCMsg_PacketEntities:
data := v.GetEntityData()
var datap []byte
if len(data) > 32 {
datap = data[:32]
} else {
datap = data
}
fmt.Printf("{MaxEntries: %d UpdatedEntries: %v IsDelta: %t UpdateBaseline: %t Baseline: %d DeltaFrom: %d EntityData: %x PendingFullFrame: %t ActiveSpawngroupHandle: %d}\n", v.GetMaxEntries(), v.GetUpdatedEntries(), v.GetIsDelta(), v.GetUpdateBaseline(), v.GetBaseline(), v.GetDeltaFrom(), datap, v.GetPendingFullFrame(), v.GetActiveSpawngroupHandle())
br := bit.NewBytesReader(data)
id := -1
// for i := 0; i < int(v.GetUpdatedEntries()); i++ {
for i := 0; i < 1; i++ {
id++
// there may be a jump indicator, indicating how many id positions
// to skip.
id += int(bit.ReadUBitVar(br))
// next two bits encode one of four entity mutate operations
switch br.ReadBits(2) {
case 0:
ctx.UpdateEntity(id, br)
case 1:
ctx.LeaveEntity(id)
case 2:
ctx.CreateEntity(id, br)
case 3:
ctx.DeleteEntity(id)
}
}
}
}

@ -141,7 +141,9 @@ func main() {
case "class-info": case "class-info":
handle = dumpClasses handle = dumpClasses
case "entities": case "entities":
handle = dumpEntities ent.Debug = log.New(os.Stdout, "", 0)
d := ent.NewDict()
handle = d.Handle
default: default:
bail(1, "no such action: %s", flag.Arg(0)) bail(1, "no such action: %s", flag.Arg(0))
} }

Loading…
Cancel
Save