]> git.lizzy.rs Git - Crafter.git/blob - mods/player_mechanics/player_mechanics.lua
Update eating_mechanics.lua
[Crafter.git] / mods / player_mechanics / player_mechanics.lua
1 local minetest,math,vector,ipairs,tonumber = minetest,math,vector,ipairs,tonumber
2
3 local movement_class              = {} -- controls all data of the movement
4 local player_movement_data        = {} -- used to calculate player movement
5 local player_state_channels       = {} -- holds every player's channel
6 movement_pointer                  = {} -- allows other mods to index local data
7 movement_class.input_data         = nil
8 movement_class.hunger             = nil
9 movement_class.data               = nil
10 movement_class.data_list          = nil
11 movement_class.count              = nil
12 movement_class.name               = nil
13 movement_class.env_data           = nil
14 movement_class.channel_decyphered = nil
15 movement_class.in_water           = nil
16 movement_class.get_group          = minetest.get_item_group
17 movement_class.get_connected      = minetest.get_connected_players
18 movement_class.ipairs             = ipairs
19 movement_class.get_by_name        = minetest.get_player_by_name
20
21 -- creates volitile data for the game to use
22 movement_class.create_movement_variables = function(player)
23         movement_class.name = player:get_player_name()
24         if not player_movement_data[movement_class.name] then
25                 player_movement_data[movement_class.name] = {
26                         state        = 0    ,
27                         old_state    = 0    ,
28                         was_in_water = false,
29                         swimming     = false,
30                 }
31         end
32 end
33
34 -- sets data for the game to use
35 movement_class.set_data = function(player,data)
36         movement_class.name = player:get_player_name()
37         if player_movement_data[movement_class.name] then
38                 for index,i_data in pairs(data) do
39                         if player_movement_data[movement_class.name][index] ~= nil then
40                                 player_movement_data[movement_class.name][index] = i_data
41                         end
42                 end
43         else
44                 movement_class.create_movement_variables(player)
45         end
46 end
47
48 -- retrieves data for the game to use
49 movement_class.get_data = function(player)
50         movement_class.name = player:get_player_name()
51         if player_movement_data[movement_class.name] then
52                 return({
53                         state        = player_movement_data[movement_class.name].state       ,
54                         old_state    = player_movement_data[movement_class.name].old_state   ,
55                         was_in_water = player_movement_data[movement_class.name].was_in_water,
56                         swimming     = player_movement_data[movement_class.name].swimming    ,
57                 })
58         end
59 end
60
61 -- removes movement data
62 movement_class.terminate = function(player)
63         movement_class.name = player:get_player_name()
64         if player_movement_data[movement_class.name] then
65                 player_movement_data[movement_class.name] = nil
66         end
67 end
68
69 -- creates specific channels for players
70 minetest.register_on_joinplayer(function(player)
71         movement_class.name = player:get_player_name()
72         player_state_channels[movement_class.name] = minetest.mod_channel_join(movement_class.name..":player_movement_state")
73         player:set_physics_override({
74                         jump   = 1.25,
75                         gravity= 1.25
76         })
77         movement_class.create_movement_variables(player)
78 end)
79
80 -- resets the player's state on death
81 minetest.register_on_respawnplayer(function(player)
82         movement_class.set_data(player,{
83                 state        = 0    ,
84                 was_in_water = false,
85         })
86         movement_class.send_running_cancellation(player,false)
87 end)
88
89
90 -- delete data on player leaving
91 minetest.register_on_leaveplayer(function(player)
92         movement_class.terminate(player)
93 end)
94
95 -- tells the client to stop sending running/bunnyhop data
96 movement_class.send_running_cancellation = function(player,sneaking)
97         movement_class.name = player:get_player_name()
98         player_state_channels[movement_class.name]:send_all(
99                 minetest.serialize({
100                         stop_running=true,
101                         state=sneaking
102                 }
103         ))
104 end
105
106 -- intercept incoming data messages
107 minetest.register_on_modchannel_message(function(channel_name, sender, message)
108         movement_class.channel_decyphered = channel_name:gsub(sender,"")
109         if sender ~= "" and movement_class.channel_decyphered == ":player_movement_state" then
110                 movement_class.data = tonumber(message)
111                 if type(movement_class.data) == "number" then
112                         movement_class.set_data(movement_class.get_by_name(sender),{
113                                 state = movement_class.data
114                         })
115                 end
116         end
117 end)
118
119 -- allows other mods to set data for the game to use
120 movement_pointer.set_data = function(player,data)
121         movement_class.name = player:get_player_name()
122         if player_movement_data[movement_class.name] then
123                 for index,i_data in pairs(data) do
124                         if player_movement_data[movement_class.name][index] ~= nil then
125                                 player_movement_data[movement_class.name][index] = i_data
126                         end
127                 end
128         else
129                 movement_class.create_movement_variables(player)
130         end
131 end
132
133 -- allows other mods to retrieve data for the game to use
134 movement_pointer.get_data = function(player,requested_data)
135         movement_class.name = player:get_player_name()
136         if player_movement_data[movement_class.name] then
137                 movement_class.data_list = {}
138                 movement_class.count     = 0
139                 for index,i_data in pairs(requested_data) do
140                         if player_movement_data[movement_class.name][i_data] ~= nil then
141                                 movement_class.data_list[i_data] = player_movement_data[movement_class.name][i_data]
142                                 movement_class.count = movement_class.count + 1
143                         end
144                 end
145                 if movement_class.count > 0 then
146                         return(movement_class.data_list)
147                 else
148                         return(nil)
149                 end
150         end
151         return(nil)
152 end
153
154
155 -- controls player states
156 movement_class.control_state = function(player)
157         movement_class.hunger = hunger_pointer.get_data(player,{"hunger"}).hunger
158         movement_class.data   = movement_class.get_data(player)
159         -- water movement data
160         movement_class.env_data = environment_pointer.get_data(player,{"legs","head"})
161         movement_class.in_water = {at_all=false,head=false,legs=false}          
162         if movement_class.env_data then
163                 movement_class.in_water.legs = movement_class.get_group(movement_class.env_data.legs,"water") > 0
164                 movement_class.in_water.head = movement_class.get_group(movement_class.env_data.head,"water") > 0
165                 if movement_class.in_water.legs or movement_class.in_water.head then
166                         movement_class.in_water.at_all = true
167                         movement_class.set_data(player,{swimming=true})
168                 else
169                         movement_class.set_data(player,{swimming=false})
170                 end
171         end
172         
173         if (movement_class.in_water.at_all ~= movement_class.data.was_in_water) or 
174         (movement_class.data.state ~= movement_class.data.old_state) or 
175         ((movement_class.data.state == 1 or movement_class.data.state == 2) and movement_class.hunger and movement_class.hunger <= 6) then
176
177
178                 if not movement_class.in_water.at_all and movement_class.data.was_in_water then
179                         player:set_physics_override({
180                                 sneak   = true,
181                         })
182                         player_pointer.force_update(player)
183                         player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
184                         player_pointer.set_data(player,{
185                                 collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
186                         })
187                 elseif movement_class.in_water.at_all and not movement_class.data.was_in_water then
188                         player:set_physics_override({
189                                 sneak   = false,
190                         })
191
192                         player_pointer.force_update(player)
193                         player:set_eye_offset({x=0,y=-6,z=0},{x=0,y=-6,z=5.9})
194                         player_pointer.set_data(player,{
195                                 collisionbox = {-0.3, 0.5, -0.3, 0.3, 1.2, 0.3},
196                         })
197                 end
198
199                 -- running/swimming fov modifier
200                 if movement_class.hunger and movement_class.hunger > 6 and (movement_class.data.state == 1 or movement_class.data.state == 2) then
201                         player:set_fov(1.25, true, 0.15)
202                         if movement_class.data.state == 2 then
203                                 player:set_physics_override({speed=1.75})
204                         elseif movement_class.data.state == 1 then
205                                 player:set_physics_override({speed=1.5})
206                         end
207                 elseif (not movement_class.in_water.at_all and movement_class.data.state ~= 1 and movement_class.data.state ~= 2 and 
208                 (movement_class.data.old_state == 1 or movement_class.data.old_state == 2)) or 
209                 (movement_class.in_water.at_all and movement_class.data.state ~= 1 and movement_class.data.state ~= 2 and movement_class.data.state ~= 3 and 
210                 (movement_class.data.old_state == 1 or movement_class.data.old_state == 2 or movement_class.data.old_state == 3))then
211
212                         player:set_fov(1, true,0.15)
213                         player:set_physics_override({speed=1})
214
215                         movement_class.send_running_cancellation(player,movement_class.data.state==3) --preserve network data
216                         
217                 elseif (movement_class.data.state == 1 or movement_class.data.state == 2) and (movement_class.hunger and movement_class.hunger <= 6) then
218                         player:set_fov(1, true,0.15)
219                         player:set_physics_override({speed=1})                          
220                         movement_class.send_running_cancellation(player,false) --preserve network data
221                 end
222
223                 --sneaking
224                 if movement_class.data.state == 3 and movement_class.in_water.at_all then
225                         movement_class.send_running_cancellation(player,false)
226                 elseif not movement_class.in_water.at_all and movement_class.data.state == 3 and movement_class.data.old_state ~= 3 then
227                         player:set_eye_offset({x=0,y=-1,z=0},{x=0,y=-1,z=0})
228                 elseif not movement_class.in_water.at_all and movement_class.data.old_state == 3 and movement_class.data.state ~= 3 then
229                         player:set_eye_offset({x=0,y=0,z=0},{x=0,y=0,z=0})
230                 end
231
232                 movement_class.set_data(player,{
233                         old_state    = movement_class.data.state,
234                         was_in_water = movement_class.in_water.at_all
235                 })
236         
237         -- water movement
238         elseif movement_class.in_water.at_all then
239                 if not movement_class.data.was_in_water then
240                         player:set_physics_override({
241                                 sneak   = false ,
242                         })
243                         player:set_velocity(vector.new(0,0,0))
244                 end
245
246                 movement_class.set_data(player,{
247                         old_state    = movement_class.data.state,
248                         was_in_water = movement_class.in_water.at_all
249                 })
250         end
251 end
252
253 minetest.register_globalstep(function(dtime)
254         for _,player in movement_class.ipairs(movement_class.get_connected()) do
255                 movement_class.control_state(player)
256         end
257 end)