164 lines
3.7 KiB
Go
164 lines
3.7 KiB
Go
package gameplay
|
|
|
|
import (
|
|
"aego/core/mathx"
|
|
"aego/core/rewind"
|
|
"aego/scene"
|
|
)
|
|
|
|
var _ rewind.Keyframer = (*Service)(nil)
|
|
|
|
// noKey: the service keeps no state between steps; component state rides in the scene key.
|
|
type noKey struct{}
|
|
|
|
func (noKey) Size() int { return 0 }
|
|
|
|
func (s *Service) Capture(rewind.Key) rewind.Key {
|
|
return noKey{}
|
|
}
|
|
|
|
func (s *Service) Restore(rewind.Key) {}
|
|
|
|
type hashFns struct {
|
|
motion func(scene.NodeHandle, *Motion2D)
|
|
health func(scene.NodeHandle, *Health)
|
|
hit func(scene.NodeHandle, *Hitbox2D)
|
|
kill func(scene.NodeHandle, *KillZone2D)
|
|
cp func(scene.NodeHandle, *Checkpoint2D)
|
|
pick func(scene.NodeHandle, *Pickup2D)
|
|
resp func(scene.NodeHandle, *Respawn)
|
|
life func(scene.NodeHandle, *Lifetime)
|
|
fsm func(scene.NodeHandle, *StateMachine)
|
|
}
|
|
|
|
func newHashFns(s *Service) hashFns {
|
|
return hashFns{
|
|
motion: s.hashMotion,
|
|
health: s.hashHealth,
|
|
hit: s.hashHit,
|
|
kill: func(n scene.NodeHandle, c *KillZone2D) { s.hashZone(n, &c.st) },
|
|
cp: func(n scene.NodeHandle, c *Checkpoint2D) { s.hashZone(n, &c.st) },
|
|
pick: func(n scene.NodeHandle, c *Pickup2D) { s.hashZone(n, &c.st) },
|
|
resp: s.hashRespawn,
|
|
life: s.hashLife,
|
|
fsm: s.hashFSM,
|
|
}
|
|
}
|
|
|
|
// Hash adds the unexported component state, which the scene hash cannot see.
|
|
func (s *Service) Hash(h *rewind.Hasher) {
|
|
h.String(ServiceID)
|
|
s.hh = h
|
|
f := &s.hashFns
|
|
scene.Query1[Motion2D](s.scene).Each(f.motion)
|
|
scene.Query1[Health](s.scene).Each(f.health)
|
|
scene.Query1[Hitbox2D](s.scene).Each(f.hit)
|
|
scene.Query1[KillZone2D](s.scene).Each(f.kill)
|
|
scene.Query1[Checkpoint2D](s.scene).Each(f.cp)
|
|
scene.Query1[Pickup2D](s.scene).Each(f.pick)
|
|
scene.Query1[Respawn](s.scene).Each(f.resp)
|
|
scene.Query1[Lifetime](s.scene).Each(f.life)
|
|
scene.Query1[StateMachine](s.scene).Each(f.fsm)
|
|
s.hh = nil
|
|
}
|
|
|
|
func hashVec(h *rewind.Hasher, v mathx.Vec2) {
|
|
h.F32(v.X)
|
|
h.F32(v.Y)
|
|
}
|
|
|
|
func hashNode(h *rewind.Hasher, n scene.NodeHandle) {
|
|
h.U32(n.Index)
|
|
h.U32(n.Gen)
|
|
}
|
|
|
|
func (s *Service) hashMotion(n scene.NodeHandle, c *Motion2D) {
|
|
h, st := s.hh, &c.st
|
|
hashNode(h, n)
|
|
hashVec(h, st.move)
|
|
hashVec(h, st.dashVel)
|
|
hashVec(h, st.addVel)
|
|
hashVec(h, st.teleportTo)
|
|
hashVec(h, st.floorN)
|
|
hashVec(h, st.platVel)
|
|
hashVec(h, st.wallN)
|
|
h.F32(st.dashLeft)
|
|
h.F32(st.coyote)
|
|
h.F32(st.buffer)
|
|
h.F32(st.landSpeed)
|
|
hashNode(h, st.ground)
|
|
h.U32(uint32(st.events))
|
|
h.Bool(st.jumpReq)
|
|
h.Bool(st.jumpRel)
|
|
h.Bool(st.jumping)
|
|
h.Bool(st.stop)
|
|
h.Bool(st.teleport)
|
|
h.Bool(st.grounded)
|
|
}
|
|
|
|
func (s *Service) hashHealth(n scene.NodeHandle, c *Health) {
|
|
h, st := s.hh, &c.st
|
|
hashNode(h, n)
|
|
h.U32(uint32(st.dmg))
|
|
h.U32(uint32(st.healed))
|
|
hashNode(h, st.dmgSrc)
|
|
hashNode(h, st.diedSrc)
|
|
h.F32(st.invuln)
|
|
h.Bool(st.ready)
|
|
h.Bool(st.died)
|
|
h.Bool(st.revived)
|
|
h.Bool(st.arm)
|
|
}
|
|
|
|
func (s *Service) hashHit(n scene.NodeHandle, c *Hitbox2D) {
|
|
h, st := s.hh, &c.st
|
|
hashNode(h, n)
|
|
h.Bool(st.pulse)
|
|
h.Int(len(st.recs))
|
|
for i := range st.recs {
|
|
r := &st.recs[i]
|
|
hashNode(h, r.node)
|
|
h.F32(r.timer)
|
|
h.Bool(r.inside)
|
|
h.Bool(r.seen)
|
|
h.Bool(r.hit)
|
|
}
|
|
}
|
|
|
|
func (s *Service) hashZone(n scene.NodeHandle, z *zoneState) {
|
|
h := s.hh
|
|
hashNode(h, n)
|
|
h.Bool(z.used)
|
|
h.Int(len(z.inside))
|
|
for _, x := range z.inside {
|
|
hashNode(h, x)
|
|
}
|
|
}
|
|
|
|
func (s *Service) hashRespawn(n scene.NodeHandle, c *Respawn) {
|
|
h, st := s.hh, &c.st
|
|
hashNode(h, n)
|
|
hashVec(h, st.point)
|
|
h.U32(uint32(st.priority))
|
|
h.F32(st.pending)
|
|
h.Bool(st.hasPoint)
|
|
h.Bool(st.hasPri)
|
|
h.Bool(st.waiting)
|
|
}
|
|
|
|
func (s *Service) hashLife(n scene.NodeHandle, c *Lifetime) {
|
|
h := s.hh
|
|
hashNode(h, n)
|
|
h.Bool(c.st.started)
|
|
h.Bool(c.st.done)
|
|
}
|
|
|
|
func (s *Service) hashFSM(n scene.NodeHandle, c *StateMachine) {
|
|
h := s.hh
|
|
hashNode(h, n)
|
|
h.U32(uint32(c.Index))
|
|
h.F32(c.Time)
|
|
h.U32(uint32(c.st.queued))
|
|
h.Bool(c.st.started)
|
|
}
|