HB V5 New and Changed Features - Catman-232/Homebrewery GitHub Wiki
This update pretty much replaces the core functionality with significantly smarter code, a structure that is going to be much easier for me to maintain and extend. It comes foremost with the cool new aspect of lazy loading assets - that's PNGs, GLBs, MP3s and OGGs - loading the file only when the asset is actually going to be used. This means no more waiting for a few minutes, or several, or a dozen, only to potentially crash from running out of memory. This never particularly impacted me because I have the game on a pretty ridiculously fast drive, and I have an abundance of system memory due to buying 64GB total a couple years ago when I upgraded my PC (Thank the gods for that, considering how expensive RAM has become, and even the SSDs are like triple the price now too). However, even I noticed the load time creeping up from a brisk dozen seconds to over a minute, and when you consider how much I open and close the game between code changes, that really adds up a lot!
Additionally, HB now has a system that keeps track of assets that have been loaded, they all have a timestamp that is bumped whenever something requests the file to be loaded (it skips loading if the file was already loaded, of course!). Periodically, HB will check the list to find any assets that have a timestamp that's older than a threshold, and will then mark the asset to be "unloaded". Quotes there because we aren't truly unloading the assets, for sound effects and meshes they are destroyed, for textures they are actually overwritten by a 1x1 black pixel (this allows the texture to stay assigned to what was using it since Texture2D is just a container for image data). This will help lower the average memory usage, although it would now be extremely unlikely to reach the memory usage peak of the old content loader's code, which was preloading all assets.
I'm also going to use this page as a bit of a data dump for the time being, sorry!
Texture Assets
One of the folders you can have in HomebreweryFiles now is Texture, inside of here you can dump loose PNG files or make subfolders and put the PNGs inside of them. These will be prepared as assets for items and parts to assign via their asset string name, just like how custom Meshes work. All texture contexts now have properties in the associated param files for this purpose.
For example, the WhatOnEarth skin (the slime one) is now represented by this param file:
{
"_body": "#local#-Tex-WhatOnEarth",
"_legs": "#local#-Tex-WhatOnEarth",
"_head": "#local#-Tex-WhatOnEarth",
"_hair": "#local#-Tex-WhatOnEarth",
"_tail": "#local#-Tex-WhatOnEarth",
"_ears": "#local#-Tex-WhatOnEarth"
}
That points to HomebreweryFiles/Texture/WhatOnEarth.png (#local# being swapped to Catman-Homebrewery in this case). As the example shows, this means you can assign multiple textures with the same file, as internally that file is only being loaded once and the Texture2D is being assigned where needed. Files within subfolders will have the subfolder names inserted into the asset string, e.g. Catman-Homebrewery-Tex-PoonHair-OnImp refers to the PNG file HomebreweryFiles/Texture/PoonHair/OnImp.png.
All Textures get an asset string!
All PNG files that Homebrewery discovers are prepared in the same way whether they are in the Texture folder or any other part/item folder, meaning any file can be grabbed by its asset string from anywhere. Textures loaded from item/part folders have their asset string formed by the context of what type of thing they are, and what texture context they were for.
Catman-Homebrewery-Tex-HB_ALLRACES-Eyes-Catman_WhatTheHeck-center is the center.png from Homebrewery's Eyes called Catman_WhatTheHeck.
I wish I hadn't pointlessly put my username into the part folder name and then suggested that others do that too, these strings are so damn long, too late now haha...
The file can be found at HomebreweryFiles/Eyes/HB_ALLRACES/WhatTheHeck/center.png. I don't know why I put the race name before the part type in the asset strings but I dare not change that at this point.
Vanilla Textures can be used too!
Do you have a custom skin that changes only the body and legs of a vanilla skin and literally nothing else about it? This feature will be ideal, since it means no need to repack a bunch of vanilla assets just so you can have your additions applied to all of the vanilla skin options. Not to mention any other use cases like remixes of vanilla items etc. The way this works borrows the principle of the Texture Replacer code, which looks up a vanilla asset by its container path string.
Those look like this: _graphic/_mesh/00_player/player_meshes/_armortexturelibrary/_chesttextures/_chtex_02a. A Texture2D named _chtex_02a is in that container, the Kubold starter chestpiece uses it for its armor texture.
Another example: _graphic/_mesh/00_player/player_meshes/_racemesh_poon/poontex01_leg. I can't tell you what Poon skins use that leg texture, I think half of them do.
These container paths can be found easily using AssetStudio, see the dedicated guide.
The Property Names
Hairs, Ears, Tails, Miscs: _texture.
Eyes: _center, _closed, _pissed, _hurt, _left, _right, _up, _down (Might be adding some custom ones in the future!).
Mouths: _closed, _open.
Skins: _body, _legs, _head, _hair, _tail, _ears.
All Items: _iconTexture.
Shields: _shieldTexture.
Weapons: _weaponTexture.
All Armor Items (except rings): _armorTexture.
Leggings: _legPieceTexture_01, _legPieceTexture_02, _legPieceTexture_03, _legPieceTexture_04.
Chestpieces: _legOverlayTexture, _boobOverrideTexture, _neckCollarTexture, _chestRenderTexture, _chestRenderBoobTexture, _robeSkirtTexture, _armCuffTexture, _shoulderpadTexture, _shoulderpadTexture_LEFT, _shoulderpadTexture_RIGHT, _hipMeshTexture.
(armCuff and shoulderpad left & right are newly added custom ones, they can be assigned by PNG file like the other can)
Custom Hairs Reworked
The way hairs worked has been a bit of a pain to work with in the code and I really wanted to make a more intelligent way of handling them that would allow for altering the transform at the time of displaying the mesh, which would mean you'd only really need a single mesh for each race since you'd be able to give to edit the placement, scale and rotation properties independently. Where it goes in the Blender scene no longer matters either.
Instead of containing GLB files that have up to five meshes, the Hair folder now has the race name subfolders (except HB_ALLRACES due to wanting to avoid complexity crisis). You make part name folders like you do for skins, eyes and mouths, and inside you make a param.txthb file that may look like this:
{
"_mesh": "",
"_texture": "",
"_position": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"_scale": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"_rotation": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"_meshHelm": "",
"_positionHelmHair": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"_scaleHelmHair": {
"x": 1.0,
"y": 1.0,
"z": 1.0
},
"_rotationHelmHair": {
"x": 0.0,
"y": 0.0,
"z": 0.0
}
}
Much like how the mesh properties work for items, you use a mesh's asset string in _mesh. You can also designate a custom mesh for the _meshHelm property, this will be used when an equipped Helm has the _useHelmHairDisplay property set to true. Leaving it out will allow the vanilla code to display the race's normal helmHair mesh (Unless it's Chang since they don't have one, they get to go bald!).
The literal Mesh placement is still very much the same jank as before where it's technically at the origin point of the player model, but since you can set the mesh position properties to move it around in-game, you don't need to float the model above the scene origin in your GLTF exports. You will need to move your hair GLB files to the Mesh folder, and I recommend you edit them to only have one mesh in the export since only the first one in the file will be used.
You can also give the hair an override texture, which will be displayed instead of the hair texture from the skin, I will at some point add a character display option to be able to disable that (like the CapeTailMode option). You can use the property in the param file or a PNG file in the part's folder with one of the aliases that the hair context for Skins can have.
Custom Ears and Tails
I don't want to get your hopes up, custom meshes will not work in these parts right now due to as of yet incomprehensible jank regarding GLTF importing and how Unity Mesh and SkinnedMeshRenderers work in terms of bones, bindposes etc.
You can at least create your own alt of a vanilla part however! The param file structure has properties for altering the position, scale and rotation, and you can also provide an override texture either in the folder as a PNG or by asset string. I wrote all this code with the part spreading/sharing partly in mind, to keep it from getting painfully complicated and overwhelming to work with. I know we had the tails already but the code for that was truly slapped together on a whim and was practically impossible to update.