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 = math.ceil(minetest.get_us_time()/1000 - self.lag_check)
203 --print("lag = "..chugent.." ms")
204 if chugent > 70 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()/1000
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 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "water")>0 then
243 minetest.add_entity(pointed_thing.under, "boat:boat")
248 itemstack:take_item()
254 minetest.register_craft({
255 output = "boat:boat",
257 {"main:wood", "", "main:wood"},
258 {"main:wood", "main:wood", "main:wood"},
262 ----------------------------------
266 minetest.register_entity("boat:iron_boat", {
267 initial_properties = {
270 collide_with_objects = false,
271 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
274 textures = {"iron_boat.png"},
275 visual_size = {x=1,y=1,z=1},
277 automatic_face_movement_dir = -90.0,
278 automatic_face_movement_max_rotation_per_sec = 600,
284 get_staticdata = function(self)
285 return minetest.serialize({
286 --itemstring = self.itemstring,
290 on_activate = function(self, staticdata, dtime_s)
291 if string.sub(staticdata, 1, string.len("return")) == "return" then
292 local data = minetest.deserialize(staticdata)
293 if data and type(data) == "table" then
294 --self.itemstring = data.itemstring
297 --self.itemstring = staticdata
299 self.object:set_armor_groups({immortal = 1})
300 self.object:set_velocity({x = 0, y = 0, z = 0})
301 self.object:set_acceleration({x = 0, y = 0, z = 0})
303 on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
304 local pos = self.object:get_pos()
305 minetest.add_item(pos, "boat:iron_boat")
310 on_rightclick = function(self,clicker)
311 if not clicker or not clicker:is_player() then
314 local player_name = clicker:get_player_name()
316 if self.rider and player_name == self.rider then
318 local pos = self.object:get_pos()
321 clicker:add_player_velocity(vector.new(0,11,0))
324 player_is_attached(clicker,false)
325 force_update_animation(clicker)
327 elseif not self.rider then
328 self.rider = player_name
329 clicker:set_attach(self.object, "", {x=0, y=2, z=0}, {x=0, y=0, z=0})
331 set_player_animation(clicker,"sit",0)
332 player_is_attached(clicker,true)
335 --check if the boat is stuck on land
336 check_if_on_land = function(self)
337 local pos = self.object:get_pos()
339 local bottom_node = minetest.get_node(pos).name
340 if (bottom_node == "nether:lava" or bottom_node == "nether:lavaflow" or bottom_node == "air") then
348 --players drive the baot
349 drive = function(self)
350 if self.rider and not self.on_land == true then
351 local rider = minetest.get_player_by_name(self.rider)
352 local move = rider:get_player_control().up
355 local currentvel = self.object:get_velocity()
356 local goal = rider:get_look_dir()
357 goal = vector.multiply(goal,20)
358 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
359 acceleration = vector.multiply(acceleration, 0.01)
360 self.object:add_velocity(acceleration)
369 push = function(self)
370 local pos = self.object:get_pos()
371 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
372 if object:is_player() and object:get_player_name() ~= self.rider then
373 local player_pos = object:get_pos()
377 local currentvel = self.object:get_velocity()
378 local vel = vector.subtract(pos, player_pos)
379 vel = vector.normalize(vel)
380 local distance = vector.distance(pos,player_pos)
381 distance = (1-distance)*10
382 vel = vector.multiply(vel,distance)
383 local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
384 self.object:add_velocity(acceleration)
385 acceleration = vector.multiply(acceleration, -1)
386 object:add_player_velocity(acceleration)
391 --makes the boat float
392 float = function(self)
393 local pos = self.object:get_pos()
394 local node = minetest.get_node(pos).name
395 self.swimming = false
397 --flow normally if floating else don't
398 if node == "nether:lava" or node =="nether:lavaflow" then
400 local vel = self.object:get_velocity()
402 local acceleration = vector.new(0,goal-vel.y,0)
403 acceleration = vector.multiply(acceleration, 0.01)
404 self.object:add_velocity(acceleration)
405 --self.object:set_acceleration(vector.new(0,0,0))
407 local vel = self.object:get_velocity()
409 local acceleration = vector.new(0,goal-vel.y,0)
410 acceleration = vector.multiply(acceleration, 0.01)
411 self.object:add_velocity(acceleration)
412 --self.object:set_acceleration(vector.new(0,0,0))
417 flow = function(self)
418 local pos = self.object:get_pos()
420 local node = minetest.get_node(pos).name
421 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
425 if (node == "nether:lavaflow" or node == "nether:lava" ) and not self.moving == true and (node_above ~= "nether:lava" and node_above ~= "nether:lavaflow") then
426 local currentvel = self.object:get_velocity()
427 local level = minetest.get_node_level(pos)
428 local pos = self.object:get_pos()
432 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
433 local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
434 local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
435 if (level2 < level and nodename == "main:lavaflow") or (nodename == "main:lava" and level2 == 7) then
444 --only add velocity if there is one
445 --else this stops the boat
446 if goalx ~= 0 or goalz ~= 0 then
447 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
448 acceleration = vector.multiply(acceleration, 0.01)
449 self.object:add_velocity(acceleration)
455 --slows the boat down
456 slowdown = function(self)
457 if not self.moving == true then
458 local vel = self.object:get_velocity()
459 local acceleration = vector.new(-vel.x,0,-vel.z)
460 local deceleration = vector.multiply(acceleration, 0.01)
461 self.object:add_velocity(deceleration)
465 lag_correction = function(self,dtime)
466 local pos = self.object:get_pos()
467 local velocity = self.object:get_velocity()
468 if self.lag_check then
469 local chugent = math.ceil(minetest.get_us_time()/1000- self.lag_check)
471 --print("lag = "..chugent.." ms")
472 if chugent > 70 and self.old_pos and self.old_velocity then
473 self.object:move_to(self.old_pos)
474 self.object:set_velocity(self.old_velocity)
478 self.old_velocity = vel
479 self.lag_check = minetest.get_us_time()/1000
482 on_step = function(self, dtime)
483 self.check_if_on_land(self)
489 self.lag_correction(self,dtime)
493 minetest.register_craftitem("boat:iron_boat", {
494 description = "Iron Boat",
495 inventory_image = "iron_boatitem.png",
496 wield_image = "iron_boatitem.png",
497 liquids_pointable = true,
498 on_place = function(itemstack, placer, pointed_thing)
499 if not pointed_thing.type == "node" then
503 local sneak = placer:get_player_control().sneak
504 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
505 if not sneak and noddef.on_rightclick then
506 minetest.item_place(itemstack, placer, pointed_thing)
510 if pointed_thing.above.y < -10000 and pointed_thing.above.y > -20000 then
511 minetest.add_entity(pointed_thing.under, "boat:iron_boat")
516 itemstack:take_item()
522 minetest.register_craft({
523 output = "boat:iron_boat",
525 {"main:iron", "main:coal", "main:iron"},
526 {"main:iron", "main:iron", "main:iron"},