1 --minetest.get_node_level(pos)
2 minetest.register_entity("boat:boat", {
6 collide_with_objects = false,
7 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
10 textures = {"boat.png"},
11 visual_size = {x=1,y=1,z=1},
13 automatic_face_movement_dir = -90.0,
14 automatic_face_movement_max_rotation_per_sec = 600,
20 get_staticdata = function(self)
21 return minetest.serialize({
22 --itemstring = self.itemstring,
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
33 --self.itemstring = staticdata
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})
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")
46 on_rightclick = function(self,clicker)
47 if not clicker or not clicker:is_player() then
50 local player_name = clicker:get_player_name()
52 if self.rider and player_name == self.rider then
54 local pos = self.object:get_pos()
57 clicker:add_player_velocity(vector.new(0,11,0))
60 player_is_attached(clicker,false)
61 force_update_animation(clicker)
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})
67 set_player_animation(clicker,"sit",0)
68 player_is_attached(clicker,true)
71 --check if the boat is stuck on land
72 check_if_on_land = function(self)
73 local pos = self.object:get_pos()
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
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
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)
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()
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)
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
133 --flow normally if floating else don't
134 if node == "main:water" or node =="main:waterflow" then
135 self.object:set_acceleration(vector.new(0,0,0))
137 local vel = self.object:get_velocity()
139 local acceleration = vector.new(0,goal-vel.y,0)
140 acceleration = vector.multiply(acceleration, 0.01)
141 self.object:add_velocity(acceleration)
142 --self.object:set_acceleration(vector.new(0,0,0))
144 self.object:set_acceleration(vector.new(0,-10,0))
149 flow = function(self)
150 local pos = self.object:get_pos()
152 local node = minetest.get_node(pos).name
153 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
157 if (node == "main:waterflow" or node == "main:water" ) and not self.moving == true and (node_above ~= "main:water" and node_above ~= "main:waterflow") then
158 local currentvel = self.object:get_velocity()
159 local level = minetest.get_node_level(pos)
160 local pos = self.object:get_pos()
164 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
165 local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
166 local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
167 if (level2 < level and nodename == "main:waterflow") or (nodename == "main:water" and level2 == 7) then
176 --only add velocity if there is one
177 --else this stops the boat
178 if goalx ~= 0 or goalz ~= 0 then
179 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
180 acceleration = vector.multiply(acceleration, 0.01)
181 self.object:add_velocity(acceleration)
187 --slows the boat down
188 slowdown = function(self)
189 if not self.moving == true then
190 local vel = self.object:get_velocity()
191 local acceleration = vector.new(-vel.x,0,-vel.z)
192 local deceleration = vector.multiply(acceleration, 0.01)
193 self.object:add_velocity(deceleration)
197 lag_correction = function(self,dtime)
198 local pos = self.object:get_pos()
199 local velocity = self.object:get_velocity()
200 if self.lag_check then
201 local chugent = minetest.get_us_time()/1000000 - self.lag_check
203 --print("lag = "..chugent.." ms")
204 if chugent > 1 and self.old_pos and self.old_velocity then
205 self.object:move_to(self.old_pos)
206 self.object:set_velocity(self.old_velocity)
210 self.old_velocity = vel
211 self.lag_check = minetest.get_us_time()/1000000
214 on_step = function(self, dtime)
215 self.check_if_on_land(self)
221 self.lag_correction(self,dtime)
225 minetest.register_craftitem("boat:boat", {
226 description = "Boat",
227 inventory_image = "boatitem.png",
228 wield_image = "boatitem.png",
229 liquids_pointable = true,
230 on_place = function(itemstack, placer, pointed_thing)
231 if not pointed_thing.type == "node" then
235 local sneak = placer:get_player_control().sneak
236 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
237 if not sneak and noddef.on_rightclick then
238 minetest.item_place(itemstack, placer, pointed_thing)
242 minetest.add_entity(pointed_thing.above, "boat:boat")
244 itemstack:take_item()
250 minetest.register_craft({
251 output = "boat:boat",
253 {"main:wood", "", "main:wood"},
254 {"main:wood", "main:wood", "main:wood"},
258 ----------------------------------
262 minetest.register_entity("boat:iron_boat", {
263 initial_properties = {
266 collide_with_objects = false,
267 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
270 textures = {"iron_boat.png"},
271 visual_size = {x=1,y=1,z=1},
273 automatic_face_movement_dir = -90.0,
274 automatic_face_movement_max_rotation_per_sec = 600,
280 get_staticdata = function(self)
281 return minetest.serialize({
282 --itemstring = self.itemstring,
286 on_activate = function(self, staticdata, dtime_s)
287 if string.sub(staticdata, 1, string.len("return")) == "return" then
288 local data = minetest.deserialize(staticdata)
289 if data and type(data) == "table" then
290 --self.itemstring = data.itemstring
293 --self.itemstring = staticdata
295 self.object:set_armor_groups({immortal = 1})
296 self.object:set_velocity({x = 0, y = 0, z = 0})
297 self.object:set_acceleration({x = 0, y = 0, z = 0})
299 on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
300 local pos = self.object:get_pos()
301 minetest.add_item(pos, "boat:iron_boat")
306 on_rightclick = function(self,clicker)
307 if not clicker or not clicker:is_player() then
310 local player_name = clicker:get_player_name()
312 if self.rider and player_name == self.rider then
314 local pos = self.object:get_pos()
317 clicker:add_player_velocity(vector.new(0,11,0))
320 player_is_attached(clicker,false)
321 force_update_animation(clicker)
323 elseif not self.rider then
324 self.rider = player_name
325 clicker:set_attach(self.object, "", {x=0, y=2, z=0}, {x=0, y=0, z=0})
327 set_player_animation(clicker,"sit",0)
328 player_is_attached(clicker,true)
331 --check if the boat is stuck on land
332 check_if_on_land = function(self)
333 local pos = self.object:get_pos()
335 local bottom_node = minetest.get_node(pos).name
336 if (bottom_node == "nether:lava" or bottom_node == "nether:lavaflow" or bottom_node == "air") then
344 --players drive the baot
345 drive = function(self)
346 if self.rider and not self.on_land == true then
347 local rider = minetest.get_player_by_name(self.rider)
348 local move = rider:get_player_control().up
351 local currentvel = self.object:get_velocity()
352 local goal = rider:get_look_dir()
353 goal = vector.multiply(goal,20)
354 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
355 acceleration = vector.multiply(acceleration, 0.01)
356 self.object:add_velocity(acceleration)
365 push = function(self)
366 local pos = self.object:get_pos()
367 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
368 if object:is_player() and object:get_player_name() ~= self.rider then
369 local player_pos = object:get_pos()
373 local currentvel = self.object:get_velocity()
374 local vel = vector.subtract(pos, player_pos)
375 vel = vector.normalize(vel)
376 local distance = vector.distance(pos,player_pos)
377 distance = (1-distance)*10
378 vel = vector.multiply(vel,distance)
379 local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
380 self.object:add_velocity(acceleration)
381 acceleration = vector.multiply(acceleration, -1)
382 object:add_player_velocity(acceleration)
387 --makes the boat float
388 float = function(self)
389 local pos = self.object:get_pos()
390 local node = minetest.get_node(pos).name
391 self.swimming = false
393 --flow normally if floating else don't
394 if node == "nether:lava" or node =="nether:lavaflow" then
396 local vel = self.object:get_velocity()
398 local acceleration = vector.new(0,goal-vel.y,0)
399 acceleration = vector.multiply(acceleration, 0.01)
400 self.object:add_velocity(acceleration)
401 --self.object:set_acceleration(vector.new(0,0,0))
403 local vel = self.object:get_velocity()
405 local acceleration = vector.new(0,goal-vel.y,0)
406 acceleration = vector.multiply(acceleration, 0.01)
407 self.object:add_velocity(acceleration)
408 --self.object:set_acceleration(vector.new(0,0,0))
413 flow = function(self)
414 local pos = self.object:get_pos()
416 local node = minetest.get_node(pos).name
417 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
421 if (node == "nether:lavaflow" or node == "nether:lava" ) and not self.moving == true and (node_above ~= "nether:lava" and node_above ~= "nether:lavaflow") then
422 local currentvel = self.object:get_velocity()
423 local level = minetest.get_node_level(pos)
424 local pos = self.object:get_pos()
428 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
429 local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
430 local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
431 if (level2 < level and nodename == "main:lavaflow") or (nodename == "main:lava" and level2 == 7) then
440 --only add velocity if there is one
441 --else this stops the boat
442 if goalx ~= 0 or goalz ~= 0 then
443 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
444 acceleration = vector.multiply(acceleration, 0.01)
445 self.object:add_velocity(acceleration)
451 --slows the boat down
452 slowdown = function(self)
453 if not self.moving == true then
454 local vel = self.object:get_velocity()
455 local acceleration = vector.new(-vel.x,0,-vel.z)
456 local deceleration = vector.multiply(acceleration, 0.01)
457 self.object:add_velocity(deceleration)
461 lag_correction = function(self,dtime)
462 local pos = self.object:get_pos()
463 local velocity = self.object:get_velocity()
464 if self.lag_check then
465 local chugent = minetest.get_us_time()/1000000- self.lag_check
467 --print("lag = "..chugent.." ms")
468 if chugent > 70 and self.old_pos and self.old_velocity then
469 self.object:move_to(self.old_pos)
470 self.object:set_velocity(self.old_velocity)
474 self.old_velocity = vel
475 self.lag_check = minetest.get_us_time()/1000000
478 on_step = function(self, dtime)
479 self.check_if_on_land(self)
485 self.lag_correction(self,dtime)
489 minetest.register_craftitem("boat:iron_boat", {
490 description = "Nether Iron Boat",
491 inventory_image = "iron_boatitem.png",
492 wield_image = "iron_boatitem.png",
493 liquids_pointable = true,
494 on_place = function(itemstack, placer, pointed_thing)
495 if not pointed_thing.type == "node" then
499 local sneak = placer:get_player_control().sneak
500 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
501 if not sneak and noddef.on_rightclick then
502 minetest.item_place(itemstack, placer, pointed_thing)
506 minetest.add_entity(pointed_thing.above, "boat:iron_boat")
508 itemstack:take_item()
514 minetest.register_craft({
515 output = "boat:iron_boat",
517 {"main:iron", "main:coal", "main:iron"},
518 {"main:iron", "main:iron", "main:iron"},