]> git.lizzy.rs Git - Crafter.git/blobdiff - mods/minecart/init.lua
Add in prototype furnace engine
[Crafter.git] / mods / minecart / init.lua
index b7a5ec13d1db812474924588b7690f7523e64112..670fce60ac07766f03495e5b3823adbe48ad4a7b 100644 (file)
-local path = minetest.get_modpath("minecart")
-dofile(path.."/rail.lua")
+local pool = {}
 
+local player_pool = {}
 
---get if rail
-local function rail(pos)
-      return(minetest.get_node_group(minetest.get_node(pos).name,"rail")>0)
+
+local dirs = {
+       {x= 1,y= 0,z= 0},
+       {x=-1,y= 0,z= 0},
+
+       {x= 1,y= 1,z= 0}, 
+       {x=-1,y= 1,z= 0},
+
+       {x= 1,y=-1,z= 0},
+       {x=-1,y=-1,z= 0},
+
+       {x= 0,y= 0,z= 1},
+       {x= 0,y= 0,z=-1},
+
+       {x= 0,y= 1,z= 1},
+       {x= 0,y= 1,z=-1},
+
+       {x= 0,y=-1,z= 1},
+       {x= 0,y=-1,z=-1},
+}
+
+local function coupling_particles(pos,truth)
+       local color = "red"
+       if truth then
+               color = "green"
+       end
+
+       minetest.add_particlespawner({
+               amount = 15,
+               time = 0.001,
+               minpos = pos,
+               maxpos = pos,
+               minvel = vector.new(-10,-10,-10),
+               maxvel = vector.new(10,10,10),
+               minacc = {x=0, y=0, z=0},
+               maxacc = {x=0, y=0, z=0},
+               minexptime = 1.1,
+               maxexptime = 1.5,
+               minsize = 1,
+               maxsize = 2,
+               collisiondetection = false,
+               collision_removal = false,
+               vertical = false,
+               texture = "couple_particle.png^[colorize:"..color..":200",
+               glow = 14,
+       })
+end
+
+local function data_injection(pos,data)
+       if data then
+               pool[minetest.hash_node_position(pos)] = true
+       else
+               pool[minetest.hash_node_position(pos)] = nil
+       end
 end
 
---check if on rail
-local function on_rail(self,pos)
-      if not rail(pos) and not self.slope then
-            self.axis = nil
-            return(false)
-      else
-            return(true)
-      end
+local function speed_limiter(self,speed)
+       local test = self.object:get_velocity()--vector.multiply(self.velocity,new_vel)
+
+       if test.x > speed then
+               test.x = speed
+       elseif test.x < -speed then
+               test.x = -speed
+       end
+       if test.z > speed then
+               test.z = speed
+       elseif test.z < -speed then
+               test.z = -speed         
+       end
+       self.object:set_velocity(test)
 end
 
---set physical state
-local function physical(self,pos)
-      if on_rail(self,pos) then
-            self.object:set_properties({physical = false})
-            self.object:setacceleration(vector.new(0,0,0))
-      elseif not self.slope then
-            self.object:set_properties({physical = true})
-            self.object:setacceleration(vector.new(0,-9.81,0))
-      end
+local function create_axis(pos)
+       local possible_dirs = {}
+       for _,dir in pairs(dirs) do
+               local pos2 = vector.add(pos,dir)
+               if pool[minetest.hash_node_position(pos2)] then
+                       table.insert(possible_dirs,dir)
+               end
+       end
+       return(possible_dirs)
 end
 
---get if node in minecarts direction
-local function node_ahead(self,pos)
-      local vel = self.object:getvelocity()
-      local dir = vector.normalize(vel)
-      return(rail(vector.add(pos,dir)))
+local function collision_detect(self)
+       if not self.axis_lock then return end
+       local pos = self.object:get_pos()
+       for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
+               if object:is_player() then
+                       local pos2 = object:get_pos()
+                       if self.axis_lock == "x" then
+
+                               local velocity = (1-vector.distance(vector.new(pos.x,0,0),vector.new(pos2.x,0,0)))*5
+                               local dir = vector.direction(vector.new(pos2.x,0,0),vector.new(pos.x,0,0))
+                               local new_vel = vector.multiply(dir,velocity)
+                               self.object:add_velocity(new_vel)
+                               self.dir = dir
+                       elseif self.axis_lock == "z" then
+                               local velocity = (1-vector.distance(vector.new(0,0,pos.z),vector.new(0,0,pos2.z)))*5
+                               local dir = vector.direction(vector.new(0,0,pos2.z),vector.new(0,0,pos.z))
+                               local new_vel = vector.multiply(dir,velocity)
+                               self.object:add_velocity(new_vel)
+                               self.dir = dir
+                       end
+                       return
+               end
+       end
 end
 
