Commit graph

220 commits

Author SHA1 Message Date
42e7eabdd8 Fix modeling bug where compatible_body_ids field was not updating
Ah right, the callbacks in `ParentSwfAssetRelationship` don't get
called when Rails does automatic join-model management stuff. We need
the `Item` to call its `update_cached_fields` callback itself, too!

When fixing this, I found a new bug that arose, in how we infer
`body_id` for assets that fit all pets. Fixing that next!
2024-11-06 13:39:32 -08:00
9eaee4a2d4 Refactor item modeling
Simpler, more encapsulated, and fixes the pending jank stuff in the
tests!
2024-11-03 12:05:37 -08:00
540ce08caa Handle invalid Item state a bit better
Catch missing fields in validation before sending it to the DB, and
skip the Dyeworks stuff if the name is missing.

I ran into this looking into `test/trade_activity_test.rb`, which fails
right now because we try to create a boring placeholder item with
minimal fields, which Dyeworks can't call `name.match()` on!

Now, the test fails with a more helpful error about the item being
invalid. Next, I'll fix that!
2024-10-21 14:24:45 -07:00
71f0aa4908 Oops, fix modeling logic
Oh huh, I guess most of the new items we had when I rewrote this were
Maraquan, and I didn't test enough on standard species-specific items.

Before this change, partially-modeled items for standard pets would
appear as fully modeled, because the presence of the "nonstandard"
color Orange (because of the Orange Chia) meant that the "standard" key
didn't actually have any unique bodies (it was all `["standard", 47]`).

Here, I take my own comments' advice and move away from the standard
label as part of the logic. Instead, we look first for nonstandard
colors with unique bodies, which we'll call out as modelable; and then
check whether there are any basic bodies *not* covered by those special
colors.

That way, compatibility with the Maraquan Acara (a unique body) means
we'll treat Maraquan as a modelable color; and then we'll ignore the
basic bodies, even though it *does* fit the basic Mynci, because there
aren't any compatible basic bodies that aren't *also* Maraquan bodies.

This also means that compatibility with both the Blue Acara and Orange
Acara does *not* preclude a normal item from needing basic pets for
models: because, while Orange is a slightly nonstandard color in the
case of Chia, it doesn't have its own unique body for this item, so we
ignore it when predicting compatibility with basic colors.
2024-10-08 22:46:11 -07:00
bd001e643e Oops, avoid scooping up weird Chia bodies in predicted_body_ids
Before this change, a fully-modeled item (Dyeworks Burgundy: Gown of
the Night) was displaying as still needing the Chia. This was because
looking for "standard" body IDs like this caught up some of the weird
Chia bodies.

I think there's probably something here where we need to like, relabel
certain colors? But honestly, the better version of this logic would
probably be to lean more into the `basic` label in this logic.

But hey, that's a refactor for another time. I gotta go eat!
2024-10-03 15:39:35 -07:00
fe4db1b605 Improve prediction for what pets need modeling for an item
Noticing a lot of Maraquan items on the homepage today, and they're
doing that thing of expecting standard body types to be relevant too,
because I think we wrote this logic before the Maraquan Mynci ended up
having the same standard Mynci body? (Maybe? Or maybe I'm being
ahistorical and I just wrote this wrong to begin with lol)

In any case, this is more accurate, and I think I'm also maybe
incidentally noticing that it's running faster, at least in my brief
before/after production testing? (There's *more* queries, like 100! But
many of them are *very* fast lookups, coming in at under 1ms—and also a
lot of them are dupes being served by Rails's request-scoped query
cache.)
2024-10-03 13:49:15 -07:00
03e4233f67 Use cached compatible body IDs on homepage modeling code
This should make it load way faster! Maybe don't even need to mess with
caching the resulting HTML anymore, like we currently do?
2024-10-02 17:55:20 -07:00
b6bddb14be Oops, fix new bug in homepage modeling code
Missed a spot on `Item#basic_body_ids`!
2024-10-02 17:54:14 -07:00
e52838ba70 Use Rails serialize method to save/load cached fields in Item
Just packing some serialization complexity away into its own thing, so
the model code doesn't need to sweat it!
2024-10-02 17:50:42 -07:00
7ba68c52d4 Simplify homepage modeling code a bit
I have some other changes planned too, but these are some easy ones. I
also turn back on this stuff in development, in hopes that my changes
can make these queries fast enough to not be a big deal anymore!
2024-10-02 17:26:32 -07:00
26add4577c Use cached fields for item searches, instead of big joins
This is the second part of the previous change `efda6d74`, in which we
switch out the item search query conditions!

