26 local function data_injection(pos,data)
28 pool[minetest.hash_node_position(pos)] = true
30 pool[minetest.hash_node_position(pos)] = nil
35 local function create_axis(pos)
36 local possible_dirs = {}
37 for _,dir in pairs(dirs) do
38 local pos2 = vector.add(pos,dir)
39 if pool[minetest.hash_node_position(pos2)] then
40 table.insert(possible_dirs,dir)
46 local function collision_detect(self)
47 if not self.axis_lock then return end
48 local pos = self.object:get_pos()
49 for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
50 if object:is_player() then
51 local pos2 = object:get_pos()
52 if self.axis_lock == "x" then
53 local velocity = (1-vector.distance(vector.new(pos.x,0,0),vector.new(pos2.x,0,0)))/50
54 local dir = vector.direction(vector.new(pos2.x,0,0),vector.new(pos.x,0,0))
55 local new_vel = vector.multiply(dir,velocity)
56 self.velocity = new_vel
58 elseif self.axis_lock == "z" then
59 local velocity = (1-vector.distance(vector.new(0,0,pos.z),vector.new(0,0,pos2.z)))/50
60 local dir = vector.direction(vector.new(0,0,pos2.z),vector.new(0,0,pos.z))
61 self.velocity = vector.multiply(dir,velocity)
69 local function direction_snap(self)
72 if dir.y == 1 then pitch = math.pi/4 end
73 if dir.y == -1 then pitch = -math.pi/4 end
74 local yaw = minetest.dir_to_yaw(dir)
75 self.object:set_rotation(vector.new(pitch,yaw,0))
78 local function turn_snap(pos,self,dir,dir2)
79 if self.axis_lock == "x" then
80 if dir.x ~= 0 and dir2.z ~= 0 then
81 local inertia = math.abs(self.velocity.x)
82 self.velocity = vector.multiply(dir2,inertia)
85 self.object:set_pos(pos)
90 if self.axis_lock == "z" then
91 if dir.z ~= 0 and dir2.x ~= 0 then
92 local inertia = math.abs(self.velocity.z)
93 self.velocity = vector.multiply(dir2,inertia)
96 self.object:set_pos(pos)
104 local function climb_snap(pos,self,dir,dir2)
105 if self.axis_lock == "x" then
106 if dir.x == dir2.x and dir2.y ~= 0 then
107 local inertia = math.abs(self.velocity.x)
108 self.velocity = vector.multiply(dir2,inertia)
111 self.object:set_pos(pos)
116 if self.axis_lock == "z" then
117 if dir.z == dir2.z and dir2.y ~= 0 then
118 local inertia = math.abs(self.velocity.z)
119 self.velocity = vector.multiply(dir2,inertia)
122 self.object:set_pos(pos)
130 local function straight_snap(pos,self,dir)
131 if self.axis_lock == "x" then
132 if dir.x ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(dir.x,0,0)))] then
133 self.velocity = vector.new(self.velocity.x,0,0)
134 self.dir = vector.new(dir.x,0,0)
136 self.object:set_pos(pos)
141 if self.axis_lock == "z" then
142 if dir.z ~= 0 and pool[minetest.hash_node_position(vector.add(pos,vector.new(0,0,dir.z)))] then
143 self.velocity = vector.new(0,0,self.velocity.z)
144 self.dir = vector.new(0,0,dir.z)
146 self.object:set_pos(pos)
154 local function rail_brain(self,pos)
155 if not self.dir then return end
157 --if self.dir then print(dump(self.dir)) end
159 local pos2 = self.object:get_pos()
163 local triggered = false
165 if dir.x < 0 and pos2.x < pos.x then
167 elseif dir.x > 0 and pos2.x > pos.x then
169 elseif dir.z < 0 and pos2.z < pos.z then
171 elseif dir.z > 0 and pos2.z > pos.z then
176 if triggered and not pool[minetest.hash_node_position(vector.add(pos,dir))] then
178 if straight_snap(pos,self,dir) then
183 local possible_dirs = create_axis(pos)
185 if table.getn(possible_dirs) == 0 then
186 --print("train fails")
187 --stop slow down become physical, something
189 for _,dir2 in pairs(possible_dirs) do
190 if climb_snap(pos,self,dir,dir2) then
195 for _,dir2 in pairs(possible_dirs) do
196 if turn_snap(pos,self,dir,dir2) then
209 minecart.on_step = function(self,dtime)
210 local float_pos = self.object:get_pos()
211 local pos = vector.round(float_pos)
213 if self.velocity then
214 local new_vel = dtime*1000
215 local test = vector.multiply(self.velocity,new_vel)
219 elseif test.x < -0.5 then
224 elseif test.z < -0.5 then
227 self.object:move_to(vector.add(float_pos,test))
230 if not self.axis_lock then
231 local possible_dirs = create_axis(pos)
232 for _,dir in pairs(possible_dirs) do
235 self.dir = vector.new(1,0,0)
238 elseif dir.z ~= 0 then
240 self.dir = vector.new(0,0,1)
246 collision_detect(self)
249 self.old_pos = float_pos
252 minecart.on_rightclick = function(self,clicker)
256 minecart.on_activate = function(self,staticdata, dtime_s)
257 self.object:set_armor_groups({immortal=1})
258 if string.sub(staticdata, 1, string.len("return")) ~= "return" then
261 local data = minetest.deserialize(staticdata)
262 if type(data) ~= "table" then
265 self.old_pos = self.object:get_pos()
266 self.velocity = vector.new(0,0,0)
269 minecart.get_staticdata = function(self)
270 return minetest.serialize({
276 minecart.initial_properties = {
277 physical = false, -- otherwise going uphill breaks
278 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},
281 visual_size = {x=1, y=1},
282 textures = {"minecart.png"},
286 minecart.on_punch = function(self,puncher, time_from_last_punch, tool_capabilities, dir, damage)
287 --local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
288 --self.object:remove()
293 minetest.register_entity("minecart:minecart", minecart)
306 minetest.register_craftitem("minecart:minecart", {
307 description = "Minecart",
308 inventory_image = "minecartitem.png",
309 wield_image = "minecartitem.png",
310 on_place = function(itemstack, placer, pointed_thing)
311 if not pointed_thing.type == "node" then
315 local sneak = placer:get_player_control().sneak
316 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
317 if not sneak and noddef.on_rightclick then
318 minetest.item_place(itemstack, placer, pointed_thing)
322 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
323 minetest.add_entity(pointed_thing.under, "minecart:minecart")
328 itemstack:take_item()
334 minetest.register_craft({
335 output = "minecart:minecart",
337 {"main:iron", "", "main:iron"},
338 {"main:iron", "main:iron", "main:iron"},
346 minetest.register_node("minecart:rail",{
347 description = "Rail",
348 wield_image = "rail.png",
350 "rail.png", "railcurve.png",
351 "railt.png", "railcross.png"
353 drawtype = "raillike",
355 sunlight_propagates = true,
356 is_ground_content = false,
358 node_placement_prediction = "",
361 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
363 sounds = main.stoneSound(),
364 after_place_node = function(pos)
365 data_injection(pos,true)
367 after_destruct = function(pos)
370 groups={stone=1,wood=1,rail=1,attached_node=1},
374 minetest.register_lbm({
375 name = "minecart:rail",
376 nodenames = {"minecart:rail"},
377 run_at_every_load = true,
378 action = function(pos)
379 data_injection(pos,true)
380 print("buildin dat cash")
384 minetest.register_craft({
385 output = "minecart:rail 32",
387 {"main:iron","","main:iron"},
388 {"main:iron","main:stick","main:iron"},
389 {"main:iron","","main:iron"}