package routes import ( "dk/internal/actions" "dk/internal/auth" "dk/internal/helpers" "dk/internal/items" "dk/internal/middleware" "dk/internal/router" "dk/internal/template/components" "dk/internal/towns" "dk/internal/users" "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 = `
` + flash.Message + "
" } 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.Set("Gold", user.Gold-town.InnCost) user.Set("HP", user.MaxHP) user.Set("MP", user.MaxMP) user.Set("TP", user.MaxTP) user.Save() 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 = `
` + flash.Message + "
" } 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.Set("Gold", 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 = `
` + flash.Message + "
" } 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.Set("Gold", user.Gold-mapped.MapCost) if user.Towns == "" { user.Set("Towns", params[0]) } else { user.Set("Towns", user.Towns+","+params[0]) } user.Save() ctx.Redirect("/town/maps", 302) }