-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
command.go
137 lines (116 loc) · 2.74 KB
/
command.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package ecs
// Represents a list of commands that need to be executed on the world
type Command struct {
world *World
list map[Id]*writeCmd // TODO - Note to self: if you ever add deletion inside of commands, then the packing commands into a map based on entity Id assumption wont hold, because you'll need some amount of specific ordering
dynamicBundle dynamicBundle
}
// Create a new command to be executed
func NewCommand(world *World) *Command {
return &Command{
world: world,
list: make(map[Id]*writeCmd),
}
}
// Execute the command
func (c *Command) Execute() {
// TODO - Batch similar commands, if you ever switch to something more complex than just writing
// Execute all the commands
for i := range c.list {
c.list[i].execute(c.world)
}
// Clearing Optimization: https://go.dev/doc/go1.11#performance-compiler
for k := range c.list {
delete(c.list, k)
}
}
// TODO - maybe rename as just Write?
// Adds a write command
func WriteCmd[A any](c *Command, id Id, comp A) {
cmd, ok := c.list[id]
if !ok {
cmd = newWriteCmd(id)
c.list[id] = cmd
}
cmd.comps = append(cmd.comps, C(comp))
}
// type cmd interface {
// execute(*World)
// }
type writeCmd struct {
id Id
comps []Component
}
func newWriteCmd(id Id) *writeCmd {
return &writeCmd{
id: id,
comps: make([]Component, 0, 2), // TODO - guaranteed to at least have 1, but a bit arbitrary
}
}
func (c *writeCmd) execute(world *World) {
world.Write(c.id, c.comps...)
}
func (w *World) Spawn() Ent {
return Ent{
id: w.NewId(),
}
}
type Ent struct {
id Id
comps []Component
}
// func NewWriter[T any]() *Writer[T] {
// var t T
// return &Writer[T]{
// comp: C(t), // TODO: combine when you remove Box[T]
// }
// }
// type Writer[T any] struct {
// comp Box[T]
// }
// func (w *Writer[T]) Write(ent *Ent, t T) *Ent {
// w.Comp = t
// ent.comps = append(ent, w.Comp)
// }
func (c *Command) Spawn(bundles ...unbundler) Id {
c.dynamicBundle.comps = c.dynamicBundle.comps[:0]
for _, b := range bundles {
b.unbundleInto(&c.dynamicBundle)
}
id := c.world.NewId()
c.world.Write(id, c.dynamicBundle.comps...)
return id
}
type dynamicBundle struct {
comps []Component
}
func (b *dynamicBundle) unbundleInto(d *dynamicBundle) {
d.comps = append(d.comps, b.comps...)
}
type unbundler interface {
unbundleInto(*dynamicBundle)
}
type Bundle2[A, B any] struct {
wa Box[A]
wb Box[B]
}
func NewBundle2[A, B any]() *Bundle2[A, B] {
var a A
var b B
return &Bundle2[A, B]{
wa: C(a),
wb: C(b),
}
}
func (bun *Bundle2[A, B]) With(a A, b B) *Bundle2[A, B] {
ret := &Bundle2[A, B]{
wa: bun.wa,
wb: bun.wb,
}
ret.wa.Comp = a
ret.wb.Comp = b
return ret
}
func (b *Bundle2[A, B]) unbundleInto(d *dynamicBundle) {
d.comps = append(d.comps, b.wa, b.wb)
}