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