---get current axis (prefers x)
-local function axis(pos)
-      if rail(pos) then
-            if rail(vector.new(pos.x-1,pos.y,pos.z)) or rail(vector.new(pos.x+1,pos.y,pos.z)) then return("x") end
-            if rail(vector.new(pos.x,pos.y,pos.z-1)) or rail(vector.new(pos.x,pos.y,pos.z+1)) then return("z") end
-      end
+local function direction_snap(self)
+       local dir = self.dir
+       local pitch = 0
+       if dir.y == 1 then pitch = math.pi/4 end
+       if dir.y == -1 then pitch = -math.pi/4 end
+       local yaw = minetest.dir_to_yaw(dir)
+       self.object:set_rotation(vector.new(pitch,yaw,0))
 end
 
---snap object to rail
-local function snap_rail(self,pos)
-      local slopy = self.slope
-      if not slopy then print("the slope is nil") else
-            print("the slope is ".. slopy)
-      end
-      local railpos = vector.floor(vector.add(pos, 0.5))
-      local vel = self.object:getvelocity()
-      if self.axis == "x" and pos.x ~= railpos.x then
-            self.object:moveto(vector.new(pos.x,railpos.y,railpos.z))
-            self.object:setvelocity(vector.new(vel.x,0,0))
-            print("snapped to x")
-            return
-      end
-      if self.axis == "z" and pos.z ~= railpos.z then
-            self.object:moveto(vector.new(railpos.x,railpos.y,pos.z))
-            self.object:setvelocity(vector.new(0,0,vel.z))
-            print("snapped to z")
-            return
-      end
+local function turn_snap(pos,self,dir,dir2)
+       if self.axis_lock == "x" then
+               if dir.x ~= 0 and dir2.z ~= 0 then
+                       local velocity = self.object:get_velocity()
+                       local inertia = math.abs(velocity.x)
+                       self.object:set_velocity(vector.multiply(dir2,inertia))
+                       self.dir = dir2
+                       self.axis_lock = "z"
+                       self.object:set_pos(pos)
+                       direction_snap(self)
+                       return(true)
+               end
+       end
+       if self.axis_lock == "z" then
+               if dir.z ~= 0 and dir2.x ~= 0 then
+                       local velocity = self.object:get_velocity()
+                       local inertia = math.abs(velocity.z)
+                       self.object:set_velocity(vector.multiply(dir2,inertia))
+                       self.dir = dir2
+                       self.axis_lock = "x"
+                       self.object:set_pos(pos)
+                       direction_snap(self)
+                       return(true)
+               end
+       end
+       return(false)
 end
 
---check if entering new position
-local function newnode(self,pos)
-      local pos = vector.floor(vector.add(pos,0.5))
-      
-      pos.y = 0
-      
-      local equals = false
-      
-      
-      if self.oldpos then
-            equals = vector.equals(pos,self.oldpos)
-      end
-      
-      self.oldpos = pos
-      return(not equals)
+local function climb_snap(pos,self,dir,dir2)
+       if self.axis_lock == "x" then
+               if dir.x == dir2.x and dir2.y ~= 0 then
+                       local velocity = self.object:get_velocity()
+                       local inertia = math.abs(velocity.x)
+                       self.object:set_velocity(vector.multiply(dir2,inertia))
+                       self.dir = dir2
+                       self.axis_lock = "x"
+                       self.object:set_pos(pos)
+                       direction_snap(self)
+                       return(true)
+               end
+       end
+       if self.axis_lock == "z" then
+               if dir.z == dir2.z and dir2.y ~= 0 then
+                       local velocity = self.object:get_velocity()
+                       local inertia = math.abs(velocity.z)
+                       self.object:set_velocity(vector.multiply(dir2,inertia))
+                       self.dir = dir2
+                       self.axis_lock = "z"
+                       self.object:set_pos(pos)
+                       direction_snap(self)
+                       return(true)
+               end
+       end
+       return(false)
 end
 
