/
npc.go
114 lines (102 loc) · 3.33 KB
/
npc.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
/*
npc.go contains Npc types and func,
along with an NpcManager type which
provides npc-related funcs for ThingManager
Npc implements the Thing interface.
NpcManager is a ThingManager
*/
package main
import (
"fmt"
"github.com/Shopify/go-lua"
)
/// Animation:
/// Animate will be called every time a player enters a previously-empty room
/// The proper way to Animate, is for the dna function to continuously run while
/// The NPC is "activated," e.g. a player is in the room, it's chasing someone, etc.
/// Make the dna function sleep for a set tick time via javascript setInterval().
/// When it has nothing to do, and no players are present, the function should return
/// without further intervals, and set selfNpc.sleeping to true
/// Gomud will call Animate() again when a player enters the room.
///
/// @note room entry animation may be changed to local area entry in the future.
///
type Npc struct {
id identifier
name string
Brief string
Sleeping bool
Dna string
Location identifier
LocationType ItemLocationType ///< @todo ? remove this ? it isn't strictly necessary, as we can type assert to find the type
Items map[identifier]bool // true = npc, false = item
}
func (n *Npc) Id() identifier {
return n.id
}
func (n *Npc) SetId(id identifier) {
n.id = id
}
func (n *Npc) Name() string {
return n.name
}
func (n *Npc) selfWrappedDna() string {
return "(function(self) {" + n.Dna + "})(" + n.id.String() + ")"
}
func (n *Npc) Animate(world *World) {
if n.Dna == "" {
fmt.Println("Could not animate lifeless " + n.Name())
return
}
n.Sleeping = false
go func() {
fmt.Printf("Animating %s\n", n.id.String())
err := lua.DoString(initLua(world, n.id), n.Dna)
if err != nil {
fmt.Printf("npc.Animate error with %s: %v\n", n.id.String(), err)
}
}()
}
type NpcManager ThingManager
/// @todo remove this, after changing things which call it to store Accessors rather than IDs
/// @todo change this to return an error object with an err string, rather than printing the err and returning bool
func (m NpcManager) GetById(id identifier) (*Npc, bool) {
accessor := ThingManager(m).GetThingAccessor(id)
if accessor.ThingGetter == nil {
fmt.Println("NpcManager.GetById error: ThingGetter nil " + id.String())
return &Npc{}, false
}
thing, ok := <-accessor.ThingGetter
if !ok {
fmt.Println("NpcManager.GetById error: item ThingGetter closed " + id.String())
return &Npc{}, false
}
item, ok := thing.(*Npc)
if !ok {
fmt.Println("NpcManager.GetById error: item accessor returned non-item " + id.String())
return &Npc{}, false
}
return item, ok
}
/// @todo change this to return an error object with an err string, rather than printing the err and returning bool
func (m NpcManager) ChangeById(id identifier, modify func(p *Npc)) bool {
accessor := ThingManager(m).GetThingAccessor(id)
if accessor.ThingGetter == nil {
fmt.Println("NpcManager.ChangeById error: ThingGetter nil " + id.String())
return false
}
setMsg, ok := <-accessor.ThingSetter
if !ok {
fmt.Println("NpcManager.ChangeById error: item ThingGetter closed " + id.String())
return false
}
setMsg.chainTime <- NotChaining
item, ok := setMsg.it.(*Npc)
if !ok {
fmt.Println("NpcManager.ChangeById error: item accessor returned non-item " + id.String())
return false
}
modify(item)
setMsg.set <- item
return true
}