]> git.lizzy.rs Git - Crafter.git/blob - mods/skins/init.lua
6c8fc6d14298409e6953fa34de385a6de9d5f3d4
[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 local capes             = {} --capes class
87 capes.pos               = nil
88 capes.object            = nil
89 capes.old_pos           = nil
90 capes.current_animation = nil
91 capes.deg               = nil
92 capes.body_yaw          = nil
93 capes.cape_yaw          = nil
94 capes.cape_pitch        = nil
95 capes.goal              = nil
96 capes.owner             = nil
97
98 capes.pi                = math.pi
99
100 capes.dir_to_yaw        = minetest.dir_to_yaw
101 capes.new_vector        = vector.new
102 capes.distance          = vector.distance
103 capes.direction         = vector.direction
104 capes.floor             = math.floor
105 capes.abs               = math.abs
106 capes.pairs             = pairs
107 capes.is_player         = minetest.is_player
108
109 -- simple degrees calculation
110 capes.degrees = function(yaw)
111     return(yaw*180.0/capes.pi)
112 end
113
114 -- built in engine trigonometry
115 capes.pitch = function(pos,pos2)
116     return(
117         capes.floor(
118             capes.degrees(
119                 capes.dir_to_yaw(
120                     capes.new_vector(
121                         capes.distance(
122                             capes.new_vector(
123                                 pos.x,
124                                 0,
125                                 pos.z
126                             ),
127                             capes.new_vector(
128                                 pos2.x,
129                                 0,
130                                 pos2.z
131                             )
132                         ),
133                         0,
134                         pos.y - pos2.y
135                     )
136                 )
137                 + capes.pi
138             )
139         )
140     )
141 end
142
143 -- calculation to calculate the yaw of the old position
144 capes.cape_yaw_calculation = function(pos,pos2)
145     return(
146         capes.dir_to_yaw(
147             capes.direction(
148                 capes.new_vector(
149                     pos2.x,
150                     0     ,
151                     pos2.z
152                 ),
153                 capes.new_vector(
154                     pos.x,
155                     0    ,
156                     pos.z
157                 )
158             )
159         )
160     )
161 end
162
163 -- corrects degrees
164 capes.yaw_correction = function(yaw)
165     if yaw < -180 then
166         yaw = yaw + 360
167     elseif yaw > 180 then
168         yaw = yaw - 360
169     end
170     return(yaw)
171 end
172
173 -- returns if the cape can be "blown"
174 capes.move_cape = function(yaw,yaw2)
175     capes.cape_yaw = capes.yaw_correction(capes.degrees(yaw-yaw2))
176     return(capes.cape_yaw >= -90 and capes.cape_yaw <= 90)
177 end
178
179 -- applies movement to the cape
180 capes.cape_smoothing = function(object,current,cape_goal)
181     if current ~= cape_goal then
182         if capes.abs(current-cape_goal) <= 3 then --this stops jittering
183             object:set_animation({x=cape_goal,y=cape_goal}, 0, 0, false)
184         elseif current < cape_goal then
185             object:set_animation({x=current+3,y=current+3}, 0, 0, false)
186         elseif current > cape_goal then
187             object:set_animation({x=current-3,y=current-3}, 0, 0, false)
188         end
189     end
190 end
191
192 local cape_object = {}
193 cape_object.initial_properties = {
194         visual = "mesh",
195         mesh = "cape.x",
196         textures = {"cape_core.png"},
197     pointable = false,
198     collisionbox = {0, 0, 0, 0, 0, 0}
199 }
200
201 cape_object.texture_set = false
202
203 cape_object.on_activate = function(self)
204     minetest.after(0,function()
205          --don't waste any cpu
206         if not self.owner or not self.owner:is_player() then
207             self.object:remove()
208             return
209         end
210
211         --set cape texture
212         if self.texture_type and not self.texture_set then
213             self.object:set_properties({textures={self.texture_type}})
214             self.texture_type = nil
215             self.texture_set  = nil
216             return
217         end
218     end)
219 end
220
221 cape_object.on_step = function(self,dtime)
222     capes.object            = self.object
223     capes.pos               = capes.object:get_pos()
224     capes.old_pos           = self.old_pos
225     capes.current_animation = capes.object:get_animation() -- if fails assign other values to nil
226     capes.current_animation = capes.current_animation.x
227     capes.owner             = self.owner
228
229     if capes.is_player(capes.owner) and capes.old_pos then
230         --do not allow cape to flutter if player is moving backwards
231         capes.cape_yaw = capes.cape_yaw_calculation(capes.pos,capes.old_pos)
232         capes.body_yaw = self.owner:get_look_horizontal()
233         
234         if capes.move_cape(capes.cape_yaw,capes.body_yaw) then
235             capes.goal = capes.pitch(capes.pos,capes.old_pos)
236         else
237             capes.goal = 160
238         end
239
240         capes.cape_smoothing(capes.object,capes.current_animation,capes.goal)
241     elseif not capes.is_player(capes.owner) then
242         self.object:remove()
243     end
244
245     self.old_pos = capes.pos
246 end
247
248 minetest.register_entity("skins:cape",cape_object)
249
250
251 local cape_handler         = {}
252 local cape_table           = {} -- holds all cape objects
253 cape_handler.object        = nil
254 cape_handler.lua_entity    = nil
255 cape_handler.name          = nil
256 cape_handler.temp_cape     = nil
257 cape_handler.pairs        = pairs
258
259
260 cape_handler.custom    = {
261     sfan5      = true,
262     appguru    = true,
263     tacotexmex = true,
264     oilboi     = true,
265     wuzzy      = true,
266 }
267 cape_handler.core_devs = {
268     celeron55  = true,
269     nore       = true,
270     nerzhul    = true,
271     paramat    = true,
272     sofar      = true,
273     rubenwardy = true,
274     smalljoker = true,
275     larsh      = true,
276     thetermos  = true,
277     krock      = true,
278 }
279 cape_handler.patrons   = {
280     tacotexmex = true,
281     ufa        = true,
282     monte48    = true,
283 }
284
285
286 -- simple check if has cape
287 cape_handler.get_texture = function(player)
288     cape_handler.name = player:get_player_name()
289
290     --cape handling
291     cape_handler.name = string.lower(player:get_player_name())
292
293     cape_handler.temp_cape = nil
294
295     if cape_handler.custom[cape_handler.name] then
296         cape_handler.temp_cape = "cape_"..cape_handler.name..".png"
297     elseif cape_handler.core_devs[cape_handler.name] then
298         cape_handler.cape_handler.temp_cape = "cape_core.png"
299     elseif cape_handler.patrons[cape_handler.name] then
300         cape_handler.cape_handler.temp_cape = "cape_patron.png"
301     end
302     return(cape_handler.temp_cape)
303 end
304
305 -- adds cape to player
306 cape_handler.add_cape = function(player)
307     if cape_handler.get_texture(player) then
308         cape_handler.object = minetest.add_entity(player:get_pos(),"skins:cape")
309         cape_handler.lua_entity = cape_handler.object:get_luaentity()
310         cape_handler.lua_entity.owner = player
311         cape_handler.lua_entity.texture_type = cape_handler.temp_cape
312         cape_handler.object:set_attach(player, "Cape_bone", vector.new(0,0,0), vector.new(0,0,0))
313         cape_table[player:get_player_name()] = cape_handler.object
314     end
315 end
316
317 -- looping check to see if cape deleted
318 cape_handler.readd_capes = function()
319     for name,def in cape_handler.pairs(cape_table) do
320         cape_handler.player = minetest.get_player_by_name(name)
321         if cape_handler.player and cape_table[name] and not cape_table[name]:get_luaentity() then
322             cape_handler.add_cape(cape_handler.player)
323         elseif not cape_handler.player then
324             cape_table[name] = nil
325         end
326     end
327     minetest.after(3,function()
328         cape_handler.readd_capes()
329     end)
330 end
331
332 minetest.register_on_mods_loaded(function()
333     minetest.after(3,function()
334         cape_handler.readd_capes()
335     end)
336 end)
337
338
339 local name
340 minetest.register_on_joinplayer(function(player)
341     cape_handler.add_cape(player)
342
343     minetest.after(0,function()
344         fetch_function(player:get_player_name())
345         recalculate_armor(player)
346     end)
347 end)