Automatic Profile Changes
This commit is contained in:
parent
4607e42476
commit
347e1f6c02
|
@ -10,6 +10,7 @@ type CS struct {
|
|||
Database struct {
|
||||
URI string
|
||||
Type string
|
||||
DropAllTables bool
|
||||
}
|
||||
Output struct {
|
||||
Level string
|
||||
|
@ -33,6 +34,7 @@ func LoadConfig() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
Config.Database.DropAllTables = cfg.Section("database").Key("drop").MustBool(false)
|
||||
Config.Database.URI = cfg.Section("database").Key("uri").String()
|
||||
if Config.Database.URI == "" {
|
||||
panic("Database URI is empty")
|
||||
|
|
|
@ -6,6 +6,14 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func Print(v ...interface{}) {
|
||||
if Config.Output.Level == "prod" {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(v...)
|
||||
}
|
||||
|
||||
func PrintJSON(v interface{}) {
|
||||
if Config.Output.Level == "prod" || Config.Output.Level == "time" {
|
||||
return
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
uri="host=localhost user=postgres password=pass dbname=snow port=5432 sslmode=disable"
|
||||
; postgres
|
||||
type="postgres"
|
||||
; drop all tables at start of program
|
||||
drop=false
|
||||
|
||||
[output]
|
||||
; level of logging
|
||||
level="dev" # dev, prod
|
||||
; info = everything
|
||||
; time = only time taken
|
||||
; prod = only errors
|
||||
level="info"
|
65
main.go
65
main.go
|
@ -5,21 +5,16 @@ import (
|
|||
"github.com/ectrc/snow/person"
|
||||
"github.com/ectrc/snow/storage"
|
||||
)
|
||||
|
||||
const (
|
||||
DROP_TABLES = true
|
||||
)
|
||||
|
||||
func init() {
|
||||
aid.LoadConfig()
|
||||
|
||||
var device storage.Storage
|
||||
|
||||
switch aid.Config.Database.Type {
|
||||
case "postgres":
|
||||
postgresStorage := storage.NewPostgresStorage()
|
||||
|
||||
if DROP_TABLES {
|
||||
if aid.Config.Database.DropAllTables {
|
||||
aid.Print("Dropping all tables")
|
||||
postgresStorage.DropTables()
|
||||
}
|
||||
|
||||
|
@ -41,63 +36,17 @@ func init() {
|
|||
}
|
||||
|
||||
func init() {
|
||||
if DROP_TABLES {
|
||||
user := person.NewPerson()
|
||||
{
|
||||
user.CommonCoreProfile.Attributes.AddAttribute(person.NewAttribute("xp", 1030))
|
||||
user.CommonCoreProfile.Attributes.AddAttribute(person.NewAttribute("level", 100))
|
||||
user.CommonCoreProfile.Attributes.AddAttribute(person.NewAttribute("quest_manager", aid.JSON{}))
|
||||
|
||||
user.CommonCoreProfile.Items.AddItem(person.NewItem("Currency:MtxPurchased", 100))
|
||||
user.CommonCoreProfile.Items.AddItem(person.NewItem("Token:CampaignAccess", 1))
|
||||
|
||||
quest := person.NewQuest("Quest:Quest_1", "ChallengeBundle:Daily_1", "ChallengeBundleSchedule:Paid_1")
|
||||
{
|
||||
quest.AddObjective("quest_objective_eliminateplayers", 0)
|
||||
quest.AddObjective("quest_objective_top1", 0)
|
||||
quest.AddObjective("quest_objective_place_top10", 0)
|
||||
|
||||
quest.UpdateObjectiveCount("quest_objective_eliminateplayers", 10)
|
||||
quest.UpdateObjectiveCount("quest_objective_place_top10", -3)
|
||||
|
||||
quest.RemoveObjective("quest_objective_top1")
|
||||
}
|
||||
user.AthenaProfile.Quests.AddQuest(quest)
|
||||
|
||||
giftBox := person.NewGift("GiftBox:GB_Default", 1, user.ID, "Hello, Bully!")
|
||||
{
|
||||
giftBox.AddLoot(person.NewItemWithType("AthenaCharacter:CID_002_Athena_Commando_F_Default", 1, "athena"))
|
||||
}
|
||||
user.CommonCoreProfile.Gifts.AddGift(giftBox)
|
||||
}
|
||||
user.Save()
|
||||
|
||||
snapshot := user.CommonCoreProfile.Snapshot()
|
||||
{
|
||||
vbucks := user.CommonCoreProfile.Items.GetItemByTemplateID("Currency:MtxPurchased")
|
||||
vbucks.Quantity = 200
|
||||
vbucks.Favorite = true
|
||||
|
||||
user.CommonCoreProfile.Items.DeleteItem(user.CommonCoreProfile.Items.GetItemByTemplateID("Token:CampaignAccess").ID)
|
||||
user.CommonCoreProfile.Items.AddItem(person.NewItem("Token:ReceiveMtxCurrency", 1))
|
||||
}
|
||||
user.CommonCoreProfile.Diff(snapshot)
|
||||
user.Save()
|
||||
}
|
||||
|
||||
go storage.Cache.CacheKiller()
|
||||
}
|
||||
|
||||
func main() {
|
||||
var users []*person.Person
|
||||
|
||||
aid.PrintTime("Fetching Persons", func() {
|
||||
users = person.AllFromDatabase()
|
||||
users := person.AllFromDatabase()
|
||||
aid.Print("Found", len(users), "users")
|
||||
for _, user := range users {
|
||||
aid.Print(user.ID)
|
||||
}
|
||||
})
|
||||
|
||||
for _, user := range users {
|
||||
aid.PrintJSON(user.Snapshot())
|
||||
}
|
||||
|
||||
// aid.WaitForExit()
|
||||
}
|
|
@ -2,10 +2,6 @@ package person
|
|||
|
||||
import "github.com/ectrc/snow/aid"
|
||||
|
||||
type ProfileChange struct {
|
||||
ChangeType string `json:"changeType"`
|
||||
}
|
||||
|
||||
type FullProfileUpdate struct {
|
||||
ChangeType string `json:"changeType"`
|
||||
Profile aid.JSON `json:"profile"`
|
||||
|
|
|
@ -3,6 +3,7 @@ package person
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/ectrc/snow/storage"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
@ -47,6 +48,34 @@ func FromDatabaseGift(gift *storage.DB_Gift) *Gift {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *Gift) GenerateFortniteGiftEntry() aid.JSON {
|
||||
json := aid.JSON{
|
||||
"templateId": g.TemplateID,
|
||||
"attributes": aid.JSON{
|
||||
"params": aid.JSON{},
|
||||
"lootList": []aid.JSON{},
|
||||
"fromAccountId": g.FromID,
|
||||
"giftedOn": time.Unix(g.GiftedAt, 0).Format(time.RFC3339),
|
||||
},
|
||||
"quantity": 1,
|
||||
}
|
||||
|
||||
for _, loot := range g.Loot {
|
||||
json["attributes"].(aid.JSON)["lootList"] = append(json["attributes"].(aid.JSON)["lootList"].([]aid.JSON), aid.JSON{
|
||||
"itemGuid": loot.ID,
|
||||
"itemType": loot.TemplateID,
|
||||
"itemProfile": loot.ProfileType,
|
||||
"quantity": loot.Quantity,
|
||||
})
|
||||
}
|
||||
|
||||
if g.Message != "" {
|
||||
json["attributes"].(aid.JSON)["params"].(aid.JSON)["userMessage"] = g.Message
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
func (g *Gift) AddLoot(loot *Item) {
|
||||
g.Loot = append(g.Loot, loot)
|
||||
//storage.Repo.SaveGiftLoot(g.ID, loot)
|
||||
|
|
|
@ -70,10 +70,10 @@ func FromDatabaseLoot(item *storage.DB_Loot) *Item {
|
|||
}
|
||||
|
||||
func (i *Item) GenerateFortniteItemEntry() aid.JSON {
|
||||
varaints := []aid.JSON{}
|
||||
variants := []aid.JSON{}
|
||||
|
||||
for _, variant := range i.Variants {
|
||||
varaints = append(varaints, aid.JSON{
|
||||
variants = append(variants, aid.JSON{
|
||||
"channel": variant.Channel,
|
||||
"owned": variant.Owned,
|
||||
"active": variant.Active,
|
||||
|
@ -83,7 +83,7 @@ func (i *Item) GenerateFortniteItemEntry() aid.JSON {
|
|||
return aid.JSON{
|
||||
"templateId": i.TemplateID,
|
||||
"attributes": aid.JSON{
|
||||
"variants": varaints,
|
||||
"variants": variants,
|
||||
"favorite": i.Favorite,
|
||||
"item_seen": i.HasSeen,
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ type Profile struct {
|
|||
Quests *QuestMutex
|
||||
Attributes *AttributeMutex
|
||||
Type string
|
||||
Revision int
|
||||
Revision int
|
||||
Changes []interface{}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ func NewProfile(profile string) *Profile {
|
|||
Attributes: NewAttributeMutex(),
|
||||
Type: profile,
|
||||
Revision: 0,
|
||||
Changes: []interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,8 +119,6 @@ func (p *Profile) Diff(snapshot *ProfileSnapshot) []diff.Change {
|
|||
return nil
|
||||
}
|
||||
|
||||
// aid.PrintJSON(changes)
|
||||
|
||||
for _, change := range changes {
|
||||
switch change.Path[0] {
|
||||
case "Items":
|
||||
|
@ -138,12 +137,75 @@ func (p *Profile) Diff(snapshot *ProfileSnapshot) []diff.Change {
|
|||
if change.Type == "update" && change.Path[2] != "Quantity" {
|
||||
p.CreateItemAttributeChangedChange(p.Items.GetItem(change.Path[1]), change.Path[2])
|
||||
}
|
||||
case "Quests":
|
||||
if change.Type == "create" && change.Path[2] == "ID" {
|
||||
p.CreateQuestAddedChange(p.Quests.GetQuest(change.Path[1]))
|
||||
}
|
||||
|
||||
if change.Type == "delete" && change.Path[2] == "ID" {
|
||||
p.CreateItemRemovedChange(change.Path[1])
|
||||
}
|
||||
case "Gifts":
|
||||
if change.Type == "create" && change.Path[2] == "ID" {
|
||||
p.CreateGiftAddedChange(p.Gifts.GetGift(change.Path[1]))
|
||||
}
|
||||
|
||||
if change.Type == "delete" && change.Path[2] == "ID" {
|
||||
p.CreateItemRemovedChange(change.Path[1])
|
||||
}
|
||||
case "Attributes":
|
||||
if change.Type == "create" && change.Path[2] == "ID" {
|
||||
p.CreateStatModifiedChange(p.Attributes.GetAttribute(change.Path[1]))
|
||||
}
|
||||
|
||||
if change.Type == "update" && change.Path[2] == "Value" {
|
||||
p.CreateStatModifiedChange(p.Attributes.GetAttribute(change.Path[1]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
func (p *Profile) CreateStatModifiedChange(attribute *Attribute) {
|
||||
if attribute == nil {
|
||||
fmt.Println("error getting attribute from profile", attribute.ID)
|
||||
return
|
||||
}
|
||||
|
||||
p.Changes = append(p.Changes, StatModified{
|
||||
ChangeType: "statModified",
|
||||
Name: attribute.Key,
|
||||
Value: attribute.Value,
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Profile) CreateGiftAddedChange(gift *Gift) {
|
||||
if gift == nil {
|
||||
fmt.Println("error getting gift from profile", gift.ID)
|
||||
return
|
||||
}
|
||||
|
||||
p.Changes = append(p.Changes, ItemAdded{
|
||||
ChangeType: "itemAdded",
|
||||
ItemId: gift.ID,
|
||||
Item: gift.GenerateFortniteGiftEntry(),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Profile) CreateQuestAddedChange(quest *Quest) {
|
||||
if quest == nil {
|
||||
fmt.Println("error getting quest from profile", quest.ID)
|
||||
return
|
||||
}
|
||||
|
||||
p.Changes = append(p.Changes, ItemAdded{
|
||||
ChangeType: "itemAdded",
|
||||
ItemId: quest.ID,
|
||||
Item: quest.GenerateFortniteQuestEntry(),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Profile) CreateItemAddedChange(item *Item) {
|
||||
if item == nil {
|
||||
fmt.Println("error getting item from profile", item.ID)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package person
|
||||
|
||||
import (
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/ectrc/snow/storage"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
@ -8,6 +9,7 @@ import (
|
|||
type Quest struct {
|
||||
ID string
|
||||
TemplateID string
|
||||
State string
|
||||
Objectives []string
|
||||
ObjectiveCounts []int64
|
||||
BundleID string
|
||||
|
@ -18,6 +20,7 @@ func NewQuest(templateID string, bundleID string, scheduleID string) *Quest {
|
|||
return &Quest{
|
||||
ID: uuid.New().String(),
|
||||
TemplateID: templateID,
|
||||
State: "Active",
|
||||
Objectives: []string{},
|
||||
ObjectiveCounts: []int64{},
|
||||
BundleID: bundleID,
|
||||
|
@ -25,10 +28,21 @@ func NewQuest(templateID string, bundleID string, scheduleID string) *Quest {
|
|||
}
|
||||
}
|
||||
|
||||
func NewDailyQuest(templateID string) *Quest {
|
||||
return &Quest{
|
||||
ID: uuid.New().String(),
|
||||
TemplateID: templateID,
|
||||
State: "Active",
|
||||
Objectives: []string{},
|
||||
ObjectiveCounts: []int64{},
|
||||
}
|
||||
}
|
||||
|
||||
func FromDatabaseQuest(quest *storage.DB_Quest, profileType *string) *Quest {
|
||||
return &Quest{
|
||||
ID: quest.ID,
|
||||
TemplateID: quest.TemplateID,
|
||||
State: quest.State,
|
||||
Objectives: quest.Objectives,
|
||||
ObjectiveCounts: quest.ObjectiveCounts,
|
||||
BundleID: quest.BundleID,
|
||||
|
@ -36,6 +50,23 @@ func FromDatabaseQuest(quest *storage.DB_Quest, profileType *string) *Quest {
|
|||
}
|
||||
}
|
||||
|
||||
func (q *Quest) GenerateFortniteQuestEntry() aid.JSON {
|
||||
json := aid.JSON{
|
||||
"templateId": q.TemplateID,
|
||||
"attributes": aid.JSON{
|
||||
"quest_state": q.State,
|
||||
"challenge_bundle_id": q.BundleID,
|
||||
},
|
||||
"quantity": 1,
|
||||
}
|
||||
|
||||
for i, objective := range q.Objectives {
|
||||
json["attributes"].(aid.JSON)["completion_" + objective] = q.ObjectiveCounts[i]
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
||||
func (q *Quest) Delete() {
|
||||
storage.Repo.DeleteQuest(q.ID)
|
||||
}
|
||||
|
@ -98,6 +129,7 @@ func (q *Quest) ToDatabase(profileId string) *storage.DB_Quest {
|
|||
ProfileID: profileId,
|
||||
ID: q.ID,
|
||||
TemplateID: q.TemplateID,
|
||||
State: q.State,
|
||||
Objectives: q.Objectives,
|
||||
ObjectiveCounts: q.ObjectiveCounts,
|
||||
BundleID: q.BundleID,
|
||||
|
|
|
@ -165,17 +165,17 @@ func NewAttributeMutex() *AttributeMutex {
|
|||
}
|
||||
|
||||
func (m *AttributeMutex) AddAttribute(attribute *Attribute) {
|
||||
m.Store(attribute.Key, attribute)
|
||||
m.Store(attribute.ID, attribute)
|
||||
// storage.Repo.SaveAttribute(key, value)
|
||||
}
|
||||
|
||||
func (m *AttributeMutex) DeleteAttribute(key string) {
|
||||
m.Delete(key)
|
||||
func (m *AttributeMutex) DeleteAttribute(id string) {
|
||||
m.Delete(id)
|
||||
// storage.Repo.DeleteAttribute(key)
|
||||
}
|
||||
|
||||
func (m *AttributeMutex) GetAttribute(key string) *Attribute {
|
||||
value, ok := m.Load(key)
|
||||
func (m *AttributeMutex) GetAttribute(id string) *Attribute {
|
||||
value, ok := m.Load(id)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
@ -183,8 +183,32 @@ func (m *AttributeMutex) GetAttribute(key string) *Attribute {
|
|||
return value.(*Attribute)
|
||||
}
|
||||
|
||||
func (m *AttributeMutex) RangeAttributes(f func(key string, value *Attribute) bool) {
|
||||
func (m *AttributeMutex) GetAttributeByKey(key string) *Attribute {
|
||||
var found *Attribute
|
||||
|
||||
m.RangeAttributes(func(id string, attribute *Attribute) bool {
|
||||
if attribute.Key == key {
|
||||
found = attribute
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return found
|
||||
}
|
||||
|
||||
func (m *AttributeMutex) RangeAttributes(f func(id string, attribute *Attribute) bool) {
|
||||
m.Range(func(key, value interface{}) bool {
|
||||
return f(key.(string), value.(*Attribute))
|
||||
})
|
||||
}
|
||||
|
||||
func (m *AttributeMutex) Count() int {
|
||||
count := 0
|
||||
m.Range(func(key, value interface{}) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
return count
|
||||
}
|
34
readme.md
34
readme.md
|
@ -11,34 +11,22 @@ Performance first, universal Fortnite backend written in Go.
|
|||
|
||||
## Examples
|
||||
|
||||
### Person Structure
|
||||
### Quests
|
||||
|
||||
```golang
|
||||
user := person.NewPerson()
|
||||
{
|
||||
user.CommonCoreProfile.Items.AddItem(person.NewItem("Currency:MtxPurchased", 100))
|
||||
user.CommonCoreProfile.Items.AddItem(person.NewItem("Token:CampaignAccess", 1))
|
||||
schedule := person.NewItem("ChallengeBundleSchedule:Paid_1", 1)
|
||||
user.AthenaProfile.Items.AddItem(schedule)
|
||||
|
||||
quest := person.NewQuest("Quest:Quest_1", "ChallengeBundle:Daily_1", "ChallengeBundleSchedule:Paid_1")
|
||||
{
|
||||
quest.AddObjective("quest_objective_eliminateplayers", 0)
|
||||
quest.AddObjective("quest_objective_top1", 0)
|
||||
quest.AddObjective("quest_objective_place_top10", 0)
|
||||
bundle := person.NewItem("ChallengeBundle:Daily_1", 1)
|
||||
user.AthenaProfile.Items.AddItem(bundle)
|
||||
|
||||
quest.UpdateObjectiveCount("quest_objective_eliminateplayers", 10)
|
||||
quest.UpdateObjectiveCount("quest_objective_place_top10", -3)
|
||||
quest := person.NewQuest("Quest:Quest_2", bundle.ID, schedule.ID)
|
||||
quest.AddObjective("quest_objective_eliminateplayers", 0)
|
||||
user.AthenaProfile.Quests.AddQuest(quest)
|
||||
|
||||
quest.RemoveObjective("quest_objective_top1")
|
||||
}
|
||||
user.AthenaProfile.Quests.AddQuest(quest)
|
||||
|
||||
giftBox := person.NewGift("GiftBox:GB_Default", 1, user.ID, "Hello, Bully!")
|
||||
{
|
||||
giftBox.AddLoot(person.NewItemWithType("AthenaCharacter:CID_002_Athena_Commando_F_Default", 1, "athena"))
|
||||
}
|
||||
user.CommonCoreProfile.Gifts.AddGift(giftBox)
|
||||
}
|
||||
user.Save()
|
||||
daily := person.NewDailyQuest("Quest:Quest_3")
|
||||
daily.AddObjective("quest_objective_place_top10", 0)
|
||||
user.AthenaProfile.Quests.AddQuest(daily)
|
||||
```
|
||||
|
||||
### Profile Changes
|
||||
|
|
|
@ -27,14 +27,14 @@ func (m *PersonsCache) CacheKiller() {
|
|||
Cache.Range(func(key, value interface{}) bool {
|
||||
cacheEntry := value.(*CacheEntry)
|
||||
|
||||
if time.Since(cacheEntry.LastAccessed) >= 5 * time.Minute {
|
||||
if time.Since(cacheEntry.LastAccessed) >= 30 * time.Minute {
|
||||
Cache.Delete(key)
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
time.Sleep(5 * time.Minute)
|
||||
time.Sleep(5000 * time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ type DB_Quest struct {
|
|||
ID string `gorm:"primary_key"`
|
||||
ProfileID string
|
||||
TemplateID string
|
||||
State string
|
||||
Objectives pq.StringArray `gorm:"type:text[]"`
|
||||
ObjectiveCounts pq.Int64Array `gorm:"type:bigint[]"`
|
||||
BundleID string
|
||||
|
|
Loading…
Reference in New Issue
Block a user