---check if past center - used for turning
-local function pastcenter(self,pos)
-      
-      local center = vector.floor(vector.add(pos,0.5))
-      center.y = 0
-      local pos2d = vector.new(pos.x,0,pos.z)
-      
-      local vel = self.object:getvelocity()
-      local dir = vector.normalize(vel)
-      dir.y = 0
-      local checker = vector.round(vector.normalize(vector.subtract(pos2d,center)))
-      checker.y = 0
-      local past = vector.equals(checker, dir)
-      return(past)
+local function straight_snap(pos,self,dir)
+       if self.axis_lock == "x" then
+               if dir.x ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(dir.x,0,0)))] then
+                       local velocity = self.object:get_velocity()
+                       self.object:set_velocity(vector.new(velocity.x,0,0))
+                       self.dir = vector.new(dir.x,0,0)
+                       self.axis_lock = "x"
+                       self.object:set_pos(pos)
+                       direction_snap(self)
+                       return(true)
+               end
+       end
+       if self.axis_lock == "z" then
+               if dir.z ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(0,0,dir.z)))] then
+                       local velocity = self.object:get_velocity()
+                       self.object:set_velocity(vector.new(0,0,velocity.z))
+                       self.dir = vector.new(0,0,dir.z)
+                       self.axis_lock = "z"
+                       self.object:set_pos(pos)
+                       direction_snap(self)
+                       return(true)
+               end
+       end
+       return(false)
 end
 
---check if node ahead
-local function node_forward(self,pos)
-      local vel = self.object:getvelocity()
-      local dir = vector.normalize(vel)
-      return(rail(vector.add(pos,dir)))
+
+local function coupling_logic(self)
+       
+       if not self.axis_lock then return end
+
+       if not self.coupler1 then return end
+
+       if self.dir.y ~= 0 then return end
+
+       local pos = self.object:get_pos()
+       
+       local pos2 = self.coupler1:get_pos()
+
+       if self.axis_lock == "x" then
+               local velocity_real = self.object:get_velocity()
+               local distance = vector.distance(pos,pos2)
+               local new_vel = vector.new(0,0,0)
+               if distance > 1.5 then
+                       local velocity = (distance-1)
+                       local dir = vector.direction(vector.new(pos.x,0,0),vector.new(pos2.x,0,0))
+                       self.dir = dir
+                       new_vel = vector.multiply(dir,velocity)
+               else
+                       new_vel = vector.multiply(velocity_real,-1)
+               end
+               self.object:add_velocity(new_vel)
+       elseif self.axis_lock == "z" then
+               local velocity_real = self.object:get_velocity()
+               local distance = vector.distance(pos,pos2)
+               local new_vel = vector.new(0,0,0)
+               if distance > 1.5 then
+                       local velocity = (distance-1)
+                       local dir = vector.direction(vector.new(0,0,pos.z),vector.new(0,0,pos2.z))
+                       self.dir = dir
+                       new_vel = vector.multiply(dir,velocity)
+               else
+                       new_vel = vector.multiply(velocity_real,-1)
+               end
+               self.object:add_velocity(new_vel)
+       end
+
+       return
 end
 
---check if node above or below
-local function check_hill(self,pos)
-      local vel = self.object:getvelocity()
-      local dirup = vector.normalize(vel)
-      
-      dirup.y = dirup.y + 1
-      
-      print(dump(dirup))
-      
-      minetest.add_particlespawner({
-            amount = 5,
-            time = 0,
-            minpos = vector.add(pos,dirup),
-            maxpos = vector.add(pos,dirup),
-            minvel = vector.new(0,0,0),
-            maxvel = vector.new(0,0,0),
-            minacc = {x=0, y=0, z=0},
-            maxacc = {x=0, y=0, z=0},
-            minexptime = 5,
-            maxexptime = 5,
-            minsize = 1,
-            maxsize = 1,
-            attached = player,
-            collisiondetection = true,
-            vertical = false,
-            texture = "treecapitator.png"
-      })
-      
-      local dirdown = vector.new(0,-0.5,0)
-      
-      if rail(vector.add(pos,dirup)) then
-            self.slope = "up"
-            return("up")
-      elseif rail(vector.add(pos,dirdown)) then
-            self.slope = "down"
-            return("down")
-      else
-            self.slope = nil
-            return(nil)
-      end
+
+local function rail_brain(self,pos)
+
+
+       if not self.dir then self.dir = vector.new(0,0,0) end
+
+       local pos2 = self.object:get_pos()
+
+       local dir = self.dir
+
+       speed_limiter(self,6)
+
+       if not pool[minetest.hash_node_position(vector.add(pos,dir))] then
+
+               if straight_snap(pos,self,dir) then
+                       return
+               end
+
+               local possible_dirs = create_axis(pos)
+
+               if table.getn(possible_dirs) == 0 then
+                       --stop slow down become physical
+               else
+                       for _,dir2 in pairs(possible_dirs) do
+                               if turn_snap(pos,self,dir,dir2) then
+                                       return
+                               end
+                               if climb_snap(pos,self,dir,dir2) then
+                                       return
+                               end
+                       end
+               end
+       else
+               coupling_logic(self)
+       end
+
 end
 
