diff --git a/main.go b/main.go index d6ec417..5175bdb 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,8 @@ import ( "path/filepath" "fmt" "os" + "strings" + "strconv" "github.com/alexflint/go-arg" _ "github.com/mattn/go-sqlite3" @@ -41,17 +43,62 @@ func extractDb(saveData []byte) (int, int, error) { } var queries = map[string]string{ - "galleons": `UPDATE "InventoryDynamic" SET "Count" = %d WHERE "CharacterID" = "Player0" AND "ItemID" = "Knuts"`, - "xp": `UPDATE "MiscDataDynamic" SET "DataValue" = %d WHERE "DataName" = "ExperiencePoints"`, - "first_name": `UPDATE "MiscDataDynamic" SET "DataValue" = "%s" WHERE "DataName" = "PlayerFirstName"`, - "surname": `UPDATE "MiscDataDynamic" SET "DataValue" = "%s" WHERE "DataName" = "PlayerLastName"`, - "inventory_size": `UPDATE "MiscDataDynamic" SET "DataValue" = %d WHERE "DataName" = "BaseInventoryCapacity"`, + "galleons": `UPDATE "InventoryDynamic" SET "Count" = %d WHERE "CharacterID" = "Player0" AND "ItemID" = "Knuts"`, + "xp": `UPDATE "MiscDataDynamic" SET "DataValue" = %d WHERE "DataName" = "ExperiencePoints"`, + "first_name": `UPDATE "MiscDataDynamic" SET "DataValue" = "%s" WHERE "DataName" = "PlayerFirstName"`, + "surname": `UPDATE "MiscDataDynamic" SET "DataValue" = "%s" WHERE "DataName" = "PlayerLastName"`, + "inventory_size": `UPDATE "MiscDataDynamic" SET "DataValue" = %d WHERE "DataName" = "BaseInventoryCapacity"`, + "inventory_quant": `UPDATE "InventoryDynamic" SET "Count" = %d WHERE "CharacterID" = "Player0" AND "HolderID" = "ResourceInventory" AND LOWER(ItemId) = "%s"`, +} + +func containsItemId(parsed []*ItemPairs, itemId string) bool { + for _, pair := range parsed { + if pair.ItemID == itemId { + return true + } + } + return false +} + +func parseInvPairs(pairs []string) ([]*ItemPairs, error) { + pairsLen := len(pairs) + if pairsLen%2 !=0 { + return nil, errors.New("item quantity pairs can't be odd") + } + + var parsed []*ItemPairs + + for i := 0; i < pairsLen; i+=2 { + itemId := strings.ToLower(pairs[i]) + quantity, err := strconv.ParseInt(pairs[i+1], 10, 64) + if err != nil { + return nil, err + } + pair := &ItemPairs{ + ItemID: itemId, + Quantity: quantity, + } + if containsItemId(parsed, itemId) { + fmt.Println("filtered pair with same item ID:", pair) + continue + } + + parsed = append(parsed, pair) + } + + return parsed, nil } func parseArgs() (*Args, error) { var args Args arg.MustParse(&args) - + if len(args.ItemQuantities) > 0 { + invPairs, err := parseInvPairs(args.ItemQuantities) + if err != nil { + return nil, err + } + args.ParsedItemQuants = invPairs + } if args.XP < 0 { return nil, errors.New("xp can't be negative") } @@ -63,7 +110,7 @@ func parseArgs() (*Args, error) { return nil, errors.New("inventory size can't be less than 20") } - if !args.Probe && args.XP == 0 && args.Galleons == 0 && args.InventorySize == 0 && args.FirstName == "" && args.Surname == "" { + if !args.Probe && args.XP == 0 && args.Galleons == 0 && args.InventorySize == 0 && len(args.ItemQuantities) < 1 && args.FirstName == "" && args.Surname == "" { return nil, errors.New("no write arguments were provided") } @@ -205,7 +252,18 @@ func main() { db.Close() panic(err) } - } + } + + if len(args.ItemQuantities) > 0 { + for _, pair := range args.ParsedItemQuants { + err = updateRow(db, fmt.Sprintf(queries["inventory_quant"], pair.Quantity, pair.ItemID)) + if err != nil { + db.Close() + panic(err) + } + } + } + db.Close() updatedDbBytes, err := os.ReadFile(dbPath) if err != nil { diff --git a/probe/probe.go b/probe/probe.go index 425223f..e709943 100644 --- a/probe/probe.go +++ b/probe/probe.go @@ -113,8 +113,25 @@ func Run(db *sql.DB) error { } fmt.Printf( - "Name: %s\nXP: %d\nHouse: %s\nGalleons: %d\nInventory size: %d", + "Name: %s\nXP: %d\nHouse: %s\nGalleons: %d\nInventory size: %d\n\n", playerName, xp, house, galleons, inv_size, ) + + fmt.Println("Inventory:") + var itemId string + var quantity int64 + + rows, err := db.Query(`SELECT "ItemID", "Count" FROM "InventoryDynamic" WHERE "CharacterID" = "Player0" AND "HolderID" = "ResourceInventory"`) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + err = rows.Scan(&itemId, &quantity) + if err != nil { + return err + } + fmt.Printf("%s, %d\n", itemId, quantity) + } return nil } \ No newline at end of file diff --git a/structs.go b/structs.go index 47020bd..47c9857 100644 --- a/structs.go +++ b/structs.go @@ -1,12 +1,19 @@ package main type Args struct { - InPath string `arg:"-i, required" help:"Path of input save file."` - OutPath string `arg:"-o" help:"Path of output save file."` - XP int `arg:"--xp" help:"Set XP."` - Galleons int `arg:"--galleons" help:"Set Galleons."` - FirstName string `arg:"--first-name" help:"Set character first name."` - Surname string `arg:"--last-name" help:"Set character last name."` - InventorySize int `arg:"--inventory-size" help:"Set inventory size."` - Probe bool `arg:"-p" help:"Probe save file and exit."` + InPath string `arg:"-i, required" help:"Path of input save file."` + OutPath string `arg:"-o" help:"Path of output save file."` + XP int `arg:"--xp" help:"Set XP."` + Galleons int `arg:"--galleons" help:"Set Galleons."` + FirstName string `arg:"--first-name" help:"Set character first name."` + Surname string `arg:"--last-name" help:"Set character last name."` + InventorySize int `arg:"--inventory-size" help:"Set inventory size."` + Probe bool `arg:"-p" help:"Probe save file and exit."` + ItemQuantities []string `arg:"--item-quantities" help:"Set quantities of inventory items. pairs separated by spaces."` + ParsedItemQuants []*ItemPairs `arg:"-"` +} + +type ItemPairs struct { + ItemID string + Quantity int64 } \ No newline at end of file