Sfoglia il codice sorgente

Cleaned up object resolution, cleaned up lots of stuff. Changed flages to be strictly booleans and added properties. Added 'give x to y' and 'put x into y' commands.

Keelan Lightfoot 8 anni fa
parent
commit
41ee2f825a
5 ha cambiato i file con 463 aggiunte e 465 eliminazioni
  1. 12
    15
      client.go
  2. 29
    6
      cmd/funmow/main.go
  3. 36
    8
      db.go
  4. 332
    363
      execution_context.go
  5. 54
    73
      object.go

+ 12
- 15
client.go Vedi File

@@ -129,25 +129,22 @@ func (c *Client) handleLoginPhase(message string) {
129 129
 		}
130 130
 	case "create":
131 131
 		if len(fields) == 3 {
132
-			player, found := c.db.GetPlayer(fields[1])
133
-			if !found || (found && player.Password != fields[2]) {
134
-				c.write("Bad username or password.\n")
132
+			_, found := c.db.GetPlayer(fields[1])
133
+			if found {
134
+				c.write("That name is already taken.\n")
135 135
 				break
136 136
 			}
137 137
 			
138
-			c.playerID = player.ID
139
-			c.authenticated = true
140
-
141
-			// when a player authenticates, the ipc channels get turned on
142
-			subReq := EventSubscribeRequest{
143
-				connectionID: c.connectionID,
144
-				playerID:     c.playerID,
145
-				inbound:      c.inbound,
146
-				outbound:     make(chan chan PlayerEvent),
138
+			playerID, _ := c.db.CreatePlayer(strings.TrimSpace(fields[1]), strings.TrimSpace(fields[2]), nil)
139
+			
140
+			_, found = c.db.Fetch(playerID)
141
+			if !found {
142
+				c.write("I can't even.\n")
143
+				break
147 144
 			}
148
-
149
-			c.outbound = c.eventDistributor.Subscribe(subReq)
150
-			c.sendCommand("look")
145
+			
146
+			c.write("You have been created. Now you can connect!\n")
147
+			
151 148
 		} else {
152 149
 			c.write("What?\n")
153 150
 		}

+ 29
- 6
cmd/funmow/main.go Vedi File

@@ -4,16 +4,36 @@ import (
4 4
 	"github.com/naleek/funmow"
5 5
 	"log"
6 6
 	"net"
7
+	"flag"
7 8
 )
8 9
 
9 10
 const (
10 11
 	FunMOWVersion   = "0.2"
11 12
 	FunMOWDefaultDB = "funmow.db"
12
-	FunMOWListen    = ":4201"
13
+	FunMOWDefaultListen    = ":4201"
13 14
 )
14 15
 
15 16
 func main() {
16 17
 
18
+	var seed bool
19
+	var listen string
20
+	var dbPath string
21
+
22
+	flag.BoolVar(&seed, "seed", false, "Seed the world DB")
23
+	flag.StringVar(&listen, "listen", FunMOWDefaultListen, "Listen Address:Port of game server.")
24
+	flag.StringVar(&dbPath, "db", FunMOWDefaultDB, "Path to FunMOW database.")
25
+
26
+	help := flag.Bool("h", false, "Show usage")
27
+
28
+	flag.Parse()
29
+
30
+	if *help {
31
+		flag.PrintDefaults()
32
+		return
33
+	}
34
+
35
+
36
+
17 37
 	log.Print("Starting FunMOW Version ", FunMOWVersion)
18 38
 
19 39
 	log.Print("Using database ", FunMOWDefaultDB)
@@ -22,10 +42,13 @@ func main() {
22 42
 
23 43
 	defer db.Close()
24 44
 
25
-	seedDB(db)
45
+	if seed {
46
+		log.Print("Seeding database...")
47
+		seedDB(db)
48
+	}
26 49
 
27
-	log.Print("Listening for connections on ", FunMOWListen)
28
-	ln, err := net.Listen("tcp", FunMOWListen)
50
+	log.Print("Listening for connections on ", listen)
51
+	ln, err := net.Listen("tcp", listen)
29 52
 	if err != nil {
30 53
 		log.Fatal(err)
31 54
 	}
@@ -50,8 +73,8 @@ func seedDB(db *funmow.DB) {
50 73
 
51 74
 	f := funmow.NewObjectFactory(db)
52 75
 
53
-	keelan, _ := db.CreatePlayer("keelan", map[string]string{"wizard":"true"})
54
-	dan, _ := db.CreatePlayer("dan", nil)
76
+	keelan, _ := db.CreatePlayer("keelan", "123", map[string]bool{"wizard":true})
77
+	dan, _ := db.CreatePlayer("dan", "123", nil)
55 78
 
56 79
 	outside := f.NewObject()
57 80
 	outside.Type = "room"

+ 36
- 8
db.go Vedi File

@@ -7,6 +7,8 @@ import (
7 7
 	"fmt"
8 8
 	"github.com/boltdb/bolt"
9 9
 	"strconv"
10
+	"errors"
11
+	"regexp"
10 12
 )
11 13
 
12 14
 const (
@@ -15,15 +17,20 @@ const (
15 17
 
16 18
 type DBRef int
17 19
 
18
-func NewDBRefFromHashRef(v string) (DBRef, error) {
20
+func NewDBRefFromHashRef(v string) (DBRef, bool) {
19 21
 	var destInt int
22
+	
23
+	if matched, _ := regexp.MatchString(`^\pZ*#[0-9]+\pZ*?`, v); !matched {
24
+		return 0, false
25
+	}
26
+
20 27
 	n, err := fmt.Sscanf(v, "#%d", &destInt)
21 28
 
22 29
 	if err != nil || n == 0 {
23
-		return 0, err
30
+		return 0, false
24 31
 	}
25 32
 
26
-	return DBRef(destInt), nil
33
+	return DBRef(destInt), true
27 34
 }
28 35
 
29 36
 func NewDBRefFromString(v string) (DBRef, error) {
@@ -249,9 +256,6 @@ func (s *DB) SetPlayer(name string, player PlayerMeta) error {
249 256
 
250 257
 }
251 258
 
252
-
253
-
254
-
255 259
 func (s *DB) GetPlayer(name string) (PlayerMeta, bool) {
256 260
 	var player PlayerMeta
257 261
 	found := false
@@ -270,7 +274,31 @@ func (s *DB) GetPlayer(name string) (PlayerMeta, bool) {
270 274
 	return player, found
271 275
 }
272 276
 
273
-func (s *DB) CreatePlayer(name string, flags map[string]string) (DBRef, error) {
277
+func (s *DB) DeletePlayer(name string) error {
278
+	return s.db.Update(func(tx *bolt.Tx) error {
279
+		playerBucket := tx.Bucket([]byte("player"))
280
+		err := playerBucket.Delete([]byte(name))
281
+		return err
282
+	})
283
+}
284
+
285
+func (s *DB) RenamePlayer(oldName string, newName string) error {
286
+	// doing it this way accomplishes the change as a single transasction
287
+	// and saves a bunch of marshalling and unmarshalling
288
+	return s.db.Update(func(tx *bolt.Tx) error {
289
+		playerBucket := tx.Bucket([]byte("player"))
290
+		buf := playerBucket.Get([]byte(oldName))
291
+		if buf == nil {
292
+			return errors.New("Can't find player")
293
+		}
294
+		err := playerBucket.Delete([]byte(oldName))
295
+		if err != nil { return err }
296
+		return playerBucket.Put([]byte(newName), buf)
297
+	})
298
+}
299
+
300
+
301
+func (s *DB) CreatePlayer(name string, password string, flags map[string]bool) (DBRef, error) {
274 302
 
275 303
 	var playerID DBRef
276 304
 
@@ -283,7 +311,7 @@ func (s *DB) CreatePlayer(name string, flags map[string]string) (DBRef, error) {
283 311
 		}
284 312
 		playerID = DBRef(seq)
285 313
 		s.txStoreObject(objectBucket, Object{ID: playerID, Name: name, Type: "player", Flags: flags}, playerID)
286
-		playerMeta := PlayerMeta{ID: playerID, Password: "password"}
314
+		playerMeta := PlayerMeta{ID: playerID, Password: password}
287 315
 		buf, err := json.Marshal(playerMeta)
288 316
 		if err != nil {
289 317
 			return err

+ 332
- 363
execution_context.go
File diff suppressed because it is too large
Vedi File


+ 54
- 73
object.go Vedi File

@@ -18,14 +18,18 @@ type PlayerMeta struct {
18 18
 }
19 19
 
20 20
 type Object struct {
21
-	ID          DBRef  `json:"id"`
22
-	Next        DBRef  `json:"next"`
23
-	Type        string `json:"type"`
24
-	Name        string `json:"name"`
25
-	Description string `json:"description"`
26
-	Flags		map[string]string `json:"flags"`
27
-	Owner DBRef `json:"owner"`
21
+
22
+	ID          DBRef             `json:"id"`
23
+	Type        string            `json:"type"`
24
+	Owner       DBRef             `json:"owner"`
25
+	Next        DBRef             `json:"next"`
26
+	Name        string            `json:"name"`
27
+	Description string            `json:"description"`
28
+	Flags		map[string]bool   `json:"flags"`
29
+	Properties  map[string]string `json:"properties"`
30
+	
28 31
 	db    *DB
32
+	
29 33
 }
30 34
 
31 35
 type ObjectFactory struct {
@@ -103,37 +107,6 @@ func (o *Object) Contains(c *Object) error {
103 107
 	return o.db.Link(o.ID, c.ID, c.Type)
104 108
 }
105 109
 
106
-func (o *Object) MatchLinkNames(matchName string, player DBRef) ObjectList {
107
-	if matchName == "here" {
108
-		return ObjectList{*o}
109
-	}
110
-	if matchName == "me" {
111
-		p, found := o.db.Fetch(player)
112
-		if !found {
113
-			return ObjectList{}
114
-		} else {
115
-			return ObjectList{p}
116
-		}
117
-	}
118
-	r := make(ObjectList, 0)
119
-
120
-	children := o.db.GetChildren(o.ID) // map[DBRef]string
121
-
122
-	for childID, _ := range children {
123
-		o, found := o.db.Fetch(childID)
124
-		if found {
125
-			idName := fmt.Sprintf("#%d", o.ID)
126
-			lowerObjectName := strings.ToLower(o.Name)
127
-			lowerMatchName := strings.ToLower(matchName)
128
-			if strings.HasPrefix(lowerObjectName, lowerMatchName) || matchName == idName {
129
-				r = append(r, o)
130
-			}
131
-		}
132
-	}
133
-
134
-	return r
135
-}
136
-
137 110
 func (o *Object) MatchExitNames(name string) ObjectList { // so much copypasta
138 111
 	r := make(ObjectList, 0)
139 112
 
@@ -160,7 +133,6 @@ func (o *Object) MatchExitNames(name string) ObjectList { // so much copypasta
160 133
 					break // no need to look at other aliases
161 134
 				}
162 135
 			}
163
-
164 136
 		}
165 137
 	}
166 138
 
@@ -168,65 +140,74 @@ func (o *Object) MatchExitNames(name string) ObjectList { // so much copypasta
168 140
 }
169 141
 
170 142
 func (o *Object) DetailedName() string {
171
-	return fmt.Sprintf("%s (#%d)", o.Name, o.ID)
143
+	return fmt.Sprintf("%s <#%d>", o.Name, o.ID)
172 144
 }
173 145
 
174
-func (o *Object) GetLinkNames(matchType string, exclude DBRefList) []string {
146
+func (o *Object) GetContents(exclude DBRef) []string {
175 147
 	r := make([]string, 0)
176
-
177
-	children := o.db.GetChildren(o.ID) // map[DBRef]string
178
-
179
-childLoop:
148
+	children := o.db.GetChildren(o.ID)
180 149
 	for childID, linkType := range children {
181
-		if matchType != "*" && matchType != linkType {
182
-			continue
183
-		}
184
-		for _, excludeID := range exclude {
185
-			if excludeID == childID {
186
-				continue childLoop
187
-			}
188
-		}
150
+		if childID == exclude { continue }
151
+		if !(linkType == "player" || linkType == "thing") { continue }
189 152
 		o, found := o.db.Fetch(childID)
190
-		if found {
191
-			if linkType == "player" {
192
-				if o.GetFlag("online","false") == "true" {
193
-					r = append(r, o.DetailedName())
194
-				}
195
-			} else if linkType == "exit" {
196
-				r = append(r, o.Name)
197
-			} else {
198
-				r = append(r, o.DetailedName())
199
-			}
200
-		}
153
+		if !found { continue }
154
+		if linkType == "player" && !o.GetFlag("online") { continue }
155
+		r = append(r, o.DetailedName())
201 156
 	}
157
+	sort.Strings(r)
158
+	return r
159
+}
202 160
 
161
+func (o *Object) GetExits() []string {
162
+	r := make([]string, 0)
163
+	children := o.db.GetChildren(o.ID)
164
+	for exitID, linkType := range children {
165
+		if linkType != "exit" { continue }
166
+		exit, found := o.db.Fetch(exitID)
167
+		if !found { continue }
168
+		aliases := strings.Split(exit.Name, ";")
169
+		r = append(r, aliases[0])
170
+	}
171
+	
203 172
 	sort.Strings(r)
204 173
 	return r
205 174
 }
206 175
 
207
-func (o *Object) SetFlag(flag string, value string) {
176
+func (o *Object) SetFlag(flag string, value bool) {
208 177
 	if o.Flags == nil {
209
-		o.Flags = make(map[string]string)
178
+		o.Flags = make(map[string]bool)
210 179
 	}
211 180
 	o.Flags[flag]=value
212 181
 }
213 182
 
214
-func (o *Object) GetFlag(flag string, defaultValue string) (string) {
215
-	
216
-	if o.Flags == nil {
217
-		return defaultValue
218
-	}
183
+func (o *Object) GetFlag(flag string) bool {
219 184
 	
185
+	if o.Flags == nil { return false }
220 186
 	value, ok := o.Flags[flag]
187
+	if !ok { return false }
221 188
 	
222
-	if !ok {
223
-		return defaultValue
189
+	return value
190
+}
191
+
192
+func (o *Object) SetProp(key string, value string) {
193
+	if o.Properties == nil {
194
+		o.Properties = make(map[string]string)
224 195
 	}
196
+	o.Properties[key]=value
197
+}
198
+
199
+func (o *Object) GetProp(key string) string {
200
+	
201
+	if o.Properties == nil { return "" }
202
+	value, ok := o.Properties[key]
203
+	if !ok { return "" }
225 204
 	
226 205
 	return value
227 206
 }
228 207
 
229 208
 
209
+
210
+
230 211
 type ObjectList []Object
231 212
 
232 213
 func (l ObjectList) First() Object {