-local function gravity(self,pos)
-      
-      if self.slope == up then
-            local vel = vector.multiply(self.object:getvelocity(), 0.95)
-            self.object:set_velocity(vel)
-      end
-      if self.slope == up then
-            local vel = vector.multiply(self.object:getvelocity(), 1.05)
-            self.object:set_velocity(vel)
-      end
+local minecart = {}
 
+minecart.on_step = function(self,dtime)
+       local pos = vector.round(self.object:get_pos())
+       if not self.axis_lock then
+               local possible_dirs = create_axis(pos)
+               for _,dir in pairs(possible_dirs) do
+                       if dir.x ~=0 then
+                               self.axis_lock = "x"
+                               self.dir = dir
+                               direction_snap(self)
+                               break
+                       elseif dir.z ~= 0 then
+                               self.axis_lock = "z"
+                               self.dir = dir
+                               direction_snap(self)
+                               break
+                       end
+               end
+       else
+               rail_brain(self,pos)
+               --collision_detect(self)
+       end
 end
 
---make the minecart go up and down hills
-local function navigate_hill(self)
-      if self.slope then
-            local vel = self.object:getvelocity()
-            if self.slope == "up" then
-            
-                  local yvel = 0
-                  if self.axis == "x" then
-                        yvel = math.abs(vel.x)*1.1
-                  end
-                  if self.axis == "z" then
-                        yvel = math.abs(vel.z)*1.1
-                  end
-                  self.object:setvelocity(vector.new(vel.x,yvel,vel.z))
-            elseif self.slope == "down" then
-            
-                  local yvel = 0
-                  if self.axis == "x" then
-                        yvel = math.abs(vel.x)*-1
-                  end
-                  if self.axis == "z" then
-                        yvel = math.abs(vel.z)*-1
-                  end
-                  
-                  self.object:setvelocity(vector.new(vel.x,yvel,vel.z))
-            end
-      end
+
+minecart.on_punch = function(self, puncher)
+       if not puncher:get_wielded_item():get_name() == "minecart:wrench" then
+               return
+       end
+       if self.furnace then
+               self.object:set_velocity(vector.multiply(self.dir,6))
+               minetest.add_particlespawner({
+                       amount = 30,
+                       time = 0,
+                       minpos = vector.new(0,0.5,0),
+                       maxpos = vector.new(0,0.5,0),
+                       minvel = vector.new(0,0,0),
+                       maxvel = vector.new(0,0,0),
+                       minacc = {x=0, y=3, z=0},
+                       maxacc = {x=0, y=5, z=0},
+                       minexptime = 1.1,
+                       maxexptime = 1.5,
+                       minsize = 1,
+                       maxsize = 2,
+                       collisiondetection = false,
+                       collision_removal = false,
+                       vertical = false,
+                       texture = "smoke.png",
+                       attached = self.object
+               })
+       end
+
 end
 
