package personal_world import ( "net/url" "gno.land/p/jeronimoalbi/pager" "gno.land/p/nt/ufmt" "gno.land/r/akkadia/admin" ) // Render handles RESTful routing and returns Markdown responses func Render(iUrl string) string { u, err := url.Parse(iUrl) if err != nil { return "404\n" } query := u.Query() switch u.Path { case "": return renderHome() case "worlds": owner := query.Get("owner") if owner != "" { return renderWorldsByOwner(iUrl, owner) } return renderWorldsList(iUrl) case "biomes": return renderBiomes() case "sizes": return renderSizes() default: return renderError("Not found") } } // renderHome renders the home page func renderHome() string { output := `# Personal World Welcome to the Personal World system on Akkadia. ## What is Personal World? Personal World is a decentralized world creation and management system where users can: * Create and customize their own worlds * Manage world editors and permissions * Expand world sizes dynamically * Set custom world types and properties ## Getting Started 1. **Create Your First World**: Your first default-type world is **free**! 2. **Customize**: Set name, slug and visibility 3. **Manage**: Add editors, expand size, update properties 4. **Explore**: Browse all worlds and discover unique creations ## Config ` output += ufmt.Sprintf("* **Default Biome**: %s\n", defaultBiome) output += ufmt.Sprintf("* **Fee Collector BPS**: %d (%d.%02d%%)\n", feeCollectorBPS, feeCollectorBPS/100, feeCollectorBPS%100) output += ufmt.Sprintf("* **List Limit**: %d\n", listLimit) output += ufmt.Sprintf("* **Batch Limit**: %d\n", batchLimit) output += ` ## Stats ` output += ufmt.Sprintf("* **Total Worlds**: %d\n", worlds.Size()) output += ` ## Quick Links * [Browse All Worlds](/r/akkadia/personal_world:worlds) * [View Biomes](/r/akkadia/personal_world:biomes) * [View Sizes](/r/akkadia/personal_world:sizes) ## Search by Owner ` return output } // renderBiomes renders the biomes page func renderBiomes() string { output := `# Biomes [← Home](/r/akkadia/personal_world:) The system supports multiple biomes with different creation costs. ## How Pricing Works * **cost**: The base cost to create a world with this biome * **priceMultiplier**: Multiplier applied to world expansion costs * Example: If expansion base cost is 1000 ugnot and priceMultiplier is 1.5, actual cost = 1500 ugnot --- ` biomeInfos.Iterate("", "", func(key string, value interface{}) bool { biome := value.(map[string]string) output += ufmt.Sprintf("### %s\n\n", biome["name"]) for k, v := range biome { if k == "name" { if v == defaultBiome { output += ufmt.Sprintf("* **%s**: %s (default)\n", k, v) } else { output += ufmt.Sprintf("* **%s**: %s\n", k, v) } } else if k == "cost" { output += ufmt.Sprintf("* **%s**: %s ugnot\n", k, v) } else { output += ufmt.Sprintf("* **%s**: %s\n", k, v) } } output += "\n---\n\n" return false }) return output } // renderSizes renders the sizes page func renderSizes() string { output := `# World Sizes [← Home](/r/akkadia/personal_world:) Worlds can be expanded to larger sizes. Each expansion has a base cost. ## How Expansion Works * **size**: The world dimension (size x size blocks) * **cost**: Base cost to expand to this size level * Actual expansion cost = base cost × biome priceMultiplier * New worlds start at size level 0 --- ` sizeInfos.Iterate("", "", func(key string, value interface{}) bool { size := value.(map[string]string) output += ufmt.Sprintf("### Level %s\n\n", size["id"]) output += ufmt.Sprintf("* **Size**: %s × %s blocks\n", size["size"], size["size"]) output += ufmt.Sprintf("* **Base Cost**: %s ugnot\n", size["cost"]) output += "\n---\n\n" return false }) return output } // renderWorldsList renders a list of all worlds with pagination func renderWorldsList(iUrl string) string { output := `# All Worlds [← Home](/r/akkadia/personal_world:) ` if worlds.Size() == 0 { output += "*No worlds created yet.*\n" return output } pages, err := pager.New(iUrl, worlds.Size(), pager.WithPageSize(10)) if err != nil { return renderError("Invalid page") } // Get current page number for back links currentPage := (pages.Offset() / pages.PageSize()) + 1 worlds.ReverseIterateByOffset(pages.Offset(), pages.PageSize(), func(key string, value interface{}) bool { world := value.(map[string]string) output += renderWorldItem(world, currentPage) return false }) if pages.HasPages() { output += pager.Picker(pages) } return output } // renderWorldsByOwner renders worlds owned by a specific address with pagination func renderWorldsByOwner(iUrl string, owner string) string { u, _ := url.Parse(iUrl) page := u.Query().Get("page") output := ufmt.Sprintf("# Personal Worlds by %s\n\n", owner) if page != "" { output += ufmt.Sprintf("[← Back to List](/r/akkadia/personal_world:worlds?page=%s)\n\n", page) } else { output += "[← Home](/r/akkadia/personal_world:)\n\n" } // Collect worlds owned by the specified owner var ownerWorlds []map[string]string worlds.Iterate("", "", func(key string, value interface{}) bool { world := value.(map[string]string) if world["owner"] == owner { ownerWorlds = append(ownerWorlds, world) } return false }) if len(ownerWorlds) == 0 { output += "*No worlds found for this owner.*\n" return output } pages, err := pager.New(iUrl, len(ownerWorlds), pager.WithPageSize(10)) if err != nil { return renderError("Invalid page") } // Render paginated slice (reverse order - newest first) start := len(ownerWorlds) - pages.Offset() - 1 end := start - pages.PageSize() if end < -1 { end = -1 } for i := start; i > end; i-- { output += renderWorldItem(ownerWorlds[i], 0) } if pages.HasPages() { output += pager.Picker(pages) } return output } // renderWorldItem renders a single world item func renderWorldItem(world map[string]string, page int) string { output := "" output += ufmt.Sprintf("* **ID**: %s\n", world["id"]) output += ufmt.Sprintf("* **Name**: %s\n", world["name"]) output += ufmt.Sprintf("* **Owner**: %s [[View on Explorer](%s/m/explorer/player?address=%s)] [[Worlds by Owner](/r/akkadia/personal_world:worlds?owner=%s&page=%d)]\n", world["owner"], admin.GetExplorerURL(), world["owner"], world["owner"], page) output += ufmt.Sprintf("* **Biome**: %s\n", world["biome"]) output += ufmt.Sprintf("* **Size**: %s\n", world["size"]) output += ufmt.Sprintf("* **Slug**: `%s` [[View on Explorer](%s/m/explorer/community-realm?slug=%s)]\n", world["slug"], admin.GetExplorerURL(), world["slug"]) output += "\n---\n\n" return output } // renderError renders an error page func renderError(message string) string { output := "# Error\n\n" output += ufmt.Sprintf("> %s\n\n", message) output += "[← Back to Home](/r/akkadia/personal_world:)\n" return output }