Finish Loadouts on newer seasons; Add every item in the game.

This commit is contained in:
eccentric 2023-11-20 23:20:42 +00:00
parent 5508ad4348
commit f1d99b23c7
9 changed files with 226 additions and 53 deletions

View File

@ -27,6 +27,7 @@ type CS struct {
Fortnite struct {
Season int
Build float64
Everything bool
}
}
@ -104,4 +105,5 @@ func LoadConfig() {
}
Config.Fortnite.Season = parsedSeason
Config.Fortnite.Everything = cfg.Section("fortnite").Key("everything").MustBool(false)
}

View File

@ -27,3 +27,5 @@ secret="secret"
[fortnite]
; used for account creation + lobby
build=5.41
; own every cosmetic in the game. this applies to all accounts
everything=true

View File

@ -17,8 +17,11 @@ var (
"QueryProfile": PostQueryProfileAction,
"ClientQuestLogin": PostQueryProfileAction,
"MarkItemSeen": PostMarkItemSeenAction,
"SetItemFavoriteStatusBatch": PostSetItemFavoriteStatusBatchAction,
"EquipBattleRoyaleCustomization": PostEquipBattleRoyaleCustomizationAction,
"SetBattleRoyaleBanner": PostSetBattleRoyaleBannerAction,
"SetCosmeticLockerSlot": PostSetCosmeticLockerSlotAction,
"SetCosmeticLockerBanner": PostSetCosmeticLockerBannerAction,
}
)
@ -178,3 +181,133 @@ func PostSetBattleRoyaleBannerAction(c *fiber.Ctx, person *p.Person, profile *p.
}()
return nil
}
func PostSetItemFavoriteStatusBatchAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
var body struct {
ItemIds []string `json:"itemIds" binding:"required"`
Favorite []bool `json:"itemFavStatus" binding:"required"`
}
err := c.BodyParser(&body)
if err != nil {
return fmt.Errorf("invalid Body")
}
for i, itemId := range body.ItemIds {
item := profile.Items.GetItem(itemId)
if item == nil {
continue
}
item.Favorite = body.Favorite[i]
go item.Save()
}
return nil
}
func PostSetCosmeticLockerSlotAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
var body struct {
Category string `json:"category" binding:"required"` // item type e.g. Character
ItemToSlot string `json:"itemToSlot" binding:"required"` // template id
LockerItem string `json:"lockerItem" binding:"required"` // locker id
SlotIndex int `json:"slotIndex" binding:"required"` // index of slot
VariantUpdates []aid.JSON `json:"variantUpdates" binding:"required"` // variant updates
}
err := c.BodyParser(&body)
if err != nil {
return fmt.Errorf("invalid Body")
}
item := profile.Items.GetItemByTemplateID(body.ItemToSlot)
if item == nil {
if body.ItemToSlot != "" && !strings.Contains(strings.ToLower(body.ItemToSlot), "random") {
return fmt.Errorf("item not found")
}
item = &p.Item{
ID: body.ItemToSlot,
}
}
currentLocker := profile.Loadouts.GetLoadout(body.LockerItem)
if currentLocker == nil {
return fmt.Errorf("current locker not found")
}
switch body.Category {
case "Character":
currentLocker.CharacterID = item.ID
case "Backpack":
currentLocker.BackpackID = item.ID
case "Pickaxe":
currentLocker.PickaxeID = item.ID
case "Glider":
currentLocker.GliderID = item.ID
case "ItemWrap":
if body.SlotIndex == -1 {
for i := range currentLocker.ItemWrapID {
currentLocker.ItemWrapID[i] = item.ID
}
break
}
currentLocker.ItemWrapID[body.SlotIndex] = item.ID
profile.CreateLoadoutChangedChange(currentLocker, "ItemWrapID")
case "Dance":
if body.SlotIndex == -1 {
for i := range currentLocker.DanceID {
currentLocker.DanceID[i] = item.ID
}
break
}
currentLocker.DanceID[body.SlotIndex] = item.ID
profile.CreateLoadoutChangedChange(currentLocker, "DanceID")
case "SkyDiveContrail":
currentLocker.ContrailID = item.ID
case "LoadingScreen":
currentLocker.LoadingScreenID = item.ID
case "MusicPack":
currentLocker.MusicPackID = item.ID
}
go currentLocker.Save()
return nil
}
func PostSetCosmeticLockerBannerAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
var body struct {
LockerItem string `json:"lockerItem" binding:"required"` // locker id
BannerColorTemplateName string `json:"bannerColorTemplateName" binding:"required"` // template id
BannerIconTemplateName string `json:"bannerIconTemplateName" binding:"required"` // template id
}
err := c.BodyParser(&body)
if err != nil {
return fmt.Errorf("invalid Body")
}
color := person.CommonCoreProfile.Items.GetItemByTemplateID("HomebaseBannerColor:" + body.BannerColorTemplateName)
if color == nil {
return fmt.Errorf("color item not found")
}
icon := profile.Items.GetItemByTemplateID("HomebaseBannerIcon:" + body.BannerIconTemplateName)
if icon == nil {
// return fmt.Errorf("icon item not found")
icon = &p.Item{
ID: body.BannerIconTemplateName,
}
}
currentLocker := profile.Loadouts.GetLoadout(body.LockerItem)
if currentLocker == nil {
return fmt.Errorf("current locker not found")
}
currentLocker.BannerColorID = color.ID
currentLocker.BannerID = icon.ID
go currentLocker.Save()
return nil
}

