]> git.lizzy.rs Git - Crafter.git/blob - mods/skins/init.lua
Remove meta usage from skins
[Crafter.git] / mods / skins / init.lua
1 local minetest = minetest
2
3 local path = minetest.get_modpath(minetest.get_current_modname())
4
5 -- path for the temporary skins file
6 local temppath = minetest.get_worldpath() .. "/skins_temp.png"
7
8 local pngimage = dofile(path.."/png_lua/png.lua")
9
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
12
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!")
18     return(nil)
19 end
20
21 if not http then
22     for i = 1,5 do
23         print("!WARNING!")
24     end
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("---------------------------------------------------------------")
30     return(nil)
31 end
32
33 -- Fancy debug wrapper to download an URL
34 local function fetch_url(url, callback)
35         http.fetch({
36         url = url,
37         timeout = 3,
38     }, function(result)
39         if result.succeeded then
40             if result.code == 404 then
41                 return(nil)
42             end
43                         if result.code ~= 200 then
44                                 --core.log("warning", ("%s: STATUS=%i URL=%s"):format(
45                 --    _ID_, result.code, url))
46                 return(nil)
47             end
48             return callback(result.data)
49         else
50             return(nil)
51         end
52                 --core.log("warning", ("%s: Failed to download URL=%s"):format(
53           --  id, url))
54         return(nil)
55         end)
56 end
57
58 --https://gist.github.com/marceloCodget/3862929 rgb to hex
59
60 local function rgbToHex(rgb)
61
62         local hexadecimal = ""
63
64         for key, value in pairs(rgb) do
65                 local hex = ''
66
67                 while(value > 0)do
68                         local index = math.fmod(value, 16) + 1
69                         value = math.floor(value / 16)
70                         hex = string.sub('0123456789ABCDEF', index, index) .. hex                       
71                 end
72
73                 if(string.len(hex) == 0)then
74                         hex = '00'
75
76                 elseif(string.len(hex) == 1)then
77                         hex = '0' .. hex
78                 end
79
80                 hexadecimal = hexadecimal .. hex
81         end
82
83         return hexadecimal
84 end
85
86 local xmax = 64
87 local ymax = 32
88 local function file_to_texture(image)
89     local x = 1
90     local y = 1
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
99                 if data.A > 0 then 
100                     --https://github.com/GreenXenith/skinmaker/blob/master/init.lua#L57 Thanks :D
101
102                     base_texture = base_texture .. (":%s,%s=%s"):format(x - 1, y - 1, "(p.png\\^[colorize\\:#" .. hex .. ")")
103                 end
104             --else
105             --    print(dump(data))
106             end
107             x = x + 1
108             if x > xmax then
109                 x = 1
110                 y = y + 1
111             end
112             if y > ymax then
113                 break
114             end
115         end
116     end
117     return(base_texture)
118 end
119
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)
123         if data then
124             local f = io.open(temppath, "wb")
125             f:write(data)
126             f:close()
127
128             local img = pngimage(temppath, nil, false, false)
129             if img then
130                 local stored_texture = file_to_texture(img)
131
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)
137                     
138                     player:set_properties({textures = {stored_texture, "blank_skin.png"}})
139
140                     minetest.set_skin(player,stored_texture)
141                     
142
143                     recalculate_armor(player) --redundancy
144                     
145                     --[[
146                     player:hud_add(
147                         {
148                             hud_elem_type = "image",  -- See HUD element types
149                             -- Type of element, can be "image", "text", "statbar", or "inventory"
150                     
151                             position = {x=0.5, y=0.5},
152                             -- Left corner position of element
153                     
154                             name = "<name>",
155                     
156                             scale = {x = 2, y = 2},
157                     
158                             text = stored_texture,
159                     
160                             text2 = "<text>",
161                     
162                             number = 2,
163                     
164                             item = 3,
165                             -- Selected item in inventory. 0 for no item selected.
166                     
167                             direction = 0,
168                             -- Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top
169                     
170                             alignment = {x=0, y=0},
171                     
172                             offset = {x=0, y=0},
173                     
174                             size = { x=100, y=100 },
175                             -- Size of element in pixels
176                     
177                             z_index = 0,
178                             -- Z index : lower z-index HUDs are displayed behind higher z-index HUDs
179                         }
180                     )
181                     ]]--
182                 end
183             end
184         end
185     end)
186 end
187
188 --local img = pngimage(minetest.get_modpath("skins").."/skin_temp/temp.png", nil, false, false)
189 --print(dump(img))
190
191
192
193 local cape = {}
194 cape.initial_properties = {
195         visual = "mesh",
196         mesh = "cape.x",
197         textures = {"cape_core.png"},
198     pointable = false,
199     collisionbox = {0, 0, 0, 0, 0, 0}
200 }
201 cape.degrees = function(yaw)
202     return(yaw*180.0/math.pi)
203 end
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
208         self.object:remove()
209         return
210     end
211     --set cape texture
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
215     end
216
217     local pos = self.object:get_pos()
218     local current_animation,_,_,_ = self.object:get_animation()
219     current_animation = current_animation.x
220
221     if self.old_pos then
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)
227
228                 if cape_yaw < -180 then
229                         cape_yaw = cape_yaw + 360
230                 elseif cape_yaw > 180 then
231                         cape_yaw = cape_yaw - 360
232         end
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
236             deg = deg + 90
237             self.goal = math.floor(deg+0.5)
238         else
239             self.goal = 0
240         end
241
242         if vector.distance(pos,self.old_pos) == 0 then
243             self.goal = 25
244         end
245     end
246     --cape smoothing
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)
254         end
255     end
256     self.old_pos = pos
257 end
258 minetest.register_entity("skins:cape",cape)
259
260 --function for handling capes
261 local cape_table = {}
262
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
270 end
271
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")
276         if cape ~= "" then
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)
280             end
281         end
282     end
283     minetest.after(3,function()
284         readd_capes()
285     end)
286 end
287 minetest.register_on_mods_loaded(function()
288     minetest.after(3,function()
289         readd_capes()
290     end)
291 end)
292
293
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])
300     else
301         return("player.png")
302     end
303 end
304
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
309 end
310
311
312 local custom = {sfan5=true,appguru=true,tacotexmex=true,oilboi=true,wuzzy=true}
313
314 local core_devs = {celeron55=true,nore=true,nerzhul=true,paramat=true,sofar=true,rubenwardy=true,smalljoker=true,larsh=true,thetermos=true,krock=true}
315
316 local patrons = {tacotexmex=true,ufa=true,monte48=true}
317
318
319 minetest.register_on_joinplayer(function(player)
320     
321     --cape handling
322     local name = string.lower(player:get_player_name())
323
324     local cape = false
325     if custom[name] then
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"
331     end
332     local meta = player:get_meta()
333     if cape then
334         meta:set_string("cape",cape)
335         add_cape(player,cape)
336     else
337         meta:set_string("cape","")
338     end
339
340     minetest.after(0,function()
341         fetch_function(player:get_player_name())
342     end)
343 end)