This was a two-parter to ease deployment: first deploy the change with
the migration, then *run* the migration (because it's an unusually slow
one), then deploy this change that actually uses it.

Another way to approach this would've been to deploy it all in one
commit, but not set it as `current` until we had run the migration.
That would have been a reasonable approach too!
2024-09-30 23:16:03 -07:00
efda6d74ab Add cached fields to Item model for searching, but don't use them yet
This is the first part of a change to improve search performance, by
caching occupied zone IDs and supported body IDs onto the Item record
itself, instead of always doing joins with `SwfAsset`.

It's unfortunate, because part of the power of SQL is joins! But doing
joins with big tables, in ways that can't take advantage of indexes in
the same ways as we often want to, is… slow.

It's possible there's something I'm misunderstanding about SQL
optimization, and this _could_ be done with query optimization or
indexes instead of duplicating data like this? This complexity carries
the risk of data getting out of sync in unforeseen ways. But this is
what I know how to do, and it seems to be working, so! Okay!
2024-09-30 23:10:44 -07:00
989c96fd2b Oops, fix pb_item for "Royal Girl Elephante Gold Bracelets" and similar
There's some funny bugs we had here, like "Relic Elephante Jewellery"
and "Royal Girl Skeith Bodice" getting assigned "Ice", and
"Tyrannian Meerca Spear" being "Pea" lmao

I went and checked all the assignments now and they look good to me!

```ruby
Item.is_pb.order(:name).
  map { |i| [i.pb_color&.human_name, i.name] }
```
2024-09-13 19:56:41 -07:00
6f08abc3aa Add html5 badge to new item previews 2024-09-05 18:48:41 -07:00
edcb21558a Drastically reduce queries for item page preview
Oh right okay, I made a sloppy perf hack long ago, and now let's
actually clean it up!
2024-09-05 17:52:35 -07:00
176ab20fd1 Cache the Item#appearances field
We call it enough times on this page, and it *does* have a SQL query,
that I want to cache it! (Also I want to make it fewer species queries
if I can tbh…)
2024-09-05 17:41:04 -07:00
9f44fd47e4 Add "No data yet" to species face tooltip when needed, in item previews 2024-09-03 17:27:43 -07:00
2b2bffd9da Disable pet faces that the item doesn't fit, in new item previews 2024-09-03 16:42:04 -07:00
36f8efadbf Add more detailed zone occupy info to simplified item preview page
Adapting what the Impress 2020 UI does, but in Ruby instead!

I feel like this is case is really starting to show the power of doing
this stuff in Rails instead of via an API… we can *really* take
advantage of our models and our handy idioms at all points. This is
just so much less *code* than this feature takes in Node + GraphQL +
React.
2024-09-03 12:55:10 -07:00
e0f9a27adc Merge branch 'main' into simpler-item-previews 2024-08-31 13:43:10 -07:00
1c36276865 Remove unused special_color logic from Item
We used to use this to determine what color to show by default on the
item page preview for, like, Maraquan-specific items. Now, we infer it
from our actual customization data, rather than these heuristics!

There's still a database field for `Item#manual_special_color_id`. We
can still read and write this from the support UI, and Impress 2020
still slightly uses it from the homepage, so I'm not removing from the
database right now.
2024-08-31 13:42:25 -07:00
8ab5af1aca Remove unused logic for whether a zone is "sometimes" occupied
I'm about to reimplement the more-robust version of what this used to
be: how the item page used to say "sometimes" after certain zones in
the occupied list.

Now, we're going to do parity with 2020, and list the actual species!

I like that this takes away the weird `#sometimes` method on the `Zone`
class, which was always an odd hack for just this small thing.
2024-08-31 13:16:47 -07:00
bd62476722 Add basic zone info to simpler item previews
We're missing the feature where we enumerate the exact species in
ambiguous cases, though!
2024-08-31 13:11:50 -07:00
ac002f3151 Track preferred color/species for new item page previews
Also adapted from the Impress 2020 logic!

