diff --git a/API.md b/API.md index 2958279..830b30e 100644 --- a/API.md +++ b/API.md @@ -55,6 +55,16 @@ Get the skin texture for any reason. Note to apply them the skin:set_skin() shou Could be redefined for dynamic texture generation +## skin:set_hand(hand_node) +Set the hand node to be used with this skin + +## skin:set_hand_from_texture() +Register and set hand node based on skin texture +Only works on mod load + +## skin:get_hand() +Get hand node. Returns ItemStack + ## skin:set_preview(texture) Set the skin preview - usually at the init time only @@ -67,7 +77,7 @@ Could be redefined for dynamic preview texture generation Hook for dynamic skins updates on select. Is called in skins.set_player_skin() In skinsdb the default implementation for this function is empty. -skin:apply_skin_to_player(player) +## skin:apply_skin_to_player(player) Apply the skin to the player. Called in skins.update_player_skin() to update visuals ## skin:set_meta(key, value) diff --git a/README.md b/README.md index 03637af..0515f05 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This Minetest mod offers changeable player skins with a graphical interface for - Support for different skins lists: public and a per-player list are currently implemented - Full [3d_armor](https://forum.minetest.net/viewtopic.php?t=4654) support - Compatible to 1.0 and 1.8 Minecraft skins format +- Skinned hand in 1st person view (1.0 skins only) ## Installing skins @@ -53,6 +54,7 @@ The Script will download all the skins from the database for you. ## License: - GPLv3 - skin texture licenses: See "meta" folder +- hand model: CC0 ### Credits @@ -62,4 +64,5 @@ The Script will download all the skins from the database for you. - Krock (source code) - bell07 (source code) - stujones11 (player models) +- jordan4ibanez (1st person view hand) - sirrobzeroone (skins) diff --git a/api.lua b/api.lua index 6f956ce..b5a8211 100644 --- a/api.lua +++ b/api.lua @@ -34,7 +34,7 @@ function skins.assign_player_skin(player, skin) else return false end - return true + return true, skin_obj end -- update visuals @@ -53,11 +53,11 @@ end -- Assign and update - should be used on selection externally function skins.set_player_skin(player, skin) - local success = skins.assign_player_skin(player, skin) + local success, skin_obj = skins.assign_player_skin(player, skin) if success then skins.get_player_skin(player):set_skin(player) skins.update_player_skin(player) - minetest.log("action", player:get_player_name().." set skin to "..skin:get_meta("name")) + minetest.log("action", player:get_player_name().." set skin to "..skin_obj:get_key("")) end return success end diff --git a/formspecs.lua b/formspecs.lua index 70a5dd8..19482e8 100644 --- a/formspecs.lua +++ b/formspecs.lua @@ -1,5 +1,5 @@ local S = minetest.get_translator("skinsdb") -local ui = unified_inventory +local ui = minetest.global_exists("unified_inventory") and unified_inventory function skins.get_formspec_context(player) if player then diff --git a/init.lua b/init.lua index 33345ed..718c7c3 100644 --- a/init.lua +++ b/init.lua @@ -91,4 +91,12 @@ if not default_skin_obj then default_skin_obj:set_meta("format", '1.0') default_skin_obj:set_meta("_sort_id", 0) default_skin_obj:set_meta("name", "Sam") + default_skin_obj:set_hand_from_texture() end + +-- Secure hand inventory slot +minetest.register_allow_player_inventory_action(function(player, action, inv, data) + if data.to_list == "hand" or data.from_list == "hand" or data.listname == "hand" then + return 0 + end +end) diff --git a/models/skinsdb_hand.b3d b/models/skinsdb_hand.b3d new file mode 100644 index 0000000..a38124c Binary files /dev/null and b/models/skinsdb_hand.b3d differ diff --git a/models/skinsdb_hand.blend b/models/skinsdb_hand.blend new file mode 100644 index 0000000..495e74e Binary files /dev/null and b/models/skinsdb_hand.blend differ diff --git a/skin_meta_api.lua b/skin_meta_api.lua index 29e174b..e9a4c7c 100644 --- a/skin_meta_api.lua +++ b/skin_meta_api.lua @@ -51,6 +51,34 @@ function skin_class:get_texture() return self._texture end +function skin_class:set_hand(hand) + self._hand = hand +end + +local ALPHA_CLIP = minetest.features.use_texture_alpha_string_modes and "clip" or true +function skin_class:set_hand_from_texture() + local hand = core.get_current_modname()..':'..self._texture:gsub('[%p%c%s]', '') + + minetest.register_node(hand, { + tiles = {self:get_texture()}, + inventory_image = "wieldhand.png", + visual_scale = 1, + wield_scale = {x=1,y=1,z=1}, + paramtype = "light", + drawtype = "mesh", + mesh = "skinsdb_hand.b3d", + use_texture_alpha = ALPHA_CLIP, + node_placement_prediction = "", + groups = { not_in_creative_inventory = 1 } + }) + + self:set_hand(hand) +end + +function skin_class:get_hand() + return self._hand +end + function skin_class:set_preview(value) self._preview = value end @@ -174,6 +202,14 @@ function skin_class:apply_skin_to_player(player) y = self:get_meta("visual_size_y") or 1 } }) + + local hand = self:get_hand() + if hand then + player:get_inventory():set_size("hand", 1) + player:get_inventory():set_stack("hand", 1, hand) + else + player:get_inventory():set_stack("hand", 1, "") + end end function skin_class:set_skin(player) diff --git a/skinlist.lua b/skinlist.lua index cb8d050..a40ed56 100644 --- a/skinlist.lua +++ b/skinlist.lua @@ -48,8 +48,12 @@ for _, fn in pairs(skins_dir_list) do skin_obj:set_meta("playername", playername) end local file = io.open(skins.modpath.."/textures/"..fn, "r") - skin_obj:set_meta("format", skins.get_skin_format(file)) + local skin_format = skins.get_skin_format(file) + skin_obj:set_meta("format", skin_format) file:close() + if skin_format == "1.0" then + skin_obj:set_hand_from_texture() + end file = io.open(skins.modpath.."/meta/"..name..".txt", "r") if file then local data = string.split(file:read("*all"), "\n", 3) @@ -73,9 +77,9 @@ local function skins_sort(skinslist) local a_id = a:get_meta("_sort_id") or 10000 local b_id = b:get_meta("_sort_id") or 10000 if a_id ~= b_id then - return a:get_meta("_sort_id") < b:get_meta("_sort_id") + return a_id < b_id else - return a:get_meta("name") < b:get_meta("name") + return (a:get_meta("name") or 'ZZ') < (b:get_meta("name") or 'ZZ') end end) end