// dropInventory drops everything the player is carrying. func (p *Player) dropInventory(cmd *command.Command) { for _, o := range p.Inventory.List() { if c, ok := o.(command.Interface); ok { if aliases := o.Aliases(); len(aliases) > 0 { cmd.New("DROP " + o.Aliases()[0]) c.Process(cmd) } } } }
// cpustart implement the 'CPUSTART' command and starts CPU profiling. // // TODO: Remove - for debugging only func (p *Player) cpustart(cmd *command.Command) (handled bool) { f, err := os.Create("cpuprof") if err != nil { cmd.Respond("CPU Profile Not Started: %s", err) return false } pprof.StartCPUProfile(f) cmd.Respond("CPU profile started") return true }
// memprof implements the 'MEMPROF' command and writes out a memprofile. // // NOTE: Need to change the value of MemProfileRate in server.go // TODO: Remove - for debugging only func (p *Player) memprof(cmd *command.Command) (handled bool) { f, err := os.Create("memprof") if err != nil { cmd.Respond("Memory Profile Not Dumped: %s", err) return false } pprof.WriteHeapProfile(f) f.Close() cmd.Respond("Memory profile dumped") return true }
// get removes an Item from the command issuer's current location and puts it // into it's own inventory. For this to happen a few conditions must be true: // // 1. Issuer must be at some sort of location // 2. Issuer must implement an inventory // 3. Issuer's location must contain the requested item // func (i *Item) get(cmd *command.Command) (handled bool) { if m, ok := cmd.Issuer.(location.Locateable); ok { if inv, ok := cmd.Issuer.(inventory.Interface); ok { if l := m.Locate(); l.Contains(i) { l.Remove(i) cmd.Broadcast([]thing.Interface{cmd.Issuer}, "You see %s pick up %s.", cmd.Issuer.Name(), i.Name()) inv.Add(i) cmd.Respond("You pickup %s.", i.Name()) handled = true } } } return }
// quit implements the 'QUIT' command. // // quit extracts a player from the world cleanly. If the player's location is // not crowded it also announces their departure - in a crowded location their // departure will go unnoticed. func (p *Player) quit(cmd *command.Command) (handled bool) { log.Printf("%s is quiting", p.Name()) p.quitting = true p.dropInventory(cmd) l := p.Locate() if !l.Crowded() { cmd.Broadcast([]thing.Interface{p}, "%s gives a strangled cry of 'Bye Bye', and then slowly fades away and is gone.", p.Name()) } cmd.Flush() l.Remove(p) PlayerList.Remove(p) return true }
// inv implements the 'INVENTORY' command. This provides information about what // a mobile is currently carrying. Currently a mobile can only examine it's own // inventory - but someone like a theif might find it handy to look into someone // elses inventory ;) // // TODO: Currently very basic, needs to deal with held, weilded, worn items. func (m *Mobile) inv(cmd *command.Command) (handled bool) { if cmd.Target != "" { return } response := "" if inventory := m.Inventory.List(); len(inventory) == 0 { response = "You are not carrying anything." } else { response = "You are currently carrying:\n" for _, item := range inventory { response += "\t" + item.Name() + "\n" } } cmd.Respond(response) return true }
// look implements the 'LOOK' command. It describes the location displaying the // title, description, things and directional exits. // // TODO: Implement brief mode. // // TODO: Implement looking in a specific direction with a maximum viewing // distance. func (b *Basic) look(cmd *command.Command) (handled bool) { things := "" if b.Crowded() { things = "[GREEN]You can see a crowd here.\n" } else { list := b.List(cmd.Issuer) thingsHere := make([]string, 0, len(list)) for _, o := range list { thingsHere = append(thingsHere, "You can see "+o.Name()+" here.") } if len(thingsHere) > 0 { things = "[GREEN]" + strings.Join(thingsHere, "\n") + "\n" } } cmd.Respond("[CYAN]%s\n[WHITE]%s\n%s\n%s", b.Name(), b.Description(), things, b.directionalExits) return true }
// move implements the directional movement commands. This allows movement from // location to location by typing a direction such as N or North. // // TODO: Modify command so that it can handle buffering of multiple location // broadcasts. func (b *Basic) move(cmd *command.Command, d direction) (handled bool) { if to := b.directionalExits[d]; to != nil { if !cmd.CanLock(to) { cmd.AddLock(to) return true } b.Remove(cmd.Issuer) // If the location is crowded you are not going to notice someone leaving if !b.Crowded() { b.Broadcast([]thing.Interface{cmd.Issuer}, "[YELLOW]You see %s go %s.", cmd.Issuer.Name(), directionLongNames[d]) } to.Add(cmd.Issuer) // If the location is crowded you are not going to notice someone entering if !to.Crowded() { to.Broadcast([]thing.Interface{cmd.Issuer}, "[YELLOW]You see %s walk in.", cmd.Issuer.Name()) } to.look(cmd) } else { cmd.Respond("[RED]You can't go %s from here!", directionLongNames[d]) } return true }
// who implements the 'WHO' command. This lists all the players currently on // the server. func (l *playerList) who(cmd *command.Command) (handled bool) { b := new(bytes.Buffer) if l.Length() < 2 { b.WriteString("You are all alone in this world.") } else { cmd.Broadcast([]thing.Interface{cmd.Issuer}, "You see %s concentrate.", cmd.Issuer.Name()) for _, p := range PlayerList.nonLockingList(cmd.Issuer) { b.WriteString(" ") b.WriteString(p.Name()) b.WriteString("\n") } b.WriteString("\nTOTAL PLAYERS: ") b.WriteString(strconv.Itoa(l.Length())) } cmd.Respond(b.String()) return true }
// say implements the 'SAY' command, alias "'". Say sends a message to all // other responders at the current location. func (p *Player) say(cmd *command.Command) (handled bool) { if len(cmd.Nouns) == 0 { cmd.Respond("[RED]Was there anything in particular you wanted to say?") } else { message := strings.Join(cmd.Input[1:], ` `) cmd.Broadcast([]thing.Interface{cmd.Issuer}, "[CYAN]%s says: %s", cmd.Issuer.Name(), message) cmd.Respond("[YELLOW]You say: %s", message) } return true }
// drop removes an Item from the command issuer's inventory and puts it into // the inventory of the issuer's current location. For this to happen a few // conditions must be true: // // 1. Issuer must be at some sort of location // 2. Issuer must implement an inventory // 3. Inventory must contain the requested item // func (i *Item) drop(cmd *command.Command) (handled bool) { if m, ok := cmd.Issuer.(location.Locateable); ok { if inv, ok := cmd.Issuer.(inventory.Interface); ok { if inv.Contains(i) { inv.Remove(i) cmd.Respond("You drop %s.", i.Name()) cmd.Broadcast([]thing.Interface{cmd.Issuer}, "You see %s drop %s.", cmd.Issuer.Name(), i.Name()) m.Locate().Add(i) handled = true } } } else { cmd.Respond("You don't see anywhere to drop %s.", i.Name()) cmd.Broadcast([]thing.Interface{cmd.Issuer}, "You see %s try and drop %s.", cmd.Issuer.Name(), i.Name()) handled = true } return }
// parseStage2 is called by Parse to take advantage of defer unwinding. By // splitting the parsing we can easily obtain the locks we want and defer the // unlocking. This makes both Parse and parseStage2 very simple. func (p *Player) parseStage2(cmd *command.Command) (retry bool) { for _, l := range cmd.Locks { l.Lock() defer l.Unlock() } // If player moved before we locked we need to retry if !cmd.CanLock(p.Locate()) { return true } handled := p.Process(cmd) retry = cmd.LocksModified() if !handled && !retry { cmd.Respond("[RED]Eh?") } if !retry { cmd.Flush() } return }
// weigh estimates the weight of the specified item. func (i *Item) weigh(cmd *command.Command) (handled bool) { cmd.Respond("You estimate %s to weigh about %s.", i.Name(), i.weight) cmd.Broadcast([]thing.Interface{cmd.Issuer}, "You see %s estimate the weight of %s.", cmd.Issuer.Name(), i.Name()) return true }
// TODO: Implement junk command func (i *Item) junk(cmd *command.Command) (handled bool) { cmd.Respond("Junk not implemented yet.") return true }
// exits implements the 'EXITS' command. It displays the currently available // directional exits from the location. func (b *Basic) exits(cmd *command.Command) (handled bool) { cmd.Respond("%s", b.directionalExits) return true }
// sneeze implements the 'SNEEZE' command. // // TODO: Remove - for debugging responders and broadcasters func (p *Player) sneeze(cmd *command.Command) (handled bool) { cmd.Respond("You sneeze. Aaahhhccchhhooo!") cmd.Broadcast([]thing.Interface{p}, "You see %s sneeze.", cmd.Issuer.Name()) PlayerList.Broadcast(p.Locate().List(), "You hear a loud sneeze.") return true }
// examine describes the specific item. func (i *Item) examine(cmd *command.Command) (handled bool) { cmd.Respond("You examine %s. %s", i.Name(), i.Description()) cmd.Broadcast([]thing.Interface{cmd.Issuer}, "You see %s study %s.", cmd.Issuer.Name(), i.Name()) return true }
// cpustop implements the 'CPUSTOP' command, stops CPU profiling and writes the // profile to cpuprofile in the bin directory. // // TODO: Remove - for debugging only func (p *Player) cpustop(cmd *command.Command) (handled bool) { pprof.StopCPUProfile() cmd.Respond("CPU profile stopped") return true }