Note that I refactored `compatible_pet_type` to a series of scopes on
`PetType`. I think this is a simpler, clearer, and more flexible API!
2024-07-01 17:38:31 -07:00
fe6035d438 Default to compatible pet types in new item page preview
Just adapted from Impress 2020 logic again, easy peasy!
2024-07-01 17:20:38 -07:00
3f38fbd1b0 Support zone restriction in new item preview
Adapted from wardrobe-2020's `getVisibleLayers`! Thanks past-Matchu for
all the comments lol!
2024-07-01 16:54:39 -07:00
74748acaaf Refactor more of item outfit preview into the Outfit class
This is a cute thing that I think sets us up for other stuff down the
line: move more of the outfit appearance logic into the `Outfit` class!
Now, we set up the item page with a temporary instance of `Outfit`,
then ask for its `visible_layers`.

Still missing restricted-zones logic and such, that's next!
2024-07-01 16:07:25 -07:00
ea17e76c39 [WIP] Start replacing item page preview with simpler HTML-based version
Just stripping out the big React component, and having Rails output it!

There's a lot of work rn in extracting the Impress 2020 dependency from
the `wardrobe-2020` React app, and I'm just curious to see if we can
simplify it at all by pulling this stuff *way* back to basics, and
deleting the item page part of `wardrobe-2020` altogether.

In this draft, we regress a lot of functionality: it just shows the
item on a Blue Acara, with no ability to change it! I'm gonna play with
putting more of that back in.

I also haven't actually removed any of the item page React code; I just
stopped calling it. That can be a cleanup for another time, once we're
confident in this experiment!
2024-07-01 15:35:58 -07:00
a70b70be7d Merge remote-tracking branch 'origin/main' 2024-07-01 14:56:08 -07:00
5401ea984a Merge remote-tracking branch 'origin/main' 2024-06-22 18:47:10 -07:00
97abd6e438 Add probabilities to Dyeworks items in Item Getting Guide
I'm gonna better explain the gacha nature, I'm doing this part first!
2024-06-20 12:54:39 -07:00
1d250f3148 Remove unused Item.with_closet_hangers scope
Idk why we thought this made sense way back when? But it evidently has
no call sites now so. Goodbye!
2024-06-19 17:49:18 -07:00
015010345a Extract Dyeworks methods into Item::Dyeworks module
There's just starting to be a lot going on, so I pulled them out into
here!

I also considered a like, `Item::DyeworksStatus` class, and then you'd
go like, `item.dyeworks.buyable?`. But idk, I think it's nice that the
current API is simple for callers, and being able to do things like
`items.filter(&:dyeworks_buyable?)` is pretty darn convenient.

This solution lets us keep the increasing number of Dyeworks methods
from polluting the main `item.rb`, while still keeping the API
identical!
2024-06-18 15:21:43 -07:00
26dfe13b0e Parse "Limited Dyeworks" items from Owls
Yay thank you Owls team! I might also try to parse the dates too, the
format seems to be "Owls: Limited Dyeworks - Dyeable Thru July 15"
2024-06-18 14:59:09 -07:00
bbd1849e19 Oops, fix crash for Dyeworks without Owls info in Item Getting Guide
Silly mistake, right, we might not have a trade value listed! This is
relevant for the new Dyeworks items that just came out like a few hours
ago, which Owls doesn't have info for yet.
2024-06-17 13:07:03 -07:00
9f536f81b3 Refactor to use a new Item#source method for where an item is from
I'm doing this in preparation for maybe trying to load some of this
info into the outfit editor, too!
2024-06-16 12:37:53 -07:00
b22ccbc2a3 Use Owls to check for Permanent Dyeworks items
Previously, I added a Dyeworks section that was incorrect: the base
item being available in the NC Mall does *not* mean you can necessarily
dye it with a potion!

In this change, we lean on Owls to tell us more about Dyeworks status,
and only group items in this section that Owls has marked as "Permanent
Dyeworks".

