[Mod] Make skins in-game at runtime [skinmaker] [1.0]

Post Reply
User avatar
GreenXenith
Member
Posts: 1356
Joined: Wed Oct 28, 2015 01:26
GitHub: GreenXenith
Location: UTC-8:00
Contact:

[Mod] Make skins in-game at runtime [skinmaker] [1.0]

by GreenXenith » Post

Skinmaker

Image

Skinmaker is a live, in-game, player skin editor that can be used without server restarts. Images are saved, loaded, and applied live. This started out as a proof of concept, but is now a perfectly usable mod.

It uses one (or two) entities, a few tools, and a crap-ton of texture modifiers. The maker node is used to handle everything (spawn canvas, get tools, etc).

Please read the full documentation.
Alternatively, here's a copypasta version:
Spoiler

Skinmaker

Image

Skinmaker is a live, in-game, player skin editor that can be used without server restarts. Images are saved, loaded, and applied live.

Usage

None of the skinmaker items or tools are craftable. This mod is not exactly server-friendly (even though we all wish it was). A single node is provided to obtain all the tools needed.

Maker Node

The maker node is used to spawn the working canvas (shown in the top screenshot). Upon placing, a canvas will be placed above the node with a solid black skin texture. Note, the canvas will always be rotated in the same direction regardless of placement.

Right-clicking the maker node will reveal the maker form.
Image
This form includes all the tools needed to begin creating and editing skins. Note, the skin preview in the form is not the working canvas.

The form buttons from left to right and down are as follows:
Save: Saves the current canvas to a PNG file at the specified filepath (shown at the bottom of the form). The filepath cannot be changed as of now, and saving will override any existing file of the same name.
Load: Puts the player's current skin on the canvas.*
Apply: Applies the current canvas to the player.
Clear: Reverts the canvas back to the starting state.*
Tools: Adds the skinmaker toolset to the player's inventory. These tools are required to work with the canvas. Obtaining these items from the creative inventory could result in unexpected behavior.

* These actions are irreversable (cannot be undone).

Tools

There are currently 7 tools that can be used on the canvas.
Image

Eraser: Set a pixel to transparent.
Paintbrush: Set a pixel to a specified color.
Undo: Undo the last action (can store up to 100 actions).
Redo: Redo the next action (new actions will clear the redo queue).
Bucket: Fill a color with another.
Line: Create a line from one pixel to another (requires 2 uses to create).
Rectangle: Create a solid rectangle with corners at 2 pixels (requires 2 uses to create).

Color Selection

Tool color is chosen by right-clicking with the tool, either on the canvas or elsewhere.

Right-clicking the canvas will act as an eyedropper and set the tool to the pixel color you click on. Only the bucket can be set to transparent.

Right-clicking elsewhere will show the palette form.
Image
The palette contains up to 7 colors and a set of HSV sliders. Using the sliders or clicking on a color swatch will set the tool's color. The selected palette can be changed in the dropdown to the left.

Custom Palettes

Obtaining a palette from the creative inventory or through /giveme skinmaker:palette will allow you to create and share your own color palettes.

Customization is done by right-clicking with the palette. A form similar to color selection is shown, with a name field rather than a palette dropdown. Use the sliders to adjust the color preview in the middle, and click on a swatch to set it's color (this will override the current color, if any). Palettes do not need to fill all the colors.

When using the color selection form, any non-empty palettes in your inventory will be added to the dropdown.

Skin Preview

The maker form contains settings pertaining to the skin preview. Enabling the preview will place a mini player entity in front of the maker node. The entity can rotate in either direction at multiple speeds, and can be animated. The texture will update along with the canvas.

How does this work?

This mod spawned from an experimental mod by Aurailus that attempted to allow dynamic creation of textures at runtime. This mod is limited to 16x16 textures due to the method used and the limitations of the Minetest engine.

The Gist

