]> git.lizzy.rs Git - Crafter.git/blob - mods/player_api/init.lua
7e0c30f48200a983699aa7e22971211cc016aa62
[Crafter.git] / mods / player_api / init.lua
1 local minetest,math = minetest,math
2 local pool = {}
3
4 -- player physical data constant
5 local player_constant = {
6         visual               = "mesh"       ,
7         mesh                 = "player.b3d" ,
8         animation_speed      = 24           ,
9         visual_size          = {x = 1, y = 1, z = 1},
10         textures             = {
11                                                         "player.png"    ,
12                                                         "blank_skin.png",
13                                                    },
14         current_animation    = "stand",
15         swimming             = false,
16         collisionbox         = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
17         old_controls         = {},
18         stepheight           = 0.6  ,
19         eye_height           = 1.47 ,
20         attached             = false,
21         wield_item           = nil  ,
22 }
23
24 -- set player wield item
25 local name
26 local temp_pool
27 local item
28 local object
29 local entity
30 local object_string
31 local update_wield_item = function(player)
32         name = player:get_player_name()
33         temp_pool = pool[name]
34
35         object = temp_pool.wield_item
36
37         item = player:get_wielded_item():get_name()
38
39         if not object or (object and not object:get_luaentity()) then
40                 
41                 object = minetest.add_entity(player:get_pos(),"player_api:item")
42
43                 entity = object:get_luaentity()
44
45                 if entity then
46
47                         entity.set_item(entity,item)
48                         
49                         entity.wielder = name
50                         
51                         object:set_attach(player, "Right_Hand", vector.new(0,0,0), vector.new(0,0,0))
52                         
53                         temp_pool.wield_item = object
54                 end
55
56                 return -- catch it
57         end
58         
59         entity = object:get_luaentity()
60         object_string = entity.itemstring
61
62         if object_string ~= item then
63                 entity.itemstring = item
64                 entity.set_item(entity,item)
65         end
66 end
67
68 -- easy way to allocate new players
69 local data
70 local name
71 local temp_pool
72
73 local set_all_properties = function(player)
74         name = player:get_player_name()
75         pool[name] = {}
76         temp_pool = pool[name]
77         data = {}
78
79         temp_pool.visual       = player_constant.visual
80         temp_pool.mesh         = player_constant.mesh
81         temp_pool.textures     = player_constant.textures
82         temp_pool.collisionbox = player_constant.collisionbox
83         temp_pool.eye_height   = player_constant.eye_height
84         temp_pool.stepheight   = player_constant.stepheight
85         temp_pool.visual_size  = player_constant.visual_size
86         temp_pool.attached     = false
87         temp_pool.sleeping     = false
88         player:set_properties(temp_pool)
89 end
90
91 -- easy way to set textures
92 local set_textures = function(player, textures)
93         player:set_properties({textures = textures})
94 end
95
96
97 local animation_list = {
98         stand            = { x = 5  , y = 5   },
99         lay              = { x = 162, y = 162 },
100         walk             = { x = 168, y = 187 },
101         mine             = { x = 189, y = 198 },
102         walk_mine        = { x = 200, y = 219 },
103         sit              = { x = 81 , y = 160 },
104         sneak            = { x = 60 , y = 60  },
105         sneak_mine_stand = { x = 20 , y = 30  },
106         sneak_walk       = { x = 60 , y = 80  },
107         sneak_mine_walk  = { x = 40 , y = 59  },
108         swim             = { x = 221, y = 241 },
109         swim_still       = { x = 226, y = 226 },
110         die              = { x = 242, y = 253 },
111 }
112
113 -- easy way to set animation
114 local name
115 local temp_pool
116 local current_animation
117
118 local set_animation = function(player, animation_name, speed, loop)
119         name = player:get_player_name()
120         temp_pool = pool[name]
121         current_animation = temp_pool.animation
122
123         if current_animation == animation_name then
124                 return
125         end
126         temp_pool.animation = animation_name
127         player:set_animation(animation_list[animation_name], speed, 0, loop)
128 end
129
130 -- allows mods to force update animation
131 local name
132 force_update_animation = function(player)
133         name = player:get_player_name()
134         pool[name].force_update = true
135 end
136
137 -- force updates the player
138 local name
139 local create_force_update = function(player)
140         name = player:get_player_name()
141         pool[name].force_update = true
142 end
143
144 -- allows other mods to set animations per player
145 set_player_animation = function(player,animation,speed,loop)
146         set_animation(player, animation, speed, loop)
147 end
148
149 local name
150 player_is_attached = function(player,truth)
151         name = player:get_player_name()
152         pool[name].attached = truth
153 end
154
155 local name
156 player_is_sleeping = function(player,truth)
157         name = player:get_player_name()
158         pool[name].sleeping = truth
159 end
160
161 local name
162 get_if_player_sleeping = function(player)
163         name = player:get_player_name()
164         return(pool[name].sleeping)
165 end
166
167
168 -- toggles nametag visibility
169 local opacity
170 local show_nametag = function(player,boolean)
171         if boolean then
172                 opacity = 255
173         else
174                 opacity = 0
175         end
176         
177         player:set_nametag_attributes({
178                 color = {
179                         r = 255,
180                         b = 255,
181                         a = opacity,
182                         g = 255
183                 }
184         })
185 end
186
187 -- remove all player data
188 local name
189 minetest.register_on_leaveplayer(function(player)
190         name = player:get_player_name()
191         pool[name] = nil
192 end)
193
194
195 -- converts yaw to degrees
196 local degrees = function(yaw)
197         return(yaw*180.0/math.pi)
198 end
199
200 -- controls head bone
201 local state
202 local swimming
203 local pitch
204 local pitch_look = function(player,sneak)
205         state = get_player_state(player)
206         swimming = is_player_swimming(player)
207         pitch = degrees(player:get_look_vertical()) * -1
208         if swimming then
209                 pitch = pitch + 90
210         elseif sneak then
211                 pitch = pitch + 15
212         end
213
214         player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
215 end
216
217 -- checks if the player has done anything with their keyboard/mouse
218 local name
219 local temp_pool
220 local old_control
221
222 local control_check = function(player,control_table)
223         name = player:get_player_name()
224         temp_pool = pool[name]
225
226         if not temp_pool.old_controls then
227                 temp_pool.old_controls = control_table
228                 return(true)
229         end
230
231         if temp_pool.force_update then
232                 temp_pool.old_controls = control_table
233                 return(true)
234         end
235
236         for i,k in pairs(temp_pool.old_controls) do
237                 if control_table[i] ~= k then
238                         temp_pool.old_controls = control_table
239                         return(true)
240                 end
241         end
242
243         temp_pool.old_controls = control_table
244         return(false)
245 end
246
247 -- movement to animation translations
248 local translation_table = {
249         ["walk"] = {
250                 ["keys"]    = { -- required keys
251                         up      = true,
252                         down    = true,
253                         left    = true,
254                         right   = true,
255                 },
256                 ["states" ] = { -- states
257                         [false] = { -- mouse input
258                                 [0] = {animation = "walk", speed = 24},
259                                 [1] = {animation = "walk", speed = 36},
260                                 [2] = {animation = "walk", speed = 42},
261                         },
262                         [true ] = {
263                                 [0] = {animation = "walk_mine", speed = 24},
264                                 [1] = {animation = "walk_mine", speed = 36},
265                                 [2] = {animation = "walk_mine", speed = 42},
266                         }
267                 }
268         },
269
270         ["sneak"] = {
271                 ["keys"]    = {
272                         up      = true,
273                         down    = true,
274                         left    = true,
275                         right   = true,
276                 },
277                 ["states" ] = {
278                         [true ] = { -- moving
279                                 --mouse input
280                                 [false] = {animation = "sneak_walk"     , speed = 24},
281                                 [true ] = {animation = "sneak_mine_walk", speed = 24},
282                         },
283                         [false] = { -- moving
284                                 --mouse input
285                                 [false] = {animation = "sneak"           , speed = 0 },
286                                 [true ] = {animation = "sneak_mine_stand", speed = 24},
287                         }
288                 }
289         },
290         
291         ["stand"]   = {
292                 [true ] = {animation = "mine" , speed = 24},
293                 [false] = {animation = "stand", speed = 0 },
294         },
295
296         ["swim"] = {
297                 ["keys"]    = { -- required keys
298                         up      = true,
299                         down    = true,
300                         left    = true,
301                         right   = true,
302                 },
303                 ["states"]  = {
304                         [true ] = {animation = "swim"      , speed = 24},
305                         [false] = {animation = "swim_still", speed = 0 },
306                 }
307         }
308 }
309
310 -- translate input and combine with state
311 local name
312 local temp_pool
313 local state
314 --local swimming
315 local mouse
316 local translated
317 local control_translation = function(player,control)
318         name = player:get_player_name()
319         temp_pool = pool[name]
320
321         state = get_player_state(player)
322         swimming = is_player_swimming(player)
323
324         mouse = (control.LMB or control.RMB)
325         if swimming then
326                 for k,i in pairs(control) do
327                         if i and translation_table.swim.keys[k] then
328                                 translated = translation_table.swim.states[true]
329                                 set_animation(player, translated.animation, translated.speed)
330                                 return
331                         end
332                 end
333                 translated = translation_table.swim.states[false]
334                 set_animation(player, translated.animation, translated.speed)
335                 return
336         else
337                 if control.sneak then
338                         for k,i in pairs(control) do
339                                 if i and translation_table.sneak.keys[k] then
340                                         translated = translation_table.sneak.states[true][mouse]
341                                         set_animation(player, translated.animation, translated.speed)
342                                         return
343                                 end
344                         end
345                         translated = translation_table.sneak.states[false][mouse]
346                         set_animation(player, translated.animation, translated.speed)
347                         return
348                 else
349                         for k,i in pairs(control) do
350                                 if i and translation_table.walk.keys[k] then
351                                         translated = translation_table.walk.states[mouse][state]
352                                         if translated then
353                                                 set_animation(player, translated.animation, translated.speed)
354                                                 return
355                                         end
356                                 end
357                         end
358                 end
359
360                 translated = translation_table.stand[mouse]
361                 set_animation(player, translated.animation, translated.speed)
362         end
363 end
364
365 -- translates player movement to animation
366 local control_table
367 local update
368 local name
369 local temp_pool
370 local do_animations = function(player)
371         name = player:get_player_name()
372         temp_pool = pool[name]
373
374         control_table = player:get_player_control()
375         pitch_look(player,control_table.sneak)
376
377         if player:get_hp() <= 0 then
378                 set_animation(player,"die",40,false)
379         elseif not temp_pool.sleeping and (not temp_pool.attached or not player:get_attach()) then
380                 temp_pool.attached = false
381                 update = control_check(player,control_table)
382                 update_wield_item(player)
383                 if update and player:get_hp() > 0 then
384                         control_translation(player,control_table)
385                 end
386         end
387 end
388
389
390
391 -- Update appearance when the player joins
392 minetest.register_on_joinplayer(function(player)
393         set_all_properties(player)
394 end)
395
396 minetest.register_on_respawnplayer(function(player)
397         create_force_update(player)
398 end)
399
400 -- inject into global loop
401 minetest.register_globalstep(function()
402         for _,player in ipairs(minetest.get_connected_players()) do
403                 do_animations(player)
404         end
405 end)
406
407
408 local stack
409 local itemname
410 local def
411 local set_item = function(self, item)
412         stack = ItemStack(item or self.itemstring)
413         self.itemstring = stack:to_string()
414
415         itemname = stack:is_known() and stack:get_name() or "unknown"
416
417         def = minetest.registered_nodes[itemname]
418
419         self.object:set_properties({
420                 textures = {itemname},
421                 wield_item = self.itemstring,
422                 glow = def and def.light_source,
423         })
424 end
425
426 minetest.register_entity("player_api:item", {
427         initial_properties = {
428                 hp_max           = 1,
429                 visual           = "wielditem",
430                 physical         = false,
431                 textures         = {""},
432                 automatic_rotate = 1.5,
433                 is_visible       = true,
434                 pointable        = false,
435
436                 collide_with_objects = false,
437                 collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
438                 selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21},
439                 visual_size  = {x = 0.21, y = 0.21},
440         },
441
442         itemstring = "",
443
444         set_item = set_item,
445
446         on_step = function(self, dtime)
447                 if not self.wielder or (self.wielder and not minetest.get_player_by_name(self.wielder)) then
448                         self.object:remove()
449                 end
450         end,
451 })