Skip to content

Commit

Permalink
Merge pull request #1764 from wowsims/fixes
Browse files Browse the repository at this point in the history
Add protos for UI database and use it to replace all_items_db.json an…
  • Loading branch information
jimmyt857 authored Nov 19, 2022
2 parents 0644297 + d1cfaea commit 97b8176
Show file tree
Hide file tree
Showing 10 changed files with 65,567 additions and 214 deletions.
2,991 changes: 2,991 additions & 0 deletions assets/database/db.bin

Large diffs are not rendered by default.

62,372 changes: 62,372 additions & 0 deletions assets/database/db.json

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions proto/ui.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,57 @@ import "api.proto";
import "common.proto";
import "paladin.proto";

// Contains all information about an Item needed by the UI.
// Generally this will include everything needed by the sim, plus some
// additional data for displaying / filtering.
message UIItem {
int32 id = 1;
string name = 2;
string icon = 3;

ItemType type = 4;
ArmorType armor_type = 5;
WeaponType weapon_type = 6;
HandType hand_type = 7;
RangedWeaponType ranged_weapon_type = 8;

repeated double stats = 9;
repeated GemColor gem_sockets = 10;
repeated double socketBonus = 11;

// Weapon stats, needed for computing proper EP for melee weapons
double weapon_damage_min = 12;
double weapon_damage_max = 13;
double weapon_speed = 14;

int32 ilvl = 15;
int32 phase = 16;
ItemQuality quality = 17;
bool unique = 18;
bool heroic = 19;

// Classes that are allowed to use the item. Empty indicates no special class restrictions.
repeated Class class_allowlist = 20;
Profession required_profession = 21;
}

message IconData {
int32 id = 1;
string name = 2;
string icon = 3;
}

// Holds all WoW data for the UI.
message UIDatabase {
repeated UIItem items = 1;
// repeated UIEnchant enchants = 2;
// repeated UIGem gems = 3;

// Entities for which we just need a name/icon.
repeated IconData item_icons = 4;
repeated IconData spell_icons = 5;
}

