9 make player able to push cart
11 make carts push each other away --repel axis
13 make chest and furnace cart
16 minetest.dir_to_facedir(dir, is6d) - to get player direction converted and to convert the minecart direction
19 local path = minetest.get_modpath("minecart")
20 dofile(path.."/rail.lua")
24 local function is_rail(x,y,z)
25 return(minetest.get_node_group(minetest.get_node(vector.new(x,y,z)).name,"rail")>0)
29 initial_properties = {
30 physical = false, -- otherwise going uphill breaks
31 collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},--{-0.5, -0.4, -0.5, 0.5, 0.25, 0.5},
33 mesh = "minecart.obj",
34 visual_size = {x=1, y=1},
35 textures = {"minecart.png"},
36 automatic_face_movement_dir = 90.0,
37 automatic_face_movement_max_rotation_per_sec = 600,
46 function minecart:on_rightclick(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 --carts:manage_attachment(clicker, nil)
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")
68 function minecart:on_activate(staticdata, dtime_s)
69 self.object:set_armor_groups({immortal=1})
70 if string.sub(staticdata, 1, string.len("return")) ~= "return" then
73 local data = minetest.deserialize(staticdata)
74 if type(data) ~= "table" then
77 self.railtype = data.railtype
79 self.old_dir = data.old_dir
83 function minecart:get_staticdata()
84 return minetest.serialize({
87 function minecart:on_punch(puncher, time_from_last_punch, tool_capabilities, dir, damage)
88 local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
89 obj:get_luaentity().collection_timer = 2
98 --repel from players on track "push"
99 function minecart:push(self)
100 local pos = self.object:getpos()
101 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
102 if object:is_player() and object:get_player_name() ~= self.rider then
103 local player_pos = object:getpos()
107 local vel = vector.subtract(pos, player_pos)
108 vel = vector.normalize(vel)
109 local distance = vector.distance(pos,player_pos)
111 distance = (1-distance)*10
113 vel = vector.multiply(vel,distance)
115 --only push if it's faster than current speed
116 if distance > self.speed then
117 self.object:setvelocity(vel)
118 self.speed = distance
124 function minecart:ride_rail(self)
125 local pos = vector.floor(vector.add(self.object:getpos(),0.5))
126 local speed = self.speed
127 if self.speed > 10 then
131 local vel = self.object:getvelocity()
132 local x = math.abs(vel.x)
133 local z = math.abs(vel.z)
136 local dir = {x=0,y=0,z=0}
141 if vel.x>0 then xdir=1 elseif vel.x<0 then xdir=-1 end
143 --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
146 if is_rail(pos.x+xdir,pos.y+1,pos.z) or (not is_rail(pos.x,pos.y,pos.z) and is_rail(pos.x+xdir,pos.y,pos.z)) then
152 elseif (is_rail(pos.x,pos.y-1,pos.z) or vel.y < 0) and not is_rail(pos.x+xdir,pos.y,pos.z) then
158 elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
160 --print("forward inside")
162 if dir.y == 0 and self.object:getpos().y ~= pos.y then
163 --print("correcting y")
164 local posser = self.object:getpos()
165 self.object:moveto(vector.new(posser.x,pos.y,posser.z))
171 if vel.z>0 then zdir=1 elseif vel.z<0 then zdir=-1 end
173 --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
176 if is_rail(pos.x,pos.y+1,pos.z+zdir) or (not is_rail(pos.x,pos.y,pos.z) and is_rail(pos.x,pos.y,pos.z+zdir)) then
182 elseif (is_rail(pos.x,pos.y-1,pos.z) or vel.y < 0) and not is_rail(pos.x,pos.y,pos.z+zdir) then
189 elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
191 --print("forward inside")
193 if dir.y == 0 and self.object:getpos().y ~= pos.y then
194 --print("correcting y")
195 local posser = self.object:getpos()
196 self.object:moveto(vector.new(posser.x,pos.y,posser.z))
205 if vel.x>0 then turnx=1 elseif vel.x<0 then turnx=-1 end
206 if vel.z>0 then turnz=1 elseif vel.z<0 then turnz=-1 end
209 if turnx and turnz and dir.y == 0 and not vector.equals(dir, vector.new(0,0,0)) and not is_rail(pos.x+turnx,pos.y-1,pos.z+turnz) and not is_rail(pos.x+turnx,pos.y,pos.z+turnz) and not is_rail(pos.x+turnx,pos.y+1,pos.z+turnz) then
212 if is_rail(pos.x,pos.y+y,pos.z+1) then
215 --recenter on the rail
216 self.object:moveto(pos)
217 elseif is_rail(pos.x,pos.y+y,pos.z-1) then
220 --recenter on the rail
221 self.object:moveto(pos)
226 if is_rail(pos.x+1,pos.y+y,pos.z) then
229 --recenter on the rail
230 self.object:moveto(pos)
231 elseif is_rail(pos.x-1,pos.y+y,pos.z) then
234 --recenter on the rail
235 self.object:moveto(pos)
242 --if not vector.equals(dir,vector.new(0,0,0)) then
243 self.object:setvelocity(dir)
245 self.oldpos=self.object:getpos()
247 --make the cart move up and down on hills
248 self.object:set_properties({mesh="minecart.obj"})
250 self.object:set_properties({mesh="minecart_down.obj"})
251 elseif vel.y > 0 then
252 self.object:set_properties({mesh="minecart_up.obj"})
256 if self.speed > 0 then
257 self.speed = self.speed - 0.01
259 if self.speed < 0 then
265 function minecart:on_step(dtime)
267 minecart:ride_rail(self)
270 minetest.register_entity("minecart:minecart", minecart)
273 minetest.register_craftitem("minecart:minecart", {
274 description = "Minecart",
275 inventory_image = "minecartitem.png",
276 wield_image = "minecartitem.png",
277 on_place = function(itemstack, placer, pointed_thing)
278 if not pointed_thing.type == "node" then
282 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
283 minetest.add_entity(pointed_thing.under, "minecart:minecart")
288 itemstack:take_item()
294 minetest.register_craft({
295 output = "minecart:minecart",
297 {"main:iron", "", "main:iron"},
298 {"main:iron", "main:iron", "main:iron"},