-- Mod: appearance -- File: init.lua -- License: CC BY-NC-SA 4.0 -- Attribution: Don Michaud -- Revision: 160813 appearance = {} local DATAFILE = "appearance.dat" local DATAPATH = minetest.get_worldpath() .. "/" .. DATAFILE -- =================================================================== -- Save/Read file functions function read_appearance() local f, err = io.open (DATAPATH, "r") if err then return end if f then local data = minetest.deserialize (f:read("*a")) f:close() return data end end function save_appearance() local file = io.open (DATAPATH, "w") file:write (minetest.serialize (appearance)) file:close() end -- =================================================================== -- Load appearance data. local f, err = io.open (DATAPATH, "r") if f then appearance = read_appearance() f:close() end -- =================================================================== -- Base Textures local APMALE = "appearance_male_" local APFEMALE = "appearance_female_" local mskin = APMALE .. "skin.png" local mpants = APMALE .. "pants.png" local mshirt = APMALE .. "shirt.png" local mshoes = APMALE .. "shoes.png" local mface = APMALE .. "face.png" local meyes = APMALE .. "eyes.png" local mbelt = APMALE .. "belt.png" local moverlay = APMALE .. "overlay.png" local mhair = APMALE .. "hair.png" local fskin = APFEMALE .. "skin.png" local fpants = APFEMALE .. "pants.png" local fshirt = APFEMALE .. "shirt.png" local fshoes = APFEMALE .. "shoes.png" local fface = APFEMALE .. "face.png" local feyes = APFEMALE .. "eyes.png" local fbelt = APFEMALE .. "belt.png" local foverlay = APFEMALE .. "overlay.png" local fhair = APFEMALE .. "hair.png" -- =================================================================== -- Function to set a player's appearance function appearance_update (name) local player = minetest.get_player_by_name (name) if appearance and appearance [name] then local apname = appearance [name] local skintex = apname.skin local pantstex = apname.pants local shirttex = apname.shirt local shoestex = apname.shoes local facetex = apname.face local eyestex = apname.eyes local belttex = apname.belt local overlaytex = apname.overlay local hairtex = apname.hair player:set_properties ({ mesh = "appearance_character.b3d" , textures = { skintex .. pantstex .. shirttex .. shoestex .. facetex .. eyestex .. belttex .. overlaytex .. hairtex } , visual = "mesh" , visual_size = { x=1, y=1} , }) end end -- =================================================================== -- Chat Commands local colors_table = { { "black" , "Black" , "#000000b0" } , { "blue" , "Blue" , "#015dbb70" } , { "brown" , "Brown" , "#a78c4570" } , { "cyan" , "Cyan" , "#01ffd870" } , { "darkgreen" , "Dark Green" , "#005b0770" } , { "darkgrey" , "Dark Grey" , "#303030b0" } , { "green" , "Green" , "#61ff0170" } , { "grey" , "Grey" , "#5b5b5bb0" } , { "magenta" , "Magenta" , "#ff05bb70" } , { "orange" , "Orange" , "#ff840170" } , { "pink" , "Pink" , "#ff65b570" } , { "red" , "Red" , "#ff000070" } , { "violet" , "Violet" , "#2000c970" } , { "white" , "White" , "#abababc0" } , { "yellow" , "Yellow" , "#e3ff0070" } , } -- =================================================================== local function change_appearance(name,fields) local f = minetest.serialize(fields) for i in ipairs(colors_table) do local col = colors_table[i][1] if string.find(f,"sex") ~= nil then if string.find(f, "female") ~= nil then appearance[name].sex = "female" appearance[name].skin = fskin.."^" appearance[name].pants = fpants.."^" appearance[name].shirt = fshirt.."^" appearance[name].shoes = fshoes.."^" appearance[name].face = fface.."^" appearance[name].eyes = "("..feyes.."^[colorize:blue:220)^" appearance[name].belt = "("..fbelt.."^[colorize:blue:220)^" appearance[name].overlay = foverlay.."^" appearance[name].hair = fhair else appearance[name].sex = "male" appearance[name].skin = mskin.."^" appearance[name].pants = mpants.."^" appearance[name].shirt = mshirt.."^" appearance[name].shoes = mshoes.."^" appearance[name].face = mface.."^" appearance[name].eyes = "("..meyes.."^[colorize:blue:220)^" appearance[name].belt = "("..mbelt.."^[colorize:blue:220)^" appearance[name].overlay = moverlay.."^" appearance[name].hair = mhair end elseif string.find(f,"skin") ~= nil then local b = string.find(f, "%d" ) local c = tonumber(string.sub(f, b, b + 1)) if c ~= nil then appearance.skin_col = c if appearance[name].sex == "male" then appearance[name].skin = "("..mskin.."^[colorize:#4b2700:"..tostring(c*20)..")^" else appearance[name].skin = "("..fskin.."^[colorize:#4b2700:"..tostring(c*20)..")^" end end elseif string.find(f,"eyes") ~= nil then if string.find(f, col) ~= nil then appearance.eyes_col = col if appearance[name].sex == "male" then appearance[name].eyes = "("..meyes.."^[colorize:"..col..":220)^" else appearance[name].eyes = "("..feyes.."^[colorize:"..col..":220)^" end end elseif string.find(f,"hair") ~= nil then if string.find(f, col) ~= nil then appearance.hair_col = col if appearance[name].sex == "male" then appearance[name].hair = "("..mhair.."^[colorize:"..col..":220)" else appearance[name].hair = "("..fhair.."^[colorize:"..col..":220)" end end elseif string.find(f,"shirt") ~= nil then if string.find(f, col) ~= nil then appearance.shirt_col = col if appearance[name].sex == "male" then appearance[name].shirt = "("..mshirt.."^[colorize:"..col..":200)^" else appearance[name].shirt = "("..fshirt.."^[colorize:"..col..":200)^" end end elseif string.find(f,"pants") ~= nil then if string.find(f, col) ~= nil then appearance.pants_col = col if appearance[name].sex == "male" then appearance[name].pants = "("..mpants.."^[colorize:"..col..":200)^" else appearance[name].pants = "("..fpants.."^[colorize:"..col..":200)^" end end elseif string.find(f,"shoes") ~= nil then if string.find(f, col) ~= nil then appearance.shoes_col = col if appearance[name].sex == "male" then appearance[name].shoes = "("..mshoes.."^[colorize:"..col..":150)^" else appearance[name].shoes = "("..fshoes.."^[colorize:"..col..":240)^" end end elseif string.find(f,"belt") ~= nil then if string.find(f, col) ~= nil then appearance.belt_col = col if appearance[name].sex == "male" then appearance[name].belt = "("..mbelt.."^[colorize:"..col..":220)^" else appearance[name].belt = "("..fbelt.."^[colorize:"..col..":220)^" end end else return end end appearance_update(name) save_appearance() end -- =================================================================== local appearance_form_mirror = "size[8.5,6;]".. --"bgcolor[#40a7dc;true]".. "background[0,0;8.5,6.25;appearance_form_background.png]".. --Sex "label[0.5,0.5;Male or Female]".. "image_button[2.5,0.5;1,1;appearance_male.png;sex_male;]".. "image_button[4,0.5;1,1;appearance_female.png;sex_female;]".. --Skin "label[0.5,1.5;Skin Color]".. "image_button[0.5,2;0.5,0.5;appearance_skin01.png;skin_01;]".. "image_button[1,2;0.5,0.5;appearance_skin02.png;skin_02;]".. "image_button[1.5,2;0.5,0.5;appearance_skin03.png;skin_03;]".. "image_button[2,2;0.5,0.5;appearance_skin04.png;skin_04;]".. "image_button[2.5,2;0.5,0.5;appearance_skin05.png;skin_05;]".. "image_button[3,2;0.5,0.5;appearance_skin06.png;skin_06;]".. "image_button[3.5,2;0.5,0.5;appearance_skin07.png;skin_07;]".. "image_button[4,2;0.5,0.5;appearance_skin08.png;skin_08;]".. "image_button[4.5,2;0.5,0.5;appearance_skin09.png;skin_09;]".. "image_button[5,2;0.5,0.5;appearance_skin10.png;skin_10;]".. --Eyes "label[0.5,2.5;Eye Color]".. "image_button[0.5,3;0.5,0.5;wool_black.png;eyes_black;]".. "image_button[1,3;0.5,0.5;wool_blue.png;eyes_blue;]".. "image_button[1.5,3;0.5,0.5;wool_brown.png;eyes_brown;]".. "image_button[2,3;0.5,0.5;wool_cyan.png;eyes_cyan;]".. "image_button[2.5,3;0.5,0.5;wool_dark_green.png;eyes_darkgreen;]".. "image_button[3,3;0.5,0.5;wool_dark_grey.png;eyes_darkgray;]".. "image_button[3.5,3;0.5,0.5;wool_green.png;eyes_green;]".. "image_button[4,3;0.5,0.5;wool_grey.png;eyes_gray;]".. "image_button[4.5,3;0.5,0.5;wool_magenta.png;eyes_magenta;]".. "image_button[5,3;0.5,0.5;wool_orange.png;eyes_orange;]".. "image_button[5.5,3;0.5,0.5;wool_pink.png;eyes_pink;]".. "image_button[6,3;0.5,0.5;wool_red.png;eyes_red;]".. "image_button[6.5,3;0.5,0.5;wool_violet.png;eyes_violet;]".. "image_button[7,3;0.5,0.5;wool_white.png;eyes_white;]".. "image_button[7.5,3;0.5,0.5;wool_yellow.png;eyes_yellow;]".. --Hair "label[0.5,3.5;Hair Color]".. "image_button[0.5,4;0.5,0.5;wool_black.png;hair_black;]".. "image_button[1,4;0.5,0.5;wool_blue.png;hair_blue;]".. "image_button[1.5,4;0.5,0.5;wool_brown.png;hair_brown;]".. "image_button[2,4;0.5,0.5;wool_cyan.png;hair_cyan;]".. "image_button[2.5,4;0.5,0.5;wool_dark_green.png;hair_darkgreen;]".. "image_button[3,4;0.5,0.5;wool_dark_grey.png;hair_darkgray;]".. "image_button[3.5,4;0.5,0.5;wool_green.png;hair_green;]".. "image_button[4,4;0.5,0.5;wool_grey.png;hair_gray;]".. "image_button[4.5,4;0.5,0.5;wool_magenta.png;hair_magenta;]".. "image_button[5,4;0.5,0.5;wool_orange.png;hair_orange;]".. "image_button[5.5,4;0.5,0.5;wool_pink.png;hair_pink;]".. "image_button[6,4;0.5,0.5;wool_red.png;hair_red;]".. "image_button[6.5,4;0.5,0.5;wool_violet.png;hair_violet;]".. "image_button[7,4;0.5,0.5;wool_white.png;hair_white;]".. "image_button[7.5,4;0.5,0.5;wool_yellow.png;hair_yellow;]".. "button_exit[6.5,5;1.5,1;exit;Exit]" local appearance_form_wardrobe = "size[8.5,6;]".. --"bgcolor[#0000;false]".. "background[0,0;8.5,6.25;appearance_form_background.png]".. --Shirt "label[0.5,0.5;Shirt Color]".. "image_button[0.5,1;0.5,0.5;wool_black.png;shirt_black;]".. "image_button[1,1;0.5,0.5;wool_blue.png;shirt_blue;]".. "image_button[1.5,1;0.5,0.5;wool_brown.png;shirt_brown;]".. "image_button[2,1;0.5,0.5;wool_cyan.png;shirt_cyan;]".. "image_button[2.5,1;0.5,0.5;wool_dark_green.png;shirt_darkgreen;]".. "image_button[3,1;0.5,0.5;wool_dark_grey.png;shirt_darkgray;]".. "image_button[3.5,1;0.5,0.5;wool_green.png;shirt_green;]".. "image_button[4,1;0.5,0.5;wool_grey.png;shirt_gray;]".. "image_button[4.5,1;0.5,0.5;wool_magenta.png;shirt_magenta;]".. "image_button[5,1;0.5,0.5;wool_orange.png;shirt_orange;]".. "image_button[5.5,1;0.5,0.5;wool_pink.png;shirt_pink;]".. "image_button[6,1;0.5,0.5;wool_red.png;shirt_red;]".. "image_button[6.5,1;0.5,0.5;wool_violet.png;shirt_violet;]".. "image_button[7,1;0.5,0.5;wool_white.png;shirt_white;]".. "image_button[7.5,1;0.5,0.5;wool_yellow.png;shirt_yellow;]".. --Pants "label[0.5,1.5;Pants Color]".. "image_button[0.5,2;0.5,0.5;wool_black.png;pants_black;]".. "image_button[1,2;0.5,0.5;wool_blue.png;pants_blue;]".. "image_button[1.5,2;0.5,0.5;wool_brown.png;pants_brown;]".. "image_button[2,2;0.5,0.5;wool_cyan.png;pants_cyan;]".. "image_button[2.5,2;0.5,0.5;wool_dark_green.png;pants_darkgreen;]".. "image_button[3,2;0.5,0.5;wool_dark_grey.png;pants_darkgray;]".. "image_button[3.5,2;0.5,0.5;wool_green.png;pants_green;]".. "image_button[4,2;0.5,0.5;wool_grey.png;pants_gray;]".. "image_button[4.5,2;0.5,0.5;wool_magenta.png;pants_magenta;]".. "image_button[5,2;0.5,0.5;wool_orange.png;pants_orange;]".. "image_button[5.5,2;0.5,0.5;wool_pink.png;pants_pink;]".. "image_button[6,2;0.5,0.5;wool_red.png;pants_red;]".. "image_button[6.5,2;0.5,0.5;wool_violet.png;pants_violet;]".. "image_button[7,2;0.5,0.5;wool_white.png;pants_white;]".. "image_button[7.5,2;0.5,0.5;wool_yellow.png;pants_yellow;]".. --Shoes "label[0.5,2.5;Shoes Color]".. "image_button[0.5,3;0.5,0.5;wool_black.png;shoes_black;]".. "image_button[1,3;0.5,0.5;wool_blue.png;shoes_blue;]".. "image_button[1.5,3;0.5,0.5;wool_brown.png;shoes_brown;]".. "image_button[2,3;0.5,0.5;wool_cyan.png;shoes_cyan;]".. "image_button[2.5,3;0.5,0.5;wool_dark_green.png;shoes_darkgreen;]".. "image_button[3,3;0.5,0.5;wool_dark_grey.png;shoes_darkgray;]".. "image_button[3.5,3;0.5,0.5;wool_green.png;shoes_green;]".. "image_button[4,3;0.5,0.5;wool_grey.png;shoes_gray;]".. "image_button[4.5,3;0.5,0.5;wool_magenta.png;shoes_magenta;]".. "image_button[5,3;0.5,0.5;wool_orange.png;shoes_orange;]".. "image_button[5.5,3;0.5,0.5;wool_pink.png;shoes_pink;]".. "image_button[6,3;0.5,0.5;wool_red.png;shoes_red;]".. "image_button[6.5,3;0.5,0.5;wool_violet.png;shoes_violet;]".. "image_button[7,3;0.5,0.5;wool_white.png;shoes_white;]".. "image_button[7.5,3;0.5,0.5;wool_yellow.png;shoes_yellow;]".. --Belt "label[0.5,3.5;Belt Color]".. "image_button[0.5,4;0.5,0.5;wool_black.png;belt_black;]".. "image_button[1,4;0.5,0.5;wool_blue.png;belt_blue;]".. "image_button[1.5,4;0.5,0.5;wool_brown.png;belt_brown;]".. "image_button[2,4;0.5,0.5;wool_cyan.png;belt_cyan;]".. "image_button[2.5,4;0.5,0.5;wool_dark_green.png;belt_darkgreen;]".. "image_button[3,4;0.5,0.5;wool_dark_grey.png;belt_darkgray;]".. "image_button[3.5,4;0.5,0.5;wool_green.png;belt_green;]".. "image_button[4,4;0.5,0.5;wool_grey.png;belt_gray;]".. "image_button[4.5,4;0.5,0.5;wool_magenta.png;belt_magenta;]".. "image_button[5,4;0.5,0.5;wool_orange.png;belt_orange;]".. "image_button[5.5,4;0.5,0.5;wool_pink.png;belt_pink;]".. "image_button[6,4;0.5,0.5;wool_red.png;belt_red;]".. "image_button[6.5,4;0.5,0.5;wool_violet.png;belt_violet;]".. "image_button[7,4;0.5,0.5;wool_white.png;belt_white;]".. "image_button[7.5,4;0.5,0.5;wool_yellow.png;belt_yellow;]".. "button_exit[6.5,5;1.5,1;exit;Exit]" -- =================================================================== -- Sets Player appearance on first join -- minetest.register_on_newplayer (function (player) local function newplayer (player) local name = player:get_player_name() appearance [name] = { sex = "male", skin = mskin.."^", skin_col = "4", pants = mpants.."^", pants_col = "blue", shirt = mshirt.."^", shirt_col = "green", shoes = mshoes.."^", shoes_col = "black", belt = mbelt.."^", belt_col = "black", face = mface.."^", eyes = meyes.."^", eyes_col = "blue", overlay = moverlay.."^", hair = mhair, hair_col = "brown", } save_appearance() default.player_register_model("appearance_character.b3d", { animation_speed = 30, --textures = tex, 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.show_formspec(name, "appearance", appearance_form) minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if formname == "appearance" then change_appearance(name,fields) end end) end -- =================================================================== -- Update appearance when the player joins minetest.register_on_joinplayer (function (player) local name = player:get_player_name() if appearance [name] then appearance_update (name) else newplayer (player) end end) -- =================================================================== --mirror and wardrobe nodes minetest.register_node("appearance:wardrobe",{ description = "Wardrobe - Change clothes", drawtype = "normal", inventory_image = "appearance_wardrobe_inv.png", wield_image = "appearance_wardrobe_inv.png", paramtype = "light", paramtype2 = "facedir", tiles = {"appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_front.png", }, groups = {cracky = 2}, on_place = function(itemstack, placer, pointed_thing) local pos = pointed_thing.above local node = minetest.get_node(pos) local unode = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}) local facedir = minetest.dir_to_facedir(placer:get_look_dir()) if minetest.get_node(pointed_thing.under).name == "appearance:wardrobe" then minetest.show_formspec(placer:get_player_name(), "appearance_wardrobe", appearance_form_wardrobe) minetest.register_on_player_receive_fields(function(player, formname, fields) local name = placer:get_player_name() if formname == "appearance_wardrobe" then change_appearance (name,fields) end end) elseif minetest.get_node(pointed_thing.under).name == "appearance:mirror" then minetest.show_formspec(placer:get_player_name(), "appearance_mirror", appearance_form_mirror) minetest.register_on_player_receive_fields(function(player, formname, fields) local name = placer:get_player_name() if formname == "appearance_mirror" then change_appearance (name,fields) end end) elseif minetest.get_node(pointed_thing.under).name ~= "appearance:wardrobe" or minetest.get_node(pointed_thing.under).name ~= "appearance:mirror" then if unode.name == "air" then minetest.set_node(pos, {name = "appearance:wardrobe", param2 = facedir}) minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "appearance:mirror", param2 = facedir}) else minetest.chat_send_player(placer:get_player_name(), "Not enough room there!") return end end end, after_dig_node = function(pos, oldnode, oldmetadata, digger) local unode = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}) if unode.name == "appearance:mirror" then minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "air"}) end end, on_rightclick = function(pos, node, player, itemstack, pointed_thing) minetest.show_formspec(player:get_player_name(), "appearance_wardrobe", appearance_form_wardrobe) minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if formname == "appearance_wardrobe" then change_appearance (name,fields) end end) end, }) minetest.register_node("appearance:mirror",{ description = "Mirror - Change appearance", drawtype = "nodebox", tiles = {"appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_top.png", "appearance_wardrobe_mirror.png", }, paramtype = "light", paramtype2 = "facedir", drops = "appearance:wardrobe", groups = {cracky = 2, not_in_creative_inventory = 1}, node_box = { type = "fixed", fixed = { {-0.5, -0.5, 0.4375, 0.5, 0.5, 0.5}, } }, on_rightclick = function(pos, node, player, itemstack, pointed_thing) minetest.show_formspec(player:get_player_name(), "appearance_mirror", appearance_form_mirror) minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if formname == "appearance_mirror" then change_appearance (name,fields) end end) end, after_dig_node = function(pos, oldnode, oldmetadata, digger) local unode = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}) if unode.name == "appearance:wardrobe" then minetest.set_node({x = pos.x, y = pos.y - 1, z = pos.z}, {name = "air"}) end end, }) minetest.register_craft({ output = "appearance:wardrobe", recipe = { {"group:stick", "default:glass", "group:stick"}, {"group:wood", "group:stick", "group:wood"}, {"group:wood", "group:wood", "group:wood"} } })