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,
45 function minecart:on_rightclick(clicker)
46 if not clicker or not clicker:is_player() then
49 local player_name = clicker:get_player_name()
51 if self.rider and player_name == self.rider then
53 --carts:manage_attachment(clicker, nil)
54 elseif not self.rider then
55 self.rider = player_name
56 clicker:set_attach(self.object, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0})
57 --player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
58 --carts:manage_attachment(clicker, self.object)
60 -- player_api does not update the animation
61 -- when the player is attached, reset to default animation
63 --player_api.set_animation(clicker, "stand")
67 function minecart:on_activate(staticdata, dtime_s)
68 self.object:set_armor_groups({immortal=1})
69 if string.sub(staticdata, 1, string.len("return")) ~= "return" then
72 local data = minetest.deserialize(staticdata)
73 if type(data) ~= "table" then
76 self.railtype = data.railtype
78 self.old_dir = data.old_dir
82 function minecart:get_staticdata()
83 return minetest.serialize({
86 function minecart:on_punch(puncher, time_from_last_punch, tool_capabilities, dir, damage)
87 local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
88 obj:get_luaentity().collection_timer = 2
97 --repel from players on track "push"
98 function minecart:push(self)
99 local pos = self.object:getpos()
100 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
101 if object:is_player() and object:get_player_name() ~= self.rider then
102 local player_pos = object:getpos()
106 local vel = vector.subtract(pos, player_pos)
107 vel = vector.normalize(vel)
108 local distance = vector.distance(pos,player_pos)
110 distance = (1-distance)*10
112 vel = vector.multiply(vel,distance)
114 --only push if it's faster than current speed
115 if distance > self.speed then
116 self.object:setvelocity(vel)
117 self.speed = distance
123 function minecart:ride_rail(self)
124 local pos = vector.floor(vector.add(self.object:getpos(),0.5))
125 local speed = self.speed
126 if self.speed > 10 then
130 local vel = self.object:getvelocity()
131 local x = math.abs(vel.x)
132 local z = math.abs(vel.z)
135 local dir = {x=0,y=0,z=0}
140 if vel.x>0 then xdir=1 elseif vel.x<0 then xdir=-1 end
142 --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
145 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
151 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
157 elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
159 --print("forward inside")
161 if dir.y == 0 and self.object:getpos().y ~= pos.y then
162 --print("correcting y")
163 local posser = self.object:getpos()
164 self.object:moveto(vector.new(posser.x,pos.y,posser.z))
170 if vel.z>0 then zdir=1 elseif vel.z<0 then zdir=-1 end
172 --print(minetest.get_node(vector.new(pos.x,pos.y,pos.z)).name)
175 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
181 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
188 elseif is_rail(pos.x,pos.y,pos.z) then --currently on rail
190 --print("forward inside")
192 if dir.y == 0 and self.object:getpos().y ~= pos.y then
193 --print("correcting y")
194 local posser = self.object:getpos()
195 self.object:moveto(vector.new(posser.x,pos.y,posser.z))
204 if vel.x>0 then turnx=1 elseif vel.x<0 then turnx=-1 end
205 if vel.z>0 then turnz=1 elseif vel.z<0 then turnz=-1 end
208 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
211 if is_rail(pos.x,pos.y+y,pos.z+1) then
214 --recenter on the rail
215 self.object:moveto(pos)
216 elseif is_rail(pos.x,pos.y+y,pos.z-1) then
219 --recenter on the rail
220 self.object:moveto(pos)
225 if is_rail(pos.x+1,pos.y+y,pos.z) then
228 --recenter on the rail
229 self.object:moveto(pos)
230 elseif is_rail(pos.x-1,pos.y+y,pos.z) then
233 --recenter on the rail
234 self.object:moveto(pos)
241 --if not vector.equals(dir,vector.new(0,0,0)) then
242 self.object:setvelocity(dir)
244 self.oldpos=self.object:getpos()
246 --make the cart move up and down on hills
247 self.object:set_properties({mesh="minecart.obj"})
249 self.object:set_properties({mesh="minecart_down.obj"})
250 elseif vel.y > 0 then
251 self.object:set_properties({mesh="minecart_up.obj"})
255 if self.speed > 0 then
256 self.speed = self.speed - 0.01
258 if self.speed < 0 then
264 function minecart:on_step(dtime)
266 minecart:ride_rail(self)
269 minetest.register_entity("minecart:minecart", minecart)
272 minetest.register_craftitem("minecart:minecart", {
273 description = "Minecart",
274 inventory_image = "minecartitem.png",
275 wield_image = "minecartitem.png",
276 on_place = function(itemstack, placer, pointed_thing)
277 if not pointed_thing.type == "node" then
281 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
282 minetest.add_entity(pointed_thing.under, "minecart:minecart")
287 itemstack:take_item()
293 minetest.register_craft({
294 output = "minecart:minecart",
296 {"main:iron", "", "main:iron"},
297 {"main:iron", "main:iron", "main:iron"},