340 lines
9.9 KiB
Go
340 lines
9.9 KiB
Go
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/google/uuid"
|
|
"github.com/iliadenisov/galaxy/internal/controller"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/gin-gonic/gin/binding"
|
|
"github.com/iliadenisov/galaxy/internal/model/rest"
|
|
)
|
|
|
|
func CommandHandler(c *gin.Context, executor CommandExecutor) {
|
|
var cmd rest.Command
|
|
if errorResponded(c, c.ShouldBindJSON(&cmd)) {
|
|
return
|
|
}
|
|
|
|
commands := make([]Command, 0)
|
|
for i := range cmd.Commands {
|
|
command, err := parseCommand(cmd.Actor, cmd.Commands[i])
|
|
if errorResponded(c, err) {
|
|
return
|
|
}
|
|
commands = append(commands, command)
|
|
}
|
|
if len(commands) == 0 {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "no commands given"})
|
|
return
|
|
}
|
|
|
|
if errorResponded(c, executor.Execute(commands...)) {
|
|
return
|
|
}
|
|
|
|
c.Status(http.StatusNoContent)
|
|
}
|
|
|
|
func parseCommand(actor string, c json.RawMessage) (Command, error) {
|
|
meta := new(rest.CommandMeta)
|
|
if err := json.Unmarshal(c, meta); err != nil {
|
|
return nil, err
|
|
}
|
|
switch t := meta.Type; t {
|
|
case rest.CommandTypeRaceQuit:
|
|
return commandRaceQuit(actor)
|
|
case rest.CommandTypeRaceVote:
|
|
return commandRaceVote(actor, c)
|
|
case rest.CommandTypeRaceRelation:
|
|
return commandRaceRelation(actor, c)
|
|
case rest.CommandTypeShipClassCreate:
|
|
return commandShipClassCreate(actor, c)
|
|
case rest.CommandTypeShipClassMerge:
|
|
return commandShipClassMerge(actor, c)
|
|
case rest.CommandTypeShipClassRemove:
|
|
return commandShipClassRemove(actor, c)
|
|
case rest.CommandTypeShipGroupBreak:
|
|
return commandShipGroupBreak(actor, c)
|
|
case rest.CommandTypeShipGroupLoad:
|
|
return commandShipGroupLoad(actor, c)
|
|
case rest.CommandTypeShipGroupUnload:
|
|
return commandShipGroupUnload(actor, c)
|
|
case rest.CommandTypeShipGroupSend:
|
|
return commandShipGroupSend(actor, c)
|
|
case rest.CommandTypeShipGroupUpgrade:
|
|
return commandShipGroupUpgrade(actor, c)
|
|
case rest.CommandTypeShipGroupMerge:
|
|
return commandShipGroupMerge(actor, c)
|
|
case rest.CommandTypeShipGroupDismantle:
|
|
return commandShipGroupDismantle(actor, c)
|
|
case rest.CommandTypeShipGroupTransfer:
|
|
return commandShipGroupTransfer(actor, c)
|
|
case rest.CommandTypeShipGroupJoinFleet:
|
|
return commandShipGroupJoinFleet(actor, c)
|
|
case rest.CommandTypeFleetMerge:
|
|
return commandFleetMerge(actor, c)
|
|
case rest.CommandTypeFleetSend:
|
|
return commandFleetSend(actor, c)
|
|
case rest.CommandTypeScienceCreate:
|
|
return commandScienceCreate(actor, c)
|
|
case rest.CommandTypeScienceRemove:
|
|
return commandScienceRemove(actor, c)
|
|
case rest.CommandTypePlanetRename:
|
|
return commandPlanetRename(actor, c)
|
|
case rest.CommandTypePlanetProduce:
|
|
return commandPlanetProduce(actor, c)
|
|
case rest.CommandTypePlanetRouteSet:
|
|
return commandPlanetRouteSet(actor, c)
|
|
case rest.CommandTypePlanetRouteRemove:
|
|
return commandPlanetRouteRemove(actor, c)
|
|
default:
|
|
return nil, fmt.Errorf("unknown comman type: %s", t)
|
|
}
|
|
}
|
|
|
|
func commandRaceQuit(actor string) (Command, error) {
|
|
return func(c controller.Ctrl) error { return c.RaceQuit(actor) }, nil
|
|
}
|
|
|
|
func commandRaceVote(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandRaceVote)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.RaceVote(actor, v.Acceptor)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandRaceRelation(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandRaceRelation)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.RaceRelation(actor, v.Acceptor, v.Relation)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipClassCreate(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipClassCreate)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipClassCreate(actor, v.Name, v.Drive, int(v.Armament), v.Weapons, v.Shields, v.Cargo)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipClassMerge(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipClassMerge)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipClassMerge(actor, v.Name, v.Target)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipClassRemove(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipClassRemove)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipClassRemove(actor, v.Name)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupBreak(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupBreak)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupBreak(actor, uuid.MustParse(v.ID), uuid.MustParse(v.NewID), uint(v.Quantity))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupLoad(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupLoad)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupLoad(actor, uuid.MustParse(v.ID), v.Cargo, v.Quantity)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupUnload(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupUnload)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupUnload(actor, uuid.MustParse(v.ID), v.Quantity)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupSend(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupSend)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupSend(actor, uuid.MustParse(v.ID), uint(v.Destination))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupUpgrade(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupUpgrade)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupUpgrade(actor, uuid.MustParse(v.ID), v.Tech, v.Level)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupMerge(actor string, c json.RawMessage) (Command, error) {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupMerge(actor)
|
|
}, nil
|
|
}
|
|
|
|
func commandShipGroupDismantle(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupDismantle)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupDismantle(actor, uuid.MustParse(v.ID))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupTransfer(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupTransfer)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupTransfer(actor, v.Acceptor, uuid.MustParse(v.ID))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandShipGroupJoinFleet(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandShipGroupJoinFleet)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ShipGroupJoinFleet(actor, v.Name, uuid.MustParse(v.ID))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandFleetMerge(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandFleetMerge)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.FleetMerge(actor, v.Name, v.Target)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandFleetSend(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandFleetSend)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.FleetSend(actor, v.Name, uint(v.Destination))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandScienceCreate(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandScienceCreate)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ScienceCreate(actor, v.Name, v.Drive, v.Weapons, v.Shields, v.Cargo)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandScienceRemove(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandScienceRemove)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.ScienceRemove(actor, v.Name)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandPlanetRename(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandPlanetRename)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.PlanetRename(actor, v.Number, v.Name)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandPlanetProduce(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandPlanetProduce)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.PlanetProduce(actor, v.Number, v.Production, v.Subject)
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandPlanetRouteSet(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandPlanetRouteSet)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.PlanetRouteSet(actor, v.LoadType, uint(v.Origin), uint(v.Destination))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
func commandPlanetRouteRemove(actor string, c json.RawMessage) (Command, error) {
|
|
if v, err := unmarshallCommand(c, new(rest.CommandPlanetRouteRemove)); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return func(c controller.Ctrl) error {
|
|
return c.PlanetRouteRemove(actor, v.LoadType, uint(v.Origin))
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
// Helpers
|
|
|
|
func unmarshallCommand[T rest.DecodableCommand](c json.RawMessage, v *T) (*T, error) {
|
|
if err := json.Unmarshal(c, v); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := validateCommand(v); err != nil {
|
|
return nil, err
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
func validateCommand(v any) error {
|
|
if ve, ok := binding.Validator.Engine().(*validator.Validate); ok {
|
|
if err := ve.Struct(v); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|