func (self *Session) Exec() { defer events.Unregister(self.pc) defer model.Logout(self.pc) self.WriteLine("Welcome, " + self.pc.GetName()) self.PrintRoom() // Main routine in charge of actually reading input from the connection object, // also has built in throttling to limit how fast we are allowed to process // commands from the user. go func() { defer func() { self.panicChannel <- recover() }() throttler := utils.NewThrottler(200 * time.Millisecond) for { mode := <-self.inputModeChannel prompter := <-self.prompterChannel input := "" switch mode { case CleanUserInput: input = utils.GetUserInputP(self.conn, prompter, self.user.GetColorMode()) case RawUserInput: input = utils.GetRawUserInputP(self.conn, prompter, self.user.GetColorMode()) default: panic("Unhandled case in switch statement (userInputMode)") } throttler.Sync() self.userInputChannel <- input } }() // Main loop for { input := self.getUserInputP(RawUserInput, self) if input == "" || input == "logout" || input == "quit" { return } if input == "." { input = self.lastInput } self.lastInput = input if strings.HasPrefix(input, "/") { self.handleCommand(utils.Argify(input[1:])) } else { self.handleAction(utils.Argify(input)) } } }
func manageSpawner(spawner types.Spawner) { throttler := utils.NewThrottler(5 * time.Second) go func() { for { rooms := model.GetAreaRooms(spawner.GetAreaId()) if len(rooms) > 0 { npcs := model.GetSpawnerNpcs(spawner.GetId()) diff := spawner.GetCount() - len(npcs) for diff > 0 && len(rooms) > 0 { room := rooms[utils.Random(0, len(rooms)-1)] npc := model.CreateNpc(spawner.GetName(), room.GetId(), spawner.GetId()) npc.SetHealth(spawner.GetHealth()) manageNpc(npc) diff-- } } throttler.Sync() } }() }
func init() { _listeners = map[EventReceiver]chan Event{} eventMessages = make(chan interface{}, 1) go func() { for message := range eventMessages { switch msg := message.(type) { case register: _listeners[msg.Receiver] = msg.Channel case unregister: delete(_listeners, msg.Receiver) case broadcast: for char, channel := range _listeners { if msg.Event.IsFor(char) { go func(c chan Event) { c <- msg.Event }(channel) } } default: panic("Unhandled event message") } } _listeners = nil }() go func() { throttler := utils.NewThrottler(1 * time.Second) for { throttler.Sync() Broadcast(TickEvent{}) } }() }
func init() { fights = map[types.Character]combatInfo{} combatMessages = make(chan interface{}, 1) go func() { defer func() { recover() }() throttler := utils.NewThrottler(combatInterval) for { throttler.Sync() combatMessages <- combatTick(true) } }() go func() { for message := range combatMessages { Switch: switch m := message.(type) { case combatTick: for a, info := range fights { d := info.Defender if a.GetRoomId() == d.GetRoomId() { var power int skill := info.Skill if skill == nil { power = utils.Random(1, 10) } else { power = skill.GetPower() variance := utils.Random(-skill.GetVariance(), skill.GetVariance()) power += variance } d.Hit(power) events.Broadcast(events.CombatEvent{Attacker: a, Defender: d, Skill: skill, Power: power}) if d.GetHitPoints() <= 0 { Kill(d) } } else { doCombatStop(a) } } case combatStart: oldInfo, found := fights[m.Attacker] if m.Defender == oldInfo.Defender { break } if found { doCombatStop(m.Attacker) } fights[m.Attacker] = combatInfo{ Defender: m.Defender, Skill: m.Skill, } events.Broadcast(events.CombatStartEvent{Attacker: m.Attacker, Defender: m.Defender}) case combatStop: doCombatStop(m.Attacker) case combatQuery: _, found := fights[m.Character] if found { m.Ret <- true } else { for _, info := range fights { if info.Defender == m.Character { m.Ret <- true break Switch } } m.Ret <- false } default: panic("Unhandled combat message") } } }() }