enable [multiskin]

master
elite 2017-07-15 21:31:10 -04:00
parent 6a36c3b6ed
commit 2aee4873af
9 changed files with 342 additions and 0 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,51 @@
[mod] Multiskin [multiskin] [0.1.1]
===================================
**Minetest Version:** 0.4.16
**Depends:** default
Adds per-player support for version 1.8 minecraft skins.
On its own this mod acts as a replacement for the out-dated player_textures
mod by PilzAdam. Individual player textures can be placed in the mod's
textures directory and will be automatically assigned to a player by naming
the texture file as `player_<player_name>.png`
This mod also supports the following skin-switching mods which can be used
in conjuction with the multiskin default skins and chat commands.
```
[mod] Skins [skins] by Zeg9
[mod] Simple Skins [simple_skins] by TenPlus1
[mod] Unified Skins [u_skins] by SmallJoker
[mod] Wardrobe [wardrobe] by prestidigitator
```
Note that auto skin format detection is only available for these mods if
the multiskin mod is listed in the `secure.trusted_mods` setting.
Configuration
-------------
You can set the default skin by including the following settings in your
minetest.conf
Supported formats are `1.0` and `1.8`
```
multiskin_skin = <texture>
multiskin_format = <format>
```
Chat Commands
-------------
Requires `server` priv in multiplayer mode, no privs required in singleplayer.
```
/multiskin format <player_name> <format>
/multiskin set <player_name> <texture>
/multiskin unset <player_name>
/multiskin help
```
TODO
----
Document the api and add support to my 3d_armor and clothing mods.

View File

@ -0,0 +1,2 @@
default
sfinv?

View File

@ -0,0 +1,2 @@
Dual skin format player model.
Supports minecraft 1.0 and 1.8 skin formats on a per-player basis.

View File