---swap axis and speed 90 degrees
-local function turn_check(self,pos)
-      local axis = self.axis
-      local vel = self.object:getvelocity()
-      vel.x = math.abs(vel.x)
-      vel.y = math.abs(vel.y)
-      vel.z = math.abs(vel.z)
-      
-      if axis == "x" then
-            if rail(vector.new(pos.x,pos.y,pos.z-1)) then
-                  print("-x")
-                  self.object:setvelocity(vector.new(0,0,vel.x*-1))
-                  self.axis = "z"
-                  snap_rail(self,pos)
-                  self.turn_timer = 0
-                  return
-            elseif rail(vector.new(pos.x,pos.y,pos.z+1)) then 
-                  print("+x")
-                  self.object:setvelocity(vector.new(0,0,vel.x))
-                  self.axis = "z"
-                  snap_rail(self,pos)
-                  self.turn_timer = 0
-                  return
-            end
-      end
-      if axis == "z" then
-            if rail(vector.new(pos.x-1,pos.y,pos.z)) then
-                  print("-z")
-                  self.object:setvelocity(vector.new(vel.z*-1,0,0))
-                  self.axis = "x"
-                  snap_rail(self,pos)
-                  self.turn_timer = 0
-                  return
-            elseif rail(vector.new(pos.x+1,pos.y,pos.z)) then 
-                  print("+z")
-                  self.object:setvelocity(vector.new(vel.z,0,0))
-                  self.axis = "x"
-                  snap_rail(self,pos)
-                  self.turn_timer = 0
-                  return
-            end
-      end
+
+minecart.on_rightclick = function(self,clicker)
+       local pos = self.object:get_pos()
+       if clicker:get_wielded_item():get_name() == "utility:furnace" then
+               local obj = minetest.add_entity(pos, "minecart:furnace")
+               obj:set_attach(self.object,"",vector.new(0,0,0),vector.new(0,0,0))
+               minetest.sound_play("wrench",{
+                       object = self.object,
+                       gain = 1.0,
+                       max_hear_distance = 64,
+               })
+               coupling_particles(pos,true)
+               self.furnace = true
+               return
+       end
+
+       if not clicker:get_wielded_item():get_name() == "minecart:wrench" then
+               return
+       end
+
+       local name = clicker:get_player_name()
+       if not pool[name] then
+               if not self.coupler2 then
+                       pool[name] = self.object
+                       minetest.sound_play("wrench",{
+                               object = self.object,
+                               gain = 1.0,
+                               max_hear_distance = 64,
+                       })
+                       coupling_particles(pos,true)
+               else
+                       minetest.sound_play("wrench",{
+                               object = self.object,
+                               gain = 1.0,
+                               max_hear_distance = 64,
+                               pitch = 0.7,
+                       })
+                       coupling_particles(pos,false)
+               end
+       else
+               if not (pool[name]:get_luaentity().coupler1 and pool[name]:get_luaentity().coupler1 == self.object or self.coupler2) then
+                       self.coupler1 = pool[name]
+                       pool[name]:get_luaentity().coupler2 = self.object
+                       minetest.sound_play("wrench",{
+                               object = self.object,
+                               gain = 1.0,
+                               max_hear_distance = 64,
+                       })
+                       coupling_particles(pos,true)
+               else
+                       minetest.sound_play("wrench",{
+                               object = self.object,
+                               gain = 1.0,
+                               max_hear_distance = 64,
+                               pitch = 0.7,
+                       })
+                       coupling_particles(pos,false)
+               end
+               pool[name] = nil
+       end
 end
---try to turn
-local function turn(self,pos)
-      if pastcenter(self,pos) then
-            if not node_forward(self,pos) and self.axis then
-                  turn_check(self,pos)
-            end
-      end
+
+--get old data
+minecart.on_activate = function(self,staticdata, dtime_s)
+       self.object:set_armor_groups({immortal=1})
+       if string.sub(staticdata, 1, string.len("return")) ~= "return" then
+               return
+       end
+       local data = minetest.deserialize(staticdata)
+       if type(data) ~= "table" then
+               return
+       end
+       self.old_pos = self.object:get_pos()
+       self.velocity = vector.new(0,0,0)
 end
 
