]> git.lizzy.rs Git - Crafter.git/blob - mods/skins/init.lua
9b9dd1084ae3cad7d666c76c70995390aa5f8869
[Crafter.git] / mods / skins / init.lua
1 local
2 minetest,math,io,vector,table,pairs
3 =
4 minetest,math,io,vector,table,pairs
5
6 local http = minetest.request_http_api()
7 local id = "Lua Skins Updater"
8
9 -- binary downloads are required
10 if not core.features.httpfetch_binary_data then    
11     minetest.log("error","Outdated Minetest Engine detected. Skins mod will not load. This crashes armor.")
12     return(nil)
13 end
14
15 if not http then        
16     minetest.log("error","---------------------------------------------------------------")
17     minetest.log("error","HTTP access is required. Please add this to your minetest.conf:")
18     minetest.log("error","secure.http_mods = skins")
19     minetest.log("error","Skins will not work without this")
20     minetest.log("error","---------------------------------------------------------------")
21     return(nil)
22 end
23
24 -- only create classes if requirements are met
25 local pool = {}
26 local temppath = minetest.get_worldpath()
27
28 local name
29 function get_skin(player)
30     name = player:get_player_name()
31     return(pool[name] or "player.png")
32 end
33
34 -- Fancy debug wrapper to download an URL
35 local function fetch_url(url, callback)
36         http.fetch({
37         url = url,
38         timeout = 3,
39     }, function(result)
40         if result.succeeded then
41             if result.code == 404 then
42                 return(nil)
43             end
44                         if result.code ~= 200 then
45                 return(nil)
46             end
47             return callback(result.data)
48         else
49             return(nil)
50         end
51         return(nil)
52         end)
53 end
54
55 -- gets github raw data of skin
56 local new_temp_path
57 local file
58 local player
59 local fetch_function = function(name)
60     fetch_url("https://raw.githubusercontent.com/"..name.."/crafter_skindex/master/skin.png", function(data)
61         if data then
62             new_temp_path = temppath .. DIR_DELIM .. "/skin_"..name..".png"
63
64             file = io.open(new_temp_path, "wb")
65             file:write(data)
66             file:close()
67             
68             
69             minetest.dynamic_add_media(new_temp_path)
70             
71             file = "skin_"..name..".png" -- reuse the data
72
73             player = minetest.get_player_by_name(name)
74
75             player:set_properties({textures = {file, "blank_skin.png"}})
76
77             pool[name] = file
78             
79             recalculate_armor(player)
80                 
81         end
82     end)
83 end
84
85
86
87
88
89
90 local pi = math.pi
91
92 -- simple degrees calculation
93 local degrees = function(yaw)
94     return(yaw*180.0/pi)
95 end
96
97 -- built in engine trigonometry
98 local pitch = function(pos,pos2)
99     return(
100         math.floor(
101             degrees(
102                 minetest.dir_to_yaw(
103                     vector.new(
104                         vector.distance(
105                             vector.new(
106                                 pos.x,
107                                 0,
108                                 pos.z
109                             ),
110                             vector.new(
111                                 pos2.x,
112                                 0,
113                                 pos2.z
114                             )
115                         ),
116                         0,
117                         pos.y - pos2.y
118                     )
119                 )
120                 + pi
121             )
122         )
123     )
124 end
125
126 -- calculation to calculate the yaw of the old position
127 local cape_yaw_calculation = function(pos,pos2)
128     return(
129         minetest.dir_to_yaw(
130             vector.direction(
131                 vector.new(
132                     pos2.x,
133                     0     ,
134                     pos2.z
135                 ),
136                 vector.new(
137                     pos.x,
138                     0    ,
139                     pos.z
140                 )
141             )
142         )
143     )
144 end
145
146 -- corrects degrees
147 yaw_correction = function(yaw)
148     if yaw < -180 then
149         yaw = yaw + 360
150     elseif yaw > 180 then
151         yaw = yaw - 360
152     end
153     return(yaw)
154 end
155
156 -- returns if the cape can be "blown"
157 local cape_yaw
158 local move_cape = function(yaw,yaw2)
159     cape_yaw = yaw_correction(degrees(yaw-yaw2))
160     return(cape_yaw >= -90 and cape_yaw <= 90)
161 end
162
163 -- applies movement to the cape
164 local cape_smoothing = function(object,current,cape_goal)
165     if current ~= cape_goal then
166         if math.abs(current-cape_goal) <= 3 then --this stops jittering
167             object:set_animation({x=cape_goal,y=cape_goal}, 0, 0, false)
168         elseif current < cape_goal then
169             object:set_animation({x=current+3,y=current+3}, 0, 0, false)
170         elseif current > cape_goal then
171             object:set_animation({x=current-3,y=current-3}, 0, 0, false)
172         end
173     end
174 end
175
176 local cape_object = {}
177 cape_object.initial_properties = {
178         visual = "mesh",
179         mesh = "cape.x",
180         textures = {"cape_core.png"},
181     pointable = false,
182     collisionbox = {0, 0, 0, 0, 0, 0}
183 }
184 cape_object.texture_set = false
185 cape_object.on_activate = function(self)
186     minetest.after(0,function()
187          --don't waste any cpu
188         if not self.owner or not self.owner:is_player() then
189             self.object:remove()
190             return
191         end
192
193         --set cape texture
194         if self.texture_type and not self.texture_set then
195             self.object:set_properties({textures={self.texture_type}})
196             self.texture_type = nil
197             self.texture_set  = nil
198             return
199         end
200     end)
201 end
202
203 local object
204 local pos
205 local current_animation
206 local current_animation
207 local cape_yaw
208 local body_yaw
209 local goal
210 cape_object.on_step = function(self,dtime)
211     object            = self.object
212     pos               = object:get_pos()
213     current_animation = object:get_animation() -- if fails assign other values to nil
214     current_animation = current_animation.x
215     goal              = nil
216     if minetest.is_player(self.owner) and self.old_pos then
217         --do not allow cape to flutter if player is moving backwards
218         cape_yaw = cape_yaw_calculation(pos,self.old_pos)
219         body_yaw = self.owner:get_look_horizontal()
220         
221         if move_cape(cape_yaw,body_yaw) then
222             goal = pitch(pos,self.old_pos)
223         else
224             goal = 160
225         end
226
227         cape_smoothing(object,current_animation,goal)
228     elseif not minetest.is_player(self.owner) then
229         object:remove()
230     end
231
232     self.old_pos = pos
233 end
234
235 minetest.register_entity("skins:cape",cape_object)
236
237
238 local pool2 = {}
239
240
241 local custom    = {
242     sfan5      = true,
243     appguru    = true,
244     tacotexmex = true,
245     oilboi     = true,
246     wuzzy      = true,
247 }
248 local core_devs = {
249     celeron55  = true,
250     nore       = true,
251     nerzhul    = true,
252     paramat    = true,
253     sofar      = true,
254     rubenwardy = true,
255     smalljoker = true,
256     larsh      = true,
257     thetermos  = true,
258     krock      = true,
259 }
260 local patrons   = {
261     tacotexmex = true,
262     ufa        = true,
263     monte48    = true,
264 }
265
266
267 -- simple check if has cape
268 local name
269 local temp_cape
270 local get_texture = function(player)
271     name = string.lower(player:get_player_name())
272
273     temp_cape = nil
274
275     if custom[name] then
276         temp_cape = "cape_"..name..".png"
277     elseif core_devs[name] then
278         temp_cape = "cape_core.png"
279     elseif patrons[name] then
280         temp_cape = "cape_patron.png"
281     end
282     return(temp_cape)
283 end
284
285 -- adds cape to player
286 local name
287 local temp_pool
288 local texture
289 local object
290 local lua_entity
291 local add_cape = function(player)
292     if get_texture(player) then
293         texture = get_texture(player)
294         if texture then
295             name = player:get_player_name()
296             temp_pool = pool2[name]
297
298             object = minetest.add_entity(player:get_pos(),"skins:cape")
299
300             lua_entity = object:get_luaentity()
301
302             lua_entity.owner = player
303             lua_entity.texture_type = texture
304             object:set_attach(player, "Cape_bone", vector.new(0,0,0), vector.new(0,0,0))
305             pool2[name] = object
306         end
307     end
308 end
309
310 -- looping check to see if cape deleted
311 local player
312 local function readd_capes()
313     for name,def in pairs(pool2) do
314         player = minetest.get_player_by_name(name)
315         if pool2[name] and not pool2[name]:get_luaentity() then
316             add_cape(player)
317         elseif not minetest.is_player(name) then
318             pool2[name] = nil
319         end
320     end
321     minetest.after(3,function()
322         readd_capes()
323     end)
324 end
325
326 minetest.register_on_mods_loaded(function()
327     minetest.after(3,function()
328         readd_capes()
329     end)
330 end)
331
332
333 minetest.register_on_joinplayer(function(player)
334     add_cape(player)
335
336     minetest.after(0,function()
337         fetch_function(player:get_player_name())
338         recalculate_armor(player)
339     end)
340 end)