Each texture is a [combine modifier composed of a lot of [colorize modifiers, 1568 of them to be exact. This, in turn, creates a massive string that can be used as a texture. Painting is done using Raycast().

The Drawbacks

The reason Aurailus' mod is limited to 16x16 is the hard limit on texture modifiers used in nodes. Entities do not share this limit. Entities do, on the other hand, have a limit of how large a serialized table can be. If the textures table contains more than 65535 bytes, Minetest will silently segfault with no errors (or give a serialization error). For this reason, the pixel image is named px.png, in order to keep the string as small as possible. However, even with a short image name, 64x32 (2048) colorize modifiers brings the string size to around 70000 bytes. In order to circumvent this, all unused parts of the skin are left out, bringing the string size down to around 50000 bytes.

It is worth noting that formspecs do not care how large the generated image is (or the limit is much higher).

Should I use this on my server?

Probably not. I question the performance of this mod and the stabillity is definitely sub-par.

That said, if you don't care about the risks, this could potentially be very good for a multiplayer server. The abillity to load skins live is a much missed feature in Minetest. Do note that this mod is not intended to apply new skins, it is simply to make new ones from scratch or edit already applied skins. I may create a sister mod to provide the live-load function.

Todo and Bugs

Todo

  • An efficient(!) method of exactly viewing which pixel is being pointed at
  • Scalable canvas
  • Support param2/canvas rotation
  • Use invisible placeholder nodes in the canvas and preview to prevent node placement

Known Bugs

  • Pointing is not 100% accurate
  • Preview enabled with rotation of 0 will not reset yaw when rotation is 0 again
TL;DR Feature List:
  • Simple and fast(ish) painting
  • Easy color selection
  • Color palettes, preset and custom
  • Export to PNG file
  • Apply current skin to canvas
  • Full undo/redo support
  • Line/Square/Fill tools
  • Skin preview using mini-player model (supports animations)
  • Bugs!
Yes, this mod is pretty experimental.
I do plan to make a similar mod that serves the sole purpose of loading skins live to solve the issue of waiting for server restarts to apply player skins.
Spoiler
Q: Why?
A: Because.

Q: Is there a more efficient way to do this?
A: Possibly, but it would be much more difficult to accomplish without losing your sanity.

Q: How long did this take to make?
A: Roughly 4 days.

Q: I don't like ____!
A: That's nice.

Q: This is a hack!
A: Uh, yeah?

Q: How to ____?
A: Read the docs. (And if I missed something in the docs, let me know)
Sauce: https://github.com/GreenXenith/skinmaker
ContentDB: https://content.minetest.net/packages/G ... skinmaker/
License: MIT
Minetest Version: 5.0.0+
Depends: player_api (MTG mod)
YouTube | Mods | Patreon | Minetest Discord @greenxenith

You should not be able to read this message.

User avatar
Lone_Wolf
Member
Posts: 2578
Joined: Sun Apr 09, 2017 05:50
GitHub: LoneWolfHT
IRC: LandarVargan
In-game: LandarVargan

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by Lone_Wolf » Post

Brilliant!
My ContentDB -|- Working on CaptureTheFlag -|- Minetest Forums Dark Theme!! (You need it)

Chiantos
Member
Posts: 377
Joined: Sun Jan 15, 2017 09:04

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by Chiantos » Post

Deleted message
Last edited by Chiantos on Mon Sep 30, 2019 05:35, edited 1 time in total.

User avatar
TumeniNodes
Member
Posts: 2943
Joined: Fri Feb 26, 2016 19:49
GitHub: TumeniNodes
IRC: tumeninodes
In-game: TumeniNodes
Location: in the dark recesses of the mind
Contact:

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by TumeniNodes » Post

DUDE! This is so neat... :D
I wonder if you can assign a coordinate for each pixel? That might help with pixel selection and viewing
Meaning break the texture field up into a grid (as you would a sprite sheet), and assign a coord to each pixel
A Wonderful World

User avatar
GreenXenith
Member
Posts: 1356
Joined: Wed Oct 28, 2015 01:26
GitHub: GreenXenith
Location: UTC-8:00
Contact:

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by GreenXenith » Post

TumeniNodes wrote:I wonder if you can assign a coordinate for each pixel? That might help with pixel selection and viewing
Meaning break the texture field up into a grid (as you would a sprite sheet), and assign a coord to each pixel
I'm not sure what this means - the pixels already have coordinates.
YouTube | Mods | Patreon | Minetest Discord @greenxenith

You should not be able to read this message.

Angelbear
New member
Posts: 2
Joined: Sun Dec 06, 2020 13:38
In-game: Angelbear

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by Angelbear » Post

How doues this work? My current skin doues not shown the canvas and I can only find an empty paint pallete.

User avatar
GreenXenith
Member
Posts: 1356
Joined: Wed Oct 28, 2015 01:26
GitHub: GreenXenith
Location: UTC-8:00
Contact:

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by GreenXenith » Post

Angelbear wrote:
Sun Dec 06, 2020 16:24
How doues this work? My current skin doues not shown the canvas and I can only find an empty paint pallete.
To load your current skin, use the load button (manila folder, second button). The empty paint palette is only for custom palettes. To get the default palettes, rightclick with the paintbrush outside of the canvas and use the dropdown. Please read the instructions linked/pasted in the top post.
YouTube | Mods | Patreon | Minetest Discord @greenxenith

You should not be able to read this message.

Angelbear
New member
Posts: 2
Joined: Sun Dec 06, 2020 13:38
In-game: Angelbear

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by Angelbear » Post

K, I'm on iPad, so is there any way to load my skin onto it on iPad?

User avatar
GreenXenith
Member
Posts: 1356
Joined: Wed Oct 28, 2015 01:26
GitHub: GreenXenith
Location: UTC-8:00
Contact:

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by GreenXenith » Post

Angelbear wrote:
Mon Dec 07, 2020 15:31
K, I'm on iPad, so is there any way to load my skin onto it on iPad?
Controls are inside the canvas base. Tap/doubletap(?) the block to open the menu.
YouTube | Mods | Patreon | Minetest Discord @greenxenith

You should not be able to read this message.

hacknorris
Member
Posts: 68
Joined: Mon Mar 28, 2022 21:34
GitHub: hacknorris-aka-penguin
IRC: hacknorris
In-game: hacknorris

Re: [Mod] Make skins in-game at runtime [skinmaker] [1.0]

by hacknorris » Post

e. is this normal ?
debug.txt :

Code: Select all

2022-06-23 12:53:13: ACTION[Server]: singleplayer places node skinmaker:maker at (408,9,-269)
2022-06-23 12:53:26: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:53:27: ACTION[Server]: singleplayer digs default:snow at (409,9,-268)
2022-06-23 12:53:29: ACTION[Server]: singleplayer right-clicks object 42: LuaEntitySAO "skinmaker:canvas" at (408,10,-269)
2022-06-23 12:53:32: WARNING[Server]: Undeclared global variable "_" accessed at ...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:1014
2022-06-23 12:53:32: WARNING[Server]: Assignment to undeclared global "b" inside a function at ...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:1021.
2022-06-23 12:53:32: WARNING[Server]: Assignment to undeclared global "g" inside a function at ...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:1021.
2022-06-23 12:53:32: WARNING[Server]: Assignment to undeclared global "r" inside a function at ...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:1021.
2022-06-23 12:55:24: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:25: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:26: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:26: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:26: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:27: ACTION[Server]: singleplayer right-clicks object 42: LuaEntitySAO "skinmaker:canvas" at (408,10,-269)
2022-06-23 12:55:29: WARNING[Server]: Undeclared global variable "_" accessed at ...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:952
2022-06-23 12:55:32: ACTION[Server]: singleplayer right-clicks object 42: LuaEntitySAO "skinmaker:canvas" at (408,10,-269)
2022-06-23 12:55:33: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:36: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:36: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:36: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:36: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:37: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:37: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:37: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:37: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:37: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:38: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:38: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:38: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:43: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:44: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:44: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:55:44: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:16: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:17: ACTION[Server]: singleplayer right-clicks object 42: LuaEntitySAO "skinmaker:canvas" at (408,10,-269)
2022-06-23 12:56:35: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:36: ACTION[Server]: singleplayer right-clicks object 42: LuaEntitySAO "skinmaker:canvas" at (408,10,-269)
2022-06-23 12:56:52: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:53: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:53: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:53: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:54: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:55: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:55: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:56: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:56:57: ACTION[Server]: singleplayer digs default:snow at (410,9,-269)
2022-06-23 12:57:04: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:57:04: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:57:04: ACTION[Server]: player singleplayer (id=1, hp=20) punched LuaEntitySAO "skinmaker:canvas" at (408,10,-269) (id=42, hp=10), damage=0
2022-06-23 12:57:08: ERROR[Main]: ServerError: AsyncErr: Lua: Runtime error from mod 'skinmaker' in callback luaentity_Punch(): ...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:1183: attempt to index local 'pixel' (a nil value)
2022-06-23 12:57:08: ERROR[Main]: stack traceback:
2022-06-23 12:57:08: ERROR[Main]: 	...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:1183: in function 'canvas'
2022-06-23 12:57:08: ERROR[Main]: 	...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:386: in function <...in64\minetest-5.5.1-win64\bin\..\mods\skinmaker\init.lua:367>
2022-06-23 12:57:08: ACTION[Server]: singleplayer leaves game. List of players: 
2022-06-23 12:57:09: ACTION[Main]: Server: Shutting down
i use newest minetest btw.

also - when clicking no pixels is showing.

Post Reply

Who is online

Users browsing this forum: No registered users and 13 guests