220 lines
5.3 KiB
Go

package routes
import (
"dk/internal/actions"
"dk/internal/auth"
"dk/internal/helpers"
"dk/internal/middleware"
"dk/internal/models/items"
"dk/internal/models/towns"
"dk/internal/models/users"
"dk/internal/router"
"dk/internal/template/components"
"slices"
"strconv"
)
// Map acts as a representation of owned/unowned maps in the town stores.
type Map struct {
ID int
Name string
Cost int
Owned bool
X int
Y int
TP int
}
func RegisterTownRoutes(r *router.Router) {
group := r.Group("/town")
group.Use(middleware.RequireAuth())
group.Use(middleware.RequireTown())
group.Get("/", showTown)
group.Get("/inn", showInn)
group.WithMiddleware(middleware.CSRF(auth.Manager)).Post("/inn", rest)
group.Get("/shop", showShop)
group.Get("/shop/buy/:id", buyItem)
group.Get("/maps", showMaps)
group.Get("/maps/buy/:id", buyMap)
}
func showTown(ctx router.Ctx, _ []string) {
town := ctx.UserValue("town").(*towns.Town)
components.RenderPage(ctx, town.Name, "town/town.html", map[string]any{
"town": town,
"newscontent": components.GenerateTownNews(),
"whosonline": components.GenerateTownWhosOnline(),
})
}
func showInn(ctx router.Ctx, _ []string) {
var errorHTML string
if flash := auth.GetFlashMessage(ctx); flash != nil {
errorHTML = `<div style="color: red; margin-bottom: 1rem;">` + flash.Message + "</div>"
}
town := ctx.UserValue("town").(*towns.Town)
components.RenderPage(ctx, town.Name+" Inn", "town/inn.html", map[string]any{
"town": town,
"rested": false,
"error_message": errorHTML,
})
}
func rest(ctx router.Ctx, _ []string) {
town := ctx.UserValue("town").(*towns.Town)
user := ctx.UserValue("user").(*users.User)
if user.Gold < town.InnCost {
auth.SetFlashMessage(ctx, "error", "You can't afford to stay here tonight.")
ctx.Redirect("/town/inn", 303)
return
}
user.Gold -= town.InnCost
user.HP, user.MP, user.TP = user.MaxHP, user.MaxMP, user.MaxTP
components.RenderPage(ctx, town.Name+" Inn", "town/inn.html", map[string]any{
"town": town,
"rested": true,
})
}
func showShop(ctx router.Ctx, _ []string) {
var errorHTML string
if flash := auth.GetFlashMessage(ctx); flash != nil {
errorHTML = `<div style="color: red; margin-bottom: 1rem;">` + flash.Message + "</div>"
}
town := ctx.UserValue("town").(*towns.Town)
var itemlist []*items.Item
if town.ShopList != "" {
itemMap := helpers.NewOrderedMap[int, *items.Item]()
for _, id := range town.GetShopItems() {
if item, err := items.Find(id); err == nil {
itemMap.Set(id, item)
}
}
itemlist = itemMap.ToSlice()
}
components.RenderPage(ctx, town.Name+" Shop", "town/shop.html", map[string]any{
"town": town,
"itemlist": itemlist,
"error_message": errorHTML,
})
}
func buyItem(ctx router.Ctx, params []string) {
id, err := strconv.Atoi(params[0])
if err != nil {
auth.SetFlashMessage(ctx, "error", "Error purchasing item; "+err.Error())
ctx.Redirect("/town/shop", 302)
return
}
town := ctx.UserValue("town").(*towns.Town)
if !slices.Contains(town.GetShopItems(), id) {
auth.SetFlashMessage(ctx, "error", "The item doesn't exist in this shop.")
ctx.Redirect("/town/shop", 302)
return
}
item, err := items.Find(id)
if err != nil {
auth.SetFlashMessage(ctx, "error", "Error purchasing item; "+err.Error())
ctx.Redirect("/town/shop", 302)
return
}
user := ctx.UserValue("user").(*users.User)
if user.Gold < item.Value {
auth.SetFlashMessage(ctx, "error", "You don't have enough gold to buy "+item.Name)
ctx.Redirect("/town/shop", 302)
return
}
user.Gold -= item.Value
actions.UserEquipItem(user, item)
user.Save()
ctx.Redirect("/town/shop", 302)
}
func showMaps(ctx router.Ctx, _ []string) {
var errorHTML string
if flash := auth.GetFlashMessage(ctx); flash != nil {
errorHTML = `<div style="color: red; margin-bottom: 1rem;">` + flash.Message + "</div>"
}
town := ctx.UserValue("town").(*towns.Town)
user := ctx.UserValue("user").(*users.User)
maplist := helpers.NewOrderedMap[int, Map]()
towns, _ := towns.All()
var mapped []int
if user.Towns != "" {
mapped = user.GetTownIDs()
}
for _, town := range towns {
var owned bool
if mapped != nil && slices.Contains(mapped, town.ID) {
owned = true
} else {
owned = false
}
maplist.Set(town.ID, Map{
ID: town.ID,
Name: town.Name,
Cost: town.MapCost,
Owned: owned,
X: town.X,
Y: town.Y,
TP: town.TPCost,
})
}
components.RenderPage(ctx, town.Name+" Maps", "town/maps.html", map[string]any{
"town": town,
"maplist": maplist.ToSlice(),
"error_message": errorHTML,
})
}
func buyMap(ctx router.Ctx, params []string) {
id, err := strconv.Atoi(params[0])
if err != nil {
auth.SetFlashMessage(ctx, "error", "Error purchasing map; "+err.Error())
ctx.Redirect("/town/maps", 302)
return
}
mapped, err := towns.Find(id)
if err != nil {
auth.SetFlashMessage(ctx, "error", "Error purchasing map; "+err.Error())
ctx.Redirect("/town/maps", 302)
return
}
user := ctx.UserValue("user").(*users.User)
if user.Gold < mapped.MapCost {
auth.SetFlashMessage(ctx, "error", "You don't have enough gold to buy the map to "+mapped.Name)
ctx.Redirect("/town/maps", 302)
return
}
user.Gold -= mapped.MapCost
if user.Towns == "" {
user.Towns = params[0]
} else {
user.Towns += "," + params[0]
}
user.Save()
ctx.Redirect("/town/maps", 302)
}