]> git.lizzy.rs Git - Crafter.git/blob - mods/boat/init.lua
switch os.clock to minetest.get_us_time
[Crafter.git] / mods / boat / init.lua
1 --minetest.get_node_level(pos)
2 minetest.register_entity("boat:boat", {
3         initial_properties = {
4                 hp_max = 1,
5                 physical = true,
6                 collide_with_objects = false,
7                 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
8                 visual = "mesh",
9                 mesh = "boat.x",
10                 textures = {"boat.png"},
11                 visual_size = {x=1,y=1,z=1},
12                 is_visible = true,
13                 automatic_face_movement_dir = -90.0,
14                 automatic_face_movement_max_rotation_per_sec = 600,
15         },
16         
17         rider = nil,
18         boat = true,
19
20         get_staticdata = function(self)
21                 return minetest.serialize({
22                         --itemstring = self.itemstring,
23                 })
24         end,
25
26         on_activate = function(self, staticdata, dtime_s)
27                 if string.sub(staticdata, 1, string.len("return")) == "return" then
28                         local data = minetest.deserialize(staticdata)
29                         if data and type(data) == "table" then
30                                 --self.itemstring = data.itemstring
31                         end
32                 else
33                         --self.itemstring = staticdata
34                 end
35                 self.object:set_armor_groups({immortal = 1})
36                 self.object:set_velocity({x = 0, y = 0, z = 0})
37                 self.object:set_acceleration({x = 0, y = 0, z = 0})
38         end,
39         on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
40                 local pos = self.object:get_pos()
41                 minetest.add_item(pos, "boat:boat")
42                 self.object:remove()
43         end,
44         
45         
46         on_rightclick = function(self,clicker)
47                 if not clicker or not clicker:is_player() then
48                         return
49                 end
50                 local player_name = clicker:get_player_name()
51                 
52                 if self.rider and player_name == self.rider then
53                         clicker:set_detach()
54                         local pos = self.object:get_pos()
55                         pos.y = pos.y + 1
56                         clicker:move_to(pos)
57                         clicker:add_player_velocity(vector.new(0,11,0))
58                         self.rider = nil
59                         
60                         player_is_attached(clicker,false)
61                         force_update_animation(clicker)
62
63                 elseif not self.rider then
64                         self.rider = player_name
65                         clicker:set_attach(self.object, "", {x=0, y=2, z=0}, {x=0, y=0, z=0})
66                         
67                         set_player_animation(clicker,"sit",0)
68                         player_is_attached(clicker,true)
69                 end
70         end,
71         --check if the boat is stuck on land
72         check_if_on_land = function(self)
73                 local pos = self.object:get_pos()
74                 pos.y = pos.y - 0.37
75                 local bottom_node = minetest.get_node(pos).name
76                 if (bottom_node == "main:water" or bottom_node == "main:waterflow" or bottom_node == "air") then
77                         self.on_land = false
78                 else
79                         self.on_land = true
80                 end
81         
82         end,
83         
84         --players drive the baot
85         drive = function(self)
86                 if self.rider and not self.on_land == true then
87                         local rider = minetest.get_player_by_name(self.rider)
88                         local move = rider:get_player_control().up
89                         self.moving = nil
90                         if move then
91                                 local currentvel = self.object:get_velocity()
92                                 local goal = rider:get_look_dir()
93                                 goal = vector.multiply(goal,20)
94                                 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
95                                 acceleration = vector.multiply(acceleration, 0.01)
96                                 self.object:add_velocity(acceleration)
97                                 self.moving = true
98                         end
99                 else
100                         self.moving = nil
101                 end
102         end,
103         
104         --players push boat
105         push = function(self)
106                 local pos = self.object:get_pos()
107                 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
108                         if object:is_player() and object:get_player_name() ~= self.rider then
109                                 local player_pos = object:get_pos()
110                                 pos.y = 0
111                                 player_pos.y = 0
112                                 
113                                 local currentvel = self.object:get_velocity()
114                                 local vel = vector.subtract(pos, player_pos)
115                                 vel = vector.normalize(vel)
116                                 local distance = vector.distance(pos,player_pos)
117                                 distance = (1-distance)*10
118                                 vel = vector.multiply(vel,distance)
119                                 local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
120                                 self.object:add_velocity(acceleration)
121                                 acceleration = vector.multiply(acceleration, -1)
122                                 object:add_player_velocity(acceleration)
123                         end
124                 end
125         end,
126         
127         --makes the boat float
128         float = function(self)
129                 local pos = self.object:get_pos()
130                 local node = minetest.get_node(pos).name
131                 self.swimming = false
132                 
133                 --flow normally if floating else don't
134                 if node == "main:water" or node =="main:waterflow" then
135                         self.swimming = true
136                         local vel = self.object:get_velocity()
137                         local goal = 9
138                         local acceleration = vector.new(0,goal-vel.y,0)
139                         acceleration = vector.multiply(acceleration, 0.01)
140                         self.object:add_velocity(acceleration)
141                         --self.object:set_acceleration(vector.new(0,0,0))
142                 else
143                         local vel = self.object:get_velocity()
144                         local goal = -9.81
145                         local acceleration = vector.new(0,goal-vel.y,0)
146                         acceleration = vector.multiply(acceleration, 0.01)
147                         self.object:add_velocity(acceleration)
148                         --self.object:set_acceleration(vector.new(0,0,0))
149                 end
150         end,
151         
152         --makes boats flow
153         flow = function(self)
154                 local pos = self.object:get_pos()
155                 pos.y = pos.y - 0.4
156                 local node = minetest.get_node(pos).name
157                 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
158                 local goalx = 0
159                 local goalz = 0
160                 --print(node_above)
161                 if (node == "main:waterflow" or node == "main:water" ) and not self.moving == true and (node_above ~= "main:water" and node_above ~= "main:waterflow") then
162                         local currentvel = self.object:get_velocity()
163                         local level = minetest.get_node_level(pos)
164                         local pos = self.object:get_pos()
165                         for x = -1,1 do
166                                 for y = -1,0 do
167                                         for z = -1,1 do
168                                                 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
169                                                         local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
170                                                         local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
171                                                         if (level2 < level and nodename == "main:waterflow") or (nodename == "main:water" and level2 == 7)  then
172                                                                 goalx = x*7
173                                                                 goalz = z*7
174                                                                 --break
175                                                         end
176                                                 end
177                                         end
178                                 end
179                         end
180                         --only add velocity if there is one
181                         --else this stops the boat
182                         if goalx ~= 0 or goalz ~= 0 then
183                                 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
184                                 acceleration = vector.multiply(acceleration, 0.01)
185                                 self.object:add_velocity(acceleration)
186                         end
187                 end
188         end,
189         
190         
191         --slows the boat down
192         slowdown = function(self)
193                 if not self.moving == true then
194                         local vel = self.object:get_velocity()
195                         local acceleration = vector.new(-vel.x,0,-vel.z)
196                         local deceleration = vector.multiply(acceleration, 0.01)
197                         self.object:add_velocity(deceleration)
198                 end
199         end,
200
201         lag_correction = function(self,dtime)
202                 local pos = self.object:get_pos()
203                 local velocity = self.object:get_velocity()
204                 if self.lag_check then
205                         local chugent = math.ceil(minetest.get_us_time()/1000 - self.lag_check)
206
207                         --print("lag = "..chugent.." ms")
208                         if chugent > 70 and  self.old_pos and self.old_velocity then
209                                 self.object:move_to(self.old_pos)
210                                 self.object:set_velocity(self.old_velocity)
211                         end
212                 end
213                 self.old_pos = pos
214                 self.old_velocity = vel
215                 self.lag_check = minetest.get_us_time()/1000
216         end,
217
218         on_step = function(self, dtime)
219                 self.check_if_on_land(self)
220                 self.push(self)
221                 self.drive(self)
222                 self.float(self)
223                 self.flow(self)
224                 self.slowdown(self)
225                 self.lag_correction(self,dtime)
226         end,
227 })
228
229 minetest.register_craftitem("boat:boat", {
230         description = "Boat",
231         inventory_image = "boatitem.png",
232         wield_image = "boatitem.png",
233         liquids_pointable = true,
234         on_place = function(itemstack, placer, pointed_thing)
235                 if not pointed_thing.type == "node" then
236                         return
237                 end
238                 
239                 local sneak = placer:get_player_control().sneak
240                 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
241                 if not sneak and noddef.on_rightclick then
242                         minetest.item_place(itemstack, placer, pointed_thing)
243                         return
244                 end
245                 
246                 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "water")>0 then
247                         minetest.add_entity(pointed_thing.under, "boat:boat")
248                 else
249                         return
250                 end
251
252                 itemstack:take_item()
253
254                 return itemstack
255         end,
256 })
257
258 minetest.register_craft({
259         output = "boat:boat",
260         recipe = {
261                 {"main:wood", "", "main:wood"},
262                 {"main:wood", "main:wood", "main:wood"},
263         },
264 })
265
266 ----------------------------------
267
268
269
270 minetest.register_entity("boat:iron_boat", {
271         initial_properties = {
272                 hp_max = 1,
273                 physical = true,
274                 collide_with_objects = false,
275                 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
276                 visual = "mesh",
277                 mesh = "boat.x",
278                 textures = {"iron_boat.png"},
279                 visual_size = {x=1,y=1,z=1},
280                 is_visible = true,
281                 automatic_face_movement_dir = -90.0,
282                 automatic_face_movement_max_rotation_per_sec = 600,
283         },
284         
285         rider = nil,
286         iron_boat = true,
287
288         get_staticdata = function(self)
289                 return minetest.serialize({
290                         --itemstring = self.itemstring,
291                 })
292         end,
293
294         on_activate = function(self, staticdata, dtime_s)
295                 if string.sub(staticdata, 1, string.len("return")) == "return" then
296                         local data = minetest.deserialize(staticdata)
297                         if data and type(data) == "table" then
298                                 --self.itemstring = data.itemstring
299                         end
300                 else
301                         --self.itemstring = staticdata
302                 end
303                 self.object:set_armor_groups({immortal = 1})
304                 self.object:set_velocity({x = 0, y = 0, z = 0})
305                 self.object:set_acceleration({x = 0, y = 0, z = 0})
306         end,
307         on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
308                 local pos = self.object:get_pos()
309                 minetest.add_item(pos, "boat:iron_boat")
310                 self.object:remove()
311         end,
312         
313         
314         on_rightclick = function(self,clicker)
315                 if not clicker or not clicker:is_player() then
316                         return
317                 end
318                 local player_name = clicker:get_player_name()
319                 
320                 if self.rider and player_name == self.rider then
321                         clicker:set_detach()
322                         local pos = self.object:get_pos()
323                         pos.y = pos.y + 1
324                         clicker:move_to(pos)
325                         clicker:add_player_velocity(vector.new(0,11,0))
326                         self.rider = nil
327                         
328                         player_is_attached(clicker,false)
329                         force_update_animation(clicker)
330
331                 elseif not self.rider then
332                         self.rider = player_name
333                         clicker:set_attach(self.object, "", {x=0, y=2, z=0}, {x=0, y=0, z=0})
334                         
335                         set_player_animation(clicker,"sit",0)
336                         player_is_attached(clicker,true)
337                 end
338         end,
339         --check if the boat is stuck on land
340         check_if_on_land = function(self)
341                 local pos = self.object:get_pos()
342                 pos.y = pos.y - 0.37
343                 local bottom_node = minetest.get_node(pos).name
344                 if (bottom_node == "nether:lava" or bottom_node == "nether:lavaflow" or bottom_node == "air") then
345                         self.on_land = false
346                 else
347                         self.on_land = true
348                 end
349         
350         end,
351         
352         --players drive the baot
353         drive = function(self)
354                 if self.rider and not self.on_land == true then
355                         local rider = minetest.get_player_by_name(self.rider)
356                         local move = rider:get_player_control().up
357                         self.moving = nil
358                         if move then
359                                 local currentvel = self.object:get_velocity()
360                                 local goal = rider:get_look_dir()
361                                 goal = vector.multiply(goal,20)
362                                 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
363                                 acceleration = vector.multiply(acceleration, 0.01)
364                                 self.object:add_velocity(acceleration)
365                                 self.moving = true
366                         end
367                 else
368                         self.moving = nil
369                 end
370         end,
371         
372         --players push boat
373         push = function(self)
374                 local pos = self.object:get_pos()
375                 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
376                         if object:is_player() and object:get_player_name() ~= self.rider then
377                                 local player_pos = object:get_pos()
378                                 pos.y = 0
379                                 player_pos.y = 0
380                                 
381                                 local currentvel = self.object:get_velocity()
382                                 local vel = vector.subtract(pos, player_pos)
383                                 vel = vector.normalize(vel)
384                                 local distance = vector.distance(pos,player_pos)
385                                 distance = (1-distance)*10
386                                 vel = vector.multiply(vel,distance)
387                                 local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
388                                 self.object:add_velocity(acceleration)
389                                 acceleration = vector.multiply(acceleration, -1)
390                                 object:add_player_velocity(acceleration)
391                         end
392                 end
393         end,
394         
395         --makes the boat float
396         float = function(self)
397                 local pos = self.object:get_pos()
398                 local node = minetest.get_node(pos).name
399                 self.swimming = false
400                 
401                 --flow normally if floating else don't
402                 if node == "nether:lava" or node =="nether:lavaflow" then
403                         self.swimming = true
404                         local vel = self.object:get_velocity()
405                         local goal = 9
406                         local acceleration = vector.new(0,goal-vel.y,0)
407                         acceleration = vector.multiply(acceleration, 0.01)
408                         self.object:add_velocity(acceleration)
409                         --self.object:set_acceleration(vector.new(0,0,0))
410                 else
411                         local vel = self.object:get_velocity()
412                         local goal = -9.81
413                         local acceleration = vector.new(0,goal-vel.y,0)
414                         acceleration = vector.multiply(acceleration, 0.01)
415                         self.object:add_velocity(acceleration)
416                         --self.object:set_acceleration(vector.new(0,0,0))
417                 end
418         end,
419         
420         --makes boats flow
421         flow = function(self)
422                 local pos = self.object:get_pos()
423                 pos.y = pos.y - 0.4
424                 local node = minetest.get_node(pos).name
425                 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
426                 local goalx = 0
427                 local goalz = 0
428                 --print(node_above)
429                 if (node == "nether:lavaflow" or node == "nether:lava" ) and not self.moving == true and (node_above ~= "nether:lava" and node_above ~= "nether:lavaflow") then
430                         local currentvel = self.object:get_velocity()
431                         local level = minetest.get_node_level(pos)
432                         local pos = self.object:get_pos()
433                         for x = -1,1 do
434                                 for y = -1,0 do
435                                         for z = -1,1 do
436                                                 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
437                                                         local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
438                                                         local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
439                                                         if (level2 < level and nodename == "main:lavaflow") or (nodename == "main:lava" and level2 == 7)  then
440                                                                 goalx = x*7
441                                                                 goalz = z*7
442                                                                 --break
443                                                         end
444                                                 end
445                                         end
446                                 end
447                         end
448                         --only add velocity if there is one
449                         --else this stops the boat
450                         if goalx ~= 0 or goalz ~= 0 then
451                                 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
452                                 acceleration = vector.multiply(acceleration, 0.01)
453                                 self.object:add_velocity(acceleration)
454                         end
455                 end
456         end,
457         
458         
459         --slows the boat down
460         slowdown = function(self)
461                 if not self.moving == true then
462                         local vel = self.object:get_velocity()
463                         local acceleration = vector.new(-vel.x,0,-vel.z)
464                         local deceleration = vector.multiply(acceleration, 0.01)
465                         self.object:add_velocity(deceleration)
466                 end
467         end,
468
469         lag_correction = function(self,dtime)
470                 local pos = self.object:get_pos()
471                 local velocity = self.object:get_velocity()
472                 if self.lag_check then
473                         local chugent = math.ceil(minetest.get_us_time()/1000- self.lag_check)
474
475                         --print("lag = "..chugent.." ms")
476                         if chugent > 70 and  self.old_pos and self.old_velocity then
477                                 self.object:move_to(self.old_pos)
478                                 self.object:set_velocity(self.old_velocity)
479                         end
480                 end
481                 self.old_pos = pos
482                 self.old_velocity = vel
483                 self.lag_check = minetest.get_us_time()/1000
484         end,
485
486         on_step = function(self, dtime)
487                 self.check_if_on_land(self)
488                 self.push(self)
489                 self.drive(self)
490                 self.float(self)
491                 self.flow(self)
492                 self.slowdown(self)
493                 self.lag_correction(self,dtime)
494         end,
495 })
496
497 minetest.register_craftitem("boat:iron_boat", {
498         description = "Iron Boat",
499         inventory_image = "iron_boatitem.png",
500         wield_image = "iron_boatitem.png",
501         liquids_pointable = true,
502         on_place = function(itemstack, placer, pointed_thing)
503                 if not pointed_thing.type == "node" then
504                         return
505                 end
506                 
507                 local sneak = placer:get_player_control().sneak
508                 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
509                 if not sneak and noddef.on_rightclick then
510                         minetest.item_place(itemstack, placer, pointed_thing)
511                         return
512                 end
513                 
514                 if pointed_thing.above.y < -10000 and pointed_thing.above.y > -20000 then
515                         minetest.add_entity(pointed_thing.under, "boat:iron_boat")
516                 else
517                         return
518                 end
519
520                 itemstack:take_item()
521
522                 return itemstack
523         end,
524 })
525
526 minetest.register_craft({
527         output = "boat:iron_boat",
528         recipe = {
529                 {"main:iron", "main:coal", "main:iron"},
530                 {"main:iron", "main:iron", "main:iron"},
531         },
532 })