WildfireRomeo / WildfireFemaleGenderMod

A female gender mod created for Minecraft. No longer actively supporting Forge!
https://www.curseforge.com/minecraft/mc-mods/female-gender-fabric
GNU Lesser General Public License v3.0
97 stars 60 forks source link

[Feature] Encode player data as magic pixels in the skin #113

Open diademiemi opened 1 year ago

diademiemi commented 1 year ago

Hi! I just had an idea of encoding players' data of this mod in their skin files as hidden pixels, just as how the Ears mod does it. This would remove the need for having the server also run the mod, and make it work on non-Forge/Fabric servers too.

UX-wise it could just be taken as the players default, but you can still overwrite it which would be stored in a local file like it currently is. Maybe we could add a button like "Revert to player suggested" to reset it if it differs from what is encoded in the skin.

Technical proposal

It might require patching of the skin loader in Minecraft. For why this is necessary, check the Ears documentation so we'll need to be careful to avoid conflicts with the Ears mod.

If we include pixels in a place where the vanilla game doesn't even attempt to look, it might be fine though without patching. The Ears mod needs to do it to gain extra room since it needs to add actual textures, we only need a tiny bit of space to encode some data. Maybe this corner would be good? This space also is not used by the Ears mod.

image

Example

I'll show an example of how this could work with my data.

Let's first start with the data related to how the mod makes the breasts look, the relevant values are:

"bust_size":1.0,
"breasts_xOffset":-0.013333334,
"breasts_yOffset":-0.18,
"breasts_zOffset":0.0,
"breasts_cleavage":0.041,
"bounce_multiplier":0.12666667,
"floppy_multiplier":0.40333334

Let's encode these as floating point numbers and show them as hexadecimal values according to https://en.wikipedia.org/wiki/IEEE_754.
This results in the following values:

0x3f800000
0xbc5a740e
0xbe3851ec
0x00000000
0x3d27ef9e
0x3e01b4e8
0x3ece81b5

Conveniently these are the same size as an RGBA pixel, exactly what we need here!

We don't need to encode gender, let's just assume that if the bits are set in a way that the mod can read that their gender is set to "Other". Though as you'll see later we do have room to still encode a toggle for Other/Female if wanted.

Now as for the boolean toggles, we can encode these in just a single pixel.

"hurt_sounds":false,
"breasts_uniboob":false,
"breast_physics":true,
"breast_physics_armor":false,
"show_in_armor":false,
"show_elytra":true

There's 6 booleans, 64 possible combinations.
One RGBA pixel can encode 4294967296 (256*256*256*256) values, should be enough!

Let's assume the previous values, this maps to 001001.
We need to pad this to the length of a pixel, this leaves plenty of room for future additional options too. This results in 00100100000000000000000000000000.
We can encode this as a bitarray to hexadecimal, this results in 0x24000000

I think this amount of options is a bit overkill, so why don't we add a check to this pixel that must be met before this mod will read the data (to prevent it from reading random data). Let's add b00b which results in 0x2400b00b :P. The binary representation of this is 00100100000000001011000000001011. We still have 16 booleans we can encode here, still plenty!

Now we can place 8 pixels on the skin canvas to encode all the data we need, and with plenty of room to spare for future booleans.

A quick script to encode this to an image:

from PIL import Image

hex_values = [
  "3f800000",
  "bc5a740e",
  "be3851ec",
  "00000000",
  "3d27ef9e",
  "3e01b4e8",
  "3ece81b5",
  "2400b00b"
]

# Convert hex values to RGBA tuples
rgba_values = []
for hex_value in hex_values:
  rgba_values.append(tuple(int(hex_value[i:i+2], 16) for i in (0, 2, 4, 6)))

# Create 4x2 image
image = Image.new("RGBA", (4, 2))

# Place pixels
for x in range(4):
  for y in range(2):
    image.putpixel((x, y), rgba_values[x + y * 4])

# Save image
image.save("boob_pixels.png")

2023-03-30_13-54

If I now open this image in GIMP and inspect the pixels, I can see on the right hand side that the values are encoded in it. All other pixels are present too, they just aren't all visible due to a low alpha channel value (opacity).

On the 3rd pixel I read the decimal RGBA values of (190, 56, 81, 236). If we convert that back to hex we get 0xbe3851ec! If we now read this as a floating point number can reverse that back to it's original value of -0.18!

Summary

I'm pretty sure this should be doable within this mod. I think it would be a great feature to add to be able to see other players' options without a mod needing to be installed on a server.

If this sounds like a good idea and would be accepted, I'd be glad to start working on this feature and contribute it!

diademiemi commented 1 year ago

Of course making this manually is a bit of a pain so there'd need to be some simple tool to encode this data into your skin. I'm thinking just a simple Python script at first that takes your json file and skin file as input and adds this data, that shouldn't be hard to make. Maybe sometime later I could make it into a simple website.

sylv256 commented 1 month ago

Ears already has boobs and I made a tutorial on it recently. https://gist.github.com/sylv256/a96b2c369e48ba50d9ed4d175033c693 Maybe we could make some inter-mod compatibility there?

diademiemi commented 1 month ago

I've since the making of this issue switched to Ears too, but it being compatible might be possible!