message DatabaseFilters {
// TODO:
// Source
Expand Down
84 changes: 0 additions & 84 deletions tools/gen_web_db/main.go

This file was deleted.

44 changes: 39 additions & 5 deletions tools/generate_items/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,24 @@ type GemData struct {
Override GemOverride
}

type SpellData struct {
ID int
Response ItemResponse
}

type WowDatabase struct {
items []ItemData
gems []GemData
items []ItemData
gems []GemData
spells []SpellData
}

func NewWowDatabase(itemOverrides []ItemOverride, gemOverrides []GemOverride, tooltipsDB map[int]WowheadItemResponse) *WowDatabase {
func NewWowDatabase(itemOverrides []ItemOverride, gemOverrides []GemOverride, itemTooltipsDB map[int]WowheadItemResponse, spellTooltipsDB map[int]WowheadItemResponse) *WowDatabase {
db := &WowDatabase{}

for _, itemOverride := range itemOverrides {
itemData := ItemData{
Override: itemOverride,
Response: tooltipsDB[itemOverride.ID],
Response: itemTooltipsDB[itemOverride.ID],
}
if itemData.Response.GetName() == "" {
continue
Expand All @@ -61,14 +67,21 @@ func NewWowDatabase(itemOverrides []ItemOverride, gemOverrides []GemOverride, to
for _, gemOverride := range gemOverrides {
gemData := GemData{
Override: gemOverride,
Response: tooltipsDB[gemOverride.ID],
Response: itemTooltipsDB[gemOverride.ID],
}
if gemData.Response.GetName() == "" {
continue
}
db.gems = append(db.gems, gemData)
}

for spellID, spellResponse := range spellTooltipsDB {
db.spells = append(db.spells, SpellData{
ID: spellID,
Response: spellResponse,
})
}

slices.SortStableFunc(db.items, func(i1, i2 ItemData) bool {
if i1.Response.GetName() == i2.Response.GetName() {
return i1.Override.ID < i2.Override.ID
Expand All @@ -83,6 +96,13 @@ func NewWowDatabase(itemOverrides []ItemOverride, gemOverrides []GemOverride, to
return g1.Response.GetName() < g2.Response.GetName()
})

slices.SortStableFunc(db.spells, func(s1, s2 SpellData) bool {
if s1.Response.GetName() == s2.Response.GetName() {
return s1.ID < s2.ID
}
return s1.Response.GetName() < s2.Response.GetName()
})

return db
}

Expand Down Expand Up @@ -166,3 +186,17 @@ func (db *WowDatabase) getSimmableGems() []GemData {

return included
}

func (db *WowDatabase) toUIDatabase() *proto.UIDatabase {
uiDB := &proto.UIDatabase{}
for _, itemData := range db.items {
uiDB.ItemIcons = append(uiDB.ItemIcons, &proto.IconData{Id: int32(itemData.Override.ID), Name: itemData.Response.GetName(), Icon: itemData.Response.GetIcon()})
}
for _, gemData := range db.gems {
uiDB.ItemIcons = append(uiDB.ItemIcons, &proto.IconData{Id: int32(gemData.Override.ID), Name: gemData.Response.GetName(), Icon: gemData.Response.GetIcon()})
}
for _, spellData := range db.spells {
uiDB.SpellIcons = append(uiDB.SpellIcons, &proto.IconData{Id: int32(spellData.ID), Name: spellData.Response.GetName(), Icon: spellData.Response.GetIcon()})
}
return uiDB
}
6 changes: 5 additions & 1 deletion tools/generate_items/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ func main() {
panic("outDir flag is required!")
}

db := NewWowDatabase(getItemOverrides(), getGemOverrides(), getWowheadTooltipsDB())
db := NewWowDatabase(
getItemOverrides(),
getGemOverrides(),
getWowheadTooltipsDB("./assets/item_data/all_item_tooltips.csv"),
getWowheadTooltipsDB("./assets/spell_data/all_spell_tooltips.csv"))

writeItemFile(*outDir, db.getSimmableItems())
writeGemFile(*outDir, db.getSimmableGems())
Expand Down
6 changes: 3 additions & 3 deletions tools/generate_items/readers.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ func getItemOverrides() []ItemOverride {

// Returns the prefetched list of all wowhead tooltips.
// Maps item IDs to tooltip strings.
func getWowheadTooltipsDB() map[int]WowheadItemResponse {
file, err := os.Open("./assets/item_data/all_item_tooltips.csv")
func getWowheadTooltipsDB(filepath string) map[int]WowheadItemResponse {
file, err := os.Open(filepath)
if err != nil {
log.Fatalf("Failed to open all_item_tooltips.csv: %s", err)
log.Fatalf("Failed to open %s: %s", filepath, err)
}
defer file.Close()

Expand Down
58 changes: 36 additions & 22 deletions tools/generate_items/writers.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package main

import (
"encoding/json"
"fmt"
"log"
"os"
"strings"

"github.com/wowsims/wotlk/sim/core/proto"
"github.com/wowsims/wotlk/sim/core/stats"
protojson "google.golang.org/protobuf/encoding/protojson"
googleProto "google.golang.org/protobuf/proto"
)

func writeItemFile(outDir string, itemsData []ItemData) {
Expand Down Expand Up @@ -78,35 +79,48 @@ var Gems = []Gem{
}

func writeDatabaseFile(db *WowDatabase) {
type tempItemIcon struct {
ID int
Name string
Icon string
}
uiDB := db.toUIDatabase()

var tempItems []tempItemIcon
for _, gemData := range db.gems {
tempItems = append(tempItems, tempItemIcon{ID: gemData.Override.ID, Name: gemData.Response.GetName(), Icon: gemData.Response.GetIcon()})
}
for _, itemData := range db.items {
tempItems = append(tempItems, tempItemIcon{ID: itemData.Override.ID, Name: itemData.Response.GetName(), Icon: itemData.Response.GetIcon()})
// Write database as a binary file.
outbytes, err := googleProto.Marshal(uiDB)
if err != nil {
log.Fatalf("[ERROR] Failed to marshal db: %s", err.Error())
}
os.WriteFile("./assets/database/db.bin", outbytes, 0666)

// Also write in JSON format so we can manually inspect the contents.
// Write it out line-by-line so we can have 1 line / item, making it more human-readable.
itemDB := &strings.Builder{}
itemDB.WriteString("[\n")
for i, item := range tempItems {
itemJson, err := json.Marshal(item)
builder := &strings.Builder{}
builder.WriteString("{\n")

builder.WriteString("\"itemIcons\":[\n")
for i, icon := range uiDB.ItemIcons {
json, err := protojson.MarshalOptions{}.Marshal(icon)
if err != nil {
log.Printf("[ERROR] Failed to marshal icon: %s", err.Error())
}
builder.WriteString(string(json))
if i != len(uiDB.ItemIcons)-1 {
builder.WriteString(",\n")
}
}
builder.WriteString("],\n")

builder.WriteString("\"spellIcons\":[\n")
for i, icon := range uiDB.SpellIcons {
json, err := protojson.MarshalOptions{}.Marshal(icon)
if err != nil {
log.Fatalf("failed to marshal: %s", err)
log.Printf("[ERROR] Failed to marshal icon: %s", err.Error())
}
itemDB.WriteString(string(itemJson))
if i != len(tempItems)-1 {
itemDB.WriteString(",\n")
builder.WriteString(string(json))
if i != len(uiDB.SpellIcons)-1 {
builder.WriteString(",\n")
}
}
itemDB.WriteString("]")
os.WriteFile("./assets/item_data/all_items_db.json", []byte(itemDB.String()), 0666)
builder.WriteString("]\n")

builder.WriteString("}")
os.WriteFile("./assets/database/db.json", []byte(builder.String()), 0666)
}

func gemToGoString(gemOverride GemOverride, gemResponse ItemResponse) string {
Expand Down
Loading

0 comments on commit 97b8176

Please sign in to comment.