29 local function data_injection(pos,data)
31 pool[minetest.hash_node_position(pos)] = true
33 pool[minetest.hash_node_position(pos)] = nil
38 local function create_axis(pos)
39 local possible_dirs = {}
40 for _,dir in pairs(dirs) do
41 local pos2 = vector.add(pos,dir)
42 if pool[minetest.hash_node_position(pos2)] then
43 table.insert(possible_dirs,dir)
49 local function collision_detect(self)
50 if not self.axis_lock then return end
51 local pos = self.object:get_pos()
52 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
53 if object:is_player() then
54 local pos2 = object:get_pos()
55 if self.axis_lock == "x" then
57 local velocity = (1-vector.distance(vector.new(pos.x,0,0),vector.new(pos2.x,0,0)))
58 local dir = vector.direction(vector.new(pos2.x,0,0),vector.new(pos.x,0,0))
59 local new_vel = vector.multiply(dir,velocity)
60 self.object:add_velocity(new_vel)
62 elseif self.axis_lock == "z" then
63 local velocity = (1-vector.distance(vector.new(0,0,pos.z),vector.new(0,0,pos2.z)))
64 local dir = vector.direction(vector.new(0,0,pos2.z),vector.new(0,0,pos.z))
65 local new_vel = vector.multiply(dir,velocity)
66 self.object:add_velocity(new_vel)
74 local function direction_snap(self)
77 if dir.y == 1 then pitch = math.pi/4 end
78 if dir.y == -1 then pitch = -math.pi/4 end
79 local yaw = minetest.dir_to_yaw(dir)
80 self.object:set_rotation(vector.new(pitch,yaw,0))
83 local function turn_snap(pos,self,dir,dir2)
84 if self.axis_lock == "x" then
85 if dir.x ~= 0 and dir2.z ~= 0 then
86 local velocity = self.object:get_velocity()
87 local inertia = math.abs(velocity.x)
88 self.object:set_velocity(vector.multiply(dir2,inertia))
91 self.object:set_pos(pos)
96 if self.axis_lock == "z" then
97 if dir.z ~= 0 and dir2.x ~= 0 then
98 local velocity = self.object:get_velocity()
99 local inertia = math.abs(velocity.z)
100 self.object:set_velocity(vector.multiply(dir2,inertia))
103 self.object:set_pos(pos)
111 local function climb_snap(pos,self,dir,dir2)
112 if self.axis_lock == "x" then
113 if dir.x == dir2.x and dir2.y ~= 0 then
114 local velocity = self.object:get_velocity()
115 local inertia = math.abs(velocity.x)
116 self.object:set_velocity(vector.multiply(dir2,inertia))
119 self.object:set_pos(pos)
124 if self.axis_lock == "z" then
125 if dir.z == dir2.z and dir2.y ~= 0 then
126 local velocity = self.object:get_velocity()
127 local inertia = math.abs(velocity.z)
128 self.object:set_velocity(vector.multiply(dir2,inertia))
131 self.object:set_pos(pos)
139 local function straight_snap(pos,self,dir)
140 if self.axis_lock == "x" then
141 if dir.x ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(dir.x,0,0)))] then
142 local velocity = self.object:get_velocity()
143 self.object:set_velocity(vector.new(velocity.x,0,0))
144 self.dir = vector.new(dir.x,0,0)
146 self.object:set_pos(pos)
151 if self.axis_lock == "z" then
152 if dir.z ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(0,0,dir.z)))] then
153 local velocity = self.object:get_velocity()
154 self.object:set_velocity(vector.new(0,0,velocity.z))
155 self.dir = vector.new(0,0,dir.z)
157 self.object:set_pos(pos)
165 local function rail_brain(self,pos)
166 if not self.dir then return end
168 --if self.dir then print(dump(self.dir)) end
170 local pos2 = self.object:get_pos()
174 local triggered = false
176 if dir.x < 0 and pos2.x < pos.x then
178 elseif dir.x > 0 and pos2.x > pos.x then
180 elseif dir.z < 0 and pos2.z < pos.z then
182 elseif dir.z > 0 and pos2.z > pos.z then
186 if triggered and not pool[minetest.hash_node_position(vector.add(pos,dir))] then
188 if straight_snap(pos,self,dir) then
192 local possible_dirs = create_axis(pos)
194 if table.getn(possible_dirs) == 0 then
195 --print("train fails")
196 --stop slow down become physical, something
198 for _,dir2 in pairs(possible_dirs) do
199 if climb_snap(pos,self,dir,dir2) then
204 for _,dir2 in pairs(possible_dirs) do
205 if turn_snap(pos,self,dir,dir2) then
214 local function coupling_logic(self)
216 if not self.axis_lock then return end
218 if not self.coupler1 then return end
220 if not self.dir.y == 0 then print("failing") return end
222 local pos = self.object:get_pos()
224 local pos2 = self.coupler1:get_pos()
226 if self.axis_lock == "x" then
227 --local velocity = self.object:get_velocity()
229 local distance = 1-vector.distance(pos,pos2)
231 local dir = vector.direction(vector.new(pos2.x,0,0),vector.new(pos.x,0,0))
233 local new_vel = vector.multiply(dir,distance)
234 self.object:add_velocity(new_vel)
237 elseif self.axis_lock == "z" then
238 local velocity = self.object:get_velocity()
239 local velocity = (1-vector.distance(pos,pos2))
240 local dir = vector.direction(vector.new(0,0,pos2.z),vector.new(0,0,pos.z))
241 local new_vel = vector.multiply(dir,velocity)
242 self.object:add_velocity(new_vel)
252 minecart.on_step = function(self,dtime)
253 local float_pos = self.object:get_pos()
254 local pos = vector.round(float_pos)
256 --if self.velocity then
257 --local new_vel = dtime*1000
258 local test = self.object:get_velocity()--vector.multiply(self.velocity,new_vel)
262 print("slowing down 1")
263 elseif test.x < -10 then
265 print("slowing down 2")
269 print("slowing down 3")
270 elseif test.z < -10 then
272 print("slowing down 4")
275 self.object:set_velocity(test)
276 --self.object:move_to(vector.add(float_pos,test))
279 if not self.axis_lock then
280 local possible_dirs = create_axis(pos)
281 for _,dir in pairs(possible_dirs) do
284 self.dir = vector.new(1,0,0)
285 --self.velocity = vector.new(0,0,0)
288 elseif dir.z ~= 0 then
290 self.dir = vector.new(0,0,1)
291 --self.velocity = vector.new(0,0,0)
298 collision_detect(self)
304 self.old_pos = float_pos
307 minecart.on_rightclick = function(self,clicker)
308 local name = clicker:get_player_name()
309 if not pool[name] then
310 pool[name] = self.object
312 self.coupler1 = pool[name]
313 --pool[name]:get_luaentity().coupler1 = self.object
320 minecart.on_activate = function(self,staticdata, dtime_s)
321 self.object:set_armor_groups({immortal=1})
322 if string.sub(staticdata, 1, string.len("return")) ~= "return" then
325 local data = minetest.deserialize(staticdata)
326 if type(data) ~= "table" then
329 self.old_pos = self.object:get_pos()
330 self.velocity = vector.new(0,0,0)
333 minecart.get_staticdata = function(self)
334 return minetest.serialize({
340 minecart.initial_properties = {
341 physical = false, -- otherwise going uphill breaks
342 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},
345 visual_size = {x=1, y=1},
346 textures = {"minecart.png"},
350 minecart.on_punch = function(self,puncher, time_from_last_punch, tool_capabilities, dir, damage)
351 --local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
352 --self.object:remove()
357 minetest.register_entity("minecart:minecart", minecart)
370 minetest.register_craftitem("minecart:minecart", {
371 description = "Minecart",
372 inventory_image = "minecartitem.png",
373 wield_image = "minecartitem.png",
374 on_place = function(itemstack, placer, pointed_thing)
375 if not pointed_thing.type == "node" then
379 local sneak = placer:get_player_control().sneak
380 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
381 if not sneak and noddef.on_rightclick then
382 minetest.item_place(itemstack, placer, pointed_thing)
386 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
387 minetest.add_entity(pointed_thing.under, "minecart:minecart")
392 itemstack:take_item()
398 minetest.register_craft({
399 output = "minecart:minecart",
401 {"main:iron", "", "main:iron"},
402 {"main:iron", "main:iron", "main:iron"},
410 minetest.register_node("minecart:rail",{
411 description = "Rail",
412 wield_image = "rail.png",
414 "rail.png", "railcurve.png",
415 "railt.png", "railcross.png"
417 drawtype = "raillike",
419 sunlight_propagates = true,
420 is_ground_content = false,
422 node_placement_prediction = "",
425 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
427 sounds = main.stoneSound(),
428 after_place_node = function(pos)
429 data_injection(pos,true)
431 after_destruct = function(pos)
434 groups={stone=1,wood=1,rail=1,attached_node=1},
438 minetest.register_lbm({
439 name = "minecart:rail",
440 nodenames = {"minecart:rail"},
441 run_at_every_load = true,
442 action = function(pos)
443 data_injection(pos,true)
444 --print("buildin dat cashay")
448 minetest.register_craft({
449 output = "minecart:rail 32",
451 {"main:iron","","main:iron"},
452 {"main:iron","main:stick","main:iron"},
453 {"main:iron","","main:iron"}