1 --minetest.get_node_level(pos)
2 minetest.register_entity("boat:boat", {
6 collide_with_objects = false,
7 collisionbox = {-0.4, -0.35, -0.4, 0.4, 0.3, 0.4},
10 textures = {"boat.png"},
11 visual_size = {x=3,y=3,z=3},
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 = -9.81, z = 0})
39 on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
40 local pos = self.object:getpos()
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
55 elseif not self.rider then
56 self.rider = player_name
57 clicker:set_attach(self.object, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0})
58 --player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
59 --carts:manage_attachment(clicker, self.object)
61 -- player_api does not update the animation
62 -- when the player is attached, reset to default animation
64 --player_api.set_animation(clicker, "stand")
67 --check if the boat is stuck on land
68 check_if_on_land = function(self)
69 local pos = self.object:getpos()
71 local bottom_node = minetest.get_node(pos).name
72 if (bottom_node == "main:water" or bottom_node == "main:waterflow" or bottom_node == "air") then
80 --players drive the baot
81 drive = function(self)
82 if self.rider and not self.on_land == true then
83 local rider = minetest.get_player_by_name(self.rider)
84 local move = rider:get_player_control().up
87 local currentvel = self.object:getvelocity()
88 local goal = rider:get_look_dir()
89 goal = vector.multiply(goal,9)
90 local acceleration = vector.new(goal.x-currentvel.x,0,goal.z-currentvel.z)
91 acceleration = vector.multiply(acceleration, 0.01)
92 self.object:add_velocity(acceleration)
101 push = function(self)
102 local pos = self.object:getpos()
103 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
104 if object:is_player() and object:get_player_name() ~= self.rider then
105 local player_pos = object:getpos()
109 local currentvel = self.object:getvelocity()
110 local vel = vector.subtract(pos, player_pos)
111 vel = vector.normalize(vel)
112 local distance = vector.distance(pos,player_pos)
113 distance = (1-distance)*10
114 vel = vector.multiply(vel,distance)
115 local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
116 self.object:add_velocity(acceleration)
117 acceleration = vector.multiply(acceleration, -1)
118 object:add_player_velocity(acceleration)
123 --makes the boat float
124 float = function(self)
125 local pos = self.object:getpos()
126 local node = minetest.get_node(pos).name
127 self.swimming = false
129 --flow normally if floating else don't
130 if node == "main:water" or node =="main:waterflow" then
132 local vel = self.object:getvelocity()
134 local acceleration = vector.new(0,goal-vel.y,0)
135 self.object:add_velocity(acceleration)
140 flow = function(self)
141 local pos = self.object:getpos()
143 local node = minetest.get_node(pos).name
144 local node_above = minetest.get_node(vector.new(pos.x,pos.y+1,pos.z)).name
148 if (node == "main:waterflow" or node == "main:water" ) and not self.moving == true and (node_above ~= "main:water" and node_above ~= "main:waterflow") then
149 local currentvel = self.object:getvelocity()
150 local level = minetest.get_node_level(pos)
151 local pos = self.object:getpos()
155 if (x == 0 and z ~= 0) or (z == 0 and x ~=0) then
156 local nodename = minetest.get_node(vector.new(pos.x+x,pos.y+y,pos.z+z)).name
157 local level2 = minetest.get_node_level(vector.new(pos.x+x,pos.y+y,pos.z+z))
158 if (level2 < level and nodename == "main:waterflow") or (nodename == "main:water" and level2 == 7) then
167 --only add velocity if there is one
168 --else this stops the boat
169 if goalx ~= 0 or goalz ~= 0 then
170 local acceleration = vector.new(goalx-currentvel.x,0,goalz-currentvel.z)
171 acceleration = vector.multiply(acceleration, 0.01)
172 self.object:add_velocity(acceleration)
178 --slows the boat down
179 slowdown = function(self)
180 if not self.moving == true then
181 local vel = self.object:getvelocity()
182 local deceleration = vector.multiply(vel, -0.01)
183 self.object:add_velocity(deceleration)
187 on_step = function(self, dtime)
188 self.check_if_on_land(self)
197 minetest.register_craftitem("boat:boat", {
198 description = "Boat",
199 inventory_image = "boatitem.png",
200 wield_image = "boatitem.png",
201 liquids_pointable = true,
202 on_place = function(itemstack, placer, pointed_thing)
203 if not pointed_thing.type == "node" then
207 local sneak = placer:get_player_control().sneak
208 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
209 if not sneak and noddef.on_rightclick then
210 minetest.item_place(itemstack, placer, pointed_thing)
214 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "water")>0 then
215 minetest.add_entity(pointed_thing.under, "boat:boat")
220 itemstack:take_item()
226 minetest.register_craft({
227 output = "boat:boat",
229 {"main:wood", "", "main:wood"},
230 {"main:wood", "main:wood", "main:wood"},