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
136 local vel = self.object:get_velocity()
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))
143 local vel = self.object:get_velocity()
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))
153 flow = function(self)
154 local pos = self.object:get_pos()
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
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()
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
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)
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)
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)
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)
214 self.old_velocity = vel
215 self.lag_check = minetest.get_us_time()/1000
218 on_step = function(self, dtime)
219 self.check_if_on_land(self)
225 self.lag_correction(self,dtime)
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
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)
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")
252 itemstack:take_item()
258 minetest.register_craft({
259 output = "boat:boat",
261 {"main:wood", "", "main:wood"},
262 {"main:wood", "main:wood", "main:wood"},
266 ----------------------------------
270 minetest.register_entity("boat:iron_boat", {
271 initial_properties = {
274 collide_with_objects = false,
275 collisionbox = {-0.4, 0, -0.4, 0.4, 0.5, 0.4},
278 textures = {"iron_boat.png"},
279 visual_size = {x=1,y=1,z=1},
281 automatic_face_movement_dir = -90.0,
282 automatic_face_movement_max_rotation_per_sec = 600,
288 get_staticdata = function(self)
289 return minetest.serialize({
290 --itemstring = self.itemstring,
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
301 --self.itemstring = staticdata
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})
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")
314 on_rightclick = function(self,clicker)
315 if not clicker or not clicker:is_player() then
318 local player_name = clicker:get_player_name()
320 if self.rider and player_name == self.rider then
322 local pos = self.object:get_pos()
325 clicker:add_player_velocity(vector.new(0,11,0))
328 player_is_attached(clicker,false)
329 force_update_animation(clicker)
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})
335 set_player_animation(clicker,"sit",0)
336 player_is_attached(clicker,true)
339 --check if the boat is stuck on land
340 check_if_on_land = function(self)
341 local pos = self.object:get_pos()
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
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
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)
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()
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)
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
401 --flow normally if floating else don't
402 if node == "nether:lava" or node =="nether:lavaflow" then
404 local vel = self.object:get_velocity()
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))
411 local vel = self.object:get_velocity()
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))
421 flow = function(self)
422 local pos = self.object:get_pos()
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
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()
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
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)
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)
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)
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)
482 self.old_velocity = vel
483 self.lag_check = minetest.get_us_time()/1000
486 on_step = function(self, dtime)
487 self.check_if_on_land(self)
493 self.lag_correction(self,dtime)
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
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)
514 if pointed_thing.above.y < -10000 and pointed_thing.above.y > -20000 then
515 minetest.add_entity(pointed_thing.under, "boat:iron_boat")
520 itemstack:take_item()
526 minetest.register_craft({
527 output = "boat:iron_boat",
529 {"main:iron", "main:coal", "main:iron"},
530 {"main:iron", "main:iron", "main:iron"},