1 local minetest,math = minetest,math
4 -- player physical data constant
5 local player_constant = {
9 visual_size = {x = 1, y = 1, z = 1},
14 current_animation = "stand",
16 collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
24 -- set player wield item
31 local update_wield_item = function(player)
32 name = player:get_player_name()
33 temp_pool = pool[name]
35 object = temp_pool.wield_item
37 item = player:get_wielded_item():get_name()
39 if not object or (object and not object:get_luaentity()) then
41 object = minetest.add_entity(player:get_pos(),"player_api:item")
43 entity = object:get_luaentity()
47 entity.set_item(entity,item)
51 object:set_attach(player, "Right_Hand", vector.new(0,0,0), vector.new(0,0,0))
53 temp_pool.wield_item = object
59 entity = object:get_luaentity()
60 object_string = entity.itemstring
62 if object_string ~= item then
63 entity.itemstring = item
64 entity.set_item(entity,item)
68 -- easy way to allocate new players
73 local set_all_properties = function(player)
74 name = player:get_player_name()
76 temp_pool = pool[name]
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
87 player:set_properties(temp_pool)
90 -- easy way to set textures
91 local set_textures = function(player, textures)
92 player:set_properties({textures = textures})
96 local animation_list = {
97 stand = { x = 5 , y = 5 },
98 lay = { x = 162, y = 162 },
99 walk = { x = 168, y = 187 },
100 mine = { x = 189, y = 198 },
101 walk_mine = { x = 200, y = 219 },
102 sit = { x = 81 , y = 160 },
103 sneak = { x = 60 , y = 60 },
104 sneak_mine_stand = { x = 20 , y = 30 },
105 sneak_walk = { x = 60 , y = 80 },
106 sneak_mine_walk = { x = 40 , y = 59 },
107 swim = { x = 221, y = 241 },
108 swim_still = { x = 226, y = 226 },
109 die = { x = 242, y = 253 },
112 -- easy way to set animation
115 local current_animation
117 local set_animation = function(player, animation_name, speed, loop)
118 name = player:get_player_name()
119 temp_pool = pool[name]
120 current_animation = temp_pool.animation
122 if current_animation == animation_name then
125 temp_pool.animation = animation_name
126 player:set_animation(animation_list[animation_name], speed, 0, loop)
129 -- allows mods to force update animation
131 force_update_animation = function(player)
132 name = player:get_player_name()
133 pool[name].force_update = true
136 -- force updates the player
138 local create_force_update = function(player)
139 name = player:get_player_name()
140 pool[name].force_update = true
144 -- toggles nametag visibility
146 local show_nametag = function(player,boolean)
153 player:set_nametag_attributes({
163 -- remove all player data
165 minetest.register_on_leaveplayer(function(player)
166 name = player:get_player_name()
171 -- converts yaw to degrees
172 local degrees = function(yaw)
173 return(yaw*180.0/math.pi)
176 -- controls head bone
180 local pitch_look = function(player,sneak)
181 state = get_player_state(player)
182 swimming = is_player_swimming(player)
183 pitch = degrees(player:get_look_vertical()) * -1
190 player:set_bone_position("Head", vector.new(0,6.3,0), vector.new(pitch,0,0))
193 -- checks if the player has done anything with their keyboard/mouse
198 local control_check = function(player,control_table)
199 name = player:get_player_name()
200 temp_pool = pool[name]
202 if not temp_pool.old_controls then
203 temp_pool.old_controls = control_table
207 if temp_pool.force_update then
208 temp_pool.old_controls = control_table
212 for i,k in pairs(temp_pool.old_controls) do
213 if control_table[i] ~= k then
214 temp_pool.old_controls = control_table
219 temp_pool.old_controls = control_table
223 -- movement to animation translations
224 local translation_table = {
226 ["keys"] = { -- required keys
232 ["states" ] = { -- states
233 [false] = { -- mouse input
234 [0] = {animation = "walk", speed = 24},
235 [1] = {animation = "walk", speed = 36},
236 [2] = {animation = "walk", speed = 42},
239 [0] = {animation = "walk_mine", speed = 24},
240 [1] = {animation = "walk_mine", speed = 36},
241 [2] = {animation = "walk_mine", speed = 42},
254 [true ] = { -- moving
256 [false] = {animation = "sneak_walk" , speed = 24},
257 [true ] = {animation = "sneak_mine_walk", speed = 24},
259 [false] = { -- moving
261 [false] = {animation = "sneak" , speed = 0 },
262 [true ] = {animation = "sneak_mine_stand", speed = 24},
268 [true ] = {animation = "mine" , speed = 24},
269 [false] = {animation = "stand", speed = 0 },
273 ["keys"] = { -- required keys
280 [true ] = {animation = "swim" , speed = 24},
281 [false] = {animation = "swim_still", speed = 0 },
286 -- translate input and combine with state
293 local control_translation = function(player,control)
294 name = player:get_player_name()
295 temp_pool = pool[name]
297 state = get_player_state(player)
298 swimming = is_player_swimming(player)
300 mouse = (control.LMB or control.RMB)
303 for k,i in pairs(control) do
304 if i and translation_table.swim.keys[k] then
305 translated = translation_table.swim.states[true]
306 set_animation(player, translated.animation, translated.speed)
310 translated = translation_table.swim.states[false]
311 set_animation(player, translated.animation, translated.speed)
314 if control.sneak then
315 for k,i in pairs(control) do
316 if i and translation_table.sneak.keys[k] then
317 translated = translation_table.sneak.states[true][mouse]
318 set_animation(player, translated.animation, translated.speed)
322 translated = translation_table.sneak.states[false][mouse]
323 set_animation(player, translated.animation, translated.speed)
326 for k,i in pairs(control) do
327 if i and translation_table.walk.keys[k] then
328 translated = translation_table.walk.states[mouse][state]
330 set_animation(player, translated.animation, translated.speed)
337 translated = translation_table.stand[mouse]
338 set_animation(player, translated.animation, translated.speed)
342 -- translates player movement to animation
345 local do_animations = function(player)
346 control_table = player:get_player_control()
347 update = control_check(player,control_table)
348 pitch_look(player,control_table.sneak)
349 update_wield_item(player)
350 if update and player:get_hp() > 0 then
351 control_translation(player,control_table)
352 elseif player:get_hp() <= 0 then
353 set_animation(player,"die",40,false)
359 -- Update appearance when the player joins
360 minetest.register_on_joinplayer(function(player)
361 set_all_properties(player)
364 minetest.register_on_respawnplayer(function(player)
365 create_force_update(player)
368 -- inject into global loop
369 minetest.register_globalstep(function()
370 for _,player in ipairs(minetest.get_connected_players()) do
371 do_animations(player)
378 minetest.register_entity("player_api:item", {
379 initial_properties = {
382 collide_with_objects = false,
383 collisionbox = {0, 0, 0, 0, 0, 0},
384 visual = "wielditem",
385 visual_size = {x = 0.21, y = 0.21},
387 spritediv = {x = 1, y = 1},
388 initial_sprite_basepos = {x = 0, y = 0},
395 set_item = function(self, item)
396 local stack = ItemStack(item or self.itemstring)
398 self.itemstring = stack:to_string()
401 -- Backwards compatibility: old clients use the texture
402 -- to get the type of the item
403 local itemname = stack:is_known() and stack:get_name() or "unknown"
405 local max_count = stack:get_stack_max()
406 local count = math.min(stack:get_count(), max_count)
409 local coll_height = size * 0.75
410 local def = minetest.registered_nodes[itemname]
411 local glow = def and def.light_source
413 local is_visible = true
414 if self.itemstring == "" then
415 -- item not yet known
419 self.object:set_properties({
420 is_visible = is_visible,
421 visual = "wielditem",
422 textures = {itemname},
423 visual_size = {x = size, y = size},
424 collisionbox = {-size, -0.21, -size,
425 size, coll_height, size},
426 selectionbox = {-size, -size, -size, size, size, size},
427 --automatic_rotate = math.pi * 0.5 * 0.2 / size,
428 wield_item = self.itemstring,
433 on_step = function(self, dtime)
434 if not self.wielder then