]> git.lizzy.rs Git - Crafter.git/blob - mods/player_mechanics/player_mechanics.lua
27e785502ba085f2fd840e4cd4ba4c8177b50a01
[Crafter.git] / mods / player_mechanics / player_mechanics.lua
1 local minetest,math,vector,ipairs,tonumber = minetest,math,vector,ipairs,tonumber
2
3 local state_channels = {} -- holds every player's channel
4 local pool           = {}
5
6 -- creates specific channels for players
7 local name
8 local temp_pool
9 minetest.register_on_joinplayer(function(player)
10         name = player:get_player_name()
11
12         state_channels[name] = minetest.mod_channel_join(name..":player_movement_state")
13         player:set_physics_override({
14                         jump   = 1.25,
15                         gravity= 1.25
16         })
17
18         pool[name] = {}
19         temp_pool = pool[name]
20         temp_pool.state        = 0
21         temp_pool.old_state    = 0
22         temp_pool.was_in_water = false
23         temp_pool.swimming     = false
24         temp_pool.swim_bumped  = minetest.get_us_time()/1000000
25 end)
26
27 -- resets the player's state on death
28 local name
29 minetest.register_on_respawnplayer(function(player)
30         name = player:get_player_name()
31         pool[name].state = 0
32         pool[name].was_in_water = false
33         pool[name].swim_bumped = minetest.get_us_time()/1000000
34         send_running_cancellation(player,false)
35         player:set_properties({
36                 collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
37         })
38 end)
39
40
41 -- delete data on player leaving
42 local name
43 minetest.register_on_leaveplayer(function(player)
44         name = player:get_player_name()
45         pool[name] = nil
46 end)
47
48 -- tells the client to stop sending running/bunnyhop data
49 local name
50 send_running_cancellation = function(player,sneaking)
51         name = player:get_player_name()
52         state_channels[name]:send_all(
53                 minetest.serialize({
54                         stop_running=true,
55                         state=sneaking
56                 }
57         ))
58 end
59
60 -- intercept incoming data messages
61 local channel_decyphered
62 local state
63 minetest.register_on_modchannel_message(function(channel_name, sender, message)
64         channel_decyphered = channel_name:gsub(sender,"")
65         if sender ~= "" and channel_decyphered == ":player_movement_state" then
66                 state = tonumber(message)
67                 if type(state) == "number" then
68                         pool[sender].state = state
69                 end
70         end
71 end)
72
73
74
75
76 -- allows other mods to retrieve data for the game to use
77 local name
78 get_player_state = function(player)
79         name = player:get_player_name()
80         return(pool[name].state)
81 end
82 local name
83 is_player_swimming = function(player)
84         name = player:get_player_name()
85         return(pool[name].swimming)
86 end
87
88 -- controls player states
89 local hunger
90 local name
91 local temp_pool
92 local head
93 local legs
94 local in_water
95 local swim_unlock
96 local swim_bump
97 local control_state = function(player)
98         hunger    = get_player_hunger(player)
99         name      = player:get_player_name()
100         temp_pool = pool[name]
101
102
103         -- water movement data
104         head = minetest.get_item_group(get_player_head_env(player),"water") > 0
105         legs = minetest.get_item_group(get_player_legs_env(player),"water") > 0
106
107         in_water = temp_pool.swimming
108
109         --check if in water
110         if head then
111                 in_water = true
112                 temp_pool.swimming = true
113         elseif temp_pool.swimming == true then
114                 swim_unlock = player_swim_under_check(player)
115                 swim_bump = player_swim_check(player)
116                 if swim_unlock then
117                         in_water = false
118                         temp_pool.swimming = false
119                         temp_pool.swim_bumped = minetest.get_us_time()/1000000
120                 elseif swim_bump and minetest.get_us_time()/1000000-temp_pool.swim_bumped > 1 then
121                         if player:get_player_velocity().y <= 0 then
122                                 temp_pool.swim_bumped = minetest.get_us_time()/1000000
123                                 player:add_player_velocity(vector.new(0,9,0))
124                         end
125                 end
126         end     
127         if (in_water ~= temp_pool.was_in_water) or 
128         (temp_pool.state ~= temp_pool.old_state) or 
129         ((temp_pool.state == 1 or temp_pool.state == 2) and hunger <= 6) then
130
131                 if (not in_water and temp_pool.was_in_water) then
132                         player:set_physics_override({
133                                 sneak   = true,
134                         })
135
136                         force_update_animation(player)
137
138                         player:set_properties({
139                                 collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
140                         })
141                 elseif in_water and not temp_pool.was_in_water then
142                         
143                         player:set_physics_override({
144                                 sneak   = false,
145                         })
146
147                         force_update_animation(player)
148
149                         player:set_properties({
150                                 collisionbox = {-0.3, 0.8, -0.3, 0.3, 1.6, 0.3},
151                         })
152                         player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
153                 end
154
155                 -- running/swimming fov modifier
156                 if hunger > 6 and (temp_pool.state == 1 or temp_pool.state == 2) then
157                         player:set_fov(1.25, true, 0.15)
158
159                         if temp_pool.state == 2 then
160                                 player:set_physics_override({speed=1.75})
161                         elseif temp_pool.state == 1 then
162                                 player:set_physics_override({speed=1.5})
163                         end
164
165                 elseif (not in_water and temp_pool.state ~= 1 and temp_pool.state ~= 2 and 
166                 (temp_pool.old_state == 1 or temp_pool.old_state == 2)) or
167                 (in_water and temp_pool.state ~= 1 and temp_pool.state ~= 2 and temp_pool.state ~= 3 and 
168                 (temp_pool.old_state == 1 or temp_pool.old_state == 2 or temp_pool.old_state == 3))then
169
170                         player:set_fov(1, true,0.15)
171                         player:set_physics_override({speed=1})
172
173                         send_running_cancellation(player,temp_pool.state==3) --preserve network data
174                         
175                 elseif (temp_pool.state == 1 or temp_pool.state == 2) and hunger <= 6 then
176                         player:set_fov(1, true,0.15)
177                         player:set_physics_override({speed=1})                          
178                         send_running_cancellation(player,false) --preserve network data
179                 end
180
181                 --sneaking
182                 if temp_pool.state == 3 and in_water then
183                         --send_running_cancellation(player,false)
184                 elseif not in_water and temp_pool.state == 3 and temp_pool.old_state ~= 3 then
185                         player:set_eye_offset({x=0,y=-1,z=0},{x=0,y=0,z=0})
186                 elseif not in_water and temp_pool.old_state == 3 and temp_pool.state ~= 3 then
187                         player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
188                 end
189
190                 temp_pool.old_state    = state
191                 temp_pool.was_in_water = in_water
192         
193         -- water movement
194
195         elseif in_water then
196                 if not temp_pool.was_in_water then
197                         player:set_physics_override({
198                                 sneak   = false ,
199                         })
200                 end
201                 temp_pool.old_state    = temp_pool.old_state
202                 temp_pool.was_in_water = in_water
203         end
204
205 end
206
207 minetest.register_globalstep(function(dtime)
208         for _,player in ipairs(minetest.get_connected_players()) do
209                 control_state(player)
210         end
211 end)