123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881 |
- package funmow
-
- import (
- "fmt"
- "regexp"
- "strings"
- "time"
- )
-
- type ExecutionContext struct {
- actor Object
- inbound chan PlayerEvent
- outbound chan PlayerEvent
- eventDistributor *EventDistributor
- db *DB
- factory *ObjectFactory
- forceContext bool
- }
-
- func NewForceContext(e *EventDistributor, w *DB, outbound chan PlayerEvent) *ExecutionContext {
-
- c := new(ExecutionContext)
-
- c.outbound = outbound
- c.eventDistributor = e
- c.db = w
- c.factory = NewObjectFactory(w)
- c.forceContext = true
- return c
- }
-
- func NewExecutionContext(actorID DBRef, e *EventDistributor, w *DB, outbound chan PlayerEvent) *ExecutionContext {
-
- c := new(ExecutionContext)
-
- actor, found := w.Fetch(actorID)
- if !found {
- return nil
- }
-
- c.actor = actor
- c.outbound = outbound
- c.eventDistributor = e
- c.db = w
- c.factory = NewObjectFactory(w)
-
- return c
- }
-
- func (c *ExecutionContext) StartInboundChannel() chan PlayerEvent {
- c.inbound = make(chan PlayerEvent)
- inboundBuffer := make(chan PlayerEvent)
- c.outbound = c.outbound
-
- go func() {
- //inbound event buffer to protect the event distributor from long running tasks
- // the alternative is to run each inbound event in a separate goroutine
- // but that has potential problems (ie, two emits arrive in order. the first one
- // requires an extra DB lookup to sort out context. now the second one ends up
- // sending its output event before the first, and the client sees things backwards
- // this isn't just an edge case, it happens quite frequently.
- // The alternative is to buffer inbound events, which is the safest, as it doesn't
- // impact the eventdistributor.
-
- queue := make([]*PlayerEvent, 0)
- running := true
- for running {
- if len(queue) == 0 {
- select {
- case newEvent, ok := <-c.inbound:
- if !ok {
- running = false
- break
- }
- queue = append(queue, &newEvent)
- }
- } else {
- event := queue[0]
- select {
- case newEvent, ok := <-c.inbound:
- if !ok {
- running = false
- break
- }
- queue = append(queue, &newEvent)
- case inboundBuffer <- *event:
- queue = queue[1:]
- }
- }
- }
- // closure of c.inbound is the signal from the event distributor that we need to die.
- // we then close inboundBuffer to tell the event goroutine to die
- fmt.Println("close(inboundBuffer)")
- close(inboundBuffer)
- }()
-
- go func() {
- for {
- event, ok := <-inboundBuffer
- if !ok {
- break
- }
- c.HandleEvent(event)
- }
- // and finally we tell the event distributor to delete us.
- fmt.Println("Sending EventTypeTeardownComplete")
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: c.actor.ID, messageType: EventTypeTeardownComplete}
-
- }()
-
- return c.inbound
- }
-
- func (c *ExecutionContext) HandleEvent(m PlayerEvent) {
- inside, _ := c.db.GetParent(c.actor.ID)
- switch m.messageType {
- case EventTypeEmit:
- fallthrough
- case EventTypeOEmit:
- if m.dst == inside {
- c.output("%s", m.message)
- }
- case EventTypePEmit:
- c.output("%s", m.message)
- case EventTypeWall:
- speaker, found := c.db.Fetch(m.src)
- if !found {
- break
- }
- c.output("In the distance, you hear %s bellow out \"%s\"", speaker.Name, m.message)
- case EventTypePage:
- speaker, found := c.db.Fetch(m.src)
- if !found {
- break
- }
- c.output("%s pages you: \"%s\"", speaker.Name, m.message)
- case EventTypeSay:
- if m.dst == inside {
- speaker, found := c.db.Fetch(m.src)
- if !found {
- break
- }
- c.output("%s says \"%s\"", speaker.Name, m.message)
- }
- case EventTypePose:
- if m.dst == inside {
- if m.src == c.actor.ID {
- c.output("%s %s", c.actor.Name, m.message)
- } else {
- speaker, found := c.db.Fetch(m.src)
- if !found {
- break
- }
- c.output("%s %s", speaker.Name, m.message)
- }
- }
- case EventTypeForce:
- actor, found := c.db.Fetch(m.dst)
- if !found {
- break
- }
- c.actor = actor
- c.evaluateCommand(m)
- case EventTypeCommand:
- c.evaluateCommand(m)
- }
- }
-
- func (c *ExecutionContext) evaluateCommand(m PlayerEvent) {
- message := m.message
- c.actor.Refresh()
- switch {
- case message == "l":
- c.lookCmd("")
- case message == "look":
- c.lookCmd("")
- case strings.HasPrefix(message, "l "): // look at
- c.lookCmd(strings.TrimPrefix(message, "l "))
- case strings.HasPrefix(message, "look "): // look at
- c.lookCmd(strings.TrimPrefix(message, "look "))
- case strings.HasPrefix(message, "ex "):
- c.examineCmd(strings.TrimPrefix(message, "ex "))
- case strings.HasPrefix(message, "examine "):
- c.examineCmd(strings.TrimPrefix(message, "examine "))
- case strings.HasPrefix(message, "\""):
- c.sayCmd(strings.TrimPrefix(message, "\""))
- case strings.HasPrefix(message, "say "):
- c.sayCmd(strings.TrimPrefix(message, "say "))
- case strings.HasPrefix(message, ":"):
- c.poseCmd(strings.TrimPrefix(message, ":"))
- case strings.HasPrefix(message, "pose "):
- c.poseCmd(strings.TrimPrefix(message, "pose "))
- case message == "i":
- c.inventoryCmd()
- case message == "inventory":
- c.inventoryCmd()
- case strings.HasPrefix(message, "get "):
- c.getCmd(strings.TrimPrefix(message, "get "))
- case strings.HasPrefix(message, "drop "):
- c.dropCmd(strings.TrimPrefix(message, "drop "))
- case strings.HasPrefix(message, "enter "):
- c.enterCmd(strings.TrimPrefix(message, "enter "))
- case message == "leave":
- c.leaveCmd()
- case message == "quit":
- c.quitCmd(m.connectionID)
- case message == "WHO":
- c.whoCmd()
- case message == "HOWLONG":
- time.Sleep(5 * time.Second)
- case strings.HasPrefix(message, "@create "):
- c.createCmd(strings.TrimPrefix(message, "@create "))
- case strings.HasPrefix(message, "@dig "):
- c.digCmd(message)
- case strings.HasPrefix(message, "@open "):
- c.openCmd(message)
- case strings.HasPrefix(message, "@name "):
- c.nameCmd(message)
- case strings.HasPrefix(message, "@desc "):
- c.descCmd(message)
- case strings.HasPrefix(message, "@tel "):
- c.telCmd(strings.TrimPrefix(message, "@tel "))
- case strings.HasPrefix(message, "@dump "):
- c.dumpCmd(strings.TrimPrefix(message, "@dump "))
- case strings.HasPrefix(message, "@destroy "):
- c.destroyCmd(strings.TrimPrefix(message, "@destroy "))
- case strings.HasPrefix(message, "@force "):
- c.forceCmd(message)
- default:
- if !c.goCmd(message) {
- c.output("What?\n")
- }
- }
-
- }
-
- func (c *ExecutionContext) lookCmd(at string) {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- c.output("True Limbo (#NaN)\nThere's nothing to see here. You are inside an object that doesn't exist.")
- return
- }
-
- if len(at) > 0 {
- object, matchType := room.MatchLinkNames(at, c.actor.ID).ExactlyOne()
- switch matchType {
- case MatchOne:
- c.output("%s\n%s", object.DetailedName(), object.Description)
- case MatchNone:
- c.output("I don't see that here.")
- case MatchMany:
- c.output("I don't now which one you're trying to look at.")
- }
- } else {
- c.output("%s\n%s", room.DetailedName(), room.Description)
- lookLinks := func(linkType string, pretty string) {
- linknames := room.GetLinkNames(linkType, DBRefList{c.actor.ID})
- if len(linknames) > 0 {
- c.output("%s\n %s", pretty, strings.Join(linknames, "\n "))
- }
- }
- lookLinks("thing", "Things:")
- lookLinks("player", "Players:")
- exits := room.GetLinkNames("exit", nil)
- if len(exits) > 0 {
- c.output("Exits:")
- exitList := make([]string, 0)
- for _, e := range exits {
- aliases := strings.Split(e, ";")
- exitList = append(exitList, aliases[0])
- }
- c.output(strings.Join(exitList, " "))
- }
- }
-
- }
-
- func (c *ExecutionContext) objectName(id DBRef) string {
- o, found := c.db.Fetch(id)
- if found {
- return o.DetailedName()
- } else {
- return fmt.Sprintf("MISSING OBJECT (#%d)", id)
- }
- }
-
- func (c *ExecutionContext) examineCmd(at string) {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- object, matchType := room.MatchLinkNames(at, c.actor.ID).ExactlyOne()
-
- switch matchType {
- case MatchOne:
-
- objectParentID, _ := c.db.GetParent(object.ID)
-
- c.output("%s", object.DetailedName())
- c.output("ID: %d", object.ID)
- c.output("Type: %s", object.Type)
- c.output("@name: %s", object.Name)
- c.output("@desc: %s", object.Description)
- c.output("Inside: %s", c.objectName(objectParentID))
- c.output("Next: %s", c.objectName(object.Next))
- c.output("Owner: %s", c.objectName(object.Owner))
-
- inventory := object.GetLinkNames("*", nil)
- if len(inventory) > 0 {
- c.output("Contents:\n %s", strings.Join(inventory, "\n "))
- }
- case MatchNone:
- c.output("I don't see that here.")
- case MatchMany:
- c.output("I don't know which one you're trying to examine.")
- }
-
- }
-
- func (c *ExecutionContext) forceCmd(input string) {
-
- r, _ := regexp.Compile(`^@force\pZ+([^=]*[^=\pZ]{1})\pZ*=\pZ*(.*)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- objectName, command := params[1], params[2]
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- objectID, err := NewDBRefFromHashRef(objectName)
- wizard := false
- if err == nil {
- object, found := c.db.Fetch(objectID)
- if !found {
- c.output("I can't force what doesn't exist.")
- }
- if object.Type == "thing" || (object.Type == "player" && wizard) {
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: object.ID, message: command, messageType: EventTypeForce}
- } else {
- c.output("Some things just can't be forced.")
- }
- } else {
-
- object, matchType := room.MatchLinkNames(objectName, c.actor.ID).ExactlyOne()
-
- switch matchType {
- case MatchOne:
- if object.Type == "thing" || (object.Type == "player" && wizard) {
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: object.ID, message: command, messageType: EventTypeForce}
- } else {
- c.output("Some things just can't be forced.")
- }
- case MatchNone:
- c.output("I don't see that here.")
- case MatchMany:
- c.output("I don't know which one you're trying to examine.")
- }
- }
- }
-
- func (c *ExecutionContext) sayCmd(message string) {
-
- inside, _ := c.db.GetParent(c.actor.ID)
- c.output("You say \"%s\"", message)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: inside, message: message, messageType: EventTypeSay}
-
- }
-
- func (c *ExecutionContext) poseCmd(message string) {
-
- inside, _ := c.db.GetParent(c.actor.ID)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: inside, message: message, messageType: EventTypePose}
-
- }
-
- func (c *ExecutionContext) inventoryCmd() {
-
- inventory := c.actor.GetLinkNames("*", nil)
-
- if len(inventory) > 0 {
- c.output("Inventory:\n %s", strings.Join(inventory, "\n "))
- } else {
- c.output("You're not carrying anything.")
- }
-
- }
-
- func (c *ExecutionContext) getCmd(message string) {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- object, matchType := room.MatchLinkNames(message, c.actor.ID).ExactlyOne()
-
- switch matchType {
- case MatchOne:
- if object.ID == c.actor.ID {
- c.output("You can't pick yourself up.")
- return
- }
- err := c.actor.Contains(&object)
- if err != nil {
- return
- }
- //c.actor.Refresh()
- c.output("You pick up %s.", object.Name)
- c.pemit(object.ID, "%s picked you up.", c.actor.Name)
- c.oemit(room.ID, "%s picks up %s.", c.actor.Name, object.Name)
- case MatchNone:
- c.output("I don't see that here.")
- case MatchMany:
- c.output("I don't know which one.")
- }
-
- }
-
- func (c *ExecutionContext) dropCmd(message string) {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- object, matchType := c.actor.MatchLinkNames(message, c.actor.ID).ExactlyOne()
-
- switch matchType {
- case MatchOne:
- err := room.Contains(&object)
- if err != nil {
- return
- }
- inside, _ := c.db.GetParent(c.actor.ID)
- c.output("You drop %s.", object.Name)
- c.pemit(object.ID, "%s drops you.", c.actor.Name)
- c.oemit(inside, "%s drops %s.", c.actor.Name, object.Name)
- case MatchNone:
- c.output("You're not carrying that.")
- case MatchMany:
- c.output("I don't now which one.")
- }
-
- }
-
- func (c *ExecutionContext) enterCmd(message string) {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- object, matchType := room.MatchLinkNames(message, c.actor.ID).ExactlyOne()
-
- switch matchType {
- case MatchOne:
- if object.ID == c.actor.ID {
- c.output("Entering yourself would be a bad idea.")
- return
- }
- err := object.Contains(&c.actor)
- if err != nil {
- return
- }
- c.output("You climb into %s.", object.Name)
- c.oemit(room.ID, "%s climbs into %s.", c.actor.Name, object.Name)
- c.oemit(object.ID, "%s squeezes into %s with you.", c.actor.Name, object.Name)
- case MatchNone:
- c.output("I don't see that here.")
- case MatchMany:
- c.output("I don't now which one.")
- }
- }
-
- func (c *ExecutionContext) leaveCmd() {
-
- inside, _ := c.db.GetParent(c.actor.ID)
- object, found := c.db.Fetch(inside)
- if !found {
- return
- }
- objectInside, _ := c.db.GetParent(inside)
- if objectInside == 0 { // probably trying to 'leave' a room
- c.output("You can't leave here.")
- return
- }
-
- room, found := c.db.Fetch(objectInside)
- if !found {
- return
- }
-
- err := room.Contains(&c.actor)
- if err != nil {
- return
- }
-
- //c.actor.Refresh()
-
- c.output("You climb out of %s.", object.Name)
- c.oemit(object.ID, "%s climbs out of %s.", c.actor.Name, object.Name)
- c.oemit(room.ID, "%s climbs out of %s.", c.actor.Name, object.Name)
-
- }
-
- func (c *ExecutionContext) quitCmd(connectionID int) {
-
- c.output("So long, it's been good to know yah.")
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: c.actor.ID, messageType: EventTypeQuit, connectionID: connectionID}
-
- }
-
- func (c *ExecutionContext) whoCmd() {
- // onlinePlayers := c.eventDistributor.OnlinePlayers()
-
- c.output("Currently Online:\n")
-
- //for _, ref := range onlinePlayers {
- // c.output("%s\n", c.db.GetName(ref))
- //}
- }
-
- func (c *ExecutionContext) createCmd(message string) {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- o := c.factory.NewThing()
- o.Name = strings.TrimSpace(message)
- o.Owner = c.actor.ID
- o.Commit()
-
- err := room.Contains(&o)
- if err != nil {
- return
- }
-
- c.oemit(room.ID, "A %s appears out of the ether.", o.Name)
- c.output("%s Created.", o.DetailedName())
-
- }
-
- func (c *ExecutionContext) openCmd(input string) {
- // @open <in1;in2;in3;etc>=#<room>,<out1;out2;out3;etc>
-
- r, _ := regexp.Compile(`^@open\pZ+([^=]*[^=\pZ]+)\pZ*=#([0-9]+)(?:\pZ*,\pZ*([^,]*[^,\pZ]+)\pZ*)?`)
- params := r.FindStringSubmatch(input)
-
- if params == nil {
- return
- }
-
- inExit, roomIDStr, outExit := params[1], params[2], params[3]
-
- if len(inExit) == 0 || len(roomIDStr) == 0 {
- c.output("Bad command or file name.")
- return
- }
-
- targetID, _ := NewDBRefFromString(roomIDStr) // this will never fail, the regexp guarantees that
- targetRoom, found := c.db.Fetch(targetID)
- if !found {
- c.output("Target not found.")
- return
- }
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- toExit := c.factory.NewExit(inExit, targetRoom.ID, c.actor.ID)
- toExit.Commit()
- err := room.Contains(&toExit)
- if err != nil {
- return
- }
- c.output("%s Created.", toExit.DetailedName())
-
- if len(outExit) > 0 {
- fromExit := c.factory.NewExit(outExit, room.ID, c.actor.ID)
- fromExit.Commit()
- err = targetRoom.Contains(&fromExit)
- if err != nil {
- return
- }
- c.output("%s Created.", fromExit.DetailedName())
- }
-
- }
-
- func (c *ExecutionContext) digCmd(input string) {
- // @dig <Room name>=<in1;in2;in3;etc>,<out1;out2;out3;etc>
- //@dig foo bar = <F>oo;foo;f,<B>ack;back;b
-
- r, _ := regexp.Compile(`^@dig\pZ+([^=]*[^=\pZ]+)(\pZ*=\pZ*(?:([^,]*[^,\pZ]+)\pZ*)?(?:\pZ*,\pZ*([^,]*[^,\pZ]+)\pZ*)?)?`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- roomName, inExit, outExit := params[1], params[2], params[3]
-
- if len(roomName) == 0 {
- c.output("Rooms can't not have names.")
- return
- }
-
- newRoom := c.factory.NewRoom()
- newRoom.Name = roomName
- newRoom.Owner = c.actor.ID
- newRoom.Commit()
-
- c.output("%s Created.", newRoom.DetailedName())
-
- if len(inExit) > 0 || len(outExit) > 0 {
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
- if len(inExit) > 0 {
- toExit := c.factory.NewExit(inExit, newRoom.ID, c.actor.ID)
- toExit.Commit()
- err := room.Contains(&toExit)
- if err != nil {
- return
- }
- c.output("%s Created.", toExit.DetailedName())
- }
- if len(outExit) > 0 {
- fromExit := c.factory.NewExit(outExit, room.ID, c.actor.ID)
- fromExit.Commit()
- err := newRoom.Contains(&fromExit)
- if err != nil {
- return
- }
- c.output("%s Created.", fromExit.DetailedName())
- }
- }
-
- }
-
- func (c *ExecutionContext) nameCmd(input string) {
-
- r, _ := regexp.Compile(`^@name\pZ+([^=]*[^=\pZ]{1})\pZ*=\pZ*(.*)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- objectName, name := params[1], params[2]
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- candidate, matchType := room.MatchLinkNames(objectName, c.actor.ID).ExactlyOne()
- switch matchType {
- case MatchOne:
- candidate.Name = name
- candidate.Commit()
- c.output("Name set.")
- //c.actor.Refresh()
- case MatchNone:
- c.output("I don't see that here.")
- case MatchMany:
- c.output("I don't now which one.")
- }
-
- }
-
- func (c *ExecutionContext) descCmd(input string) {
-
- r, _ := regexp.Compile(`^@desc\pZ+([^=]*[^=\pZ]{1})\pZ*=\pZ*(.*)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- objectName, description := params[1], params[2]
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
-
- if !found {
- return
- }
-
- var editObject *Object
- switch objectName {
- case "here":
- editObject = &room
- case "me":
- editObject = &c.actor
- default:
- candidate, matchType := room.MatchLinkNames(objectName, c.actor.ID).ExactlyOne()
- switch matchType {
- case MatchOne:
- editObject = &candidate
- case MatchNone:
- c.output("I don't see that here.")
- return
- case MatchMany:
- c.output("I don't now which one.")
- return
- }
- }
-
- editObject.Description = description
- editObject.Commit()
- //c.actor.Refresh()
- c.output("Description set.")
-
- }
-
- func (c *ExecutionContext) telCmd(destStr string) {
-
- dest, err := NewDBRefFromHashRef(destStr)
-
- if err != nil {
- c.output("That doesn't look like a DBRef.")
- return
- }
-
- newRoom, found := c.db.Fetch(dest)
- if !found {
- c.output("That doesn't exist.")
- return
- }
-
- c.output("You feel an intense wooshing sensation.")
- err = newRoom.Contains(&c.actor)
- if err != nil {
- return
- }
-
- c.actor.Refresh()
- c.lookCmd("")
-
- }
-
- func (c *ExecutionContext) dumpCmd(refStr string) {
-
- ref, err := NewDBRefFromHashRef(refStr)
-
- if err != nil {
- c.output("That doesn't look like a DBRef.")
- return
- }
-
- obj, found := c.db.Fetch(ref)
- if !found {
- c.output("That doesn't exist.")
- return
- }
-
- c.output("%s", c.db.DumpObject(obj.ID))
-
- }
-
- func (c *ExecutionContext) destroyCmd(message string) {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return
- }
-
- object, matchType := room.MatchLinkNames(message, c.actor.ID).ExactlyOne()
-
- switch matchType {
- case MatchOne:
- if object.ID == c.actor.ID {
- c.output("There are alternatives to suicide.")
- return
- }
- if object.Type == "player" {
- c.output("I didn't think homicide was your thing.")
- return
- }
- name := object.DetailedName()
- err := object.Delete()
- if err == nil {
- //c.actor.Refresh()
- c.output("%s vanishes into thin air.", name)
- }
- case MatchNone:
- c.output("I don't see that here.")
- case MatchMany:
- c.output("I don't know which one.")
- }
-
- }
-
- func (c *ExecutionContext) goCmd(dir string) bool {
-
- roomID, found := c.db.GetParent(c.actor.ID)
- room, found := c.db.Fetch(roomID)
- if !found {
- return false
- }
-
- exit, matchType := room.MatchExitNames(dir).ExactlyOne()
- switch matchType {
- case MatchOne:
- if exit.Next.Valid() {
- newRoom, found := c.db.Fetch(exit.Next)
- if !found {
- c.output("That exit appears to be broken!")
- return true
- }
- err := newRoom.Contains(&c.actor)
- if err != nil {
- return false
- }
- //c.actor.Refresh()
- c.output("You head towards %s.", newRoom.Name)
- c.oemit(room.ID, "%s leaves the room.", c.actor.Name)
- c.oemit(newRoom.ID, "%s enters the room.", c.actor.Name)
- return true
- }
- case MatchNone:
- return false
- case MatchMany:
- c.output("Ambiguous exit names are ambiguous.")
- return true
- }
-
- return false
-
- }
-
- func (c *ExecutionContext) oemit(audience DBRef, format string, a ...interface{}) {
-
- message := fmt.Sprintf(format, a...)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: audience, message: message, messageType: EventTypeOEmit}
-
- }
-
- func (c *ExecutionContext) output(format string, a ...interface{}) {
-
- message := fmt.Sprintf(format, a...)
- if !c.forceContext {
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: c.actor.ID, message: message, messageType: EventTypeOutput}
- }
- }
-
- func (c *ExecutionContext) pemit(target DBRef, format string, a ...interface{}) {
-
- message := fmt.Sprintf(format, a...)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: target, message: message, messageType: EventTypePEmit}
-
- }
-
- func (c *ExecutionContext) emit(audience DBRef, format string, a ...interface{}) {
-
- message := fmt.Sprintf(format, a...)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: audience, message: message, messageType: EventTypeEmit}
-
- }
|