29 local function data_injection(pos,data)
31 pool[minetest.hash_node_position(pos)] = true
33 pool[minetest.hash_node_position(pos)] = nil
37 local function speed_limiter(self,speed)
38 local test = self.object:get_velocity()--vector.multiply(self.velocity,new_vel)
40 if test.x > speed then
42 elseif test.x < -speed then
45 if test.z > speed then
47 elseif test.z < -speed then
50 self.object:set_velocity(test)
53 local function create_axis(pos)
54 local possible_dirs = {}
55 for _,dir in pairs(dirs) do
56 local pos2 = vector.add(pos,dir)
57 if pool[minetest.hash_node_position(pos2)] then
58 table.insert(possible_dirs,dir)
64 local function collision_detect(self)
65 if not self.axis_lock then return end
66 local pos = self.object:get_pos()
67 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
68 if object:is_player() then
69 local pos2 = object:get_pos()
70 if self.axis_lock == "x" then
72 local velocity = (1-vector.distance(vector.new(pos.x,0,0),vector.new(pos2.x,0,0)))*5
73 local dir = vector.direction(vector.new(pos2.x,0,0),vector.new(pos.x,0,0))
74 local new_vel = vector.multiply(dir,velocity)
75 self.object:add_velocity(new_vel)
77 elseif self.axis_lock == "z" then
78 local velocity = (1-vector.distance(vector.new(0,0,pos.z),vector.new(0,0,pos2.z)))*5
79 local dir = vector.direction(vector.new(0,0,pos2.z),vector.new(0,0,pos.z))
80 local new_vel = vector.multiply(dir,velocity)
81 self.object:add_velocity(new_vel)
89 local function direction_snap(self)
92 if dir.y == 1 then pitch = math.pi/4 end
93 if dir.y == -1 then pitch = -math.pi/4 end
94 local yaw = minetest.dir_to_yaw(dir)
95 self.object:set_rotation(vector.new(pitch,yaw,0))
98 local function turn_snap(pos,self,dir,dir2)
99 if self.axis_lock == "x" then
100 if dir.x ~= 0 and dir2.z ~= 0 then
101 local velocity = self.object:get_velocity()
102 local inertia = math.abs(velocity.x)
103 self.object:set_velocity(vector.multiply(dir2,inertia))
106 self.object:set_pos(pos)
111 if self.axis_lock == "z" then
112 if dir.z ~= 0 and dir2.x ~= 0 then
113 local velocity = self.object:get_velocity()
114 local inertia = math.abs(velocity.z)
115 self.object:set_velocity(vector.multiply(dir2,inertia))
118 self.object:set_pos(pos)
126 local function climb_snap(pos,self,dir,dir2)
127 if self.axis_lock == "x" then
128 if dir.x == dir2.x and dir2.y ~= 0 then
129 local velocity = self.object:get_velocity()
130 local inertia = math.abs(velocity.x)
131 self.object:set_velocity(vector.multiply(dir2,inertia))
134 self.object:set_pos(pos)
139 if self.axis_lock == "z" then
140 if dir.z == dir2.z and dir2.y ~= 0 then
141 local velocity = self.object:get_velocity()
142 local inertia = math.abs(velocity.z)
143 self.object:set_velocity(vector.multiply(dir2,inertia))
146 self.object:set_pos(pos)
154 local function straight_snap(pos,self,dir)
155 if self.axis_lock == "x" then
156 if dir.x ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(dir.x,0,0)))] then
157 local velocity = self.object:get_velocity()
158 self.object:set_velocity(vector.new(velocity.x,0,0))
159 self.dir = vector.new(dir.x,0,0)
161 self.object:set_pos(pos)
166 if self.axis_lock == "z" then
167 if dir.z ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(0,0,dir.z)))] then
168 local velocity = self.object:get_velocity()
169 self.object:set_velocity(vector.new(0,0,velocity.z))
170 self.dir = vector.new(0,0,dir.z)
172 self.object:set_pos(pos)
181 local function coupling_logic(self)
183 if not self.axis_lock then return end
185 if not self.coupler1 then return end
187 if self.dir.y ~= 0 then return end
189 local pos = self.object:get_pos()
191 local pos2 = self.coupler1:get_pos()
193 if self.axis_lock == "x" then
194 local velocity_real = self.object:get_velocity()
195 local distance = vector.distance(pos,pos2)
196 local new_vel = vector.new(0,0,0)
197 if distance > 1.5 then
198 local velocity = (distance-1)
199 local dir = vector.direction(vector.new(pos.x,0,0),vector.new(pos2.x,0,0))
201 new_vel = vector.multiply(dir,velocity)
203 new_vel = vector.multiply(velocity_real,-1)
205 self.object:add_velocity(new_vel)
206 elseif self.axis_lock == "z" then
207 local velocity_real = self.object:get_velocity()
208 local distance = vector.distance(pos,pos2)
209 local new_vel = vector.new(0,0,0)
210 if distance > 1.5 then
211 local velocity = (distance-1)
212 local dir = vector.direction(vector.new(0,0,pos.z),vector.new(0,0,pos2.z))
214 new_vel = vector.multiply(dir,velocity)
216 new_vel = vector.multiply(velocity_real,-1)
218 self.object:add_velocity(new_vel)
225 local function rail_brain(self,pos)
228 if not self.dir then self.dir = vector.new(0,0,0) end
230 local pos2 = self.object:get_pos()
234 speed_limiter(self,6)
236 if not pool[minetest.hash_node_position(vector.add(pos,dir))] then
238 if straight_snap(pos,self,dir) then
242 local possible_dirs = create_axis(pos)
244 if table.getn(possible_dirs) == 0 then
245 --stop slow down become physical
247 for _,dir2 in pairs(possible_dirs) do
248 if turn_snap(pos,self,dir,dir2) then
251 if climb_snap(pos,self,dir,dir2) then
264 minecart.on_step = function(self,dtime)
265 local pos = vector.round(self.object:get_pos())
266 if not self.axis_lock then
267 local possible_dirs = create_axis(pos)
268 for _,dir in pairs(possible_dirs) do
274 elseif dir.z ~= 0 then
283 collision_detect(self)
287 minecart.on_rightclick = function(self,clicker)
288 local name = clicker:get_player_name()
289 if not pool[name] then
290 pool[name] = self.object
292 self.coupler1 = pool[name]
293 --pool[name]:get_luaentity().coupler1 = self.object
299 minecart.on_activate = function(self,staticdata, dtime_s)
300 self.object:set_armor_groups({immortal=1})
301 if string.sub(staticdata, 1, string.len("return")) ~= "return" then
304 local data = minetest.deserialize(staticdata)
305 if type(data) ~= "table" then
308 self.old_pos = self.object:get_pos()
309 self.velocity = vector.new(0,0,0)
312 minecart.get_staticdata = function(self)
313 return minetest.serialize({
319 minecart.initial_properties = {
320 physical = false, -- otherwise going uphill breaks
321 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},
324 visual_size = {x=1, y=1},
325 textures = {"minecart.png"},
329 minecart.on_punch = function(self,puncher, time_from_last_punch, tool_capabilities, dir, damage)
330 --local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
331 --self.object:remove()
336 minetest.register_entity("minecart:minecart", minecart)
349 minetest.register_craftitem("minecart:minecart", {
350 description = "Minecart",
351 inventory_image = "minecartitem.png",
352 wield_image = "minecartitem.png",
353 on_place = function(itemstack, placer, pointed_thing)
354 if not pointed_thing.type == "node" then
358 local sneak = placer:get_player_control().sneak
359 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
360 if not sneak and noddef.on_rightclick then
361 minetest.item_place(itemstack, placer, pointed_thing)
365 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
366 minetest.add_entity(pointed_thing.under, "minecart:minecart")
371 itemstack:take_item()
377 minetest.register_craft({
378 output = "minecart:minecart",
380 {"main:iron", "", "main:iron"},
381 {"main:iron", "main:iron", "main:iron"},
389 minetest.register_node("minecart:rail",{
390 description = "Rail",
391 wield_image = "rail.png",
393 "rail.png", "railcurve.png",
394 "railt.png", "railcross.png"
396 drawtype = "raillike",
398 sunlight_propagates = true,
399 is_ground_content = false,
401 node_placement_prediction = "",
404 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
406 sounds = main.stoneSound(),
407 after_place_node = function(pos)
408 data_injection(pos,true)
410 after_destruct = function(pos)
413 groups={stone=1,wood=1,rail=1,attached_node=1},
417 minetest.register_lbm({
418 name = "minecart:rail",
419 nodenames = {"minecart:rail"},
420 run_at_every_load = true,
421 action = function(pos)
422 data_injection(pos,true)
426 minetest.register_craft({
427 output = "minecart:rail 32",
429 {"main:iron","","main:iron"},
430 {"main:iron","main:stick","main:iron"},
431 {"main:iron","","main:iron"}