T5 products in the client's inventory
CI / build (push) Successful in 25s

The inventory's product list (test.showInventory) gets the community products the person has: local packs, and
hub products in their library. Hiding one is answered by the proxy (and removes a hub product from the library).
When the library changes, the client is told to load its inventory again, with the server event IMVU sends
after a purchase. A product whose revision or info changes gets a new local ID, since the client keeps product
info for good; names lose characters the client's pages could take as HTML.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-29 18:59:52 -07:00
1 parent c281fb572c
commit ca7a86ce89
8 files changed
+225 -5

No files matched your search

+17 -1
View File
@@ -50,6 +50,13 @@ type Products struct {
// Want, if set, is asked for products someone in a room wears that aren't here (the fetcher gets hub products).
Want func(id string)
// HubDir is the pack root of products from the hub; of those, only ones Owned says are in the person's library
// are in the inventory (the rest are there because someone in a room wears them). Local packs always are.
HubDir string
Owned func(id string) bool
// OnHide, if set, hears that the person hid a community product in the inventory (removing it from their
// library, for hub products).
OnHide func(id string)
roomMu sync.Mutex
room room
@@ -204,7 +211,7 @@ func (p *Products) loadLocked(dir, fp string) (*served, error) {
if err != nil {
return nil, err
}
local, err := p.state.localID(pk.Manifest.ID)
local, err := p.state.localID(versionKey(pk))
if err != nil {
return nil, err
}
@@ -224,6 +231,15 @@ func (p *Products) loadLocked(dir, fp string) (*served, error) {
return &served{dir: dir, fingerprint: fp, pack: pk, local: local, cfl: buf.Bytes(), checksum: hex.EncodeToString(sum[:])}, nil
}
// versionKey names a version of a product for its local ID: the revision and the info the client shows. The client
// keeps product info for good (its product info cache), so a product whose files or info changed gets a new local
// ID, and with it fresh info.
func versionKey(pk *pack.Pack) string {
m := pk.Manifest
sum := md5.Sum([]byte(strings.Join([]string{m.Name, m.Creator, m.Rating}, "|")))
return fmt.Sprintf("%s@%d.%s", m.ID, m.Revision, hex.EncodeToString(sum[:4]))
}
// fingerprint changes when anything in the pack directory (or its files/ directory) changes.
func fingerprint(dir string) string {
var b strings.Builder