View File

@ -47,7 +47,7 @@ func main() {
r.Get("/content/api/pages/fortnite-game", handlers.GetContentPages)
r.Get("/waitingroom/api/waitingroom", handlers.GetWaitingRoomStatus)
r.Get("/region", handlers.GetRegion)
r.Put("/profile/play_region", handlers.AnyNoContent)
// r.Put("/profile/play_region", handlers.AnyNoContent)
r.Get("/snow/cache", func(c *fiber.Ctx) error {
cache := person.AllFromCache()

View File

@ -67,8 +67,6 @@ func NewFortnitePerson(displayName string, key string) *Person {
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("season_update", 0)).Save()
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("season_num", aid.Config.Fortnite.Season)).Save()
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("permissions", []aid.JSON{})).Save()
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("last_applied_loadout", "")).Save()
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("active_loadout_index", 0)).Save()
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("accountLevel", 1)).Save()
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("level", 1)).Save()
@ -114,12 +112,14 @@ func NewFortnitePerson(displayName string, key string) *Person {
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("last_applied_loadout", loadout.ID)).Save()
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("active_loadout_index", 0)).Save()
allItemsBytes := storage.Asset("cosmetics.json")
var allItems []string
json.Unmarshal(*allItemsBytes, &allItems)
if aid.Config.Fortnite.Everything {
allItemsBytes := storage.Asset("cosmetics.json")
var allItems []string
json.Unmarshal(*allItemsBytes, &allItems)
for _, item := range allItems {
person.AthenaProfile.Items.AddItem(NewItem(item, 1)).Save()
for _, item := range allItems {
person.AthenaProfile.Items.AddItem(NewItem(item, 1)).Save()
}
}
person.Save()

View File

@ -8,6 +8,7 @@ import (
type Loadout struct {
ID string
PersonID string
ProfileID string
TemplateID string
LockerName string
@ -65,7 +66,7 @@ func NewLoadout(name string, athena *Profile) *Loadout {
return &Loadout{
ID: uuid.New().String(),
ProfileID: athena.ID,
PersonID: athena.ID,
TemplateID: "CosmeticLocker:CosmeticLocker_Athena",
LockerName: name,
CharacterID: aid.JSONParse(character.ValueJSON).(string),
@ -103,12 +104,26 @@ func FromDatabaseLoadout(loadout *storage.DB_Loadout) *Loadout {
}
func (l *Loadout) GenerateFortniteLoadoutEntry() aid.JSON {
bannerItem := Find(l.PersonID).AthenaProfile.Items.GetItem(l.BannerID)
if bannerItem == nil {
bannerItem = &Item{
TemplateID: "HomebaseBannerIcon:StandardBanner1",
}
}
bannerColorItem := Find(l.PersonID).AthenaProfile.Items.GetItem(l.BannerColorID)
if bannerColorItem == nil {
bannerColorItem = &Item{
TemplateID: "HomebaseBannerColor:DefaultColor1",
}
}
json := aid.JSON{
"templateId": l.TemplateID,
"attributes": aid.JSON{
"locker_name": l.LockerName,
"banner_icon_template": l.BannerID,
"banner_color_template": l.BannerColorID,
"banner_icon_template": bannerItem.TemplateID,
"banner_color_template": bannerColorItem.TemplateID,
"locker_slots_data": l.GenerateFortniteLockerSlotsData(),
"item_seen": true,
},
@ -118,13 +133,27 @@ func (l *Loadout) GenerateFortniteLoadoutEntry() aid.JSON {
}
func (l *Loadout) GetAttribute(attribute string) interface{} {
bannerItem := Find(l.PersonID).AthenaProfile.Items.GetItem(l.BannerID)
if bannerItem == nil {
bannerItem = &Item{
TemplateID: "HomebaseBannerIcon:StandardBanner1",
}
}
bannerColorItem := Find(l.PersonID).AthenaProfile.Items.GetItem(l.BannerColorID)
if bannerColorItem == nil {
bannerColorItem = &Item{
TemplateID: "HomebaseBannerColor:DefaultColor5",
}
}
switch attribute {
case "locker_name":
return l.LockerName
case "banner_icon_template":
return l.BannerID
return bannerItem.TemplateID
case "banner_color_template":
return l.BannerColorID
return bannerColorItem.TemplateID
case "locker_slots_data":
return l.GenerateFortniteLockerSlotsData()
}
@ -154,7 +183,7 @@ func (l *Loadout) GetItemSlotData(itemId string) aid.JSON {
"activeVariants": []aid.JSON{},
}
person := Find(l.ProfileID)
person := Find(l.PersonID)
if person == nil {
return json
}
@ -179,40 +208,38 @@ func (l *Loadout) GetItemSlotData(itemId string) aid.JSON {
func (l *Loadout) GetItemsSlotData(itemIds []string) aid.JSON {
json := aid.JSON{
"items": []string{},
"activeVariants": []aid.JSON{},
"items": make([]string, len(itemIds)),
"activeVariants": make([]aid.JSON, len(itemIds)),
}
person := Find(l.ProfileID)
person := Find(l.PersonID)
if person == nil {
return json
}
for _, itemId := range itemIds {
for idx, itemId := range itemIds {
item := person.AthenaProfile.Items.GetItem(itemId)
if item == nil {
item = &Item{
ProfileID: l.ProfileID,
TemplateID: "",
Variants: []*VariantChannel{},
}
}
items := json["items"].([]string)
items = append(items, item.TemplateID)
items[idx] = item.TemplateID
activeVariants := json["activeVariants"].([]aid.JSON)
activeVariants = append(activeVariants, aid.JSON{
"variants": item.GenerateFortniteItemVariantChannels(),
})
activeVariants[idx] = aid.JSON{
"variants": []aid.JSON{},
}
json["items"] = items
json["activeVariants"] = activeVariants
}
return aid.JSON{
"items": itemIds,
"activeVariants": []aid.JSON{},
}
return json
}
func (l *Loadout) Delete() {

View File

@ -183,6 +183,8 @@ func (p *Profile) Diff(b *ProfileSnapshot) []diff.Change {
return nil
}
aid.PrintJSON(changes)
for _, change := range changes {
switch change.Path[0] {
case "Items":
@ -333,20 +335,13 @@ func (p *Profile) CreateItemAttributeChangedChange(item *Item, attribute string)
}
p.Changes = append(p.Changes, ItemAttributeChanged{
ChangeType: "itemAttributeChanged",
ChangeType: "itemAttrChanged",
ItemId: item.ID,
AttributeName: lookup[attribute],
AttributeValue: item.GetAttribute(attribute),
})
}
func (p *Profile) CreateFullProfileUpdateChange() {
p.Changes = []interface{}{FullProfileUpdate{
ChangeType: "fullProfileUpdate",
Profile: p.GenerateFortniteProfileEntry(),
}}
}
func (p *Profile) CreateLoadoutAddedChange(loadout *Loadout) {
if loadout == nil {
fmt.Println("error getting item from profile", loadout.ID)
@ -389,13 +384,20 @@ func (p *Profile) CreateLoadoutChangedChange(loadout *Loadout, attribute string)
}
p.Changes = append(p.Changes, ItemAttributeChanged{
ChangeType: "itemAttributeChanged",
ChangeType: "itemAttrChanged",
ItemId: loadout.ID,
AttributeName: lookup[attribute],
AttributeValue: loadout.GetAttribute(lookup[attribute]),
})
}
func (p *Profile) CreateFullProfileUpdateChange() {
p.Changes = []interface{}{FullProfileUpdate{
ChangeType: "fullProfileUpdate",
Profile: p.GenerateFortniteProfileEntry(),
}}
}
func (p *Profile) ClearProfileChanges() {
p.Changes = []interface{}{}
}

View File

@ -240,17 +240,19 @@ func (m *AttributeMutex) Count() int {
type LoadoutMutex struct {
sync.Map
ProfileType string
PersonID string
ProfileID string
}
func NewLoadoutMutex(profile *storage.DB_Profile) *LoadoutMutex {
return &LoadoutMutex{
ProfileID: profile.ID,
PersonID: profile.PersonID,
ProfileID: profile.ID,
}
}
func (m *LoadoutMutex) AddLoadout(loadout *Loadout) *Loadout {
loadout.PersonID = m.PersonID
loadout.ProfileID = m.ProfileID
m.Store(loadout.ID, loadout)
// storage.Repo.SaveLoadout(loadout.ToDatabase(m.ProfileID))

View File

@ -12,8 +12,13 @@ type PostgresStorage struct {
}
func NewPostgresStorage() *PostgresStorage {
l := logger.Default.LogMode(logger.Silent)
if aid.Config.Output.Level == "time" {
l = logger.Default.LogMode(logger.Info)
}
db, err := gorm.Open(postgres.Open(aid.Config.Database.URI), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
Logger: l,
})
if err != nil {
panic(err)
@ -34,10 +39,10 @@ func (s *PostgresStorage) MigrateAll() {
s.Migrate(&DB_Item{}, "Items")
s.Migrate(&DB_Gift{}, "Gifts")
s.Migrate(&DB_Quest{}, "Quests")
s.Migrate(&DB_Loadout{}, "Loadouts")
s.Migrate(&DB_Loot{}, "Loot")
s.Migrate(&DB_VariantChannel{}, "Variants")
s.Migrate(&DB_PAttribute{}, "Attributes")
s.Migrate(&DB_Loadout{}, "Loadouts")
}
func (s *PostgresStorage) DropTables() {
@ -48,13 +53,13 @@ func (s *PostgresStorage) GetPerson(personId string) *DB_Person {
var dbPerson DB_Person
s.Postgres.
Preload("Profiles").
Preload("Profiles.Loadouts").
Preload("Profiles.Items.Variants").
Preload("Profiles.Gifts.Loot").
Preload("Profiles.Attributes").
Preload("Profiles.Items").
Preload("Profiles.Gifts").
Preload("Profiles.Quests").
Preload("Profiles.Loadouts").
Where("id = ?", personId).
Find(&dbPerson)
@ -68,14 +73,14 @@ func (s *PostgresStorage) GetPerson(personId string) *DB_Person {
func (s *PostgresStorage) GetPersonByDisplay(displayName string) *DB_Person {
var dbPerson DB_Person
s.Postgres.
// Preload("Profiles").
// Preload("Profiles.Items.Variants").
// Preload("Profiles.Gifts.Loot").
// Preload("Profiles.Attributes").
// Preload("Profiles.Items").
// Preload("Profiles.Gifts").
// Preload("Profiles.Quests").
// Preload("Profiles.Loadouts").
Preload("Profiles").
Preload("Profiles.Loadouts").
Preload("Profiles.Items.Variants").
Preload("Profiles.Gifts.Loot").
Preload("Profiles.Attributes").
Preload("Profiles.Items").
Preload("Profiles.Gifts").
Preload("Profiles.Quests").
Where("display_name = ?", displayName).
Find(&dbPerson)
@ -91,13 +96,13 @@ func (s *PostgresStorage) GetAllPersons() []*DB_Person {
s.Postgres.
Preload("Profiles").
Preload("Profiles.Loadouts").
Preload("Profiles.Items.Variants").
Preload("Profiles.Gifts.Loot").
Preload("Profiles.Attributes").
Preload("Profiles.Items").
Preload("Profiles.Gifts").
Preload("Profiles.Quests").
Preload("Profiles.Loadouts").
Find(&dbPersons)
return dbPersons