243 lines
4.6 KiB
Go
243 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type command interface {
|
|
run(context.Context)
|
|
}
|
|
|
|
type commandHandler struct {
|
|
commandChan chan command
|
|
}
|
|
|
|
func newCommandHandler() *commandHandler {
|
|
return &commandHandler{
|
|
commandChan: make(chan command, 50),
|
|
}
|
|
}
|
|
|
|
func (h *commandHandler) handle(c command) {
|
|
h.commandChan <- c
|
|
}
|
|
|
|
func (h *commandHandler) run(ctx context.Context) {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case c := <-h.commandChan: // TODO if close ??
|
|
c.run(ctx)
|
|
}
|
|
}
|
|
}
|
|
|
|
type joinCommand struct {
|
|
name string
|
|
}
|
|
|
|
func (c *joinCommand) run(ctx context.Context) {
|
|
db := getDB(ctx)
|
|
log := getLogger(ctx)
|
|
pb := getDPlayersBoard(ctx)
|
|
ms := getMessageStorage(ctx)
|
|
|
|
err := ms.apply(ctx, fmt.Sprintf("join:%s", c.name), time.Minute/2, func(d interface{}) (string, interface{}) {
|
|
if v, _ := d.(bool); v {
|
|
return fmt.Sprintf("%s подключился снова", c.name), true
|
|
}
|
|
|
|
return fmt.Sprintf("%s подключился", c.name), true
|
|
})
|
|
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
p, err := db.getPlayerByName(ctx, c.name)
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
|
|
if p == nil {
|
|
p, err = db.createPlayer(ctx, c.name, time.Now())
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
} else {
|
|
err = db.updatePlayerLastLogin(ctx, p.id, time.Now())
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
pb.getPlayerBoard(p.id).setOnline(true)
|
|
|
|
err = pb.update(ctx, achievementVeryLongOnline)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
type quitCommand struct {
|
|
name string
|
|
}
|
|
|
|
func (c *quitCommand) run(ctx context.Context) {
|
|
db := getDB(ctx)
|
|
log := getLogger(ctx)
|
|
pb := getDPlayersBoard(ctx)
|
|
ms := getMessageStorage(ctx)
|
|
|
|
err := ms.apply(ctx, fmt.Sprintf("quit:%s", c.name), time.Minute/2, func(d interface{}) (string, interface{}) {
|
|
if v, _ := d.(bool); v {
|
|
return fmt.Sprintf("%s отключился снова", c.name), true
|
|
}
|
|
|
|
return fmt.Sprintf("%s отключился", c.name), true
|
|
})
|
|
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
p, err := db.getPlayerByName(ctx, c.name)
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
|
|
err = db.updatePlayerLastLogout(ctx, p.id, time.Now())
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
err = db.increasePlayerOnlineDuration(ctx, p.id, time.Since(p.lastLogin))
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
pb.getPlayerBoard(p.id).setOnline(false)
|
|
|
|
err = pb.update(ctx, achievementVeryLongOnline)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
type deathCommand struct {
|
|
name string
|
|
deathType string
|
|
}
|
|
|
|
func (c *deathCommand) run(ctx context.Context) {
|
|
db := getDB(ctx)
|
|
log := getLogger(ctx)
|
|
pb := getDPlayersBoard(ctx)
|
|
ms := getMessageStorage(ctx)
|
|
|
|
err := ms.apply(ctx, fmt.Sprintf("death:%s", c.name), time.Minute/2, func(d interface{}) (string, interface{}) {
|
|
if v, _ := d.(bool); v {
|
|
return fmt.Sprintf("%s умудрился опять помереть от %s", c.name, c.deathType), true
|
|
}
|
|
|
|
return fmt.Sprintf("%s пал смертью храбрых от %s", c.name, c.deathType), true
|
|
})
|
|
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
p, err := db.getPlayerByName(ctx, c.name)
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
|
|
err = db.increasePlayerDeath(ctx, p.id, 1)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
err = pb.update(ctx, achievementDeathless, achievementBestFeeder)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
type killCommand struct {
|
|
name string
|
|
entity string
|
|
}
|
|
|
|
func (c *killCommand) run(ctx context.Context) {
|
|
db := getDB(ctx)
|
|
log := getLogger(ctx)
|
|
pb := getDPlayersBoard(ctx)
|
|
ms := getMessageStorage(ctx)
|
|
|
|
p, err := db.getPlayerByName(ctx, c.name)
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
|
|
err = db.increasePlayerEntryKills(ctx, p.id, c.entity, 1)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
f := func(d interface{}) (string, interface{}) {
|
|
if fragsNum, ok := d.(int); ok {
|
|
fragsNum++
|
|
|
|
return fmt.Sprintf("%s убил %s ✗ *%d*", p.name, c.entity, fragsNum), fragsNum
|
|
}
|
|
|
|
return fmt.Sprintf("%s убил %s", p.name, c.entity), 1
|
|
}
|
|
|
|
err = ms.apply(ctx, fmt.Sprintf("kill:%s:%s", p.id, c.entity), time.Minute/2, f)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
err = pb.update(ctx, achievementMaxFrags, achievementPeaceable)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
type changeLevelCommand struct {
|
|
name string
|
|
newLevel int
|
|
}
|
|
|
|
func (c *changeLevelCommand) run(ctx context.Context) {
|
|
db := getDB(ctx)
|
|
log := getLogger(ctx)
|
|
pb := getDPlayersBoard(ctx)
|
|
|
|
p, err := db.getPlayerByName(ctx, c.name)
|
|
if err != nil {
|
|
log.Error(err)
|
|
return
|
|
}
|
|
|
|
err = db.updatePlayerLevel(ctx, p.id, c.newLevel)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
err = pb.update(ctx, achievementMaxLevel)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|