Rework automatic storefront!
This commit is contained in:
parent
dea3770027
commit
3fcda14f1a
16
aid/aid.go
16
aid/aid.go
|
@ -1,7 +1,6 @@
|
|||
package aid
|
||||
|
||||
import (
|
||||
m "math/rand"
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
|
@ -15,20 +14,6 @@ func WaitForExit() {
|
|||
<-sc
|
||||
}
|
||||
|
||||
func RandomString(n int) string {
|
||||
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
|
||||
s := make([]rune, n)
|
||||
for i := range s {
|
||||
s[i] = letters[m.Intn(len(letters))]
|
||||
}
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func RandomInt(min, max int) int {
|
||||
return m.Intn(max - min) + min
|
||||
}
|
||||
|
||||
func FormatNumber(number int) string {
|
||||
str := ""
|
||||
for i, char := range ReverseString(strconv.Itoa(number)) {
|
||||
|
@ -60,7 +45,6 @@ func ToHex(number int) string {
|
|||
}
|
||||
|
||||
func Regex(str, regex string) *string {
|
||||
// reg := regexp.MustCompile(`(?:CID_)(\d+|A_\d+)(?:_.+)`).FindStringSubmatch(strings.Join(split[:], "_"))
|
||||
reg := regexp.MustCompile(regex).FindStringSubmatch(str)
|
||||
if len(reg) > 1 {
|
||||
return ®[1]
|
||||
|
|
|
@ -48,6 +48,7 @@ type CS struct {
|
|||
Everything bool
|
||||
Password bool
|
||||
DisableClientCredentials bool
|
||||
ShopSeed int
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,4 +174,5 @@ func LoadConfig(file []byte) {
|
|||
Config.Fortnite.Everything = cfg.Section("fortnite").Key("everything").MustBool(false)
|
||||
Config.Fortnite.Password = !(cfg.Section("fortnite").Key("disable_password").MustBool(false))
|
||||
Config.Fortnite.DisableClientCredentials = cfg.Section("fortnite").Key("disable_client_credentials").MustBool(false)
|
||||
Config.Fortnite.ShopSeed = cfg.Section("fortnite").Key("shop_seed").MustInt(0)
|
||||
}
|
24
aid/random.go
Normal file
24
aid/random.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package aid
|
||||
|
||||
import "math/rand"
|
||||
|
||||
var Random *rand.Rand
|
||||
|
||||
func SetRandom(r *rand.Rand) {
|
||||
Random = r
|
||||
}
|
||||
|
||||
func RandomString(n int) string {
|
||||
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
|
||||
s := make([]rune, n)
|
||||
for i := range s {
|
||||
s[i] = letters[Random.Intn(len(letters))]
|
||||
}
|
||||
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func RandomInt(min, max int) int {
|
||||
return Random.Intn(max-min) + min
|
||||
}
|
|
@ -17,6 +17,10 @@ func TimeEndOfWeekString() string {
|
|||
return time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 23, 59, 59, 999999999, time.Now().Location()).AddDate(0, 0, 7).Format("2006-01-02T15:04:05.999Z")
|
||||
}
|
||||
|
||||
func CurrentDayUnix() int64 {
|
||||
return time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Now().Location()).Unix()
|
||||
}
|
||||
|
||||
// everything below is taken from the golang standard library I just added the extra units to the map
|
||||
|
||||
var unitMap = map[string]uint64{
|
||||
|
|
|
@ -75,4 +75,8 @@ disable_password=false
|
|||
; this will disable the client credentials grant type
|
||||
; however this will also disable a user to get the hotfixes before login
|
||||
; so xmpp and other hotfix related things will be delayed by ~1 minute
|
||||
disable_client_credentials=false
|
||||
disable_client_credentials=false
|
||||
; this is used to generate a random shop
|
||||
; each number will generate a different shop for the day
|
||||
; the shop will stay the same for the entire day even after server restarts
|
||||
shop_seed=0
|
|
@ -157,7 +157,7 @@ func (c *ExternalDataClient) AddDisplayAssetToItem(displayAsset string) {
|
|||
if found == nil && split[0] == "CID" {
|
||||
r := aid.Regex(strings.Join(split[:], "_"), `(?:CID_)(\d+|A_\d+)(?:_.+)`)
|
||||
if r != nil {
|
||||
found = ItemByShallowID(*r)
|
||||
found = GetItemByShallowID(*r)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ func PreloadCosmetics() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ItemByShallowID(shallowID string) *FortniteItem {
|
||||
func GetItemByShallowID(shallowID string) *FortniteItem {
|
||||
for _, item := range External.TypedFortniteItems["AthenaCharacter"] {
|
||||
if strings.Contains(item.ID, shallowID) {
|
||||
return item
|
||||
|
@ -203,43 +203,54 @@ func ItemByShallowID(shallowID string) *FortniteItem {
|
|||
return nil
|
||||
}
|
||||
|
||||
func RandomItemByType(itemType string) *FortniteItem {
|
||||
items := External.TypedFortniteItemsWithDisplayAssets[itemType]
|
||||
func GetRandomItemWithDisplayAsset() *FortniteItem {
|
||||
items := External.FortniteItemsWithDisplayAssets
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return items[aid.RandomInt(0, len(items))]
|
||||
flat := []FortniteItem{}
|
||||
for _, item := range items {
|
||||
flat = append(flat, *item)
|
||||
}
|
||||
|
||||
slices.SortFunc[[]FortniteItem](flat, func(a, b FortniteItem) int {
|
||||
return strings.Compare(a.ID, b.ID)
|
||||
})
|
||||
|
||||
return &flat[aid.RandomInt(0, len(flat))]
|
||||
}
|
||||
|
||||
func RandomItemByNotType(notItemType string) *FortniteItem {
|
||||
allItems := []*FortniteItem{}
|
||||
|
||||
for key, items := range External.TypedFortniteItemsWithDisplayAssets {
|
||||
if key == notItemType {
|
||||
func GetRandomItemWithDisplayAssetOfNotType(notType string) *FortniteItem {
|
||||
flat := []FortniteItem{}
|
||||
|
||||
for t, items := range External.TypedFortniteItemsWithDisplayAssets {
|
||||
if t == notType {
|
||||
continue
|
||||
}
|
||||
|
||||
allItems = append(allItems, items...)
|
||||
for _, item := range items {
|
||||
flat = append(flat, *item)
|
||||
}
|
||||
}
|
||||
|
||||
return allItems[aid.RandomInt(0, len(allItems))]
|
||||
slices.SortFunc[[]FortniteItem](flat, func(a, b FortniteItem) int {
|
||||
return strings.Compare(a.ID, b.ID)
|
||||
})
|
||||
|
||||
return &flat[aid.RandomInt(0, len(flat))]
|
||||
}
|
||||
|
||||
func RandomItemWithFeaturedImage() *FortniteItem {
|
||||
items := External.FortniteItemsWithFeaturedImage
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return items[aid.RandomInt(0, len(items))]
|
||||
}
|
||||
|
||||
func RandomSet() *FortniteSet {
|
||||
sets := []*FortniteSet{}
|
||||
func GetRandomSet() *FortniteSet {
|
||||
sets := []FortniteSet{}
|
||||
for _, set := range External.FortniteSets {
|
||||
sets = append(sets, set)
|
||||
sets = append(sets, *set)
|
||||
}
|
||||
|
||||
return sets[aid.RandomInt(0, len(sets))]
|
||||
slices.SortFunc[[]FortniteSet](sets, func(a, b FortniteSet) int {
|
||||
return strings.Compare(a.BackendName, b.BackendName)
|
||||
})
|
||||
|
||||
return &sets[aid.RandomInt(0, len(sets))]
|
||||
}
|
744
fortnite/shop.go
744
fortnite/shop.go
|
@ -1,476 +1,350 @@
|
|||
package fortnite
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/ectrc/snow/person"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
Rarities = map[string]map[string]int{
|
||||
priceLookup = map[string]map[string]int{
|
||||
"EFortRarity::Legendary": {
|
||||
"AthenaCharacter": 2000,
|
||||
"AthenaBackpack": 1500,
|
||||
"AthenaPickaxe": 1500,
|
||||
"AthenaGlider": 1800,
|
||||
"AthenaDance": 500,
|
||||
"AthenaItemWrap": 800,
|
||||
"AthenaBackpack": 1500,
|
||||
"AthenaPickaxe": 1500,
|
||||
"AthenaGlider": 1800,
|
||||
"AthenaDance": 500,
|
||||
"AthenaItemWrap": 800,
|
||||
},
|
||||
"EFortRarity::Epic": {
|
||||
"AthenaCharacter": 1500,
|
||||
"AthenaBackpack": 1200,
|
||||
"AthenaPickaxe": 1200,
|
||||
"AthenaGlider": 1500,
|
||||
"AthenaDance": 800,
|
||||
"AthenaItemWrap": 800,
|
||||
"AthenaBackpack": 1200,
|
||||
"AthenaPickaxe": 1200,
|
||||
"AthenaGlider": 1500,
|
||||
"AthenaDance": 800,
|
||||
"AthenaItemWrap": 800,
|
||||
},
|
||||
"EFortRarity::Rare": {
|
||||
"AthenaCharacter": 1200,
|
||||
"AthenaBackpack": 800,
|
||||
"AthenaPickaxe": 800,
|
||||
"AthenaGlider": 800,
|
||||
"AthenaDance": 500,
|
||||
"AthenaItemWrap": 600,
|
||||
"AthenaBackpack": 800,
|
||||
"AthenaPickaxe": 800,
|
||||
"AthenaGlider": 800,
|
||||
"AthenaDance": 500,
|
||||
"AthenaItemWrap": 600,
|
||||
},
|
||||
"EFortRarity::Uncommon": {
|
||||
"AthenaCharacter": 800,
|
||||
"AthenaBackpack": 200,
|
||||
"AthenaPickaxe": 500,
|
||||
"AthenaGlider": 500,
|
||||
"AthenaDance": 200,
|
||||
"AthenaItemWrap": 300,
|
||||
"AthenaBackpack": 200,
|
||||
"AthenaPickaxe": 500,
|
||||
"AthenaGlider": 500,
|
||||
"AthenaDance": 200,
|
||||
"AthenaItemWrap": 300,
|
||||
},
|
||||
"EFortRarity::Common": {
|
||||
"AthenaCharacter": 500,
|
||||
"AthenaBackpack": 200,
|
||||
"AthenaPickaxe": 500,
|
||||
"AthenaGlider": 500,
|
||||
"AthenaDance": 200,
|
||||
"AthenaItemWrap": 300,
|
||||
"AthenaBackpack": 200,
|
||||
"AthenaPickaxe": 500,
|
||||
"AthenaGlider": 500,
|
||||
"AthenaDance": 200,
|
||||
"AthenaItemWrap": 300,
|
||||
},
|
||||
}
|
||||
StaticCatalog = NewCatalog()
|
||||
|
||||
dailyItemLookup = map[int]int{
|
||||
2: 4,
|
||||
4: 6,
|
||||
13: 10,
|
||||
}
|
||||
|
||||
weeklySetLookup = map[int]int{
|
||||
2: 2,
|
||||
4: 3,
|
||||
11: 4,
|
||||
13: 3,
|
||||
}
|
||||
)
|
||||
|
||||
func GetPriceForRarity(rarity string, backendType string) int {
|
||||
return Rarities[rarity][backendType]
|
||||
func price(rarity, type_ string) int {
|
||||
return priceLookup[rarity][type_]
|
||||
}
|
||||
|
||||
type Catalog struct {
|
||||
RefreshIntervalHrs int `json:"refreshIntervalHrs"`
|
||||
DailyPurchaseHrs int `json:"dailyPurchaseHrs"`
|
||||
Expiration string `json:"expiration"`
|
||||
Storefronts []Storefront `json:"storefronts"`
|
||||
}
|
||||
func dailyItems(season int) int {
|
||||
var items int
|
||||
|
||||
func NewCatalog() *Catalog {
|
||||
return &Catalog{
|
||||
RefreshIntervalHrs: 24,
|
||||
DailyPurchaseHrs: 24,
|
||||
Expiration: aid.TimeEndOfDay(),
|
||||
Storefronts: []Storefront{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Catalog) Add(storefront *Storefront) {
|
||||
c.Storefronts = append(c.Storefronts, *storefront)
|
||||
}
|
||||
|
||||
func (c *Catalog) GenerateFortniteCatalog(p *person.Person) aid.JSON {
|
||||
json := aid.JSON{
|
||||
"refreshIntervalHrs": c.RefreshIntervalHrs,
|
||||
"dailyPurchaseHrs": c.DailyPurchaseHrs,
|
||||
"expiration": c.Expiration,
|
||||
"storefronts": []aid.JSON{},
|
||||
}
|
||||
|
||||
for _, storefront := range c.Storefronts {
|
||||
json["storefronts"] = append(json["storefronts"].([]aid.JSON), storefront.GenerateResponse(p))
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
func (c *Catalog) CheckIfOfferIsDuplicate(entry Entry) bool {
|
||||
for _, storefront := range c.Storefronts {
|
||||
for _, catalogEntry := range storefront.CatalogEntries {
|
||||
if catalogEntry.Grants[0] == entry.Grants[0] {
|
||||
return true
|
||||
}
|
||||
for s, i := range dailyItemLookup {
|
||||
if season >= s {
|
||||
items = i
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return items
|
||||
}
|
||||
|
||||
func (c *Catalog) GetOfferById(id string) *Entry {
|
||||
for _, storefront := range c.Storefronts {
|
||||
for _, catalogEntry := range storefront.CatalogEntries {
|
||||
if catalogEntry.ID == id {
|
||||
return &catalogEntry
|
||||
func weeklySets(season int) int {
|
||||
var sets int
|
||||
|
||||
for s, i := range weeklySetLookup {
|
||||
if season >= s {
|
||||
sets = i
|
||||
}
|
||||
}
|
||||
|
||||
return sets
|
||||
}
|
||||
|
||||
type FortniteCatalogSectionOffer struct {
|
||||
ID string
|
||||
Grants []*FortniteItem
|
||||
TotalPrice int
|
||||
Meta struct {
|
||||
DisplayAssetPath string
|
||||
NewDisplayAssetPath string
|
||||
SectionId string
|
||||
TileSize string
|
||||
Category string
|
||||
ProfileId string
|
||||
}
|
||||
Frontend struct {
|
||||
Title string
|
||||
Description string
|
||||
ShortDescription string
|
||||
}
|
||||
Giftable bool
|
||||
BundleInfo struct {
|
||||
IsBundle bool
|
||||
PricePercent float32
|
||||
}
|
||||
}
|
||||
|
||||
func NewFortniteCatalogSectionOffer() *FortniteCatalogSectionOffer {
|
||||
return &FortniteCatalogSectionOffer{}
|
||||
}
|
||||
|
||||
func (f *FortniteCatalogSectionOffer) GenerateID() {
|
||||
for _, item := range f.Grants {
|
||||
f.ID += item.Type.BackendValue + ":" + item.ID + ","
|
||||
}
|
||||
|
||||
f.ID = "v2:/" + aid.Hash([]byte(f.ID))
|
||||
}
|
||||
|
||||
func (f *FortniteCatalogSectionOffer) GenerateTotalPrice() {
|
||||
if !f.BundleInfo.IsBundle {
|
||||
f.TotalPrice = price(f.Grants[0].Rarity.BackendValue, f.Grants[0].Type.BackendValue)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range f.Grants {
|
||||
f.TotalPrice += price(item.Rarity.BackendValue, item.Rarity.BackendValue)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FortniteCatalogSectionOffer) GenerateFortniteCatalogSectionOffer() aid.JSON {
|
||||
f.GenerateTotalPrice()
|
||||
|
||||
itemGrantResponse := []aid.JSON{}
|
||||
purchaseRequirementsResponse := []aid.JSON{}
|
||||
|
||||
for _, item := range f.Grants {
|
||||
itemGrantResponse = append(itemGrantResponse, aid.JSON{
|
||||
"templateId": item.Type.BackendValue + ":" + item.ID,
|
||||
"quantity": 1,
|
||||
})
|
||||
|
||||
purchaseRequirementsResponse = append(purchaseRequirementsResponse, aid.JSON{
|
||||
"requirementType": "DenyOnItemOwnership",
|
||||
"requiredId": item.Type.BackendValue + ":" + item.ID,
|
||||
"minQuantity": 1,
|
||||
})
|
||||
}
|
||||
|
||||
return aid.JSON{
|
||||
"devName": uuid.New().String(),
|
||||
"offerId": f.ID,
|
||||
"offerType": "StaticPrice",
|
||||
"prices": []aid.JSON{{
|
||||
"currencyType": "MtxCurrency",
|
||||
"currencySubType": "",
|
||||
"regularPrice": f.TotalPrice,
|
||||
"dynamicRegularPrice": f.TotalPrice,
|
||||
"finalPrice": f.TotalPrice,
|
||||
"basePrice": f.TotalPrice,
|
||||
"saleExpiration": "9999-12-31T23:59:59.999Z",
|
||||
}},
|
||||
"itemGrants": itemGrantResponse,
|
||||
"meta": aid.JSON{
|
||||
"TileSize": f.Meta.TileSize,
|
||||
"SectionId": f.Meta.SectionId,
|
||||
"NewDisplayAssetPath": f.Meta.NewDisplayAssetPath,
|
||||
"DisplayAssetPath": f.Meta.DisplayAssetPath,
|
||||
},
|
||||
"metaInfo": []aid.JSON{
|
||||
{
|
||||
"Key": "TileSize",
|
||||
"Value": f.Meta.TileSize,
|
||||
},
|
||||
{
|
||||
"Key": "SectionId",
|
||||
"Value": f.Meta.SectionId,
|
||||
},
|
||||
{
|
||||
"Key": "NewDisplayAssetPath",
|
||||
"Value": f.Meta.NewDisplayAssetPath,
|
||||
},
|
||||
{
|
||||
"Key": "DisplayAssetPath",
|
||||
"Value": f.Meta.DisplayAssetPath,
|
||||
},
|
||||
},
|
||||
"giftInfo": aid.JSON{
|
||||
"bIsEnabled": f.Giftable,
|
||||
"forcedGiftBoxTemplateId": "",
|
||||
"purchaseRequirements": purchaseRequirementsResponse,
|
||||
"giftRecordIds": []string{},
|
||||
},
|
||||
"purchaseRequirements": purchaseRequirementsResponse,
|
||||
"categories": []string{f.Meta.Category},
|
||||
"title": f.Frontend.Title,
|
||||
"description": f.Frontend.Description,
|
||||
"shortDescription": f.Frontend.ShortDescription,
|
||||
"displayAssetPath": f.Meta.DisplayAssetPath,
|
||||
"appStoreId": []string{},
|
||||
"fufillmentIds": []string{},
|
||||
"dailyLimit": -1,
|
||||
"weeklyLimit": -1,
|
||||
"monthlyLimit": -1,
|
||||
"sortPriority": 0,
|
||||
"catalogGroupPriority": 0,
|
||||
"filterWeight": 0,
|
||||
"refundable": true,
|
||||
}
|
||||
}
|
||||
|
||||
type FortniteCatalogSection struct {
|
||||
Name string
|
||||
Offers []*FortniteCatalogSectionOffer
|
||||
}
|
||||
|
||||
func NewFortniteCatalogSection(name string) *FortniteCatalogSection {
|
||||
return &FortniteCatalogSection{
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FortniteCatalogSection) GenerateFortniteCatalogSection() aid.JSON {
|
||||
catalogEntiresResponse := []aid.JSON{}
|
||||
for _, offer := range f.Offers {
|
||||
catalogEntiresResponse = append(catalogEntiresResponse, offer.GenerateFortniteCatalogSectionOffer())
|
||||
}
|
||||
|
||||
return aid.JSON{
|
||||
"name": f.Name,
|
||||
"catalogEntries": catalogEntiresResponse,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FortniteCatalogSection) GetGroupedOffers() map[string][]*FortniteCatalogSectionOffer {
|
||||
groupedOffers := map[string][]*FortniteCatalogSectionOffer{}
|
||||
|
||||
for _, offer := range f.Offers {
|
||||
if groupedOffers[offer.Meta.Category] == nil {
|
||||
groupedOffers[offer.Meta.Category] = []*FortniteCatalogSectionOffer{}
|
||||
}
|
||||
|
||||
groupedOffers[offer.Meta.Category] = append(groupedOffers[offer.Meta.Category], offer)
|
||||
}
|
||||
|
||||
return groupedOffers
|
||||
}
|
||||
|
||||
type FortniteCatalog struct {
|
||||
Sections []*FortniteCatalogSection
|
||||
}
|
||||
|
||||
func NewFortniteCatalog() *FortniteCatalog {
|
||||
return &FortniteCatalog{}
|
||||
}
|
||||
|
||||
func (f *FortniteCatalog) GenerateFortniteCatalog() aid.JSON {
|
||||
catalogSectionsResponse := []aid.JSON{}
|
||||
for _, section := range f.Sections {
|
||||
catalogSectionsResponse = append(catalogSectionsResponse, section.GenerateFortniteCatalogSection())
|
||||
}
|
||||
|
||||
return aid.JSON{
|
||||
"storefronts": catalogSectionsResponse,
|
||||
"refreshIntervalHrs": 24,
|
||||
"dailyPurchaseHrs": 24,
|
||||
"expiration": "9999-12-31T23:59:59.999Z",
|
||||
}
|
||||
}
|
||||
|
||||
func NewRandomFortniteCatalog() *FortniteCatalog {
|
||||
aid.SetRandom(rand.New(rand.NewSource(int64(aid.Config.Fortnite.ShopSeed) + aid.CurrentDayUnix())))
|
||||
catalog := NewFortniteCatalog()
|
||||
|
||||
daily := NewFortniteCatalogSection("BRDailyStorefront")
|
||||
for len(daily.Offers) < dailyItems(aid.Config.Fortnite.Season) {
|
||||
entry := newEntryFromFortniteItem(GetRandomItemWithDisplayAssetOfNotType("AthenaCharacter"), false)
|
||||
entry.Meta.SectionId = "Daily"
|
||||
daily.Offers = append(daily.Offers, entry)
|
||||
}
|
||||
catalog.Sections = append(catalog.Sections, daily)
|
||||
|
||||
weekly := NewFortniteCatalogSection("BRWeeklyStorefront")
|
||||
for len(weekly.GetGroupedOffers()) < weeklySets(aid.Config.Fortnite.Season) {
|
||||
set := GetRandomSet()
|
||||
for _, item := range set.Items {
|
||||
if item.DisplayAssetPath == "" || item.DisplayAssetPath2 == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
entry := newEntryFromFortniteItem(item, true)
|
||||
entry.Meta.Category = set.BackendName
|
||||
entry.Meta.SectionId = "Featured"
|
||||
weekly.Offers = append(weekly.Offers, entry)
|
||||
}
|
||||
}
|
||||
catalog.Sections = append(catalog.Sections, weekly)
|
||||
|
||||
return catalog
|
||||
}
|
||||
|
||||
func newEntryFromFortniteItem(fortniteItem *FortniteItem, addAssets bool) *FortniteCatalogSectionOffer {
|
||||
displayAsset := regexp.MustCompile(`[^/]+$`).FindString(fortniteItem.DisplayAssetPath)
|
||||
|
||||
entry := NewFortniteCatalogSectionOffer()
|
||||
entry.Meta.TileSize = "Small"
|
||||
if fortniteItem.Type.BackendValue == "AthenaCharacter" {
|
||||
entry.Meta.TileSize = "Normal"
|
||||
}
|
||||
if addAssets {
|
||||
entry.Meta.NewDisplayAssetPath = "/Game/Catalog/NewDisplayAssets/" + fortniteItem.DisplayAssetPath2 + "." + fortniteItem.DisplayAssetPath2
|
||||
if displayAsset != "" {
|
||||
entry.Meta.DisplayAssetPath = "/Game/Catalog/DisplayAssets/" + displayAsset + "." + displayAsset
|
||||
}
|
||||
}
|
||||
entry.Meta.ProfileId = "athena"
|
||||
entry.Giftable = true
|
||||
entry.Grants = append(entry.Grants, fortniteItem)
|
||||
entry.GenerateTotalPrice()
|
||||
entry.GenerateID()
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
func GetOfferByOfferId(id string) *FortniteCatalogSectionOffer {
|
||||
catalog := NewRandomFortniteCatalog()
|
||||
|
||||
for _, section := range catalog.Sections {
|
||||
for _, offer := range section.Offers {
|
||||
if offer.ID == id {
|
||||
return offer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Storefront struct {
|
||||
Name string `json:"name"`
|
||||
CatalogEntries []Entry `json:"catalogEntries"`
|
||||
}
|
||||
|
||||
func NewStorefront(name string) *Storefront {
|
||||
return &Storefront{
|
||||
Name: name,
|
||||
CatalogEntries: []Entry{},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Storefront) Add(entry Entry) {
|
||||
s.CatalogEntries = append(s.CatalogEntries, entry)
|
||||
}
|
||||
|
||||
func (s *Storefront) GenerateResponse(p *person.Person) aid.JSON {
|
||||
json := aid.JSON{
|
||||
"name": s.Name,
|
||||
"catalogEntries": []aid.JSON{},
|
||||
}
|
||||
|
||||
for _, entry := range s.CatalogEntries {
|
||||
json["catalogEntries"] = append(json["catalogEntries"].([]aid.JSON), entry.GenerateResponse(p))
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
ID string
|
||||
Name string
|
||||
Price int
|
||||
Meta []aid.JSON
|
||||
Panel string
|
||||
Priority int
|
||||
Grants []string
|
||||
DisplayAssetPath string
|
||||
NewDisplayAssetPath string
|
||||
Title string
|
||||
ShortDescription string
|
||||
ProfileType string
|
||||
}
|
||||
|
||||
func NewCatalogEntry(profile string, meta ...aid.JSON) *Entry {
|
||||
return &Entry{
|
||||
ID: uuid.New().String(),
|
||||
Meta: meta,
|
||||
ProfileType: profile,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Entry) AddGrant(templateId string) *Entry {
|
||||
e.Grants = append(e.Grants, templateId)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) AddMeta(key string, value interface{}) *Entry {
|
||||
e.Meta = append(e.Meta, aid.JSON{
|
||||
"Key": key,
|
||||
"Value": value,
|
||||
})
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetTileSize(size string) *Entry {
|
||||
e.Meta = append(e.Meta, aid.JSON{
|
||||
"Key": "TileSize",
|
||||
"Value": size,
|
||||
})
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetPanel(panel string) *Entry {
|
||||
e.Panel = panel
|
||||
return e
|
||||
}
|
||||
|
||||
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{
|
||||
"Key": "SectionId",
|
||||
"Value": sectionId,
|
||||
})
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetDisplayAsset(asset string) *Entry {
|
||||
displayAsset := "DAv2_Featured_" + asset
|
||||
e.DisplayAssetPath = "/Game/Catalog/DisplayAssets/" + displayAsset + "." + displayAsset
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetNewDisplayAsset(asset string) *Entry {
|
||||
e.NewDisplayAssetPath = "/Game/Catalog/NewDisplayAssets/" + asset + "." + asset
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetDisplayAssetPath(path string) *Entry {
|
||||
paths := strings.Split(path, "/")
|
||||
id := paths[len(paths)-1]
|
||||
|
||||
e.DisplayAssetPath = "/Game/Catalog/DisplayAssets/" + id + "." + id
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetNewDisplayAssetPath(path string) *Entry {
|
||||
e.NewDisplayAssetPath = path
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetTitle(title string) *Entry {
|
||||
e.Title = title
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetShortDescription(description string) *Entry {
|
||||
e.ShortDescription = description
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) SetPrice(price int) *Entry {
|
||||
e.Price = price
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Entry) GenerateResponse(p *person.Person) aid.JSON {
|
||||
grantStrings := e.Grants
|
||||
for _, grant := range grantStrings {
|
||||
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{
|
||||
"offerId": e.ID,
|
||||
"devName": e.Name,
|
||||
"offerType": "StaticPrice",
|
||||
"prices": []aid.JSON{
|
||||
{
|
||||
"currencyType": "MtxCurrency",
|
||||
"currencySubType": "Currency",
|
||||
"regularPrice": e.Price,
|
||||
"dynamicRegularPrice": e.Price,
|
||||
"finalPrice": e.Price,
|
||||
"basePrice": e.Price,
|
||||
"saleExpiration": aid.TimeEndOfDay(),
|
||||
},
|
||||
},
|
||||
"categories": []string{},
|
||||
"catalogGroupPriority": 0,
|
||||
"sortPriority": e.Priority,
|
||||
"dailyLimit": -1,
|
||||
"weeklyLimit": -1,
|
||||
"monthlyLimit": -1,
|
||||
"fufillmentIds": []string{},
|
||||
"filterWeight": 0.0,
|
||||
"appStoreId": []string{},
|
||||
"refundable": false,
|
||||
"itemGrants": []aid.JSON{},
|
||||
"metaInfo": e.Meta,
|
||||
"meta": aid.JSON{},
|
||||
"title": e.Title,
|
||||
"displayAssetPath": e.DisplayAssetPath,
|
||||
"shortDescription": e.ShortDescription,
|
||||
}
|
||||
grants := []aid.JSON{}
|
||||
requirements := []aid.JSON{}
|
||||
purchaseRequirements := []aid.JSON{}
|
||||
meta := []aid.JSON{}
|
||||
|
||||
for _, templateId := range e.Grants {
|
||||
grants = append(grants, aid.JSON{
|
||||
"templateId": templateId,
|
||||
"quantity": 1,
|
||||
})
|
||||
|
||||
if item := p.AthenaProfile.Items.GetItemByTemplateID(templateId); item != nil {
|
||||
requirements = append(requirements, aid.JSON{
|
||||
"requirementType": "DenyOnItemOwnership",
|
||||
"requiredId": item.ID,
|
||||
"minQuantity": 1,
|
||||
})
|
||||
|
||||
purchaseRequirements = append(purchaseRequirements, aid.JSON{
|
||||
"requirementType": "DenyOnItemOwnership",
|
||||
"requiredId": item.ID,
|
||||
"minQuantity": 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range e.Meta {
|
||||
meta = append(meta, m)
|
||||
json["meta"].(aid.JSON)[m["Key"].(string)] = m["Value"]
|
||||
}
|
||||
|
||||
if e.Panel != "" {
|
||||
json["categories"] = []string{e.Panel}
|
||||
}
|
||||
|
||||
json["itemGrants"] = grants
|
||||
json["requirements"] = requirements
|
||||
json["metaInfo"] = meta
|
||||
json["giftInfo"] = aid.JSON{
|
||||
"bIsEnabled": true,
|
||||
"forcedGiftBoxTemplateId": "",
|
||||
"purchaseRequirements": purchaseRequirements,
|
||||
"giftRecordIds": []any{},
|
||||
}
|
||||
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
func GenerateRandomStorefront() {
|
||||
storefront := NewCatalog()
|
||||
|
||||
daily := NewStorefront("BRDailyStorefront")
|
||||
weekly := NewStorefront("BRWeeklyStorefront")
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
if aid.Config.Fortnite.Season < 14 {
|
||||
break
|
||||
}
|
||||
|
||||
item := RandomItemByType("AthenaCharacter")
|
||||
entry := NewCatalogEntry("athena")
|
||||
entry.SetSection("Daily")
|
||||
entry.SetNewDisplayAsset(item.DisplayAssetPath2)
|
||||
|
||||
if item.DisplayAssetPath != "" {
|
||||
entry.SetDisplayAssetPath(item.DisplayAssetPath)
|
||||
}
|
||||
entry.SetPrice(GetPriceForRarity(item.Rarity.BackendValue, item.Type.BackendValue))
|
||||
entry.AddGrant(item.Type.BackendValue + ":" + item.ID)
|
||||
entry.SetTileSize("Normal")
|
||||
entry.Priority = 1
|
||||
|
||||
if item.Backpack != nil {
|
||||
entry.AddGrant("AthenaBackpack:" + item.Backpack.ID)
|
||||
}
|
||||
|
||||
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
daily.Add(*entry)
|
||||
}
|
||||
|
||||
for i := 0; i < 6; i++ {
|
||||
item := RandomItemByNotType("AthenaCharacter")
|
||||
entry := NewCatalogEntry("athena")
|
||||
entry.SetSection("Daily")
|
||||
|
||||
if item.DisplayAssetPath2 == "" {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
entry.SetNewDisplayAsset(item.DisplayAssetPath2)
|
||||
|
||||
if item.DisplayAssetPath != "" {
|
||||
entry.SetDisplayAssetPath(item.DisplayAssetPath)
|
||||
}
|
||||
entry.SetPrice(GetPriceForRarity(item.Rarity.BackendValue, item.Type.BackendValue))
|
||||
entry.AddGrant(item.Type.BackendValue + ":" + item.ID)
|
||||
entry.SetTileSize("Small")
|
||||
|
||||
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
daily.Add(*entry)
|
||||
}
|
||||
|
||||
minimumItems := 8
|
||||
if aid.Config.Fortnite.Season < 11 {
|
||||
minimumItems = 3
|
||||
}
|
||||
|
||||
minimumSets := 4
|
||||
if aid.Config.Fortnite.Season <+ 12 {
|
||||
minimumSets = 3
|
||||
}
|
||||
|
||||
setsAdded := 0
|
||||
for len(weekly.CatalogEntries) < minimumItems || setsAdded < minimumSets {
|
||||
set := RandomSet()
|
||||
|
||||
itemsAdded := 0
|
||||
itemsToAdd := []*Entry{}
|
||||
for _, item := range set.Items {
|
||||
entry := NewCatalogEntry("athena")
|
||||
entry.SetSection("Featured")
|
||||
entry.SetPanel(set.BackendName)
|
||||
entry.SetNewDisplayAsset(item.DisplayAssetPath2)
|
||||
|
||||
if item.Type.BackendValue == "AthenaCharacter" {
|
||||
entry.SetTileSize("Normal")
|
||||
if aid.Config.Fortnite.Season < 14 {
|
||||
itemsAdded += 1
|
||||
} else {
|
||||
itemsAdded += 2
|
||||
}
|
||||
entry.Priority = 1
|
||||
} else {
|
||||
entry.SetTileSize("Small")
|
||||
itemsAdded += 1
|
||||
}
|
||||
|
||||
if item.DisplayAssetPath != "" {
|
||||
entry.SetDisplayAssetPath(item.DisplayAssetPath)
|
||||
}
|
||||
entry.SetPrice(GetPriceForRarity(item.Rarity.BackendValue, item.Type.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 {
|
||||
if storefront.CheckIfOfferIsDuplicate(*entry) {
|
||||
continue
|
||||
}
|
||||
|
||||
weekly.Add(*entry)
|
||||
}
|
||||
|
||||
setsAdded++
|
||||
}
|
||||
|
||||
storefront.Add(daily)
|
||||
storefront.Add(weekly)
|
||||
|
||||
StaticCatalog = storefront
|
||||
aid.Print("(snow) generated random storefront")
|
||||
}
|
|
@ -601,12 +601,12 @@ func clientPurchaseCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p
|
|||
return fmt.Errorf("invalid Body")
|
||||
}
|
||||
|
||||
offer := fortnite.StaticCatalog.GetOfferById(body.OfferID)
|
||||
offer := fortnite.GetOfferByOfferId(body.OfferID)
|
||||
if offer == nil {
|
||||
return fmt.Errorf("offer not found")
|
||||
}
|
||||
|
||||
if offer.Price != body.ExpectedTotalPrice {
|
||||
if offer.TotalPrice != body.ExpectedTotalPrice {
|
||||
return fmt.Errorf("invalid price")
|
||||
}
|
||||
|
||||
|
@ -629,7 +629,7 @@ func clientPurchaseCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p
|
|||
vbucks.Save()
|
||||
profile0Vbucks.Save()
|
||||
|
||||
if offer.ProfileType != "athena" {
|
||||
if offer.Meta.ProfileId != "athena" {
|
||||
return fmt.Errorf("save the world not implemeted yet")
|
||||
}
|
||||
|
||||
|
@ -637,15 +637,16 @@ func clientPurchaseCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p
|
|||
purchase := p.NewPurchase(body.OfferID, body.ExpectedTotalPrice)
|
||||
for i := 0; i < body.PurchaseQuantity; i++ {
|
||||
for _, grant := range offer.Grants {
|
||||
if profile.Items.GetItemByTemplateID(grant) != nil {
|
||||
item := profile.Items.GetItemByTemplateID(grant)
|
||||
templateId := grant.Type.BackendValue + ":" + grant.ID
|
||||
if profile.Items.GetItemByTemplateID(templateId) != nil {
|
||||
item := profile.Items.GetItemByTemplateID(templateId)
|
||||
item.Quantity++
|
||||
go item.Save()
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
item := p.NewItem(grant, 1)
|
||||
item := p.NewItem(templateId, 1)
|
||||
person.AthenaProfile.Items.AddItem(item)
|
||||
purchase.AddLoot(item)
|
||||
|
||||
|
@ -653,7 +654,7 @@ func clientPurchaseCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p
|
|||
"itemType": item.TemplateID,
|
||||
"itemGuid": item.ID,
|
||||
"quantity": item.Quantity,
|
||||
"itemProfile": offer.ProfileType,
|
||||
"itemProfile": offer.Meta.ProfileId,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -746,12 +747,12 @@ func clientGiftCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p.Pro
|
|||
return fmt.Errorf("invalid Body")
|
||||
}
|
||||
|
||||
offer := fortnite.StaticCatalog.GetOfferById(body.OfferId)
|
||||
offer := fortnite.GetOfferByOfferId(body.OfferId)
|
||||
if offer == nil {
|
||||
return fmt.Errorf("offer not found")
|
||||
}
|
||||
|
||||
if offer.Price != body.ExpectedTotalPrice {
|
||||
if offer.TotalPrice != body.ExpectedTotalPrice {
|
||||
return fmt.Errorf("invalid price")
|
||||
}
|
||||
|
||||
|
@ -762,13 +763,13 @@ func clientGiftCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p.Pro
|
|||
}
|
||||
|
||||
for _, grant := range offer.Grants {
|
||||
if receiverPerson.AthenaProfile.Items.GetItemByTemplateID(grant) != nil {
|
||||
if receiverPerson.AthenaProfile.Items.GetItemByTemplateID(grant.Type.BackendValue + ":" + grant.ID) != nil {
|
||||
return fmt.Errorf("one or more receivers has one of the items")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
price := offer.Price * len(body.ReceiverAccountIds)
|
||||
price := offer.TotalPrice * len(body.ReceiverAccountIds)
|
||||
|
||||
vbucks := profile.Items.GetItemByTemplateID("Currency:MtxPurchased")
|
||||
if vbucks == nil {
|
||||
|
@ -793,8 +794,8 @@ func clientGiftCatalogEntryAction(c *fiber.Ctx, person *p.Person, profile *p.Pro
|
|||
receiverPerson := p.Find(receiverAccountId)
|
||||
gift := p.NewGift(body.GiftWrapTemplateId, 1, person.ID, body.PersonalMessage)
|
||||
for _, grant := range offer.Grants {
|
||||
item := p.NewItem(grant, 1)
|
||||
item.ProfileType = offer.ProfileType
|
||||
item := p.NewItem(grant.Type.BackendValue + ":" + grant.ID, 1)
|
||||
item.ProfileType = offer.Meta.ProfileId
|
||||
gift.AddLoot(item)
|
||||
}
|
||||
|
||||
|
|
|
@ -72,5 +72,6 @@ func GetSnowParties(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
func GetSnowShop(c *fiber.Ctx) error {
|
||||
return c.JSON(fortnite.StaticCatalog)
|
||||
shop := fortnite.NewRandomFortniteCatalog()
|
||||
return c.JSON(shop.GenerateFortniteCatalog())
|
||||
}
|
|
@ -21,7 +21,7 @@ func MiddlewareWebsocket(c *fiber.Ctx) error {
|
|||
protocol = "matchmaking"
|
||||
}
|
||||
|
||||
c.Locals("identifier", "ws-"+aid.RandomString(8))
|
||||
c.Locals("identifier", "ws-"+aid.RandomString(18))
|
||||
c.Locals("protocol", protocol)
|
||||
|
||||
return c.Next()
|
||||
|
|
|
@ -5,15 +5,13 @@ import (
|
|||
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/ectrc/snow/fortnite"
|
||||
"github.com/ectrc/snow/person"
|
||||
"github.com/ectrc/snow/storage"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func GetStorefrontCatalog(c *fiber.Ctx) error {
|
||||
person := c.Locals("person").(*person.Person)
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fortnite.StaticCatalog.GenerateFortniteCatalog(person))
|
||||
shop := fortnite.NewRandomFortniteCatalog()
|
||||
return c.Status(200).JSON(shop.GenerateFortniteCatalog())
|
||||
}
|
||||
|
||||
func GetStorefrontKeychain(c *fiber.Ctx) error {
|
||||
|
@ -23,5 +21,5 @@ func GetStorefrontKeychain(c *fiber.Ctx) error {
|
|||
return c.Status(fiber.StatusInternalServerError).JSON(aid.JSON{"error":err.Error()})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(keychain)
|
||||
return c.Status(200).JSON(keychain)
|
||||
}
|
|
@ -105,7 +105,7 @@ func (t *tcpServer) handle(conn net.Conn) {
|
|||
c: &conn,
|
||||
buffer: make([]byte, 1024),
|
||||
}
|
||||
tcpClient.jabber = socket.NewJabberSocket(tcpClient, "tcp-"+aid.RandomString(8), socket.JabberData{})
|
||||
tcpClient.jabber = socket.NewJabberSocket(tcpClient, "tcp-"+aid.RandomString(18), socket.JabberData{})
|
||||
socket.JabberSockets.Set(tcpClient.jabber.ID, tcpClient.jabber)
|
||||
|
||||
tcpClient.loop()
|
||||
|
|
7
main.go
7
main.go
|
@ -21,7 +21,6 @@ var configFile []byte
|
|||
|
||||
func init() {
|
||||
aid.LoadConfig(configFile)
|
||||
|
||||
var device storage.Storage
|
||||
switch aid.Config.Database.Type {
|
||||
case "postgres":
|
||||
|
@ -46,7 +45,7 @@ func init() {
|
|||
func init() {
|
||||
discord.IntialiseClient()
|
||||
fortnite.PreloadCosmetics()
|
||||
fortnite.GenerateRandomStorefront()
|
||||
fortnite.NewRandomFortniteCatalog()
|
||||
|
||||
for _, username := range aid.Config.Accounts.Gods {
|
||||
found := person.FindByDisplay(username)
|
||||
|
@ -192,8 +191,8 @@ func main() {
|
|||
r.All("*", func(c *fiber.Ctx) error { return c.Status(fiber.StatusNotFound).JSON(aid.ErrorNotFound) })
|
||||
|
||||
if aid.Config.Fortnite.Season <= 2 {
|
||||
// t := handlers.NewServer()
|
||||
// go t.Listen()
|
||||
t := handlers.NewServer()
|
||||
go t.Listen()
|
||||
}
|
||||
|
||||
err := r.Listen("0.0.0.0" + aid.Config.API.Port)
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
## What's up next?
|
||||
|
||||
- Seeded randomization for the **Item Shop** instead of a random number generator. This will ensure that even if the backend is restarted, the same random items will be in the shop during that day.
|
||||
- Purchasing the **Battle Pass**. This will require the Battle Pass Storefront ID for every build. I am yet to think of a solution for this.
|
||||
- Interaction with a Game Server to handle **Event Tracking** for player statistics and challenges. This will be a very large task as a new specialised game server will need to be created.
|
||||
- After the game server addition, a **Matchmaking System** will be added to match players together for a game. It will use a bin packing algorithm to ensure that games are filled as much as possible.
|
||||
|
@ -27,10 +26,10 @@ And once battle royale is completed ...
|
|||
- **XMPP** For interacting with friends, parties and gifting.
|
||||
- **Friends** On every build, this will allow for adding, removing and blocking friends.
|
||||
- **Party System V2** This replaces the legacy xmpp driven party system.
|
||||
- **Automatic Item Shop** Will automatically update the item shop for the day, for all builds.
|
||||
- **Gifting** Of any item shop entry to any friend.
|
||||
- **Locker Loadouts** On seasons 12 onwards, this allows for the saving and loading of multiple locker presets.
|
||||
- **Item Refunding** Of previous shop purchases, will use a refund ticket if refunded in time.
|
||||
- **Universal Item Shop** Works on all builds and will be updated every 24 hours.
|
||||
- **Client Settings Storage** Uses amazon buckets to store client settings.
|
||||
- **Support A Creator 5%** Use any display name and each purchase will give them 5% of the vbucks spent.
|
||||
- **Discord Bot** Very useful to control players, their inventory and their settings
|
||||
|
|
|
@ -3,7 +3,6 @@ package socket
|
|||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/beevik/etree"
|
||||
"github.com/ectrc/snow/aid"
|
||||
|
@ -26,11 +25,8 @@ var jabberHandlers = map[string]func(*Socket[JabberData], *etree.Document) error
|
|||
}
|
||||
|
||||
func HandleNewJabberSocket(identifier string) {
|
||||
aid.Print("new jabber handle: " + identifier)
|
||||
|
||||
socket, ok := JabberSockets.Get(identifier)
|
||||
if !ok {
|
||||
aid.Print("socket not found", identifier)
|
||||
return
|
||||
}
|
||||
defer JabberSockets.Delete(socket.ID)
|
||||
|
@ -38,7 +34,6 @@ func HandleNewJabberSocket(identifier string) {
|
|||
for {
|
||||
_, message, failed := socket.Connection.ReadMessage()
|
||||
if failed != nil {
|
||||
aid.Print("jabber message failed", failed)
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -47,14 +42,8 @@ func HandleNewJabberSocket(identifier string) {
|
|||
}
|
||||
|
||||
func JabberSocketOnMessage(socket *Socket[JabberData], message []byte) {
|
||||
if strings.Contains(string(message), `">`) {
|
||||
message = []byte(strings.ReplaceAll(string(message), `">`, `"/>`))
|
||||
}
|
||||
|
||||
aid.Print("jabber message", string(message))
|
||||
parsed := etree.NewDocument()
|
||||
if err := parsed.ReadFromString(string(message)); err != nil {
|
||||
aid.Print("jabber message failed to parse", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -63,11 +52,8 @@ func JabberSocketOnMessage(socket *Socket[JabberData], message []byte) {
|
|||
socket.Connection.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
aid.Print("jabber message handled")
|
||||
}
|
||||
|
||||
func jabberStreamHandler(socket *Socket[JabberData], parsed *etree.Document) error {
|
||||
|
|
Loading…
Reference in New Issue
Block a user