package routes import ( "dk/internal/actions" "dk/internal/auth" "dk/internal/components" "dk/internal/helpers" "dk/internal/middleware" "dk/internal/models/items" "dk/internal/models/towns" "dk/internal/models/users" "dk/internal/router" "dk/internal/session" "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(auth.RequireAuth()) group.Use(middleware.RequireTown()) group.Get("/", showTown) group.Get("/inn", showInn) group.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) { sess := ctx.UserValue("session").(*session.Session) var errorHTML string if flash, exists := sess.GetFlash("error"); exists { if msg, ok := flash.(string); ok { errorHTML = `
` + msg + "
" } } 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) { sess := ctx.UserValue("session").(*session.Session) town := ctx.UserValue("town").(*towns.Town) user := ctx.UserValue("user").(*users.User) if user.Gold < town.InnCost { sess.SetFlash("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) { sess := ctx.UserValue("session").(*session.Session) var errorHTML string if flash, exists := sess.GetFlash("error"); exists { if msg, ok := flash.(string); ok { errorHTML = `
` + msg + "
" } } 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) { sess := ctx.UserValue("session").(*session.Session) id, err := strconv.Atoi(params[0]) if err != nil { sess.SetFlash("error", "Error purchasing item; "+err.Error()) ctx.Redirect("/town/shop", 302) return } town := ctx.UserValue("town").(*towns.Town) if !slices.Contains(town.GetShopItems(), id) { sess.SetFlash("error", "The item doesn't exist in this shop.") ctx.Redirect("/town/shop", 302) return } item, err := items.Find(id) if err != nil { sess.SetFlash("error", "Error purchasing item; "+err.Error()) ctx.Redirect("/town/shop", 302) return } user := ctx.UserValue("user").(*users.User) if user.Gold < item.Value { sess.SetFlash("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) { sess := ctx.UserValue("session").(*session.Session) var errorHTML string if flash, exists := sess.GetFlash("error"); exists { if msg, ok := flash.(string); ok { errorHTML = `
` + msg + "
" } } 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) { sess := ctx.UserValue("session").(*session.Session) id, err := strconv.Atoi(params[0]) if err != nil { sess.SetFlash("error", "Error purchasing map; "+err.Error()) ctx.Redirect("/town/maps", 302) return } mapped, err := towns.Find(id) if err != nil { sess.SetFlash("error", "Error purchasing map; "+err.Error()) ctx.Redirect("/town/maps", 302) return } user := ctx.UserValue("user").(*users.User) if user.Gold < mapped.MapCost { sess.SetFlash("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) }