unascribed / Ears

Faithful fancy fashion features for fuzzy folk.
https://ears.unascribed.com
MIT License
92 stars 14 forks source link

"Fallback Skin" or "Area Replacement" - could something like this ever be possible? #115

Open IdrisQe opened 1 year ago

IdrisQe commented 1 year ago

So, before I even say anything I know that because of how the mod works and the limited space available this is a pipe-dream but one thing that always stops me from consistently using Ears is the multiplayer aspect of what happens when someone doesn't have Ears installed- of course the ears, tails, etc. won't render for them. And sometimes I'm playing a modpack that just doesn't support Ears for whatever reason (Optifine is unfortunately still important for a lot of older Minecraft versions for example and has pretty inconsistent compatability)

The problem with this is my Vanilla skin has the ears drawn on the sides of the head. For Ears to really make sense to use I need to remove those from my skin and put them in the special Ears zone, so if I then want to play a pack without Ears I need to swap my skin back to my original or have no ears at all, and to anyone without Ears installed it would just appear like i have no ears if I'm using the Ears skin... So I was thinking of some (pretty bad) solutions which would be horrible to implement (don't take this as a serious suggestion, more a discussion on possible ways it could maybe one day be achieved)


The first option would require third party servers which I know is a big nono for this mod:

-Skin V: Uploaded to Mojang, ears textured on side of head like normal Java Edition skin limitations -Skin E: Uploaded to... i dunno, Imgur or something. Has all the Ears features enabled, side-of-head ears removed so two pairs of ears aren't present at once.

You connect to a Multiplayer server: -Player A has the Ears mod too, it communicates with your Ears mod (unfortunately this would probably require an external server since the clients would need to communicate without the server knowing unless there's some sort of P2P protocol but even then that would probably be risky...) and Skin E is shown to Player A -Player B does not hav the Ears mod, or it isn't enabled, or whatever servers are used aren't reachable (so you wouldn't be left with a default Steve/Alex/Etc. if the image host went down) and Skin V is shown to Player B through normal Mojang Skin means -If you disable Ears, you will automatically use Skin V again since it's the Mojang-hosted one.


Another option which wouldn't require additional skin files or servers would be to have a zone that replaces another zone on the skin to hide unwanted painted-on-ears, painted-on-tail, etc. if using Ears, but space limitations would come into play quite quickly, unless some sort of encoding was used in a single pixel to determine what spots should be replaced with what colour... A grid of 4x4 would allow 8 colours to be painted on to replace existing spots assuming that you could encode the "mask" into a single pixel as well...

So for example a RGBA pixel of (216,172,11,87) could correspond to a mask of 0 and 1 values across the skin, selecting specific pixels, and then the pixel beside that pixel would show which RGBA colour to replace that with. This would allow Ears to hide painted-on ears and tails from skins without removing them for people who don't have the Ears mod, serving as a sort of inverse-fallback?

But even compressing a mask of 0 or 1 values of a single face of a single layer of the head (8x8) into one pixel wouldn't really work, since there would be 18446744073709551616 possible combinations while a single pixel of RGBA value could only represent 1677721599 combinations (since many programs will not save the colour data of a pixel with 0 alpha, otherwise it would be 1677721600) which isn't even remotely close to enough to account for a single face, much less the top, front, left, right, back of both layers of the head (for ears and muzzle), and both layers of the torso back (for tail)... That would be (8x8 + 8x8 + 8x8 + 8x8 + 8x8 + 8x12)x2 (since two layers) which is... 2.8638903918474961204418783933675e+250 combinations of possible pixels to mask. Yeahhh... no.

This feels wildly infeasible without taking up more and more space on the limited skin real-estate though, but I'm not the smartest person by any stretch of the imagination, and sleep-deprived, so maybe someone could come up with some compression wizardry to make this idea work, but probably not.

Infinidoge commented 1 year ago

Another option which wouldn't require additional skin files or servers would be to have a zone that replaces another zone on the skin to hide unwanted painted-on-ears, painted-on-tail, etc.

The mod actually already includes a feature to accomplish this, though it isn't currently easily accomplished within the manipulator. If you set pixels on the skin to have an alpha of 254 (as opposed to the full 255), they will be hidden when Ears is loaded and displaying the extra parts on your skin. (Incorrect, see Una's comment below) Since Minecraft ignores the alpha value already, these parts of your skin will display normally to people who aren't using Ears.

IdrisQe commented 1 year ago

Another option which wouldn't require additional skin files or servers would be to have a zone that replaces another zone on the skin to hide unwanted painted-on-ears, painted-on-tail, etc.

The mod actually already includes a feature to accomplish this, though it isn't currently easily accomplished within the manipulator. If you set pixels on the skin to have an alpha of 254 (as opposed to the full 255), they will be hidden when Ears is loaded and displaying the extra parts on your skin. Since Minecraft ignores the alpha value already, these parts of your skin will display normally to people who aren't using Ears.

Forgive me if I'm mistaken but isn't alpha a value between 0 and 100, not 0 and 255? At least that's what every program I've used for image editing has shown it as. That said...