We don't have support for limited-time Dyeworks items yet—I've sent out
a message asking the Owls team for more info on what they do for those
items!
2024-06-09 14:46:24 -07:00
5de9e2a27b Add Dyeworks section to Item Getting Guide (but it's currently wrong!)
I started writing this up, then sent a preview to a friend, and he was
like "oh cool, but also this is not correct?"

I didn't realize Dyeworks has limited-time support to be *able* to dye
certain items. Hey, glad we're writing this guide for people like me,
then! lol

I wonder if we can lean on Owls for this. It seems like they already
list "Permanent Dyeworks" for some items, I wonder if they say
something special for active limited-edition Dyeworks items!
2024-06-09 13:25:59 -07:00
857cb547ed Add Item#dyeworks_base_item database field, and populate it
In this change, instead of *always* inferring the Dyeworks base item
from the item name at runtime, we now have a database field that tracks
it, and auto-populates whenever an item *seems* to need a Dyeworks base
item but doesn't have one yet.

This will enable us to set the base item manually in cases where it
can't be inferred, and load Dyeworks base items for the Item Getting
Guide in one query with `includes(:dyeworks_base_item)`.

This migration does a bit more of the fix-em-up scripting work *in* the
migration itself than I usually do, mainly because there's so much in
this one that I think being extra-explicit is useful. We make sure to
do it gracefully though!
2024-06-07 20:10:06 -07:00
68cb44d159 Add logic to infer the base for Dyeworks items
This works for most of the current 1,094 Dyeworks items! But there are
a few exceptions, for cases where the base item name is not quite the
same (e.g. the Dyeworks version is more concise). Maybe we'll add a
database field to override this?

- Dyeworks Baby Blue: Baby Valentine Jumper
- Dyeworks Baby Pink: Baby Valentine Jumper
- Dyeworks Black: Field of Flowers
- Dyeworks Black: Games Master Challenge 2010 Lulu Shirt
- Dyeworks Blue: Field of Flowers
- Dyeworks Blue: Stars and Glitter Facepaint
- Dyeworks Brown: Hanging Winter Candles Garland
- Dyeworks Green: Stars and Glitter Facepaint
- Dyeworks Magenta: Lovely Berry Blush
- Dyeworks Orange & Pink: Winter Lights Effects
- Dyeworks Orange: Games Master Challenge 2010 Lulu Shirt
- Dyeworks Peach: Lovely Berry Blush
- Dyeworks Purple: Baby Valentine Jumper
- Dyeworks Purple: Games Master Challenge 2010 Lulu Shirt
- Dyeworks Purple: Hanging Winter Candles Garland
- Dyeworks Purple: Stars and Glitter Facepaint
- Dyeworks Red & Green: Winter Lights Effects
- Dyeworks Silver: Hanging Winter Candles Garland
- Dyeworks Soft Pink: Lovely Berry Blush
- Dyeworks Yellow & Magenta: Winter Lights Effects
- Dyeworks Yellow: Field of Flowers
2024-06-07 19:35:43 -07:00
31c281390d Add explanations for why Item#pb_{species,color} would return nil 2024-06-05 19:46:12 -07:00
193b1fa5e3 Improve performance for occupies:X searches
I noticed in the app that these queries were slowwww! I was able to
track it down to a bad query plan, as we explain in the comment.

I searched online for "mysql query performance filter on one join table
sort by another", and was surprised to find this answer suggest a
subquery, which I've often been told to expect to be slower compared to
joins? But it certainly worked in this case!

https://stackoverflow.com/questions/35679693/mysql-optimize-join-with-filter-and-order-on-different-tables
2024-06-03 11:45:51 -07:00
758b62e7d5 Improve performance of Owls values in Item Getting Guide
Now we preload them all concurrently, instead of in sequence when the
template gets around to asking for them!
2024-05-27 16:21:22 -07:00
d34bebc336 Use a pet face when there's no paint brush, in Item Getting Guide
Now, for colors like Mutant or Magma where there's no paint brush
image to show, we use a sample pet image instead, to help it have equal
visual weight and clarity as the cases with the paint brushes.

We do some cleverness in here to make sure to always show the relevant
species, if possible!
2024-05-22 17:53:52 -07:00
1b03c2caed Add more PB item info and links to Item Getting Guide
I add some infrastructural support for inferring an item's paintbrush
color (if any), and a field to the database to manually track an item's
paint brush item name! This is both useful for tracking which colors
are even *available* via paint brush, and also for working with colors
with unusual paint brush names, like the "Get Off My Lawn Paint Brush"
(for Elderly pets).

Here's the script I ran to backfill this for current colors and their
paint brushes!

```rb
Color.find_by_name("Baby").update!(pb_item_name: "Baby Paint Brush")
Color.find_by_name("Biscuit").update!(pb_item_name: "Biscuit Paint Brush")
Color.find_by_name("Blue").update!(pb_item_name: "Blue Paint Brush")
Color.find_by_name("Brown").update!(pb_item_name: "Brown Paint Brush")
Color.find_by_name("Camouflage").update!(pb_item_name: "Camouflage Paint Brush")
Color.find_by_name("Candy").update!(pb_item_name: "Candy Paint Brush")
Color.find_by_name("Checkered").update!(pb_item_name: "Checkered Paint Brush")
Color.find_by_name("Christmas").update!(pb_item_name: "Christmas Paint Brush")
Color.find_by_name("Cloud").update!(pb_item_name: "Cloud Paint Brush")
Color.find_by_name("Darigan").update!(pb_item_name: "Darigan Paint Brush")
Color.find_by_name("Dimensional").update!(pb_item_name: "Dimensional Paint Brush")
Color.find_by_name("Disco").update!(pb_item_name: "Disco Fever Paint Brush")
Color.find_by_name("Electric").update!(pb_item_name: "Electric Blue Paint Brush")
Color.find_by_name("Eventide").update!(pb_item_name: "Eventide Paint Brush")
Color.find_by_name("Faerie").update!(pb_item_name: "Faerie Paint Brush")
Color.find_by_name("Fire").update!(pb_item_name: "Fire, Fire, Your Pants On Fire Paint Brush")
Color.find_by_name("Elderlyboy").update!(pb_item_name: "Get Off My Lawn Paint Brush")
Color.find_by_name("Elderlygirl").update!(pb_item_name: "Get Off My Lawn Paint Brush")
Color.find_by_name("Ghost").update!(pb_item_name: "Ghost Paint Brush")
Color.find_by_name("Glowing").update!(pb_item_name: "Glowing Paint Brush")
Color.find_by_name("Gold").update!(pb_item_name: "Golden Paint Brush")
Color.find_by_name("Green").update!(pb_item_name: "Green Paint Brush")
Color.find_by_name("Grey").update!(pb_item_name: "Grey Paint Brush")
Color.find_by_name("Halloween").update!(pb_item_name: "Halloween Paint Brush")
Color.find_by_name("Invisible").update!(pb_item_name: "Invisible Paint Brush")
Color.find_by_name("Desert").update!(pb_item_name: "Lost Desert Paint Brush")
Color.find_by_name("Maractite").update!(pb_item_name: "Maractite Paint Brush")
Color.find_by_name("Maraquan").update!(pb_item_name: "Maraquan Paint Brush")
Color.find_by_name("Marble").update!(pb_item_name: "Marble Paint Brush")
Color.find_by_name("Island").update!(pb_item_name: "Mystery Island Paint Brush")
Color.find_by_name("Oil Paint").update!(pb_item_name: "Oil Paint Brush")
Color.find_by_name("Orange").update!(pb_item_name: "Orange Paint Brush")
Color.find_by_name("Origami").update!(pb_item_name: "Origami Paint Brush")
Color.find_by_name("Pastel").update!(pb_item_name: "Pastel Paint Brush")
Color.find_by_name("Pink").update!(pb_item_name: "Pink Paint Brush")
Color.find_by_name("Pirate").update!(pb_item_name: "Pirate Paint Brush")
Color.find_by_name("Plushie").update!(pb_item_name: "Plushie Paint Brush")
Color.find_by_name("Polka Dot").update!(pb_item_name: "Polka Dot Paint Brush")
Color.find_by_name("Purple").update!(pb_item_name: "Purple Paint Brush")
Color.find_by_name("Rainbow").update!(pb_item_name: "Rainbow Paint Brush")
Color.find_by_name("Red").update!(pb_item_name: "Red Paint Brush")
Color.find_by_name("Relic").update!(pb_item_name: "Relic Paint Brush")
Color.find_by_name("Royalboy").update!(pb_item_name: "Royal Paint Brush")
Color.find_by_name("Royalgirl").update!(pb_item_name: "Royal Paint Brush")
Color.find_by_name("Sketch").update!(pb_item_name: "Scritchy Sketchy Paint Brush")
Color.find_by_name("Shadow").update!(pb_item_name: "Shadow Paint Brush")
Color.find_by_name("Silver").update!(pb_item_name: "Silver Paint Brush")
Color.find_by_name("Skunk").update!(pb_item_name: "Skunk Paint Brush")
Color.find_by_name("Snow").update!(pb_item_name: "Snow Paint Brush")
Color.find_by_name("Speckled").update!(pb_item_name: "Speckled Paint Brush")
Color.find_by_name("Split").update!(pb_item_name: "Split Paint Brush")
Color.find_by_name("Spotted").update!(pb_item_name: "Spotted Paint Brush")
Color.find_by_name("Starry").update!(pb_item_name: "Starry Paint Brush")
Color.find_by_name("Stealthy").update!(pb_item_name: "Stealth Paint Brush")
Color.find_by_name("Steampunk").update!(pb_item_name: "Steampunk Paint Brush")
Color.find_by_name("Strawberry").update!(pb_item_name: "Strawberry Fields Forever Paint Brush")
Color.find_by_name("Striped").update!(pb_item_name: "Striped Paint Brush")
Color.find_by_name("Swamp Gas").update!(pb_item_name: "Swamp Gas Paint Brush")
Color.find_by_name("Toy").update!(pb_item_name: "Toy Paint Brush")
Color.find_by_name("Transparent").update!(pb_item_name: "Transparent Paint Brush")
Color.find_by_name("Tyrannian").update!(pb_item_name: "Tyrannian Paint Brush")
Color.find_by_name("Usuki Boy").update!(pb_item_name: "Usuki Paint Brush")
Color.find_by_name("Usuki Girl").update!(pb_item_name: "Usuki Paint Brush")
Color.find_by_name("Valentine").update!(pb_item_name: "Valentine Paint Brush")
Color.find_by_name("Water").update!(pb_item_name: "Water Paint Brush")
Color.find_by_name("White").update!(pb_item_name: "White Paint Brush")
Color.find_by_name("Woodland").update!(pb_item_name: "Woodland Paint Brush")
Color.find_by_name("Wraith").update!(pb_item_name: "Wraith Paint Brush")
Color.find_by_name("Yellow").update!(pb_item_name: "Yellow Paint Brush")
Color.find_by_name("Zombie").update!(pb_item_name: "Zombie Paint Brush")

```
2024-05-22 16:09:49 -07:00
23ad52a8db Oops, don't crash calling current_nc_price on non-NC-Mall items
If `nc_mall_record` is `nil`, return `nil`! (This is the nil method
chaining operator!)
2024-05-21 17:24:55 -07:00
d8b577aab1 Add more info to NC Mall section of Item Getting Guide
NC prices, some CSS, and also a new application-level helper that adds
a feature I've long wanted and been working around for Turbo: the
ability to specific that a stylesheet is specific to the current page,
and should be unloaded when removed!

I use this to write `sources.sass` without the usual
`body.items-sources` scoping that we've historically used to control
what pages a stylesheet applies to. (In the long past, this was because
a lot of stylesheets were—and still are–routed through the
`application.sass` stylesheet! But even for more recent standalone page
stylesheets, I've done the scoping, to avoid issues with styles leaking
beyond the page they're meant for when Turbo does a navigation.)
2024-05-14 16:04:40 -07:00
d3b3a3060c Split Item Getting Guide between NC Mall items and Other NC items
This'll affect the recommended acquisition method by a lot!

NC Mall info like current price isn't surfaced anywhere else in the app
right now. It'd probably be good to add to the item page, and maybe
some other places too!
2024-05-14 00:09:27 -07:00
9733ceae25 Add bare-bones Item Getting Guide page
TNT requested that we figure out ways to connect the dots between
people's intentions on DTI to their purchases in the NC Mall.

But rather than just slam ad links everywhere, our plan is to design an
actually useful feature about it: the "Item Getting Guide". It'll break
down items by how you can actually get them (NP economy, NC Mall,
retired NC, Dyeworks, etc), and we're planning some cute actions you
can take, like shortcuts for getting them onto trade wishlists or into
your NC Mall cart.

This is just a little demo version of the page, just breaking down
items specified in the URL into NC/NP/PB! Later we'll do more granular
breakdown than this, with more info and actions—and we'll also like,
link to it at all, which isn't the case yet! (The main way we expect
people to get here is by a "Get these items" button we'll add to the
outfit editor, but there might be other paths, too.)
2024-05-06 20:37:59 -07:00
0943e2dbba Fix broken default value in schema for item description
Idk how we got into this state, or if it's environment-dependent or
MySQL-version-dependent or what, but setting up the dev environment on
my macOS machine is complaining that `TEXT` columns can't have default
values.

Well, in that case, let's just have it be a non-nullable field, and add
a note to our code that missing fields *can* cause item saving to fail!
(This was always true, but I'm just extra-noting it because it's
becoming *more* true.)
2024-05-02 13:00:10 -07:00