12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100 |
- package funmow
-
- import (
- "fmt"
- "regexp"
- "strings"
- "unicode"
- )
-
- const (
- MatchContext = 1 << iota
- MatchGlobalDBRef = 1 << iota
- MatchGlobalPlayer = 1 << iota
- MatchInventory = 1 << iota
- MatchRelative = 1 << iota
- MatchExitAliases = 1 << iota
- MatchExitType = 1 << iota
- MatchRoomType = 1 << iota
- MatchPlayerType = 1 << iota
- MatchThingType = 1 << iota
- MatchAnyType = MatchExitType|MatchRoomType|MatchPlayerType|MatchThingType
- MatchStuffTypes = MatchExitType|MatchRoomType|MatchThingType
-
- )
-
- type ExecutionContext struct {
- actor Object
- context 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() {
-
- // An 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.
-
- 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
- close(inboundBuffer)
- }()
-
- go func() {
- for {
- event, ok := <-inboundBuffer
- if !ok {
- break
- }
- c.HandleEvent(event)
- }
- // mark player as offline
- if c.actor.Type == "player" {
- c.actor.SetFlag("online", false)
- c.actor.Commit()
- }
- // and finally we tell the event distributor to delete us.
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: c.actor.ID, messageType: EventTypeTeardownComplete}
- }()
-
- return c.inbound
- }
-
- func (c *ExecutionContext) HandleEvent(m PlayerEvent) {
- c.actor.Refresh()
- contextID, found := c.db.GetParent(c.actor.ID)
- if found {
- c.context, _ = c.db.Fetch(contextID)
- }
-
- switch m.messageType {
- case EventTypeLogin:
- if c.actor.Type == "player" {
- c.actor.SetFlag("online", true)
- c.actor.Commit()
- c.system("Yay! %s has connected! Oh boy!", c.actor.ColorName())
- c.oemit(c.context.ID, "You hear a rustling as %s awakens from a slumber.", c.actor.ColorName())
- }
- case EventTypeEmit:
- fallthrough
- case EventTypeOEmit:
- if m.dst == c.context.ID {
- 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.ColorName(), m.message)
- case EventTypeSystem:
- c.output(m.message)
- case EventTypePage:
- speaker, found := c.db.Fetch(m.src)
- if !found {
- break
- }
- c.output("%s pages: %s", speaker.ColorName(), m.message)
- case EventTypeSay:
- if m.dst == c.context.ID {
- speaker, found := c.db.Fetch(m.src)
- if !found {
- break
- }
- c.output("%s says \"%s\"", speaker.ColorName(), m.message)
- }
- case EventTypePose:
- if m.dst == c.context.ID {
- if m.src == c.actor.ID {
- c.output("%s %s", c.actor.ColorName(), m.message)
- } else {
- speaker, found := c.db.Fetch(m.src)
- if !found {
- break
- }
- c.output("%s %s", speaker.ColorName(), 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) {
- command := m.message
- switch {
- case command == "whoami":
- c.output(c.actor.Name)
- case command == "l":
- c.lookCmd("")
- case command == "look":
- c.lookCmd("")
- case strings.HasPrefix(command, "l "): // look at
- c.lookCmd(strings.TrimPrefix(command, "l "))
- case strings.HasPrefix(command, "look "): // look at
- c.lookCmd(strings.TrimPrefix(command, "look "))
- case strings.HasPrefix(command, "ex "):
- c.examineCmd(strings.TrimPrefix(command, "ex "))
- case strings.HasPrefix(command, "examine "):
- c.examineCmd(strings.TrimPrefix(command, "examine "))
- case strings.HasPrefix(command, "\""):
- c.sayCmd(strings.TrimPrefix(command, "\""))
- case strings.HasPrefix(command, "say "):
- c.sayCmd(strings.TrimPrefix(command, "say "))
- case strings.HasPrefix(command, ":"):
- c.poseCmd(strings.TrimPrefix(command, ":"))
- case strings.HasPrefix(command, "pose "):
- c.poseCmd(strings.TrimPrefix(command, "pose "))
- case strings.HasPrefix(command, "p "):
- c.pageCmd(command)
- case strings.HasPrefix(command, "page "):
- c.pageCmd(command)
- case command == "i":
- c.inventoryCmd()
- case command == "inventory":
- c.inventoryCmd()
- case strings.HasPrefix(command, "get "):
- c.getCmd(strings.TrimPrefix(command, "get "))
- case strings.HasPrefix(command, "drop "):
- c.dropCmd(strings.TrimPrefix(command, "drop "))
- case strings.HasPrefix(command, "give "):
- c.giveCmd(command)
- case strings.HasPrefix(command, "put "):
- c.putCmd(command)
- case strings.HasPrefix(command, "enter "):
- c.enterCmd(strings.TrimPrefix(command, "enter "))
- case command == "leave":
- c.leaveCmd()
- case command == "quit":
- c.quitCmd(m.connectionID)
- case command == "WHO":
- c.whoCmd()
- case strings.HasPrefix(command, "@create "):
- c.createCmd(strings.TrimPrefix(command, "@create "))
- case strings.HasPrefix(command, "@dig "):
- c.digCmd(command)
- case strings.HasPrefix(command, "@open "):
- c.openCmd(command)
- case strings.HasPrefix(command, "@name "):
- c.nameCmd(command)
- case strings.HasPrefix(command, "@desc "):
- c.descCmd(command)
- case strings.HasPrefix(command, "@password "):
- c.passwordCmd(command)
- case strings.HasPrefix(command, "@set "):
- c.setCmd(command)
- case strings.HasPrefix(command, "@color "):
- c.colorCmd(command)
- case strings.HasPrefix(command, "@tel "):
- c.telCmd(strings.TrimPrefix(command, "@tel "))
- case strings.HasPrefix(command, "@dump "):
- c.dumpCmd(strings.TrimPrefix(command, "@dump "))
- case strings.HasPrefix(command, "@destroy "):
- c.destroyCmd(strings.TrimPrefix(command, "@destroy "))
- case strings.HasPrefix(command, "@force "):
- c.forceCmd(command)
-
- default:
- if !c.goCmd(command) {
- c.output("What?\n")
- }
- }
-
- }
-
- func (c *ExecutionContext) lookCmd(target string) {
-
- if len(target) > 0 {
- object, found := c.MatchFirst(c.context.ID, target, MatchContext|MatchInventory|MatchRelative|MatchAnyType|MatchExitAliases)
- if !found {
- c.output("I don't see that here.")
- return
- }
- c.output("%s\n%s", object.DetailedName(), object.Description)
- } else {
- c.output("%s\n%s", c.context.DetailedName(), c.context.Description)
- contents := c.context.GetContents(c.actor.ID)
- if len(contents) > 0 {
- c.output("Contents:\n" + strings.Join(contents, "\n"))
- }
- exits := c.context.GetExits(true)
- if len(exits) > 0 {
- c.output("Obvious Exits:\n" + strings.Join(exits, " "))
- }
- }
-
- }
-
- 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(objectName string) {
-
- object, found := c.MatchFirst(c.context.ID, objectName, MatchContext|MatchInventory|MatchRelative|MatchAnyType|MatchExitAliases|MatchGlobalDBRef)
- if !found {
- c.output("I don't see that here.")
- return
- }
-
- containerID, _ := c.db.GetParent(object.ID)
-
- c.output("%s", object.DetailedName())
- c.output("Type: %s", object.Type)
- c.output("@name: %s", object.Name)
- c.output("@desc: %s", object.Description)
- c.output("Next: %s", c.objectName(object.Next))
- c.output("Owner: %s", c.objectName(object.Owner))
- c.output("Location: %s", c.objectName(containerID))
-
- contents := object.GetContents(0)
- if len(contents) > 0 {
- c.output("Contains:\n%s", strings.Join(contents, "\n"))
- }
-
- exits := object.GetExits(false)
- if len(exits) > 0 {
- c.output("Exits:\n%s", strings.Join(exits, "\n"))
- }
-
- flags := make([]string, 0, len(object.Flags))
- for k, v := range object.Flags {
- if v {
- flags = append(flags, k)
- }
- }
- c.output("Flags: %s", strings.Join(flags, ", "))
-
- properties := make([]string, 0, len(object.Properties))
- for k, v := range object.Properties {
- properties = append(properties, fmt.Sprintf("@%s: %s", k, v))
- }
- c.output("Properties:\n%s", strings.Join(properties, "\n"))
-
- }
-
- 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]
-
- wizard := c.actor.GetFlag("wizard")
-
- object, found := c.MatchFirst(c.context.ID, objectName, MatchContext|MatchGlobalDBRef|MatchExitAliases|MatchInventory|MatchRelative|MatchStuffTypes)
- if !found {
- c.output("I don't see that here.")
- return
- }
- if object.Owner != c.actor.ID && !wizard {
- c.output("It's not nice to touch other people's things.")
- return
- }
-
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: object.ID, message: command, messageType: EventTypeForce}
-
- }
-
- func (c *ExecutionContext) sayCmd(message string) {
-
- c.output(`You say "%s"`, message)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: c.context.ID, message: message, messageType: EventTypeSay}
-
- }
-
- func (c *ExecutionContext) poseCmd(message string) {
-
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: c.context.ID, message: message, messageType: EventTypePose}
-
- }
-
- func (c *ExecutionContext) pageCmd(input string) {
-
- r, _ := regexp.Compile(`^p(?:age)*\pZ+([^=]*[^=\pZ]{1})\pZ*=\pZ*(.*[^\pZ]+)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- searchName, message := params[1], params[2]
-
- candidate, found := c.MatchPlayerName(searchName)
- if !found {
- c.output("I don't know who you're trying to page.")
- return
- }
- if !candidate.GetFlag("online") {
- c.output("That player appears to be offline.")
- return
- }
-
- c.output(`You paged %s with "%s".`, candidate.ColorName(), message)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: candidate.ID, message: message, messageType: EventTypePage}
-
- }
-
- func (c *ExecutionContext) inventoryCmd() {
-
- inventory := c.actor.GetContents(0)
-
- 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(objectName string) {
-
- object, found := c.MatchFirst(c.context.ID, objectName, MatchContext|MatchGlobalDBRef|MatchAnyType)
- if !found {
- c.output("I don't see that here.")
- return
- }
- if object.Type == "exit" {
- c.output("You can't pick pick up exits.")
- return
- }
- if object.Type == "player" {
- c.output("That's really annoying. Don't be that person.")
- return
- }
- 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.ColorName())
- c.pemit(object.ID, "%s picked you up.", c.actor.ColorName())
- c.oemit(c.context.ID, "%s picks up %s.", c.actor.ColorName(), object.ColorName())
-
- }
-
- func (c *ExecutionContext) putCmd(input string) {
- c.xferCmd(input, "put", "into")
- }
-
- func (c *ExecutionContext) giveCmd(input string) {
- c.xferCmd(input, "give", "to")
- }
-
- func (c *ExecutionContext) xferCmd(input string, verb string, preposition string) {
-
- r, _ := regexp.Compile(`^` + verb + `\pZ+([^=]*[^=\pZ]{1})\pZ*` + preposition + `\pZ*(.*)\pZ*$`)
-
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- objectName, receiverName := params[1], params[2]
-
- object, found := c.MatchFirst(c.actor.ID, objectName, MatchInventory|MatchThingType)
- if !found {
- c.output("You can't " + verb + " what you don't have.")
- return
- }
- receiver, found := c.MatchFirst(c.context.ID, receiverName, MatchContext|MatchThingType)
- if !found {
- c.output("I cant find who or what you want to " + verb + " this " + preposition + ".")
- return
- }
-
- err := receiver.Contains(&object)
- if err != nil {
- return
- }
-
- c.output("You "+verb+" %s "+preposition+" %s.", object.ColorName(), receiver.ColorName())
- c.pemit(object.ID, "%s "+verb+"s you "+preposition+" %s.", c.actor.ColorName(), receiver.ColorName())
-
- if verb == "give" {
- c.pemit(receiver.ID, "%s gives you %s.", c.actor.ColorName(), object.ColorName())
- } else {
- c.pemit(receiver.ID, "%s puts %s into you.", c.actor.ColorName(), object.ColorName())
- }
-
- }
-
- func (c *ExecutionContext) MatchPlayerName(matchName string) (Object, bool) {
- playerMeta, foundMeta := c.db.GetPlayer(matchName)
- if foundMeta {
- o, found := c.db.Fetch(playerMeta.ID)
- if found {
- return o, true
- }
- }
- return Object{}, false
- }
-
- func (c *ExecutionContext) MatchFirst(context DBRef, matchName string, matchType int) (Object, bool) {
-
- wanted := map[string]bool{
- "player": matchType & MatchPlayerType != 0,
- "exit": matchType & MatchExitType != 0,
- "room": matchType & MatchRoomType != 0,
- "thing": matchType & MatchThingType != 0,
- }
-
- if matchType & MatchRelative != 0 {
- if matchName == "here" {
- o, found := c.db.Fetch(context)
- if found && wanted[o.Type] {
- return o, true
- }
- }
-
- if matchName == "me" {
- if wanted[c.actor.Type] {
- return c.actor, true
- }
- }
- }
-
- ref, valid := NewDBRefFromHashRef(matchName)
-
- if valid {
- o, found := c.db.Fetch(ref)
- if found && wanted[o.Type] {
- container, _ := c.db.GetParent(o.ID)
- if container == context && matchType & MatchContext != 0 {
- return o, true
- }
- if container == c.actor.ID && matchType & MatchInventory != 0 {
- return o, true
- }
- if matchType & MatchGlobalDBRef != 0 {
- return o, true
- }
- }
- }
-
-
- if wanted["player"] && matchType & MatchGlobalPlayer != 0 {
- o, found := c.MatchPlayerName(matchName)
- if found {
- return o, true
- }
- }
-
- if matchType & MatchContext != 0 {
- for childID, _ := range c.db.GetChildren(context) {
- o, found := c.db.Fetch(childID)
- if found && wanted[o.Type] {
- if o.Type == "exit" && matchType & MatchExitAliases != 0 {
- aliases := strings.Split(o.Name, ";")
- for _, v := range aliases {
- if strings.EqualFold(v, matchName) {
- return o, true
- }
- }
- }
- lowerObjectName := strings.ToLower(o.Name)
- lowerMatchName := strings.ToLower(matchName)
- if strings.HasPrefix(lowerObjectName, lowerMatchName) {
- return o, true
- }
- }
- }
- }
-
- if matchType & MatchInventory != 0 {
- for childID, _ := range c.db.GetChildren(c.actor.ID) {
- o, found := c.db.Fetch(childID)
- if found && wanted[o.Type] {
- lowerObjectName := strings.ToLower(o.Name)
- lowerMatchName := strings.ToLower(matchName)
- if strings.HasPrefix(lowerObjectName, lowerMatchName) {
- return o, true
- }
- }
- }
- }
-
- return Object{}, false
-
- }
-
- func (c *ExecutionContext) dropCmd(objectName string) {
-
- object, found := c.MatchFirst(c.actor.ID, objectName, MatchInventory|MatchAnyType)
- if !found {
- c.output("You're not carrying that.")
- return
- }
-
- err := c.context.Contains(&object)
- if err != nil {
- return
- }
-
- c.output("You drop %s.", object.ColorName())
- c.pemit(object.ID, "%s drops you.", c.actor.ColorName())
- c.oemit(c.context.ID, "%s drops %s.", c.actor.ColorName(), object.ColorName())
-
- }
-
- func (c *ExecutionContext) enterCmd(objectName string) {
-
- object, found := c.MatchFirst(c.context.ID, objectName, MatchContext|MatchThingType)
- if !found {
- c.output("I don't see that here.")
- return
- }
-
- if object.Type == "player" {
- c.output("Maybe you should seek consent prior to entering another player.")
- return
- }
- if object.Type == "exit" {
- c.output("This s not how exits are meant to be used.")
- return
- }
- 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.ColorName())
- c.oemit(c.context.ID, "%s climbs into %s.", c.actor.ColorName(), object.ColorName())
- c.oemit(object.ID, "%s squeezes into %s with you.", c.actor.ColorName(), object.ColorName())
-
- }
-
- func (c *ExecutionContext) leaveCmd() {
-
- outerObjectID, _ := c.db.GetParent(c.context.ID)
- if outerObjectID == 0 { // probably trying to 'leave' a room
- c.output("You can't leave here.")
- return
- }
-
- container, found := c.db.Fetch(outerObjectID)
- if !found {
- return
- }
-
- err := container.Contains(&c.actor)
- if err != nil {
- return
- }
-
- c.output("You climb out of %s.", c.context.ColorName())
- c.oemit(c.context.ID, "%s climbs out of %s.", c.actor.ColorName(), c.context.ColorName())
- c.oemit(container.ID, "%s climbs out of %s.", c.actor.ColorName(), c.context.ColorName())
-
- }
-
- 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) {
-
- o := c.factory.NewThing()
- o.Name = strings.TrimSpace(message)
- o.Owner = c.actor.ID
- o.Commit()
-
- err := c.actor.Contains(&o)
- if err != nil {
- return
- }
-
- 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]{1})\pZ*=#([0-9]+)(?:\pZ*,\pZ*([^,]*[^,\pZ]{1})\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
- }
-
- toExit := c.factory.NewExit(inExit, targetRoom.ID, c.actor.ID)
- toExit.Commit()
- err := c.context.Contains(&toExit)
- if err != nil {
- return
- }
- c.output("%s Created.", toExit.DetailedName())
-
- if len(outExit) > 0 {
- fromExit := c.factory.NewExit(outExit, c.context.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]{1})(?:\pZ*=\pZ*(?:([^,]*[^,\pZ]{1})\pZ*)?(?:\pZ*,\pZ*([^,]*[^,\pZ]{1})\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 {
- if len(inExit) > 0 {
- toExit := c.factory.NewExit(inExit, newRoom.ID, c.actor.ID)
- toExit.Commit()
- err := c.context.Contains(&toExit)
- if err != nil {
- return
- }
- c.output("%s Created.", toExit.DetailedName())
- }
- if len(outExit) > 0 {
- fromExit := c.factory.NewExit(outExit, c.context.ID, c.actor.ID)
- fromExit.Commit()
- err := newRoom.Contains(&fromExit)
- if err != nil {
- return
- }
- c.output("%s Created.", fromExit.DetailedName())
- }
- }
-
- }
-
- func (c *ExecutionContext) passwordCmd(input string) {
-
- if c.actor.Type != "player" {
- c.output("Only players can have passwords.")
- return
- }
-
- r, _ := regexp.Compile(`^@password\pZ+([^\pZ]+)\pZ*=\pZ*([^\pZ]+)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- oldPassword, newPassword := params[1], params[2]
-
- if len(oldPassword) == 0 || len(newPassword) == 0 {
- c.output("Password can't be blank.")
- return
- }
-
- changed := c.db.SetPlayerPassword(c.actor.Name, oldPassword, newPassword)
- if changed {
- c.output("Password updated.")
- } else {
- c.output("Old password is wrong.")
- }
-
- }
-
- func (c *ExecutionContext) nameCmd(input string) {
-
- r, _ := regexp.Compile(`^@name\pZ+([^=]*[^=\pZ]{1})\pZ*=\pZ*(.*)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- searchName, newName := params[1], params[2]
-
- candidate, found := c.MatchFirst(c.context.ID, searchName, MatchContext|MatchInventory|MatchRelative|MatchGlobalDBRef|MatchExitAliases|MatchAnyType)
-
- if !found {
- c.output("I don't see that here.")
- return
- }
-
- if candidate.Type == "player" {
- i := strings.IndexFunc(newName, func(c rune) bool {
- return unicode.IsSpace(c)
- })
- if i != -1 {
- c.output("Player names can't have spaces.")
- return
- }
- if c.actor.ID != candidate.ID && !c.actor.GetFlag("wizard") {
- c.output("Only wizards can rename other players.")
- return
- }
- err := c.db.RenamePlayer(candidate.Name, newName)
- if err != nil {
- c.output("I can't do that. Something has gone wrong.")
- return
- }
- }
- candidate.Name = newName
- candidate.Commit()
- c.output("Name set.")
-
- }
-
- 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]
-
-
- object, found := c.MatchFirst(c.context.ID, objectName, MatchContext|MatchInventory|MatchRelative|MatchGlobalDBRef|MatchExitAliases|MatchAnyType)
- if !found {
- c.output("I don't see that here.")
- return
- }
-
- object.Description = description
- object.Commit()
-
- c.output("Description set.")
-
- }
-
- func (c *ExecutionContext) setCmd(input string) {
- r, _ := regexp.Compile(`^@set\pZ+([^=]*[^=\pZ]{1})\pZ*=\pZ*(!)?(.*)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- objectName, value, flag := params[1], params[2] != "!", params[3]
-
- object, found := c.MatchFirst(c.context.ID, objectName, MatchContext|MatchInventory|MatchRelative|MatchGlobalDBRef|MatchExitAliases|MatchAnyType)
- if !found {
- c.output("I don't know what that is")
- return
- }
-
- object.SetFlag(flag, value)
- object.Commit()
-
- c.output("It is so.")
-
- }
-
-
- func (c *ExecutionContext) colorCmd(input string) {
-
- r, _ := regexp.Compile(`^@color\pZ+([^=]*[^=\pZ]{1})\pZ*=\pZ*([^\pZ]*)\pZ*$`)
- params := r.FindStringSubmatch(input)
- if params == nil {
- return
- }
-
- objectName, value := params[1], params[2]
-
- object, found := c.MatchFirst(c.context.ID, objectName, MatchContext|MatchInventory|MatchRelative|MatchGlobalDBRef|MatchExitAliases|MatchAnyType)
-
- if !found {
- c.output("I don't know what that is")
- return
- }
-
- object.SetProp("color", value)
- object.Commit()
-
- c.output("It is so.")
-
- }
-
-
-
- func (c *ExecutionContext) telCmd(destStr string) {
-
- var dest Object
- var found bool
-
- dest, found = c.MatchFirst(c.context.ID, destStr, MatchGlobalDBRef|MatchRoomType)
-
- if !found {
- c.output("Invalid destination.")
- return
- }
-
- if dest.Owner != c.actor.ID && !dest.GetFlag("jump_ok") && !c.actor.GetFlag("wizard") {
- c.output("You're not allowed to do that.")
- return
- }
-
- c.output("You feel an intense wooshing sensation.")
- c.oemit(c.context.ID, "%s teleports out of the room.", c.actor.ColorName())
- c.oemit(dest.ID, "%s teleports in to the room.", c.actor.ColorName())
-
- err := dest.Contains(&c.actor)
- if err != nil {
- return
- }
-
- c.command("look")
-
- }
-
- func (c *ExecutionContext) dumpCmd(input string) {
-
- object, found := c.MatchFirst(c.context.ID, input, MatchContext|MatchInventory|MatchRelative|MatchGlobalDBRef|MatchGlobalPlayer|MatchExitAliases|MatchAnyType)
-
- if !found {
- c.output("I can't find that.")
- return
- }
-
- c.output("%s", c.db.DumpObject(object.ID))
-
- }
-
- func (c *ExecutionContext) destroyCmd(target string) {
-
- object, found := c.MatchFirst(c.context.ID, target, MatchContext|MatchGlobalDBRef|MatchRelative|MatchExitAliases|MatchInventory|MatchStuffTypes)
- if !found {
- c.output("I don't see that here.")
- return
- }
-
- 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.output("%s vanishes into thin air.", name)
- }
-
- }
-
- func (c *ExecutionContext) goCmd(dir string) bool {
-
- exit, found := c.MatchFirst(c.context.ID, dir, MatchContext|MatchExitType|MatchExitAliases)
-
- if !found {
- return false
- }
-
- if !exit.Next.Valid() {
- return false
- }
-
- 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.DetailedName())
- c.oemit(c.context.ID, "%s leaves the room.", c.actor.ColorName())
- c.oemit(newRoom.ID, "%s enters the room.", c.actor.ColorName())
- return true
-
-
- return false
-
- }
-
- func (c *ExecutionContext) command(format string, a ...interface{}) {
-
- command := fmt.Sprintf(format, a...)
- c.outbound <- PlayerEvent{src: c.actor.ID, dst: c.actor.ID, message: command, messageType: EventTypeCommand}
-
- }
-
- func (c *ExecutionContext) wall(format string, a ...interface{}) {
-
- message := fmt.Sprintf(format, a...)
- c.outbound <- PlayerEvent{src: c.actor.ID, message: message, messageType: EventTypeWall}
-
- }
-
- func (c *ExecutionContext) system(format string, a ...interface{}) {
-
- message := fmt.Sprintf(format, a...)
- c.outbound <- PlayerEvent{src: c.actor.ID, message: message, messageType: EventTypeSystem}
-
- }
-
- 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}
-
- }
|