The problem with that is it sounds like it's just hidden entirely, which would only work for the outer layer, since if you just hide parts of the inner layer you would have a hole in your skin. That said, using Alpha like that would make my idea much more feasible. There could instead be a, say, 5x2 area somewhere, where each pixel corresponds to a different alpha- On the "inner layer", any alpha of 254 would be replaced by the (0,0) slot pixel, 253 by (0,1), 252 by (0,2), etc. The "outer layer" would be the same but with 254 being (1,0), 253 being (1,1), etc. This would let you replace 5 colours seperately on both layers, giving extensive customization and allowing you to not just remove, but replace pixels. Of course a 5x2 area is still a lot to fit into the extra space so maybe something else could be done.

Edit: To give context why this is an issue, for example, the ears on my skin, and many others that I've seen, use both layers to achieve a 3d effect, but in order to properly replace them, pixels would need to be replaced on both layers (and depending on how the original skin is laid out, some more pixels may need to be added to the second layer so the hole left by the ears isn't obvious) Skin for example (oh goodness that's jittery, sorry- it should still be visible at least what I mean): a

Infinidoge commented 1 year ago

I believe alpha is stored as 0-255 because that is just the values in a byte. Programs generally represent it as 0% to 100% though, from what I've seen.

Yeah, trying to deal with things on the inner part of the skin would indeed be more difficult, as you said would require a lot more effort to handle those cases. With regards to that, the advice is generally to just put the ears on the outer layer and be done with it, since the main focus is on the Ears skin parts anyways, but I can certainly admit that that is an unsatisfactory answer.

As for a more satisfactory solution, that would be up to Una. As of right now I don't think a solution would fit within the skin area of the existing v1 format (though I may be wrong), so a solution might require a newer Ears format.

unascribed commented 1 year ago

The "eraser" format does not work as you described. It allows specifying rectangles of the skin to be erased, replacing them with transparency. The pitfalls are similar.

There's not enough space in the skin to provide replacement regions, but the eraser syntax could possibly be updated to accept a color to replace with instead of always transparent black. Ears will never require external servers.

IdrisQe commented 1 year ago

Yeah, that's why I was hoping to figure out a way to compress a region into a colour value, in order to take up minimal space on the skin, but it doesn't seem possible unless it's made way more limited, at which point it still has pretty much the same issue- a square blank space of any colour is still very visible and stands out on most skins.

TheAppleFreak commented 1 year ago

Just saw this issue, and as someone in the same boat, I'm a bit curious about something. Apologies if what I propose isn't possible with how Minecraft's servers are managed.

When you upload a skin to Mojang, it stores the file on their server with a URL like http://textures.minecraft.net/texture/898eb17397d4a229afba228763476876bcf428e7194b5a37efe0796edb0c256f (using my current skin, for example). The ID is 64 characters long using base36. What if you could encode that ID in a set of magic pixels in the as-of-yet unused areas, and decode that to pull up another skin ID that then downloads and replaces the currently active skin for a given player?

With a basic implementation, you could store 4 characters per pixel by using the RGBA channels, meaning you could encode the ID in 16 pixels. Could be possible to squeeze 6 character into each pixel by basically computing a bitmask from the unique pixel color (about 4.2B unique combinations of RGBA values) and then decoding it as a Base36 bitmask (about 3.9B unique combinations for six characters), meaning you could fit the same information into 11 pixels instead. Once you decode the ID, you grab the resultant skin from Mojang and proceed from there.

The upside to this approach is that it gives users a lot more options for using the mod. You can have two totally separate skins, one that works in vanilla and one that can take full advantage of Ears, and it wouldn't break the magic rule of not contacting third party servers. Likewise, it wouldn't create transparent regions on the skin.

There's three (maybe four) downsides I can see from this:

I dunno. Food for thought.

unascribed commented 1 year ago

This concept has been proposed before but I don't like it as it's a massive inconvenience for users to manage and makes skins no longer self-contained.


The ID is 64 characters long using base36

It's hex. Each character is therefore worth 4 bits of data, not 5¼.

...in the as-of-yet unused areas...

There are exactly zero. Ears uses every single pixel of the skin.

Obviously, this entire idea completely falls apart if Mojang deletes old skins from their servers.

They do not. This is why https://mineskin.org works.

With a basic implementation, you could store 4 characters per pixel by using the RGBA channels

Ears already has a system for this called Alfalfa that stores data in the alpha channel of pixels that the Minecraft client forces to be fully opaque. This is where wings, capes, and eraser data are stored. More data can be stored by using the LSB of the RGB channels, but I don't wish to do that.

You can have two totally separate skins, one that works in vanilla and one that can take full advantage of Ears

Except you're still restricted to a 64x64 skin, so you go to a ton of extra trouble to do basically nothing at all. If I was going to go to this much trouble I would want the second skin to contain extra regions or stitch together multiple skins into a 128x128 Ears-specific skin format. Prototypes and concepts involving this I generally refer to as involving the "Ears authoring format", where the "authoring format" is converted by the Manipulator into whatever the necessary format is for upload.

Image compressors would wreak havoc on this.

Using a lossy optimizer on an Ears skin already breaks everything. PNG is lossless, so this is generally not an issue — users technical enough to even know lossy PNG optimizers exist will likely also know that it wouldn't work here.

IdrisQe commented 1 year ago

It's a shame that every solution has so many downsides or is some way infeasible. It's too bad that Mojang doesn't just let you upload slightly larger skins, just ignoring the extra space. But that would be unneccessary strain on servers, so I get why they don't.

If the Ears Authoring Format ever gets off the ground that would be cool, but I do wonder if Mojang would take issue with people using their server space for what is effectively mod textures. Then again I guess people already do that with custom heads, so... Hm...