Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: client-side interpolation #5

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
use uint8 for interp ids and add custom binary marshalers
  • Loading branch information
damienfamed75 committed Jan 26, 2025
commit cf10ad32d2c939f978d50823299513d037b6fed3
2 changes: 1 addition & 1 deletion esync/clisync/esync_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func applyEntityDiff(world donburi.World, networkId esync.NetworkId, components
// interpolated component
if !entry.HasComponent(timeCacheComponent) {
donburi.Add(entry, timeCacheComponent, &timeCacheData{
history: make(map[uint][]componentTimeData),
history: make(map[uint8][]componentTimeData),
})
}

Expand Down
2 changes: 1 addition & 1 deletion esync/clisync/interpolation.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type componentTimeData struct {
// component key and contains a list of historic values for that type.
type timeCacheData struct {
// map[component key]historic values
history map[uint][]componentTimeData
history map[uint8][]componentTimeData
}

var (
Expand Down
47 changes: 38 additions & 9 deletions esync/esync_shared.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package esync

import (
"bytes"
"encoding/binary"
"reflect"
"unsafe"

Expand All @@ -12,21 +14,48 @@ import (
var InterpComponent = donburi.NewComponentType[InterpData]()

type InterpData struct {
Components []uint
Components []uint8
}

func (id *InterpData) MarshalBinary() ([]byte, error) {
var buf bytes.Buffer
buf.Grow(len(id.Components))

for i := range id.Components {
binary.Write(&buf, binary.LittleEndian, id.Components[i])
}

return buf.Bytes(), nil
}

func (id *InterpData) UnmarshalBinary(data []byte) error {
buf := bytes.NewReader(data)

id.Components = make([]uint8, buf.Len())
for i := 0; i < len(id.Components); i++ {
binary.Read(buf, binary.LittleEndian, &id.Components[i])
}

return nil
}

func NewInterpData(components ...donburi.IComponentType) *InterpData {
ids := []uint{}
ids := []uint8{}
for i := range components {
ids = append(ids, interpolated.LookupId(components[i].Typ()))
key := interpolated.LookupId(components[i].Typ())
if key == 0 {
continue
}

ids = append(ids, key)
}

return &InterpData{
Components: ids,
}
}

func (i *InterpData) ComponentKeys() []uint {
func (i *InterpData) ComponentKeys() []uint8 {
return i.Components
}

Expand Down Expand Up @@ -75,30 +104,30 @@ var (
// T: lerp(from.Y, to.Y, delta),
// }
// })
func RegisterInterpolated[T any](id uint, comp *donburi.ComponentType[T], lerp LerpFn[T]) error {
func RegisterInterpolated[T any](id uint8, comp *donburi.ComponentType[T], lerp LerpFn[T]) error {
return interpolated.RegisterInterpolatedComponent(id, comp, lerp)
}

// LookInterpId returns the interpolation ID for the given type, if not present
// then 0 is returned.
func LookupInterpId(typ reflect.Type) uint {
func LookupInterpId(typ reflect.Type) uint8 {
return interpolated.LookupId(typ)
}

// LookupInterpType returns the component type for the given interpolation ID,
// if not present then an empty reflect.Type is returned.
func LookupInterpType(id uint) reflect.Type {
func LookupInterpType(id uint8) reflect.Type {
return interpolated.LookupType(id)
}

// LookupInterpSetter returns the setter function for the given interpolation ID.
// This should always be type [esync.LerpFn]
func LookupInterpSetter(id uint) any {
func LookupInterpSetter(id uint8) any {
return interpolated.LookupSetter(id)
}

// RegisteredInterpId returns true if the given interpolation ID is registered.
func RegisteredInterpId(id uint) bool {
func RegisteredInterpId(id uint8) bool {
return interpolated.RegisteredId(id)
}

Expand Down
18 changes: 9 additions & 9 deletions typemapper/componentmapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ type interpolatedComponentData struct {
type ComponentMapper struct {
lock sync.Mutex

typeToId map[reflect.Type]uint
idToComponent map[uint]interpolatedComponentData
typeToId map[reflect.Type]uint8
idToComponent map[uint8]interpolatedComponentData
}

func NewComponentMapper() *ComponentMapper {
return &ComponentMapper{
typeToId: make(map[reflect.Type]uint),
idToComponent: make(map[uint]interpolatedComponentData),
typeToId: make(map[reflect.Type]uint8),
idToComponent: make(map[uint8]interpolatedComponentData),
}
}

// RegisterInterpolatedComponent registers the given component and setter with
// the provided ID, note that these IDs don't interfere with the normal esync.Register
func (c *ComponentMapper) RegisterInterpolatedComponent(id uint, comp donburi.IComponentType, lerp any) error {
func (c *ComponentMapper) RegisterInterpolatedComponent(id uint8, comp donburi.IComponentType, lerp any) error {
if lerp == nil {
return fmt.Errorf("must provide lerp function: %w", ErrNilLerpFunction)
}
Expand All @@ -60,7 +60,7 @@ func (c *ComponentMapper) RegisterInterpolatedComponent(id uint, comp donburi.IC
return nil
}

func (c *ComponentMapper) LookupSetter(id uint) any {
func (c *ComponentMapper) LookupSetter(id uint8) any {
c.lock.Lock()
defer c.lock.Unlock()

Expand All @@ -75,22 +75,22 @@ func (c *ComponentMapper) RegisteredType(typ reflect.Type) bool {
return ok
}

func (c *ComponentMapper) RegisteredId(id uint) bool {
func (c *ComponentMapper) RegisteredId(id uint8) bool {
c.lock.Lock()
defer c.lock.Unlock()

_, ok := c.idToComponent[id]
return ok
}

func (c *ComponentMapper) LookupType(id uint) reflect.Type {
func (c *ComponentMapper) LookupType(id uint8) reflect.Type {
c.lock.Lock()
defer c.lock.Unlock()

return c.idToComponent[id].typ.Typ()
}

func (c *ComponentMapper) LookupId(typ reflect.Type) uint {
func (c *ComponentMapper) LookupId(typ reflect.Type) uint8 {
c.lock.Lock()
defer c.lock.Unlock()

Expand Down