Working Multi-Season Storefront

Season 14+ have proper display assets
This commit is contained in:
eccentric 2023-12-03 02:02:19 +00:00
parent 5348295631
commit e57a2f23d6
7 changed files with 3647 additions and 93 deletions

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/ectrc/snow/aid" "github.com/ectrc/snow/aid"
"github.com/ectrc/snow/storage"
) )
type FortniteAPI struct { type FortniteAPI struct {
@ -86,6 +87,7 @@ type FAPI_Cosmetic struct {
type Set struct { type Set struct {
Items map[string]FAPI_Cosmetic `json:"items"` Items map[string]FAPI_Cosmetic `json:"items"`
Name string `json:"name"` Name string `json:"name"`
BackendName string `json:"backendName"`
} }
type CosmeticData struct { type CosmeticData struct {
@ -108,6 +110,44 @@ func (c *CosmeticData) GetRandomItem() FAPI_Cosmetic {
return c.GetRandomItem() return c.GetRandomItem()
} }
func (c *CosmeticData) GetRandomItemByType(itemType string) FAPI_Cosmetic {
randomInt := rand.Intn(len(c.Items))
i := 0
for _, item := range c.Items {
if item.Type.BackendValue != itemType {
continue
}
if i == randomInt {
return item
}
i++
}
return c.GetRandomItemByType(itemType)
}
func (c *CosmeticData) GetRandomItemByNotType(itemType string) FAPI_Cosmetic {
randomInt := rand.Intn(len(c.Items))
i := 0
for _, item := range c.Items {
if item.Type.BackendValue == itemType {
continue
}
if i == randomInt {
return item
}
i++
}
return c.GetRandomItemByNotType(itemType)
}
func (c *CosmeticData) GetRandomSet() Set { func (c *CosmeticData) GetRandomSet() Set {
randomInt := rand.Intn(len(c.Sets)) randomInt := rand.Intn(len(c.Sets))
@ -129,6 +169,7 @@ var (
Items: make(map[string]FAPI_Cosmetic), Items: make(map[string]FAPI_Cosmetic),
Sets: make(map[string]Set), Sets: make(map[string]Set),
} }
KnownDisplayAssets = make(map[string]bool)
) )
func NewFortniteAPI() *FortniteAPI { func NewFortniteAPI() *FortniteAPI {
@ -173,6 +214,8 @@ func (f *FortniteAPI) GetAllCosmetics() ([]FAPI_Cosmetic, error) {
} }
func PreloadCosmetics(max int) error { func PreloadCosmetics(max int) error {
aid.Print("Fortnite Assets from", "https://fortnite-api.com")
list, err := StaticAPI.GetAllCosmetics() list, err := StaticAPI.GetAllCosmetics()
if err != nil { if err != nil {
return err return err
@ -190,6 +233,7 @@ func PreloadCosmetics(max int) error {
Cosmetics.Sets[item.Set.BackendValue] = Set{ Cosmetics.Sets[item.Set.BackendValue] = Set{
Items: make(map[string]FAPI_Cosmetic), Items: make(map[string]FAPI_Cosmetic),
Name: item.Set.Value, Name: item.Set.Value,
BackendName: item.Set.BackendValue,
} }
} }
@ -225,7 +269,24 @@ func PreloadCosmetics(max int) error {
Cosmetics.Sets[character.Set.BackendValue].Items[characterId] = character Cosmetics.Sets[character.Set.BackendValue].Items[characterId] = character
} }
aid.Print("Could not find", len(notFound), "items with backpacks") if len(notFound) > 0 {
aid.Print("Couldn't find", len(notFound), "backpacks for characters:", notFound)
}
DAv2 := *storage.Asset("assets.json")
if DAv2 == nil {
aid.Print("Couldn't find DAv2.json")
}
var DAv2Data map[string]bool
err = json.Unmarshal(DAv2, &DAv2Data)
if err != nil {
return err
}
KnownDisplayAssets = DAv2Data
aid.Print("Preloaded", len(KnownDisplayAssets), "display assets")
return nil return nil
} }

View File

@ -1,7 +1,7 @@
package fortnite package fortnite
import ( import (
"sort" "strings"
"github.com/ectrc/snow/aid" "github.com/ectrc/snow/aid"
"github.com/ectrc/snow/person" "github.com/ectrc/snow/person"
@ -16,6 +16,7 @@ var (
"EFortRarity::Uncommon": 800, "EFortRarity::Uncommon": 800,
"EFortRarity::Common": 500, "EFortRarity::Common": 500,
} }
StaticCatalog = NewCatalog()
) )
func GetPriceForRarity(rarity string) int { func GetPriceForRarity(rarity string) int {
@ -80,33 +81,9 @@ func (s *Storefront) GenerateResponse(p *person.Person) aid.JSON {
"catalogEntries": []aid.JSON{}, "catalogEntries": []aid.JSON{},
} }
names := []string{}
for _, entry := range s.CatalogEntries { for _, entry := range s.CatalogEntries {
grantStrings := entry.Grants
sort.Strings(grantStrings)
for _, grant := range grantStrings {
entry.Name += grant + "-"
}
names = append(names, entry.Name)
}
aid.PrintJSON(names)
sort.Strings(names)
for _, devname := range names {
for _, entry := range s.CatalogEntries {
grantStrings := entry.Grants
sort.Strings(grantStrings)
for _, grant := range grantStrings {
entry.Name += grant + "-"
}
if devname == entry.Name {
json["catalogEntries"] = append(json["catalogEntries"].([]aid.JSON), entry.GenerateResponse(p)) json["catalogEntries"] = append(json["catalogEntries"].([]aid.JSON), entry.GenerateResponse(p))
} }
}
}
return json return json
} }
@ -120,6 +97,7 @@ type Entry struct {
Priority int Priority int
Grants []string Grants []string
DisplayAssetPath string DisplayAssetPath string
NewDisplayAssetPath string
Title string Title string
ShortDescription string ShortDescription string
} }
@ -145,7 +123,7 @@ func (e *Entry) AddMeta(key string, value interface{}) *Entry {
return e return e
} }
func (e *Entry) TileSize(size string) *Entry { func (e *Entry) SetTileSize(size string) *Entry {
e.Meta = append(e.Meta, aid.JSON{ e.Meta = append(e.Meta, aid.JSON{
"Key": "TileSize", "Key": "TileSize",
"Value": size, "Value": size,
@ -153,12 +131,19 @@ func (e *Entry) TileSize(size string) *Entry {
return e return e
} }
func (e *Entry) PanelType(panel string) *Entry { func (e *Entry) SetPanel(panel string) *Entry {
e.Panel = panel e.Panel = panel
return e return e
} }
func (e *Entry) Section(sectionId string) *Entry { func (e *Entry) SetSection(sectionId string) *Entry {
for _, m := range e.Meta {
if m["Key"] == "SectionId" {
m["Value"] = sectionId
return e
}
}
e.Meta = append(e.Meta, aid.JSON{ e.Meta = append(e.Meta, aid.JSON{
"Key": "SectionId", "Key": "SectionId",
"Value": sectionId, "Value": sectionId,
@ -166,8 +151,31 @@ func (e *Entry) Section(sectionId string) *Entry {
return e return e
} }
func (e *Entry) DisplayAsset(asset string) *Entry { func (e *Entry) SetDisplayAsset(asset string) *Entry {
e.DisplayAssetPath = asset displayAsset := "DAv2_Featured_" + asset
e.DisplayAssetPath = "/Game/Catalog/DisplayAssets/" + displayAsset + "." + displayAsset
return e
}
func (e *Entry) IsNewDisplayAssetValid(asset string) bool {
newDisplayAsset := "DAv2_" + strings.ReplaceAll(asset, "Athena_Commando_", "")
_, exists := KnownDisplayAssets[newDisplayAsset]
return exists
}
func (e *Entry) SetNewDisplayAsset(asset string) *Entry {
newDisplayAsset := "DAv2_" + strings.ReplaceAll(asset, "Athena_Commando_", "")
e.NewDisplayAssetPath = "/Game/Catalog/NewDisplayAssets/" + newDisplayAsset + "." + newDisplayAsset
return e
}
func (e *Entry) SetDisplayAssetPath(path string) *Entry {
e.DisplayAssetPath = strings.ReplaceAll(path, "FortniteGame/Content", "/Game")
return e
}
func (e *Entry) SetNewDisplayAssetPath(path string) *Entry {
e.NewDisplayAssetPath = path
return e return e
} }
@ -188,11 +196,23 @@ func (e *Entry) SetPrice(price int) *Entry {
func (e *Entry) GenerateResponse(p *person.Person) aid.JSON { func (e *Entry) GenerateResponse(p *person.Person) aid.JSON {
grantStrings := e.Grants grantStrings := e.Grants
sort.Strings(grantStrings)
for _, grant := range grantStrings { for _, grant := range grantStrings {
e.Name += grant + "-" e.Name += grant + "-"
} }
if e.NewDisplayAssetPath == "" && len(e.Grants) != 0 {
safeTemplateId := strings.ReplaceAll(strings.Split(e.Grants[0], ":")[1], "Athena_Commando_", "")
newDisplayAsset := "DAv2_" + safeTemplateId
e.NewDisplayAssetPath = "/Game/Catalog/NewDisplayAssets/" + newDisplayAsset + "." + newDisplayAsset
}
e.AddMeta("NewDisplayAssetPath", e.NewDisplayAssetPath)
if e.DisplayAssetPath == "" && len(e.Grants) != 0 {
displayAsset := "DA_Featured_" + strings.Split(e.Grants[0], ":")[1]
e.DisplayAssetPath = "/Game/Catalog/DisplayAssets/" + displayAsset + "." + displayAsset
}
e.AddMeta("DisplayAssetPath", e.DisplayAssetPath)
json := aid.JSON{ json := aid.JSON{
"offerId": e.ID, "offerId": e.ID,
"devName": e.Name, "devName": e.Name,
@ -210,24 +230,21 @@ func (e *Entry) GenerateResponse(p *person.Person) aid.JSON {
}, },
"categories": []string{}, "categories": []string{},
"catalogGroupPriority": 0, "catalogGroupPriority": 0,
"sortPriority": e.Priority,
"dailyLimit": -1, "dailyLimit": -1,
"weeklyLimit": -1, "weeklyLimit": -1,
"monthlyLimit": -1, "monthlyLimit": -1,
"fufillmentIds": []string{}, "fufillmentIds": []string{},
"filterWeight": e.Priority, "filterWeight": 0.0,
"appStoreId": []string{}, "appStoreId": []string{},
"refundable": false, "refundable": false,
"itemGrants": []aid.JSON{}, "itemGrants": []aid.JSON{},
"metaInfo": e.Meta, "metaInfo": e.Meta,
"meta": aid.JSON{}, "meta": aid.JSON{},
"displayAssetPath": e.DisplayAssetPath,
"title": e.Title, "title": e.Title,
"shortDescription": e.ShortDescription, "shortDescription": e.ShortDescription,
} }
if e.DisplayAssetPath != "" {
json["displayAssetPath"] = "/" + e.DisplayAssetPath
}
grants := []aid.JSON{} grants := []aid.JSON{}
requirements := []aid.JSON{} requirements := []aid.JSON{}
meta := []aid.JSON{} meta := []aid.JSON{}
@ -262,3 +279,101 @@ func (e *Entry) GenerateResponse(p *person.Person) aid.JSON {
return json return json
} }
func GenerateStorefront() {
storefront := NewCatalog()
daily := NewStorefront("BRDailyStorefront")
weekly := NewStorefront("BRWeeklyStorefront")
for i := 0; i < 4; i++ {
if aid.Config.Fortnite.Season < 14 {
break
}
item := Cosmetics.GetRandomItemByType("AthenaCharacter")
entry := NewCatalogEntry()
entry.SetSection("Daily")
if !entry.IsNewDisplayAssetValid(item.ID) {
i--
continue
}
entry.SetNewDisplayAsset(item.ID)
entry.SetDisplayAssetPath(item.DisplayAssetPath)
entry.SetPrice(GetPriceForRarity(item.Rarity.BackendValue))
entry.AddGrant(item.Type.BackendValue + ":" + item.ID)
entry.SetTileSize("Normal")
entry.Priority = 1
daily.Add(*entry)
}
for i := 0; i < 6; i++ {
item := Cosmetics.GetRandomItemByNotType("AthenaCharacter")
entry := NewCatalogEntry()
entry.SetSection("Daily")
if !entry.IsNewDisplayAssetValid(item.ID) {
i--
continue
}
entry.SetNewDisplayAsset(item.ID)
entry.SetDisplayAssetPath(item.DisplayAssetPath)
entry.SetPrice(GetPriceForRarity(item.Rarity.BackendValue))
entry.AddGrant(item.Type.BackendValue + ":" + item.ID)
entry.SetTileSize("Small")
daily.Add(*entry)
}
setsAdded := 0
for len(weekly.CatalogEntries) < 8 || setsAdded < 2 {
set := Cosmetics.GetRandomSet()
itemsAdded := 0
itemsToAdd := []*Entry{}
for _, item := range set.Items {
entry := NewCatalogEntry()
entry.SetSection("Featured")
entry.SetPanel(set.BackendName)
if !entry.IsNewDisplayAssetValid(item.ID) {
continue
}
if item.Type.BackendValue == "AthenaCharacter" {
entry.SetTileSize("Normal")
itemsAdded += 2
entry.Priority = 1
} else {
entry.SetTileSize("Small")
itemsAdded += 1
}
entry.SetNewDisplayAsset(item.ID)
entry.SetDisplayAssetPath(item.DisplayAssetPath)
entry.SetPrice(GetPriceForRarity(item.Rarity.BackendValue))
entry.AddGrant(item.Type.BackendValue + ":" + item.ID)
itemsToAdd = append(itemsToAdd, entry)
}
if itemsAdded % 2 != 0 {
itemsToAdd = itemsToAdd[:len(itemsToAdd)-1]
}
for _, entry := range itemsToAdd {
weekly.Add(*entry)
}
setsAdded++
}
storefront.Add(daily)
storefront.Add(weekly)
StaticCatalog = storefront
}

View File

@ -1,7 +1,6 @@
package handlers package handlers
import ( import (
"fmt"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -29,7 +28,6 @@ func GetLightswitchBulkStatus(c *fiber.Ctx) error {
func GetFortniteTimeline(c *fiber.Ctx) error { func GetFortniteTimeline(c *fiber.Ctx) error {
userAgent := c.Get("User-Agent") userAgent := c.Get("User-Agent")
fmt.Println(userAgent)
if !strings.Contains(userAgent, "++Fortnite") { if !strings.Contains(userAgent, "++Fortnite") {
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No User Agent")) return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No User Agent"))
} }

View File

@ -4,59 +4,16 @@ import (
"github.com/goccy/go-json" "github.com/goccy/go-json"
"github.com/ectrc/snow/aid" "github.com/ectrc/snow/aid"
"github.com/ectrc/snow/fortnite"
"github.com/ectrc/snow/person"
"github.com/ectrc/snow/storage" "github.com/ectrc/snow/storage"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func GetStorefrontCatalog(c *fiber.Ctx) error { func GetStorefrontCatalog(c *fiber.Ctx) error {
// person := c.Locals("person").(*person.Person) person := c.Locals("person").(*person.Person)
// storefront := fortnite.NewCatalog()
// daily := fortnite.NewStorefront("BRDailyStorefront") return c.Status(fiber.StatusOK).JSON(fortnite.StaticCatalog.GenerateFortniteCatalog(person))
// weekly := fortnite.NewStorefront("BRWeeklyStorefront")
// for len(weekly.CatalogEntries) < 8 {
// set := fortnite.Cosmetics.GetRandomSet()
// for _, cosmetic := range set.Items {
// if cosmetic.Type.BackendValue == "AthenaBackpack" {
// continue
// }
// entry := fortnite.NewCatalogEntry().Section("Featured").DisplayAsset(cosmetic.DisplayAssetPath).SetPrice(fortnite.GetPriceForRarity(cosmetic.Rarity.BackendValue))
// entry.AddGrant(cosmetic.Type.BackendValue + ":" + cosmetic.ID)
// if cosmetic.Backpack != "" {
// entry.AddGrant("AthenaBackpack:" + cosmetic.Backpack)
// }
// if cosmetic.Type.BackendValue != "AthenaCharacter" {
// entry.TileSize("Small")
// }
// if cosmetic.Type.BackendValue == "AthenaCharacter" {
// entry.TileSize("Normal")
// entry.Priority = -99999
// }
// entry.Panel = set.Name
// weekly.Add(*entry)
// }
// }
// storefront.Add(daily)
// storefront.Add(weekly)
// return c.Status(fiber.StatusOK).JSON(storefront.GenerateFortniteCatalog(person))
var x aid.JSON
err := json.Unmarshal(*storage.Asset("hide_a.json"), &x)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(aid.JSON{"error":err.Error()})
}
return c.Status(fiber.StatusOK).JSON(x)
} }
func GetStorefrontKeychain(c *fiber.Ctx) error { func GetStorefrontKeychain(c *fiber.Ctx) error {

View File

@ -29,6 +29,7 @@ func init() {
func init() { func init() {
fortnite.PreloadCosmetics(aid.Config.Fortnite.Season) fortnite.PreloadCosmetics(aid.Config.Fortnite.Season)
fortnite.GenerateStorefront()
if aid.Config.Database.DropAllTables { if aid.Config.Database.DropAllTables {
fortnite.NewFortnitePerson("ac", "1") fortnite.NewFortnitePerson("ac", "1")

View File

@ -1,7 +1,6 @@
package person package person
import ( import (
"fmt"
"strings" "strings"
"github.com/ectrc/snow/aid" "github.com/ectrc/snow/aid"
@ -150,7 +149,6 @@ func (l *Loadout) GetAttribute(attribute string) interface{} {
} }
} }
fmt.Println(attribute)
switch attribute { switch attribute {
case "locker_name": case "locker_name":

3424
storage/mem/assets.json Normal file

File diff suppressed because it is too large Load Diff