---the main mechanics of the minecart
-local function minecart_brain(self,dtime)
-      if self.turn_timer < 5 then
-            self.turn_timer = self.turn_timer + dtime
-      end
-      local pos = self.object:getpos()
-      pos.y = pos.y - 0.5
-
-      
-      if not self.axis then
-            self.axis = axis(pos)
-      end
-      
-      if newnode(self,pos) then
-            snap_rail(self,pos)
-      end
-      --check_hill(self,pos)
-      --navigate_hill(self)
-
-      
-      turn(self,pos)
-      
-      on_rail(self,pos)
-      physical(self,pos)
-      --print(self.axis)
-      
-      --check if falling and then fall at the same speed to go down
+minecart.get_staticdata = function(self)
+       return minetest.serialize({
+       })
 end
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-      
-
-minetest.register_entity("minecart:minecart", {
-      initial_properties = {
-            physical = true, -- otherwise going uphill breaks
-            collisionbox = {-0.4, -0.5, -0.4, 0.4, 0.45, 0.4},--{-0.5, -0.4, -0.5, 0.5, 0.25, 0.5},
-            visual = "mesh",
-            mesh = "minecart.obj",
-            visual_size = {x=1, y=1},
-            textures = {"minecart.png"},
-            automatic_face_movement_dir = 90.0,
-            automatic_face_movement_max_rotation_per_sec = 600,
-      },
-
-      rider = nil,
-      punched = false,
-      speed = 0,
-      turn_timer = 0,
-      incline = nil,
-      turn_timer = 5,
-
-      on_rightclick = function(self,clicker)
-            if not clicker or not clicker:is_player() then
-                  return
-            end
-            local player_name = clicker:get_player_name()
-            
-            if self.rider and player_name == self.rider then
-                  self.rider = nil
-                  --carts:manage_attachment(clicker, nil)
-            elseif not self.rider then
-                  self.rider = player_name
-                  clicker:set_attach(self.object, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0})
-                  --player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
-                  --carts:manage_attachment(clicker, self.object)
-
-                  -- player_api does not update the animation
-                  -- when the player is attached, reset to default animation
-                  
-                  --player_api.set_animation(clicker, "stand")
-            end
-      end,
-      
-      on_activate = function(self,staticdata, dtime_s)
-            self.object:set_armor_groups({immortal=1})
-            if string.sub(staticdata, 1, string.len("return")) ~= "return" then
-                  return
-            end
-            local data = minetest.deserialize(staticdata)
-            if type(data) ~= "table" then
-                  return
-            end
-            self.railtype = data.railtype
-            if data.old_dir then
-                  self.old_dir = data.old_dir
-            end
-      end,
-
-      get_staticdata = function(self)
-            return minetest.serialize({
-            })
-      end,
-      
-      on_punch = function(self,puncher, time_from_last_punch, tool_capabilities, dir, damage)
-            local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
-            self.object:remove()
-      end,
-
-      --repel from players on track "push"
-      push = function(self)
-            if self.turn_timer > 0.3 then
-                  local pos = self.object:getpos()
-                  local radius = 1.2
-                  for _,object in ipairs(minetest.get_objects_inside_radius(pos, radius)) do
-                        if object:is_player() and object:get_player_name() ~= self.rider then
-                              local player_pos = object:getpos()
-                              pos.y = 0
-                              player_pos.y = 0
-                              
-                              local currentvel = self.object:getvelocity()
-                              local vel = vector.subtract(pos, player_pos)
-                              vel = vector.normalize(vel)
-                              local distance = vector.distance(pos,player_pos)
-                              distance = (radius-distance)*20
-                              vel = vector.multiply(vel,distance)
-                              local acceleration = vector.new(vel.x-currentvel.x,0,vel.z-currentvel.z)
-                              
-                              
-                              if self.axis == "x"      then
-                                    self.object:add_velocity(vector.new(acceleration.x,0,0))
-                              elseif self.axis == "z" then
-                                    self.object:add_velocity(vector.new(0,0,acceleration.z))
-                              else
-                                    self.object:add_velocity(acceleration)
-                              end
-                              
-                              acceleration = vector.multiply(acceleration, -0.5)
-                              object:add_player_velocity(acceleration)
-                        end
-                  end
-            end
-      end,
-
-      --slows the minecart down
-      slowdown = function(self)
-            if not self.moving == true then
-                  local vel = self.object:getvelocity()
-                  local deceleration = vector.multiply(vel, -0.01)
-                  self.object:add_velocity(deceleration)
-            end
-      end,
-
-      --mechanics to follow rails
-      ride_rail = function(self,dtime)
-            minecart_brain(self,dtime)
-      end,
-
-      on_step = function(self,dtime)
-            self.push(self)
-            self.slowdown(self)
-            self.ride_rail(self,dtime)
-      end,
-      
-})
+
+
+
+minecart.initial_properties = {
+       physical = false, -- otherwise going uphill breaks
+       collisionbox = {-0.4, -0.5, -0.4, 0.4, 0.45, 0.4},--{-0.5, -0.4, -0.5, 0.5, 0.25, 0.5},
+       visual = "mesh",
+       mesh = "minecart.x",
+       visual_size = {x=1, y=1},
+       textures = {"minecart.png"},
+}
+
+       
+
+minetest.register_entity("minecart:minecart", minecart)
+
+
+
+
+
+
+
+
+
+
+
 
 minetest.register_craftitem("minecart:minecart", {
-      description = "Minecart",
-      inventory_image = "minecartitem.png",
-      wield_image = "minecartitem.png",
-      on_place = function(itemstack, placer, pointed_thing)
-            if not pointed_thing.type == "node" then
-                  return
-            end
-            
-            if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
-                  minetest.add_entity(pointed_thing.under, "minecart:minecart")
-            else
-                  return
-            end
-
-            itemstack:take_item()
-
-            return itemstack
-      end,
+       description = "Minecart",
+       inventory_image = "minecartitem.png",
+       wield_image = "minecartitem.png",
+       on_place = function(itemstack, placer, pointed_thing)
+               if not pointed_thing.type == "node" then
+                       return
+               end
+               
+               local sneak = placer:get_player_control().sneak
+               local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
+               if not sneak and noddef.on_rightclick then
+                       minetest.item_place(itemstack, placer, pointed_thing)
+                       return
+               end
+               
+               if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
+                       minetest.add_entity(pointed_thing.under, "minecart:minecart")
+               else
+                       return
+               end
+
+               itemstack:take_item()
+
+               return itemstack
+       end,
 })
 
 minetest.register_craft({
-      output = "minecart:minecart",
-      recipe = {
-            {"main:iron", "", "main:iron"},
-            {"main:iron", "main:iron", "main:iron"},
-      },
+       output = "minecart:minecart",
+       recipe = {
+               {"main:iron", "", "main:iron"},
+               {"main:iron", "main:iron", "main:iron"},
+       },
+})
+
+
+
+
+
+minetest.register_node("minecart:rail",{
+       description = "Rail",
+       wield_image = "rail.png",
+       tiles = {
+               "rail.png", "railcurve.png",
+               "railt.png", "railcross.png"
+       },
+       drawtype = "raillike",
+       paramtype = "light",
+       sunlight_propagates = true,
+       is_ground_content = false,
+       walkable = false,
+       node_placement_prediction = "",
+       selection_box = {
+               type = "fixed",
+               fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
+       },
+       sounds = main.stoneSound(),
+       after_place_node = function(pos)
+               data_injection(pos,true)
+       end,
+       after_destruct = function(pos)
+               data_injection(pos)
+       end,
+       groups={stone=1,wood=1,rail=1,attached_node=1},
+})
+
+
+minetest.register_lbm({
+       name = "minecart:rail",
+       nodenames = {"minecart:rail"},
+       run_at_every_load = true,
+       action = function(pos)
+               data_injection(pos,true)
+       end,
+})
+
+minetest.register_craft({
+       output = "minecart:rail 32",
+       recipe = {
+               {"main:iron","","main:iron"},
+               {"main:iron","main:stick","main:iron"},
+               {"main:iron","","main:iron"}
+       }
+})
+
+
+minetest.register_food("minecart:wrench",{
+       description = "Train Wrench",
+       texture = "wrench.png",
+})
+
+minetest.register_craft({
+       output = "minecart:wrench",
+       recipe = {
+               {"main:iron", "", "main:iron"},
+               {"main:iron", "main:lapis", "main:iron"},
+               {"", "main:lapis", ""}
+       }
+})
+
+
+
+minetest.register_entity("minecart:furnace", {
+       initial_properties = {
+               visual = "wielditem",
+               visual_size = {x = 0.6, y = 0.6},
+               textures = {},
+               physical = true,
+               is_visible = false,
+               collide_with_objects = false,
+               pointable=false,
+               collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
+       },
+       set_node = function(self)
+               self.object:set_properties({
+                       is_visible = true,
+                       textures = {"utility:furnace"},
+               })
+       end,
+
+
+       on_activate = function(self, staticdata)
+               self.object:set_armor_groups({immortal = 1})
+
+               self:set_node()
+       end,
 })