]> git.lizzy.rs Git - Crafter.git/blob - mods/minecart/init.lua
Extreme server cart test
[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 = (5-vector.distance(vector.new(pos.x,0,0),vector.new(pos2.x,0,0)))/10
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.velocity = vector.multiply(dir,velocity)
59                                 self.dir = dir
60                         elseif self.axis_lock == "z" then
61                                 local velocity = (5-vector.distance(vector.new(0,0,pos.z),vector.new(0,0,pos2.z)))/10
62                                 print(velocity)
63                                 local dir = vector.direction(vector.new(0,0,pos2.z),vector.new(0,0,pos.z))
64                                 --self.object:add_velocity(vector.multiply(dir,velocity))
65                                 self.velocity = vector.multiply(dir,velocity)
66                                 self.dir = dir
67                         end
68                         return
69                 end
70         end
71 end
72
73 local function direction_snap(self)
74         local dir = self.dir
75         local yaw = minetest.dir_to_yaw(dir)
76         self.object:set_rotation(vector.new(0,yaw,0))
77 end
78
79 local function turn_snap(pos,self,dir,dir2)
80         if dir.x ~= 0 and dir2.z ~= 0 then
81                 --local inertia = math.abs(self.object:get_velocity().x)
82                 local inertia = math.abs(self.velocity.x)
83                 --self.object:set_velocity(vector.multiply(dir2,inertia))
84
85                 self.velocity = vector.multiply(dir2,inertia)
86                 self.dir = dir2
87                 self.axis_lock = "z"
88                 self.object:set_pos(pos)
89                 direction_snap(self)
90                 return(true)
91         elseif dir.z ~= 0 and dir2.x ~= 0 then
92                 --local inertia = math.abs(self.object:get_velocity().z)
93                 --print(dump(self.velocity))
94                 local inertia = math.abs(self.velocity.z)
95                 --self.object:set_velocity(vector.multiply(dir2,inertia))
96                 
97                 self.velocity = vector.multiply(dir2,inertia)
98
99                 self.dir = dir2
100                 self.axis_lock = "x"
101                 self.object:set_pos(pos)
102                 direction_snap(self)
103                 return(true)
104         end
105 end
106
107 local function rail_brain(self,pos)
108         if not self.dir then return end
109
110         --if self.dir then print(dump(self.dir)) end
111
112         local pos2 = self.object:get_pos()
113
114         local dir = self.dir
115
116         local triggered = false
117
118         if dir.x < 0 and pos2.x < pos.x then
119                 triggered = true
120         elseif dir.x > 0 and pos2.x > pos.x then
121                 triggered = true
122         elseif dir.z < 0 and pos2.z < pos.z then
123                 triggered = true
124         elseif dir.z > 0 and pos2.z > pos.z then
125                 triggered = true
126         end
127
128         --print(dump(dir))
129         if triggered and not pool[minetest.hash_node_position(vector.add(pos,dir))] then
130                 local possible_dirs = create_axis(pos)
131                 if table.getn(possible_dirs) == 0 then
132                         --print("train fails")
133                         --stop slow down become physical, something
134                 else
135                         for _,dir2 in pairs(possible_dirs) do
136                                 if turn_snap(pos,self,dir,dir2) then
137                                         return
138                                 end
139                         end
140                 end
141         end
142 end
143
144
145
146
147 local minecart = {}
148
149 minecart.on_step = function(self,dtime)
150         local float_pos = self.object:get_pos()
151         local pos = vector.round(float_pos)
152
153         if self.velocity then
154                 local new_vel = dtime/0.01
155                 --print(new_vel)
156                 local test = vector.multiply(self.velocity,new_vel)
157                 print(dump(test))
158                 if test.x >= 0.5 then
159                         test.x = 0.4999999999
160                 elseif test.x <= -0.5 then
161                         test.x = -0.4999999999
162                 end
163                 if test.z >= 0.5 then
164                         test.z = 0.4999999999
165                 elseif test.z <= -0.5 then
166                         test.z = -0.4999999999
167                 end
168                 self.object:move_to(vector.add(float_pos,test))
169                 self.velocity = test
170         end
171
172         --stop minecarts from derailing when going super fast
173         if self.old_pos and vector.distance(float_pos,self.old_pos) > 0.5 then
174                 self.object:move_to(self.old_pos)
175                 float_pos = self.object:get_pos()
176                 pos = vector.round(self.old_pos)
177         end
178
179         if not self.axis_lock then
180                 local possible_dirs = create_axis(pos)
181                 for _,dir in pairs(possible_dirs) do
182                         if dir.x ~=0 then
183                                 self.axis_lock = "x"
184                                 break
185                         elseif dir.z ~= 0 then
186                                 self.axis_lock = "z"
187                                 break
188                         end
189                 end
190         else
191                 collision_detect(self)
192                 rail_brain(self,pos)
193         end
194         self.old_pos = float_pos
195 end
196
197 minecart.on_rightclick = function(self,clicker)
198 end
199
200 --get old data
201 minecart.on_activate = function(self,staticdata, dtime_s)
202         self.object:set_armor_groups({immortal=1})
203         if string.sub(staticdata, 1, string.len("return")) ~= "return" then
204                 return
205         end
206         local data = minetest.deserialize(staticdata)
207         if type(data) ~= "table" then
208                 return
209         end
210         self.old_pos = self.object:get_pos()
211         self.velocity = vector.new(0,0,0)
212 end
213
214 minecart.get_staticdata = function(self)
215         return minetest.serialize({
216         })
217 end
218
219
220
221 minecart.initial_properties = {
222         physical = false, -- otherwise going uphill breaks
223         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},
224         visual = "mesh",
225         mesh = "minecart.x",
226         visual_size = {x=1, y=1},
227         textures = {"minecart.png"},
228 }
229
230
231 minecart.on_punch = function(self,puncher, time_from_last_punch, tool_capabilities, dir, damage)
232         --local obj = minetest.add_item(self.object:getpos(), "minecart:minecart")
233         --self.object:remove()
234 end
235
236         
237
238 minetest.register_entity("minecart:minecart", minecart)
239
240
241
242
243
244
245
246
247
248
249
250
251 minetest.register_craftitem("minecart:minecart", {
252         description = "Minecart",
253         inventory_image = "minecartitem.png",
254         wield_image = "minecartitem.png",
255         on_place = function(itemstack, placer, pointed_thing)
256                 if not pointed_thing.type == "node" then
257                         return
258                 end
259                 
260                 local sneak = placer:get_player_control().sneak
261                 local noddef = minetest.registered_nodes[minetest.get_node(pointed_thing.under).name]
262                 if not sneak and noddef.on_rightclick then
263                         minetest.item_place(itemstack, placer, pointed_thing)
264                         return
265                 end
266                 
267                 if minetest.get_item_group(minetest.get_node(pointed_thing.under).name, "rail")>0 then
268                         minetest.add_entity(pointed_thing.under, "minecart:minecart")
269                 else
270                         return
271                 end
272
273                 itemstack:take_item()
274
275                 return itemstack
276         end,
277 })
278
279 minetest.register_craft({
280         output = "minecart:minecart",
281         recipe = {
282                 {"main:iron", "", "main:iron"},
283                 {"main:iron", "main:iron", "main:iron"},
284         },
285 })
286
287
288
289
290
291 minetest.register_node("minecart:rail",{
292         description = "Rail",
293         wield_image = "rail.png",
294         tiles = {
295                 "rail.png", "railcurve.png",
296                 "railt.png", "railcross.png"
297         },
298         drawtype = "raillike",
299         paramtype = "light",
300         sunlight_propagates = true,
301         is_ground_content = false,
302         walkable = false,
303         node_placement_prediction = "",
304         selection_box = {
305                 type = "fixed",
306                 fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
307         },
308         sounds = main.stoneSound(),
309         after_place_node = function(pos)
310                 data_injection(pos,true)
311         end,
312         after_destruct = function(pos)
313                 data_injection(pos)
314         end,
315         groups={stone=1,wood=1,rail=1,attached_node=1},
316 })
317
318
319 minetest.register_lbm({
320         name = "minecart:rail",
321         nodenames = {"minecart:rail"},
322         run_at_every_load = true,
323         action = function(pos)
324                 data_injection(pos,true)
325                 print("buildin dat cash")
326         end,
327 })
328
329 minetest.register_craft({
330         output = "minecart:rail 32",
331         recipe = {
332                 {"main:iron","","main:iron"},
333                 {"main:iron","main:stick","main:iron"},
334                 {"main:iron","","main:iron"}
335         }
336 })