-
Notifications
You must be signed in to change notification settings - Fork 0
/
queuedActions.go
145 lines (131 loc) · 3.89 KB
/
queuedActions.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
138
139
140
141
142
143
144
145
package internal
import (
"fmt"
E "github.com/ionous/sashimi/event"
G "github.com/ionous/sashimi/game"
"github.com/ionous/sashimi/util/ident"
)
// QueuedAction implements Future for named actions.
// ex. g.The("player").Go("jump")
type QueuedAction struct {
data *RuntimeAction
next *ChainedCallback
}
// QueuedAction implements Future for runtime phrases.
// ex. g.Go(Jump("player")
type QueuedPhrase struct {
data *RuntimeAction
run G.RuntimePhrase
next *ChainedCallback
}
func (c *QueuedPhrase) String() string {
return fmt.Sprint("QueuedPhrase", c.run)
}
// QueuedPhrases implements Future for a set of phrases.
// One aspect not yet? modeled are long running actions.
// Currently, there would be no difference, therefore, between chaining on QueuedPhrases and chaining on the last element of QueuedPhrases
type QueuedPhrases struct {
data *RuntimeAction
run []G.RuntimePhrase
next *ChainedCallback
}
func (c *QueuedPhrases) String() string {
return fmt.Sprint("QueuedPhrases", c.run)
}
// ChainedCallbacks implements Future for nested callbacks; created by PendingChain.
// ex. Then(func(g G.Play){ })
type ChainedCallback struct {
data *RuntimeAction
cb G.Callback
}
func (c *ChainedCallback) String() string {
return fmt.Sprint("ChainedCallback", c.cb)
}
// g.The("player").Go("hack", "the nice code").Then(trailing actions...)
func (a *QueuedAction) Run(g *Game) (err error) {
// we've looped back now; end the event.
act := a.data
// start a new event frame:
o1, o2 := act.GetTarget(), act.GetContext()
path := E.NewPathTo(NewObjectTarget(g, o1))
msg := &E.Message{Id: act.action.GetEvent().GetId(), Data: act}
frame := g.Frame.BeginEvent(o1, o2, path, msg)
// send the event, noting that new things may enter our queue.
if runDefault, e := msg.Send(path); e != nil {
err = e
} else {
// run default actions if requested, noting that new things may enter our queue.
if !runDefault {
frame.EndEvent()
} else {
play := g.newPlay(act, ident.Empty())
if callbacks, ok := act.action.GetCallbacks(); ok {
for i := 0; i < callbacks.NumCallback(); i++ {
cb := callbacks.CallbackNum(i)
if found, ok := g.LookupCallback(cb); ok {
found(play)
} else {
err = fmt.Errorf("internal error, couldnt find callback %s", cb)
break
}
}
}
frame.EndEvent()
// run "after" actions, which are queued dynamically ( though who knows why. )
if after := a.data.after; len(after) > 0 {
// fmt.Println(len(after), "after actions")
play := g.newPlay(a.data, ident.Empty())
for _, after := range after {
after.call(play)
}
}
// finally, run any trailing actions the caller may have specified.
// this is done outside of the event frame, we will see these later...
if a.next != nil {
// fmt.Println("queuing then")
a.next.Run(g)
}
}
}
return
}
func (c *QueuedPhrase) Run(g *Game) (err error) {
if e := RunPhrases(g, c.data, c.run); e != nil {
err = e
} else if c.next != nil {
g.Queue.QueueFuture(c.next)
}
return
}
//
func (c *QueuedPhrases) Run(g *Game) (err error) {
if e := RunPhrases(g, c.data, c.run...); e != nil {
err = e
} else if c.next != nil {
g.Queue.QueueFuture(c.next)
}
return
}
// during execute, whatever event we are in -- we want to stay in, until the end of execute.
// basically we want to subvert the queue -- so all queued futures come into us
func RunPhrases(g *Game, d *RuntimeAction, phrases ...G.RuntimePhrase) (err error) {
// oldQueue := g.Queue
// defer func() {
// g.Queue = oldQueue
// }()
// myQueue := NewActionQueue()
// // FIX: maybe we should get the queue from the event adapter...?
// g.Queue = myQueue
play := &GameEventAdapter{Game: g, data: d}
for _, run := range phrases {
run.Execute(play)
}
// return myQueue.ProcessActions(g)
return
}
//
func (c *ChainedCallback) Run(g *Game) (err error) {
play := &GameEventAdapter{Game: g, data: c.data}
c.cb(play)
return
}