]> git.lizzy.rs Git - Crafter.git/blob - mods/minecart/init.lua
Set minecarts rotation when turning
[Crafter.git] / mods / minecart / init.lua
1 local pool = {}
2
3 local dirs = {
4         {x= 1,y= 0,z= 0},
5         {x=-1,y= 0,z= 0},
6
7         {x= 1,y= 1,z= 0}, 
8         {x=-1,y= 1,z= 0},
9
10         {x= 1,y=-1,z= 0},
11         {x=-1,y=-1,z= 0},
12
13         {x= 0,y= 0,z= 1},
14         {x= 0,y= 0,z=-1},
15
16         {x= 0,y= 1,z= 1},
17         {x= 0,y= 1,z=-1},
18
19         {x= 0,y=-1,z= 1},
20         {x= 0,y=-1,z=-1},
21 }
22
23 local axis_order = {
24
25 }
26 local function data_injection(pos,data)
27         if data then
28                 pool[minetest.hash_node_position(pos)] = true
29         else
30                 pool[minetest.hash_node_position(pos)] = nil
31         end
32 end
33
34
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)
41                 end
42         end
43         return(possible_dirs)
44 end
45
46 local function collision_detect(self)
47         if not self.axis_lock then return end
48         local pos = self.object:get_pos()
49
50         for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
51                 if object:is_player() then
52                         local pos2 = object:get_pos()
53                         if self.axis_lock == "x" then
54                                 local velocity = 1-vector.distance(vector.new(pos.x,0,0),vector.new(pos2.x,0,0))
55                                 print(velocity)
56                                 local dir = vector.direction(vector.new(pos2.x,0,0),vector.new(pos.x,0,0))
57                                 self.object:add_velocity(vector.multiply(dir,velocity))
58                                 self.dir = dir
59                         elseif self.axis_lock == "z" then
60                                 local velocity = 1-vector.distance(vector.new(0,0,pos.z),vector.new(0,0,pos2.z))
61                                 local dir = vector.direction(vector.new(0,0,pos2.z),vector.new(0,0,pos.z))
62                                 self.object:add_velocity(vector.multiply(dir,velocity))
63                                 self.dir = dir
64                         end
65                         return
66                 end
67         end
68 end
69
70 local function direction_snap(self)
71         local dir = self.dir
72         local yaw = minetest.dir_to_yaw(dir)
73         self.object:set_rotation(vector.new(0,yaw,0))
74 end
75
76 local function rail_brain(self,pos)
77         if not self.dir then return end
78
79         --if self.dir then print(dump(self.dir)) end
80
81         local pos2 = self.object:get_pos()
82
83         local dir = self.dir
84
85         local triggered = false
86
87         if dir.x < 0 and pos2.x < pos.x then
88                 triggered = true
89         elseif dir.x > 0 and pos2.x > pos.x then
90                 triggered = true
91         elseif dir.z < 0 and pos2.z < pos.z then
92                 triggered = true
93         elseif dir.z > 0 and pos2.z > pos.z then
94                 triggered = true
95         end
96
97         --print(dump(dir))
98         if triggered and not pool[minetest.hash_node_position(vector.add(pos,dir))] then
99                 local possible_dirs = create_axis(pos)
100                 if table.getn(possible_dirs) == 0 then
101                         --stop slow down become physical, something
102                 else
103                         for _,dir2 in pairs(possible_dirs) do
104                                 if dir.x ~= 0 and dir2.z ~= 0 then
105                                         local intertia = math.abs(self.object:get_velocity().x)
106                                         self.object:set_velocity(vector.multiply(dir2,intertia))
107                                         self.dir = dir2
108                                         self.axis_lock = "z"
109                                         self.object:set_pos(pos)
110                                         direction_snap(self)
111                                         break
112                                 elseif dir.z ~= 0 and dir2.x ~= 0 then
113                                         local intertia = math.abs(self.object:get_velocity().z)
114                                         self.object:set_velocity(vector.multiply(dir2,intertia))
115                                         self.dir = dir2
116                                         self.axis_lock = "x"
117                                         self.object:set_pos(pos)
118                                         direction_snap(self)
119                                         break
120                                 end
121                         end
122                 end
123         end
124 end
125
126
127
128
129 local minecart = {}
130
131 minecart.on_step = function(self,dtime)
132         local pos = vector.round(self.object:get_pos())
133         if not self.axis_lock then
134                 local possible_dirs = create_axis(pos)
135                 for _,dir in pairs(possible_dirs) do
136                         if dir.x ~=0 then
137                                 self.axis_lock = "x"
138                                 break
139                         elseif dir.z ~= 0 then
140                                 self.axis_lock = "z"
141                                 break
142                         end
143                 end
144         else
145                 collision_detect(self)
146                 rail_brain(self,pos)
147         end
148 end
149
150 minecart.on_rightclick = function(self,clicker)
151 end
152
153 --get old data
154 minecart.on_activate = function(self,staticdata, dtime_s)
155         self.object:set_armor_groups({immortal=1})
156         if string.sub(staticdata, 1, string.len("return")) ~= "return" then
157                 return
158         end
159         local data = minetest.deserialize(staticdata)
160         if type(data) ~= "table" then
161                 return
162         end
163
164 end
165
166 minecart.get_staticdata = function(self)
167         return minetest.serialize({
168         })
169 end
170
171
172
173 minecart.initial_properties = {
174         physical = false, -- otherwise going uphill breaks
175         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},
176         visual = "mesh",
177         mesh = "minecart.x",
178         visual_size = {x=1, y=1},
179         textures = {"minecart.png"},
180 }
181
182
183 minecart.on_punch = function(self,puncher, time_from_last_punch, tool_capabilities, dir, damage)
184         --local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
185         --self.object:remove()
186 end
187
188         
189
190 minetest.register_entity("minecart:minecart", minecart)
191
192
193
194
195
196
197
198
199
200
201
202
203 minetest.register_craftitem("minecart:minecart", {
204         description = "Minecart",
205         inventory_image = "minecartitem.png",
206         wield_image = "minecartitem.png",
207         on_place = function(itemstack, placer, pointed_thing)
208                 if not pointed_thing.type == "node" then
209                         return
210                 end
211                 
212                 local sneak = placer:get_player_control().sneak
213                 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
214                 if not sneak and noddef.on_rightclick then
215                         minetest.item_place(itemstack, placer, pointed_thing)
216                         return
217                 end
218                 
219                 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
220                         minetest.add_entity(pointed_thing.under, "minecart:minecart")
221                 else
222                         return
223                 end
224
225                 itemstack:take_item()
226
227                 return itemstack
228         end,
229 })
230
231 minetest.register_craft({
232         output = "minecart:minecart",
233         recipe = {
234                 {"main:iron", "", "main:iron"},
235                 {"main:iron", "main:iron", "main:iron"},
236         },
237 })
238
239
240
241
242
243 minetest.register_node("minecart:rail",{
244         description = "Rail",
245         wield_image = "rail.png",
246         tiles = {
247                 "rail.png", "railcurve.png",
248                 "railt.png", "railcross.png"
249         },
250         drawtype = "raillike",
251         paramtype = "light",
252         sunlight_propagates = true,
253         is_ground_content = false,
254         walkable = false,
255         node_placement_prediction = "",
256         selection_box = {
257                 type = "fixed",
258                 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
259         },
260         sounds = main.stoneSound(),
261         after_place_node = function(pos)
262                 data_injection(pos,true)
263         end,
264         after_destruct = function(pos)
265                 data_injection(pos)
266         end,
267         groups={stone=1,wood=1,rail=1,attached_node=1},
268 })
269
270
271 minetest.register_lbm({
272         name = "minecart:rail",
273         nodenames = {"minecart:rail"},
274         run_at_every_load = true,
275         action = function(pos)
276                 data_injection(pos,true)
277                 print("buildin dat cash")
278         end,
279 })
280
281 minetest.register_craft({
282         output = "minecart:rail 32",
283         recipe = {
284                 {"main:iron","","main:iron"},
285                 {"main:iron","main:stick","main:iron"},
286                 {"main:iron","","main:iron"}
287         }
288 })