-
Notifications
You must be signed in to change notification settings - Fork 0
/
adapter.go
131 lines (116 loc) · 3.29 KB
/
adapter.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
package internal
import (
"fmt"
G "github.com/ionous/sashimi/game"
"github.com/ionous/sashimi/meta"
"github.com/ionous/sashimi/util/ident"
"github.com/ionous/sashimi/util/lang"
"strings"
)
// GameEventAdapter implements game.Play.
type GameEventAdapter struct {
*Game
data *RuntimeAction
// when we handle events from callbacks, we set this to the target's class to help resolve names specified by user code.
hint ident.Id
}
// NewGameAdapter gives the passed game the IPlay interface
// Public for testing.
func NewGameAdapter(game *Game) *GameEventAdapter {
return &GameEventAdapter{Game: game}
}
// NewGameObject gives the passed game object the IObject interface.
// Public for testing.
func (ga *GameEventAdapter) NewGameObjectFromId(id ident.Id) (ret G.IObject) {
var inst meta.Instance
if i, ok := ga.Model.GetInstance(id); ok {
inst = i
}
return ga.NewGameObject(inst)
}
func (ga *GameEventAdapter) NewGameObject(inst meta.Instance) (ret G.IObject) {
if inst != nil {
ret = &GameObject{ga, inst}
} else {
ret = NullObjectSource(PropertyPath{}, 2)
}
return ret
}
//
func (ga *GameEventAdapter) The(name string) G.IObject {
return ga.GetObject(name)
}
//
func (ga *GameEventAdapter) Our(name string) G.IObject {
return ga.GetObject(name)
}
//
func (ga *GameEventAdapter) A(name string) G.IObject {
return ga.GetObject(name)
}
// g.Go( Move("the player").To("the pit of disrepair") )
func (ga *GameEventAdapter) Go(phrase G.RuntimePhrase, phrases ...G.RuntimePhrase) (ret G.IPromise) {
if len(phrases) == 0 {
future := &QueuedPhrase{data: ga.data, run: phrase}
ga.Queue.QueueFuture(future)
ret = NewPendingChain(ga, future)
} else {
phrases := append([]G.RuntimePhrase{phrase}, phrases...)
future := &QueuedPhrases{data: ga.data, run: phrases}
ga.Queue.QueueFuture(future)
ret = NewPendingChain(ga, future)
}
return
}
func (ga *GameEventAdapter) Query(class string, exact bool) (ret G.IQuery) {
q := &ClassQuery{ga: ga, cls: StripStringId(class), exact: exact}
q.idx, q.next = q.Advance()
return q
}
//
func (ga *GameEventAdapter) Say(texts ...string) {
if len(texts) > 0 {
text := strings.Join(texts, " ")
lines := strings.Split(text, lang.NewLine)
ga.Output.ScriptSays(lines)
}
}
//
func (ga *GameEventAdapter) Log(texts ...interface{}) {
if len(texts) > 0 {
text := fmt.Sprintln(texts...)
ga.Output.Log(text)
}
}
//
func (ga *GameEventAdapter) StopHere() {
ga.data.cancelled = true
}
var DebugGet = false
// could make a map that implements IObject?
// could use special keys for $name, $fullname, $game, etc.
// FUTURE: use dependency injection instead
func (ga *GameEventAdapter) GetObject(name string) (ret G.IObject) {
id := StripStringId(name)
// empty names are possible from empty strings like Get("")
if !id.Empty() {
if gobj, ok := ga.Model.GetInstance(id); ok {
ret = ga.NewGameObject(gobj)
} else if ga.data != nil {
// testing against ga.data b/c sometimes the adapter isnt invoked via an event.
// to fix use different interfaces perhaps?
if obj, ok := ga.data.findByName(ga.Model, name, ga.hint); ok {
ret = ga.NewGameObject(obj)
} else {
msg := fmt.Sprintf("couldnt find object named '%s(%s)'", name, id)
ga.Log(msg)
//panic(msg)
}
}
}
if ret == nil {
ret = NullObjectSource(RawPath(name), 3)
}
DebugGet = false
return
}