1 local minetest = minetest
3 local path = minetest.get_modpath(minetest.get_current_modname())
5 -- path for the temporary skins file
6 local temppath = minetest.get_worldpath() .. "/skins_temp.png"
8 local pngimage = dofile(path.."/png_lua/png.lua")
10 --run through all the skins on the skindex and index them all locally
11 --only try to index further than the point in the current list max
13 local http = minetest.request_http_api()
14 local id = "Lua Skins Updater"
15 -- Binary downloads are required
16 if not core.features.httpfetch_binary_data then
17 print("outdated version of MINETEST detected!")
25 print("---------------------------------------------------------------")
26 print("HTTP access is required. Please add this to your minetest.conf:")
27 print("secure.http_mods = skins")
28 print("!!Skins will not work without this!!")
29 print("---------------------------------------------------------------")
33 -- Fancy debug wrapper to download an URL
34 local function fetch_url(url, callback)
39 if result.succeeded then
40 if result.code == 404 then
43 if result.code ~= 200 then
44 --core.log("warning", ("%s: STATUS=%i URL=%s"):format(
45 -- _ID_, result.code, url))
48 return callback(result.data)
52 --core.log("warning", ("%s: Failed to download URL=%s"):format(
58 --https://gist.github.com/marceloCodget/3862929 rgb to hex
60 local function rgbToHex(rgb)
62 local hexadecimal = ""
64 for key, value in pairs(rgb) do
68 local index = math.fmod(value, 16) + 1
69 value = math.floor(value / 16)
70 hex = string.sub('0123456789ABCDEF', index, index) .. hex
73 if(string.len(hex) == 0)then
76 elseif(string.len(hex) == 1)then
80 hexadecimal = hexadecimal .. hex
88 local function file_to_texture(image)
91 --local base_texture = "[combine:"..xmax.."x"..ymax
92 local base_texture = "[combine:" .. xmax .. "x" .. ymax
93 --local base_texture2 = "[combine:"..xmax.."x"..ymax
94 for _,line in pairs(image.pixels) do
95 for _,data in pairs(line) do
96 if x <= 32 or y > 16 then
97 local hex = rgbToHex({data.R,data.G,data.B})
98 --skip transparent pixels
100 --https://github.com/GreenXenith/skinmaker/blob/master/init.lua#L57 Thanks :D
102 base_texture = base_texture .. (":%s,%s=%s"):format(x - 1, y - 1, "(p.png\\^[colorize\\:#" .. hex .. ")")
120 -- Function to fetch a range of pages
121 fetch_function = function(name)
122 fetch_url("https://raw.githubusercontent.com/"..name.."/crafter_skindex/master/skin.png", function(data)
124 local f = io.open(temppath, "wb")
128 local img = pngimage(temppath, nil, false, false)
130 local stored_texture = file_to_texture(img)
132 --print("===============================================================")
133 --print(stored_texture)
134 if stored_texture then
135 --set the player's skin
136 local player = minetest.get_player_by_name(name)
138 player:set_properties({textures = {stored_texture, "blank_skin.png"}})
140 minetest.set_skin(player,stored_texture)
143 recalculate_armor(player) --redundancy
148 hud_elem_type = "image", -- See HUD element types
149 -- Type of element, can be "image", "text", "statbar", or "inventory"
151 position = {x=0.5, y=0.5},
152 -- Left corner position of element
156 scale = {x = 2, y = 2},
158 text = stored_texture,
165 -- Selected item in inventory. 0 for no item selected.
168 -- Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top
170 alignment = {x=0, y=0},
174 size = { x=100, y=100 },
175 -- Size of element in pixels
178 -- Z index : lower z-index HUDs are displayed behind higher z-index HUDs
188 --local img = pngimage(minetest.get_modpath("skins").."/skin_temp/temp.png", nil, false, false)
194 cape.initial_properties = {
197 textures = {"cape_core.png"},
199 collisionbox = {0, 0, 0, 0, 0, 0}
201 cape.degrees = function(yaw)
202 return(yaw*180.0/math.pi)
204 cape.texture_set = false
205 cape.on_step = function(self,dtime)
206 --don't waste any cpu
207 if not self.owner or not self.owner:is_player() then
212 if not self.texture_set and self.texture_type then
213 self.object:set_properties({textures={self.texture_type}})
214 self.texture_set = true
217 local pos = self.object:get_pos()
218 local current_animation,_,_,_ = self.object:get_animation()
219 current_animation = current_animation.x
222 --do not allow cape to flutter if player is moving backwards
223 local body_yaw = self.owner:get_look_horizontal()
224 local cape_yaw = minetest.dir_to_yaw(vector.direction(self.old_pos,pos))
225 cape_yaw = minetest.dir_to_yaw(minetest.yaw_to_dir(cape_yaw))
226 cape_yaw = self.degrees(cape_yaw)-self.degrees(body_yaw)
228 if cape_yaw < -180 then
229 cape_yaw = cape_yaw + 360
230 elseif cape_yaw > 180 then
231 cape_yaw = cape_yaw - 360
233 if cape_yaw >= -90 and cape_yaw <= 90 then
234 --use old position to calculate the "wind"
235 local deg = self.degrees(minetest.dir_to_yaw(vector.new(vector.distance(vector.new(pos.x,0,pos.z),vector.new(self.old_pos.x,0,self.old_pos.z)),0,pos.y-self.old_pos.y))+(math.pi/2))*-1
237 self.goal = math.floor(deg+0.5)
242 if vector.distance(pos,self.old_pos) == 0 then
247 if self.goal and current_animation ~= self.goal then
248 if math.abs(current_animation-self.goal) == 1 then --this stops jittering
249 self.object:set_animation({x=self.goal,y=self.goal}, 0, 0, false)
250 elseif current_animation < self.goal then
251 self.object:set_animation({x=current_animation+2,y=current_animation+2}, 0, 0, false)
252 elseif current_animation > self.goal then
253 self.object:set_animation({x=current_animation-2,y=current_animation-2}, 0, 0, false)
258 minetest.register_entity("skins:cape",cape)
260 --function for handling capes
261 local cape_table = {}
263 local add_cape = function(player,cape)
264 local obj = minetest.add_entity(player:get_pos(),"skins:cape")
265 obj:get_luaentity().owner = player
266 obj:set_attach(player, "Cape_bone", vector.new(0,0.25,0.5), vector.new(-90,180,0))
267 obj:get_luaentity().texture_type = cape
268 local name = player:get_player_name()
269 cape_table[name] = obj
272 local function readd_capes()
273 for _,player in ipairs(minetest.get_connected_players()) do
274 local meta = player:get_meta()
275 local cape = meta:get_string("cape")
277 local name = player:get_player_name()
278 if not cape_table[name] or (cape_table[name] and not cape_table[name]:get_luaentity()) then
279 add_cape(player,cape)
283 minetest.after(3,function()
287 minetest.register_on_mods_loaded(function()
288 minetest.after(3,function()
294 --use this to retrieve skin data
295 local player_skin_table = {}
296 minetest.get_skin = function(player)
297 local name = player:get_player_name()
298 if player_skin_table[name] then
299 return(player_skin_table[name])
305 --use this to set skin data
306 minetest.set_skin = function(player,skin)
307 local name = player:get_player_name()
308 player_skin_table[name] = skin
312 local custom = {sfan5=true,appguru=true,tacotexmex=true,oilboi=true,wuzzy=true}
314 local core_devs = {celeron55=true,nore=true,nerzhul=true,paramat=true,sofar=true,rubenwardy=true,smalljoker=true,larsh=true,thetermos=true,krock=true}
316 local patrons = {tacotexmex=true,ufa=true,monte48=true}
319 minetest.register_on_joinplayer(function(player)
322 local name = string.lower(player:get_player_name())
326 cape = "cape_"..name..".png"
327 elseif core_devs[name] then
328 cape = "cape_core.png"
329 elseif patrons[name] then
330 cape = "cape_patron.png"
332 local meta = player:get_meta()
334 meta:set_string("cape",cape)
335 add_cape(player,cape)
337 meta:set_string("cape","")
340 minetest.after(0,function()
341 fetch_function(player:get_player_name())