@ -0,0 +1,264 @@
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local dir_list = minetest.get_dir_list(modpath.."/textures")
local default_skin = minetest.setting_get("multiskin_skin") or "character.png"
local default_format = minetest.setting_get("multiskin_format") or "1.0"
local player_skins = {}
local player_format = {}
local player_textures = {}
local skin_previews = {}
local skin_format = {[default_skin]=default_format}
local function get_skin_format(file)
file:seek("set", 1)
if file:read(3) == "PNG" then
file:seek("set", 16)
local ws = file:read(4)
local hs = file:read(4)
local w = ws:sub(3, 3):byte() * 256 + ws:sub(4, 4):byte()
local h = hs:sub(3, 3):byte() * 256 + hs:sub(4, 4):byte()
if w >= 64 then
if w == h then
return "1.8"
elseif w == h * 2 then
return "1.0"
end
end
end
end
for _, fn in pairs(dir_list) do
local file = io.open(modpath.."/textures/"..fn, "rb")
if file then
skin_format[fn] = get_skin_format(file)
file:close()
end
end
-- 3rd party skin-switcher support
-- may be removed from future versions as these mods do not
-- use the proper api method for setting player textures
--
-- Auto skin format detection for 3rd party mods requires
-- that multiskin is included in 'trusted mods'
local env = minetest.request_insecure_environment()
local skin_mod = modname
local skin_mods = {"skins", "u_skins", "simple_skins", "wardrobe"}
for _, mod in pairs(skin_mods) do
local path = minetest.get_modpath(mod)
if path then
local dir_list = minetest.get_dir_list(path.."/textures")
for _, fn in pairs(dir_list) do
if fn:find("_preview.png$") then
skin_previews[fn] = true
elseif env then
local file = env.io.open(path.."/textures/"..fn, "rb")
if file then
skin_format[fn] = get_skin_format(file)
file:close()
end
end
end
skin_mod = mod
end
end
env = nil
local function get_player_skin(player)
local name = player:get_player_name()
if name then
local skin = nil
if skin_mod == "skins" or skin_mod == "simple_skins" then
skin = skins.skins[name]
elseif skin_mod == "u_skins" then
skin = u_skins.u_skins[name]
elseif skin_mod == "wardrobe" then
local skins = wardrobe.playerSkins or {}
if skins[name] then
return skins[name]
end
end
if skin then
return skin..".png"
end
for _, fn in pairs(dir_list) do
if fn == "player_"..name..".png" then
return fn
end
end
end
return default_skin
end
multiskin = {
model = "multiskin.b3d",
skins = player_skins,
textures = player_textures,
}
multiskin.set_player_skin = function(player, skin)
local name = player:get_player_name()
local format = skin_format[skin]
if format then
player_format[name] = format
player:set_attribute("multiskin_format", format)
end
player_skins[name].skin = skin
player:set_attribute("multiskin_skin", skin)
end
multiskin.set_player_format = function(player, format)
local name = player:get_player_name()
player_format[name] = format
player:set_attribute("multiskin_format", format)
end
multiskin.add_preview = function(texture)
skin_previews[texture] = true
end
multiskin.get_preview = function(player)
local skin = player:get_attribute("multiskin_skin")
if skin then
local preview = skin:gsub(".png$", "_preview.png")
if skin_previews[preview] then
return preview
end
end
end
multiskin.update_player_visuals = function(player)
local name = player:get_player_name()
if not name or not player_skins[name] then
return
end
local anim = default.player_get_animation(player) or {}
if anim.model == "character.b3d" then
default.player_set_model(player, multiskin.model)
elseif anim.model ~= multiskin.model then
return
end
local textures = player_textures[name] or {}
local skin = player_skins[name].skin or "blank.png"
local cape = player_skins[name].cape
local layers = {}
for k, v in pairs(player_skins[name]) do
if k ~= "skin" and k ~= "cape" then
table.insert(layers, v)
end
end
local overlay = table.concat(layers, "^")
local format = player_format[name] or default_format
if format == "1.8" then
if overlay ~= "" then
skin = skin.."^"..overlay
end
textures[1] = cape or "blank.png"
textures[2] = skin
else
if cape then
skin = skin.."^"..cape
end
if overlay == "" then
overlay = "blank.png"
end
textures[1] = skin
textures[2] = overlay
end
default.player_set_textures(player, table.copy(textures))
end
default.player_register_model("multiskin.b3d", {
animation_speed = 30,
textures = {
"blank.png",
"blank.png",
},
animations = {
stand = {x=0, y=79},
lay = {x=162, y=166},
walk = {x=168, y=187},
mine = {x=189, y=198},
walk_mine = {x=200, y=219},
sit = {x=81, y=160},
},
})
minetest.register_on_joinplayer(function(player)
minetest.after(0, function(player)
local name = player:get_player_name()
local skin = player:get_attribute("multiskin_skin") or
get_player_skin(player)
local anim = default.player_get_animation(player) or {}
player_textures[name] = anim.textures or {}
player_skins[name] = {skin=skin}
player_format[name] = player:get_attribute("multiskin_format")
multiskin.set_player_skin(player, skin)
multiskin.update_player_visuals(player)
end, player)
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if name then
player_skins[name] = nil
player_format[name] = nil
player_textures[name] = nil
end
end)
minetest.register_on_player_receive_fields(function(player, formname, fields)
local name = player:get_player_name()
for field, _ in pairs(fields) do
if string.find(field, "skins_set") then
minetest.after(0, function(player)
local name = player:get_player_name()
local skin = get_player_skin(player)
multiskin.set_player_skin(player, skin)
multiskin.update_player_visuals(player)
end, player)
end
end
end)
minetest.register_chatcommand("multiskin", {
params = "<cmd> [name] [args]",
description = "Multiskin player skin and format management",
func = function(name, param)
if not minetest.is_singleplayer() and
not minetest.check_player_privs(name, {server=true}) then
return false, "Insufficient privileges"
end
local cmd, player_name, args = string.match(param, "^([^ ]+) (.-) (.+)$")
if not args then
cmd, player_name = string.match(param, "([^ ]+) (.+)")
end
local player = nil
if player_name then
player = minetest.get_player_by_name(player_name)
else
cmd = string.match(param, "([^ ]+)")
end
if cmd == "help" then
local msg = "\nUsage: /multiskin <cmd> [name] [args]\n\n"..
" format <player_name> <format> (1.0 or 1.8)\n"..
" set <player_name> <texture>\n"..
" unset <player_name>\n"..
" help (show this message)\n\n"
minetest.chat_send_player(name, msg)
elseif cmd == "format" and player and args then
multiskin.set_player_format(player, args)
multiskin.update_player_visuals(player)
elseif cmd == "set" and player and args then
multiskin.set_player_skin(player, args)
multiskin.update_player_visuals(player)
elseif cmd == "unset" and player then
player_skins[player_name].skin = get_player_skin(player)
player:set_attribute("multiskin_skin", nil)
multiskin.update_player_visuals(player)
else
return false, "Invalid parameters, see /multiskin help"
end
end,
})

View File

@ -0,0 +1 @@
name = multiskin

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
Place your player skins here named as `player_<player_name>.png`