5 goal - > go to goal - > check all this and repeat
8 minecart does check axis dir then -1 1 on opposite axis (x and z)
10 minecart checks in front and above
12 minecart checks in front and below
14 if in front above start moving up
16 if in front below start moving down
18 minecart checks if rail in front then if not check sides and if none then stop
20 if a rail in front of minecart then when past center of node center, turn towards the available rail and then recenter self onto rail on the new axis
28 local path = minetest.get_modpath("minecart")
29 dofile(path.."/rail.lua")
33 local function is_rail(x,y,z)
34 return(minetest.get_node_group(minetest.get_node(vector.new(x,y,z)).name,"rail")>0)
38 initial_properties = {
39 physical = false, -- otherwise going uphill breaks
40 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},
42 mesh = "minecart.obj",
43 visual_size = {x=1, y=1},
44 textures = {"minecart.png"},
45 automatic_face_movement_dir = 90.0,
53 function minecart:on_rightclick(clicker)
54 if not clicker or not clicker:is_player() then
57 local player_name = clicker:get_player_name()
58 if self.rider and player_name == self.rider then
60 carts:manage_attachment(clicker, nil)
61 elseif not self.rider then
62 self.rider = player_name
63 carts:manage_attachment(clicker, self.object)
65 -- player_api does not update the animation
66 -- when the player is attached, reset to default animation
68 --player_api.set_animation(clicker, "stand")
72 function minecart:on_activate(staticdata, dtime_s)
73 self.object:set_armor_groups({immortal=1})
74 if string.sub(staticdata, 1, string.len("return")) ~= "return" then
77 local data = minetest.deserialize(staticdata)
78 if type(data) ~= "table" then
81 self.railtype = data.railtype
83 self.old_dir = data.old_dir
87 function minecart:get_staticdata()
88 return minetest.serialize({
91 function minecart:on_punch(puncher, time_from_last_punch, tool_capabilities, dir, damage)
100 --repel from players on track "push"
101 function minecart:push(self)
102 local pos = self.object:getpos()
103 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do
104 if object:is_player() then
105 local player_pos = object:getpos()
109 local vel = vector.subtract(pos, player_pos)
110 vel = vector.normalize(vel)
111 local distance = vector.distance(pos,player_pos)
113 distance = (2-distance)*3
115 vel = vector.multiply(vel,distance)
117 self.object:setvelocity(vel)
123 function minecart:ride_rail(self)
127 local pos = vector.floor(vector.add(self.object:getpos(),0.5))
128 local speed = 10 --change to the cart speed soon
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
210 if is_rail(pos.x,pos.y,pos.z+1) then
213 --recenter on the rail
214 self.object:moveto(pos)
215 elseif is_rail(pos.x,pos.y,pos.z-1) then
218 --recenter on the rail
219 self.object:moveto(pos)
222 if is_rail(pos.x+1,pos.y,pos.z) then
225 --recenter on the rail
226 self.object:moveto(pos)
227 elseif is_rail(pos.x-1,pos.y,pos.z) then
230 --recenter on the rail
231 self.object:moveto(pos)
237 --if not vector.equals(dir,vector.new(0,0,0)) then
238 self.object:setvelocity(dir)
240 self.oldpos=self.object:getpos()
243 self.object:set_properties({mesh="minecart.obj"})
245 self.object:set_properties({mesh="minecart_down.obj"})
246 elseif vel.y > 0 then
247 self.object:set_properties({mesh="minecart_up.obj"})
249 return(self.object:set_animation(anim, 1, 0))
254 function minecart:on_step(dtime)
256 minecart:ride_rail(self)
259 minetest.register_entity("minecart:minecart", minecart)
280 minetest.register_craftitem("minecart:minecart", {
281 description = "Minecart",
282 inventory_image = "minecartitem.png",
283 wield_image = "minecartitem.png",
284 on_place = function(itemstack, placer, pointed_thing)
285 if not pointed_thing.type == "node" then
289 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
290 minetest.add_entity(pointed_thing.under, "minecart:minecart")
295 itemstack:take_item()
301 minetest.register_craft({
302 output = "minecart:minecart",
304 {"main:iron", "", "main:iron"},
305 {"main:iron", "main:iron", "main:iron"},