From 62e3a8b9ff665a46ec2160d9b0cf72f7d4f2fdfa Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 5 Mar 2019 00:11:43 +0100 Subject: [PATCH] Add player skin support, add female skin --- mods/PLAYER/simple_skins/depends.txt | 3 + mods/PLAYER/simple_skins/description.txt | 1 + mods/PLAYER/simple_skins/init.lua | 148 ++++++++++++++++++ mods/PLAYER/simple_skins/intllib.lua | 45 ++++++ mods/PLAYER/simple_skins/license.txt | 21 +++ mods/PLAYER/simple_skins/locale/fr.po | 51 ++++++ mods/PLAYER/simple_skins/locale/it.po | 52 ++++++ mods/PLAYER/simple_skins/locale/ms.po | 51 ++++++ mods/PLAYER/simple_skins/locale/template.pot | 50 ++++++ mods/PLAYER/simple_skins/meta/character.txt | 3 + mods/PLAYER/simple_skins/meta/character_1.txt | 3 + mods/PLAYER/simple_skins/mod.conf | 1 + mods/PLAYER/simple_skins/readme.md | 7 + .../simple_skins/textures/character_1.png | Bin 0 -> 5505 bytes .../textures/inventory_plus_skins.png | Bin 0 -> 2182 bytes 15 files changed, 436 insertions(+) create mode 100644 mods/PLAYER/simple_skins/depends.txt create mode 100644 mods/PLAYER/simple_skins/description.txt create mode 100644 mods/PLAYER/simple_skins/init.lua create mode 100644 mods/PLAYER/simple_skins/intllib.lua create mode 100644 mods/PLAYER/simple_skins/license.txt create mode 100644 mods/PLAYER/simple_skins/locale/fr.po create mode 100644 mods/PLAYER/simple_skins/locale/it.po create mode 100644 mods/PLAYER/simple_skins/locale/ms.po create mode 100644 mods/PLAYER/simple_skins/locale/template.pot create mode 100644 mods/PLAYER/simple_skins/meta/character.txt create mode 100644 mods/PLAYER/simple_skins/meta/character_1.txt create mode 100644 mods/PLAYER/simple_skins/mod.conf create mode 100644 mods/PLAYER/simple_skins/readme.md create mode 100644 mods/PLAYER/simple_skins/textures/character_1.png create mode 100644 mods/PLAYER/simple_skins/textures/inventory_plus_skins.png diff --git a/mods/PLAYER/simple_skins/depends.txt b/mods/PLAYER/simple_skins/depends.txt new file mode 100644 index 000000000..1927ce890 --- /dev/null +++ b/mods/PLAYER/simple_skins/depends.txt @@ -0,0 +1,3 @@ +mcl_player +intllib? +3d_armor? diff --git a/mods/PLAYER/simple_skins/description.txt b/mods/PLAYER/simple_skins/description.txt new file mode 100644 index 000000000..61c7bff64 --- /dev/null +++ b/mods/PLAYER/simple_skins/description.txt @@ -0,0 +1 @@ +Mod that allows players to set their individual skins. \ No newline at end of file diff --git a/mods/PLAYER/simple_skins/init.lua b/mods/PLAYER/simple_skins/init.lua new file mode 100644 index 000000000..3a41490f4 --- /dev/null +++ b/mods/PLAYER/simple_skins/init.lua @@ -0,0 +1,148 @@ +-- Simple Skins mod for Minetest (MineClone 2 Edition) + +-- Released by TenPlus1 and based on Zeg9's code under MIT license + +skins = { + skins = {}, meta = {}, + modpath = minetest.get_modpath("simple_skins"), + skin_count = 0, -- counter of _custom_ skins (all skins except character.png) +} + + +-- Load support for intllib. +local S, NS = dofile(skins.modpath .. "/intllib.lua") + + +-- load skin list and metadata +local id, f, data, skin = 1 + +while true do + + skin = "character_" .. id + + -- does skin file exist ? + f = io.open(skins.modpath .. "/textures/" .. skin .. ".png") + + -- escape loop if not found and remove last entry + if not f then + id = id - 1 + break + end + + f:close() + + -- does metadata exist for that skin file ? + f = io.open(skins.modpath .. "/meta/" .. skin .. ".txt") + + if f then + data = minetest.deserialize("return {" .. f:read('*all') .. "}") + f:close() + end + + -- add metadata to list + skins.meta[skin] = { + name = data and data.name or "", + author = data and data.author or "", + } + + id = id + 1 + skins.skin_count = skins.skin_count + 1 +end + +skins.set_player_skin = function(player, skin) + if not player then + return + end + local playername = player:get_player_name() + skins.skins[playername] = skin + player:set_attribute("simple_skins:skin", skins.skins[playername]) + skins.update_player_skin(player) + if minetest.get_modpath("3d_armor") then + armor.textures[playername].skin = skin .. ".png" + armor:update_player_visuals(player) + end +end + +skins.update_player_skin = function(player) + if not player then + return + end + local playername = player:get_player_name() + mcl_player.player_set_textures(player, { skins.skins[playername] .. ".png" }) +end + +-- load player skin on join +minetest.register_on_joinplayer(function(player) + + local name = player:get_player_name() + local skin = player:get_attribute("simple_skins:skin") + local set_skin + -- do we already have a skin in player attributes? + if skin then + set_skin = skin + + -- otherwise use random skin if not set + else + local r = math.random(0, skins.skin_count) + if r == 0 then + set_skin = "character" + else + set_skin = "character_" .. r + end + end + if set_skin then + skins.set_player_skin(player, set_skin) + end +end) + +-- command to set player skin (usually for custom skins) +minetest.register_chatcommand("setskin", { + params = "[] ", + description = S("Select player skin of yourself or another player"), + privs = {}, + func = function(name, param) + + local playername, skin_id = string.match(param, "([^ ]+) (%d+)") + if not playername or not skin_id then + skin_id = string.match(param, "(%d+)") + if not skin_id then + return false, S("Insufficient or wrong parameters") + end + playername = name + end + skin_id = tonumber(skin_id) + + local player = minetest.get_player_by_name(playername) + + if not player then + return false, S("Player @1 not online!", playername) + end + if name ~= playername then + local privs = minetest.get_player_privs(name) + if not privs.server then + return false, S("You need the “server” privilege to change the skin of other players!") + end + end + + local skin + if skin_id == nil or skin_id > skins.skin_count or skin_id < 0 then + return false, S("Invalid skin number! Valid numbers: 0 to @1", skins.skin_count) + elseif skin_id == 0 then + skin = "character" + else + skin = "character_" .. tostring(skin_id) + end + + skins.set_player_skin(player, skin) + local skinfile = skin..".png" + + local your_msg = S("Your skin has been set to: @1", skinfile) + if name == playername then + return true, your_msg + else + minetest.chat_send_player(playername, your_msg) + return true, S("Skin of @1 set to: @2", playername, skinfile) + end + + end, +}) diff --git a/mods/PLAYER/simple_skins/intllib.lua b/mods/PLAYER/simple_skins/intllib.lua new file mode 100644 index 000000000..6669d7202 --- /dev/null +++ b/mods/PLAYER/simple_skins/intllib.lua @@ -0,0 +1,45 @@ + +-- Fallback functions for when `intllib` is not installed. +-- Code released under Unlicense . + +-- Get the latest version of this file at: +-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua + +local function format(str, ...) + local args = { ... } + local function repl(escape, open, num, close) + if escape == "" then + local replacement = tostring(args[tonumber(num)]) + if open == "" then + replacement = replacement..close + end + return replacement + else + return "@"..open..num..close + end + end + return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) +end + +local gettext, ngettext +if minetest.get_modpath("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + gettext, ngettext = intllib.make_gettext_pair() + else + -- Old method using text files. + gettext = intllib.Getter() + end +end + +-- Fill in missing functions. + +gettext = gettext or function(msgid, ...) + return format(msgid, ...) +end + +ngettext = ngettext or function(msgid, msgid_plural, n, ...) + return format(n==1 and msgid or msgid_plural, ...) +end + +return gettext, ngettext diff --git a/mods/PLAYER/simple_skins/license.txt b/mods/PLAYER/simple_skins/license.txt new file mode 100644 index 000000000..fec6f6aa5 --- /dev/null +++ b/mods/PLAYER/simple_skins/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 TenPlus1 + +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. diff --git a/mods/PLAYER/simple_skins/locale/fr.po b/mods/PLAYER/simple_skins/locale/fr.po new file mode 100644 index 000000000..30d8e36e7 --- /dev/null +++ b/mods/PLAYER/simple_skins/locale/fr.po @@ -0,0 +1,51 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-29 07:11+0200\n" +"PO-Revision-Date: 2017-07-29 07:17+0200\n" +"Last-Translator: fat115 \n" +"Language-Team: \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.12\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: init.lua +msgid "Select Player Skin:" +msgstr "Sélectionner l'apparence du joueur :" + +#: init.lua +msgid "Name: " +msgstr "Nom : " + +#: init.lua +msgid "Author: " +msgstr "Auteur : " + +#: init.lua +msgid "Admin command to set player skin" +msgstr "Commande admin pour définir l'apparence du joueur" + +#: init.lua +msgid "'s skin set to" +msgstr ", apparence définie pour" + +#: init.lua +msgid "Set player skin" +msgstr "Définir l'apparence du joueur" + +#: init.lua +msgid "Close" +msgstr "Fermer" + +#: init.lua +msgid "[MOD] Simple Skins loaded" +msgstr "[MOD] Simple Skins chargé" diff --git a/mods/PLAYER/simple_skins/locale/it.po b/mods/PLAYER/simple_skins/locale/it.po new file mode 100644 index 000000000..d4701316d --- /dev/null +++ b/mods/PLAYER/simple_skins/locale/it.po @@ -0,0 +1,52 @@ +# simple_skin . +# Copyright (C) 2018 +# This file is distributed under the same license as the PACKAGE package. +# Stefano Peris , 2018. +# Github: +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-02-21 07:29+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Stefano Peris \n" +"Language-Team: \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.12\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: init.lua +msgid "Select Player Skin:" +msgstr "Seleziona la skin del giocatore" + +#: init.lua +msgid "Name: " +msgstr "Nome" + +#: init.lua +msgid "Author: " +msgstr "Autore" + +#: init.lua +msgid "Admin command to set player skin" +msgstr "Comando di admin per impostare la skin del giocatore" + +#: init.lua +msgid "'s skin set to" +msgstr ", la skin è impostata su" + +#: init.lua +msgid "Set player skin" +msgstr "Imposta la skin del giocatore" + +#: init.lua +msgid "Close" +msgstr "Chiudi" + +#: init.lua +msgid "[MOD] Simple Skins loaded" +msgstr "[MOD] Skins semplici caricate" diff --git a/mods/PLAYER/simple_skins/locale/ms.po b/mods/PLAYER/simple_skins/locale/ms.po new file mode 100644 index 000000000..bba5982d4 --- /dev/null +++ b/mods/PLAYER/simple_skins/locale/ms.po @@ -0,0 +1,51 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-29 07:11+0200\n" +"PO-Revision-Date: 2018-02-14 01:23+0800\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" +"Last-Translator: MuhdNurHidayat (MNH48) \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language: ms\n" + +#: init.lua +msgid "Select Player Skin:" +msgstr "Pilih Kulit Pemain:" + +#: init.lua +msgid "Name: " +msgstr "Nama: " + +#: init.lua +msgid "Author: " +msgstr "Pencipta: " + +#: init.lua +msgid "Admin command to set player skin" +msgstr "Perintah pentadbir untuk menetapkan kulit pemain" + +#: init.lua +msgid "'s skin set to" +msgstr " telah ditukarkan kulitnya kepada" + +#: init.lua +msgid "Set player skin" +msgstr "Tetapkan kulit pemain" + +#: init.lua +msgid "Close" +msgstr "Tutup" + +#: init.lua +msgid "[MOD] Simple Skins loaded" +msgstr "[MODS] Simple Skins telah dimuatkan" diff --git a/mods/PLAYER/simple_skins/locale/template.pot b/mods/PLAYER/simple_skins/locale/template.pot new file mode 100644 index 000000000..36282e43c --- /dev/null +++ b/mods/PLAYER/simple_skins/locale/template.pot @@ -0,0 +1,50 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-29 07:11+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: init.lua +msgid "Select Player Skin:" +msgstr "" + +#: init.lua +msgid "Name: " +msgstr "" + +#: init.lua +msgid "Author: " +msgstr "" + +#: init.lua +msgid "Admin command to set player skin" +msgstr "" + +#: init.lua +msgid "'s skin set to" +msgstr "" + +#: init.lua +msgid "Set player skin" +msgstr "" + +#: init.lua +msgid "Close" +msgstr "" + +#: init.lua +msgid "[MOD] Simple Skins loaded" +msgstr "" diff --git a/mods/PLAYER/simple_skins/meta/character.txt b/mods/PLAYER/simple_skins/meta/character.txt new file mode 100644 index 000000000..5a07db19e --- /dev/null +++ b/mods/PLAYER/simple_skins/meta/character.txt @@ -0,0 +1,3 @@ +name = "Steve", +author = "(Texture pack author)", +description = "The default male skin.", diff --git a/mods/PLAYER/simple_skins/meta/character_1.txt b/mods/PLAYER/simple_skins/meta/character_1.txt new file mode 100644 index 000000000..ec4389550 --- /dev/null +++ b/mods/PLAYER/simple_skins/meta/character_1.txt @@ -0,0 +1,3 @@ +name = "Alex", +author = "(Texture pack author)", +description = "The default female skin.", diff --git a/mods/PLAYER/simple_skins/mod.conf b/mods/PLAYER/simple_skins/mod.conf new file mode 100644 index 000000000..aff90aabe --- /dev/null +++ b/mods/PLAYER/simple_skins/mod.conf @@ -0,0 +1 @@ +name = simple_skins diff --git a/mods/PLAYER/simple_skins/readme.md b/mods/PLAYER/simple_skins/readme.md new file mode 100644 index 000000000..0c6980bbb --- /dev/null +++ b/mods/PLAYER/simple_skins/readme.md @@ -0,0 +1,7 @@ +Simple Skins, MineClone 2 Edition + +Simple Skins mod to allow players to select a skin. +Use the chat command /setskin to change skin. + +Original mod: +https://forum.minetest.net/viewtopic.php?id=9100 diff --git a/mods/PLAYER/simple_skins/textures/character_1.png b/mods/PLAYER/simple_skins/textures/character_1.png new file mode 100644 index 0000000000000000000000000000000000000000..71f02471dc622249681a511a66087b803e97dbdf GIT binary patch literal 5505 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 un6! zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1bvvI8d!{O1%o0%F&3SgUe_96t@xjF)G>N>cHZ z&5Qj?pTL1##Z9sDk(O*YzxrUWn-{yeUpSaNS}%`j zYX1s*d<@7z?d{cWa#ue^9ntOheEgny-)q03j=U2)>9b)SSHshC^y|91Rp;-|Ap?vN z;mS{Oy(rM2N{i-cJ9UH@+;kbObKUu4D?U4R{g4v&MayN-GmI}_qk}cS zdAVbuGcTX{Iu*=32t6Ia8DYea%X~8am+N-4)=pg_TW+inm)kjwFgA1h7rj6TEyXk* ze9vW`^2R<9>%m|=Fc&Pa+9obqq(^S~!?Q=fXoIn`H7E~t0EjSmL@?yRfKB8hC9>JM zOavSY_^F88A?+I&pcvgCv%rn_3FH*F=f;>!r>~1n%#aok5qc zn*k)W+nm`#A-K)l=FIYztLVTQ#ZAtj%@`OAlU!VMbN68GSKdqv|B5&FjXATa`#+d7 zn>uCgCvP8E8}(Eae+b&UaARuyg0L;`sw>qs?vo)mWk2v#%5zDOcM(|LNym{*YP&^IxcJR|h?wTg6D7!K?@Pd#hK1L&1i%Qu6q2&}a}r*wVfnsG#M#3E zrPvu+K$WF5hq2*;6R7L~Iu>bAW>U;LR=H4|R1JDxhE$@){;M#8OtQH8F&>yV8L?1N zQ56OYu9#$m#r}*jkiKD2#AGJ?=_pq+^`ZMVV5y2y&o$jB@enwMLy0vHQMdwdT`Y}V z9^Pwt!XaWhg|~)4Q(*__Jg2?Eo>`PV4~HW=&k^O3YvhH~hHCw&j}q`xMqV=FmOuOh zPw(hXIgqDPRcAr$N#*RRbx z7xB1c0{}kG71`<`s^EX6sto=dUm=F1wKC_ZMLNyLStO`aw}VwpYlu~KG??#js_2G- z1GOacj?(J>O2G1#EY@-qsg$o+>W<)cn--3wZ2kt)1t<@#h~&fo000JJOGiWi{{a60 z|De66lK=n!32;bRa{vG?BLDy{BLR4&KXw2B00(qQO+^Re0|XW-2Yq6wLI3~($Vo&& zR4C7Fl0irmQ5eU6GYk~EJM7M^>ngKUDy#@)As!Y%C@2b1FJW}ZONSPc4xW-dWQV{G zdP>M30y}l|AW0oIyqLirioi>jQsB@IZ)kK@yLI^TvBVlqSL`UMNi@-Bi*| zJ-$666d0YEADx*OtH#F7%NOroA6{Hr-`??o?z6ec;=uAo_0#sBH!E+SExn%|X#r+e z>r?lx-WtDQ0gG$vO6^Zy8wOr|tS)a