Advertisement
Guest User

this

a guest
Jan 11th, 2016
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.10 KB | None | 0 0
  1.  
  2. dofile(minetest.get_modpath("carts").."/functions.lua")
  3.  
  4. --
  5. -- Cart entity
  6. --
  7.  
  8. local cart = {
  9. physical = false,
  10. collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
  11. visual = "mesh",
  12. mesh = "cart.x",
  13. visual_size = {x=1, y=1},
  14. textures = {"cart.png"},
  15.  
  16. driver = nil,
  17. velocity = {x=0, y=0, z=0},
  18. old_pos = nil,
  19. old_velocity = nil,
  20. pre_stop_dir = nil,
  21. MAX_V = 8, -- Limit of the velocity
  22. }
  23.  
  24. function cart:on_rightclick(clicker)
  25. if not clicker or not clicker:is_player() then
  26. return
  27. end
  28. if self.driver and clicker == self.driver then
  29. self.driver = nil
  30. clicker:set_detach()
  31. elseif not self.driver then
  32. self.driver = clicker
  33. clicker:set_attach(self.object, "", {x=0,y=5,z=0}, {x=0,y=0,z=0})
  34. end
  35. end
  36.  
  37. function cart:on_activate(staticdata, dtime_s)
  38. self.object:set_armor_groups({immortal=1})
  39. if staticdata then
  40. local tmp = minetest.deserialize(staticdata)
  41. if tmp then
  42. self.velocity = tmp.velocity
  43. end
  44. if tmp and tmp.pre_stop_dir then
  45. self.pre_stop_dir = tmp.pre_stop_dir
  46. end
  47. end
  48. self.old_pos = self.object:getpos()
  49. self.old_velocity = self.velocity
  50. end
  51.  
  52. function cart:get_staticdata()
  53. return minetest.serialize({
  54. velocity = self.velocity,
  55. pre_stop_dir = self.pre_stop_dir,
  56. })
  57. end
  58.  
  59. -- Remove the cart if holding a tool or accelerate it
  60. function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
  61. if not puncher or not puncher:is_player() then
  62. return
  63. end
  64.  
  65. if puncher:get_player_control().sneak then
  66. self.object:remove()
  67. local inv = puncher:get_inventory()
  68. if minetest.setting_getbool("creative_mode") then
  69. if not inv:contains_item("main", "carts:cart") then
  70. inv:add_item("main", "carts:cart")
  71. end
  72. else
  73. inv:add_item("main", "carts:cart")
  74. end
  75. return
  76. end
  77.  
  78. if puncher == self.driver then
  79. return
  80. end
  81.  
  82. local d = cart_func:velocity_to_dir(direction)
  83. local s = self.velocity
  84. if time_from_last_punch > tool_capabilities.full_punch_interval then
  85. time_from_last_punch = tool_capabilities.full_punch_interval
  86. end
  87. local f = 4*(time_from_last_punch/tool_capabilities.full_punch_interval)
  88. local v = {x=s.x+d.x*f, y=s.y, z=s.z+d.z*f}
  89. if math.abs(v.x) < 6 and math.abs(v.z) < 6 then
  90. self.velocity = v
  91. else
  92. if math.abs(self.velocity.x) < 6 and math.abs(v.x) >= 6 then
  93. self.velocity.x = 6*cart_func:get_sign(self.velocity.x)
  94. end
  95. if math.abs(self.velocity.z) < 6 and math.abs(v.z) >= 6 then
  96. self.velocity.z = 6*cart_func:get_sign(self.velocity.z)
  97. end
  98. end
  99. end
  100.  
  101. -- Returns the direction as a unit vector
  102. function cart:get_rail_direction(pos, dir)
  103. local d = cart_func.v3:copy(dir)
  104.  
  105. -- Check front
  106. d.y = 0
  107. local p = cart_func.v3:add(cart_func.v3:copy(pos), d)
  108. if cart_func:is_rail(p) then
  109. return d
  110. end
  111.  
  112. -- Check downhill
  113. d.y = -1
  114. p = cart_func.v3:add(cart_func.v3:copy(pos), d)
  115. if cart_func:is_rail(p) then
  116. return d
  117. end
  118.  
  119. -- Check uphill
  120. d.y = 1
  121. p = cart_func.v3:add(cart_func.v3:copy(pos), d)
  122. if cart_func:is_rail(p) then
  123. return d
  124. end
  125. d.y = 0
  126.  
  127. -- Check left and right
  128. local view_dir
  129. local other_dir
  130. local a
  131.  
  132. if d.x == 0 and d.z ~= 0 then
  133. view_dir = "z"
  134. other_dir = "x"
  135. if d.z < 0 then
  136. a = {1, -1}
  137. else
  138. a = {-1, 1}
  139. end
  140. elseif d.z == 0 and d.x ~= 0 then
  141. view_dir = "x"
  142. other_dir = "z"
  143. if d.x > 0 then
  144. a = {1, -1}
  145. else
  146. a = {-1, 1}
  147. end
  148. else
  149. return {x=0, y=0, z=0}
  150. end
  151.  
  152. d[view_dir] = 0
  153. d[other_dir] = a[1]
  154. p = cart_func.v3:add(cart_func.v3:copy(pos), d)
  155. if cart_func:is_rail(p) then
  156. return d
  157. end
  158. d.y = -1
  159. p = cart_func.v3:add(cart_func.v3:copy(pos), d)
  160. if cart_func:is_rail(p) then
  161. return d
  162. end
  163. d.y = 0
  164. d[other_dir] = a[2]
  165. p = cart_func.v3:add(cart_func.v3:copy(pos), d)
  166. if cart_func:is_rail(p) then
  167. return d
  168. end
  169. d.y = -1
  170. p = cart_func.v3:add(cart_func.v3:copy(pos), d)
  171. if cart_func:is_rail(p) then
  172. return d
  173. end
  174. d.y = 0
  175.  
  176. return {x=0, y=0, z=0}
  177. end
  178.  
  179. function cart:calc_rail_direction(pos, vel)
  180. local velocity = cart_func.v3:copy(vel)
  181. local p = cart_func.v3:copy(pos)
  182. if cart_func:is_int(p.x) and cart_func:is_int(p.z) then
  183.  
  184. local dir = cart_func:velocity_to_dir(velocity)
  185. local dir_old = cart_func.v3:copy(dir)
  186.  
  187. dir = self:get_rail_direction(cart_func.v3:round(p), dir)
  188.  
  189. local v = math.max(math.abs(velocity.x), math.abs(velocity.z))
  190. velocity = {
  191. x = v * dir.x,
  192. y = v * dir.y,
  193. z = v * dir.z,
  194. }
  195.  
  196. if cart_func.v3:equal(velocity, {x=0, y=0, z=0}) and not cart_func:is_rail(p) then
  197.  
  198. -- First try this HACK
  199. -- Move the cart on the rail if above or under it
  200. if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=1, z=0})) and vel.y >= 0 then
  201. p = cart_func.v3:add(p, {x=0, y=1, z=0})
  202. return self:calc_rail_direction(p, vel)
  203. end
  204. if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-1, z=0})) and vel.y <= 0 then
  205. p = cart_func.v3:add(p, {x=0, y=-1, z=0})
  206. return self:calc_rail_direction(p, vel)
  207. end
  208. -- Now the HACK gets really dirty
  209. if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=2, z=0})) and vel.y >= 0 then
  210. p = cart_func.v3:add(p, {x=0, y=1, z=0})
  211. return self:calc_rail_direction(p, vel)
  212. end
  213. if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-2, z=0})) and vel.y <= 0 then
  214. p = cart_func.v3:add(p, {x=0, y=-1, z=0})
  215. return self:calc_rail_direction(p, vel)
  216. end
  217.  
  218. return {x=0, y=0, z=0}, p
  219. end
  220.  
  221. if not cart_func.v3:equal(dir, dir_old) then
  222. return velocity, cart_func.v3:round(p)
  223. end
  224.  
  225. end
  226. return velocity, p
  227. end
  228.  
  229. function cart:on_step(dtime)
  230.  
  231. local pos = self.object:getpos()
  232. local dir = cart_func:velocity_to_dir(self.velocity)
  233.  
  234. if not cart_func.v3:equal(self.velocity, {x=0,y=0,z=0}) then
  235. self.pre_stop_dir = cart_func:velocity_to_dir(self.velocity)
  236. end
  237.  
  238. -- Stop the cart if the velocity is nearly 0
  239. -- Only if on a flat railway
  240. if dir.y == 0 then
  241. if math.abs(self.velocity.x) < 0.1 and math.abs(self.velocity.z) < 0.1 then
  242. -- Start the cart if powered from mesecons
  243. local a = tonumber(minetest.env:get_meta(pos):get_string("cart_acceleration"))
  244. if a and a ~= 0 then
  245. if self.pre_stop_dir and cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), self.pre_stop_dir), self.pre_stop_dir) then
  246. self.velocity = {
  247. x = self.pre_stop_dir.x * 0.2,
  248. y = self.pre_stop_dir.y * 0.2,
  249. z = self.pre_stop_dir.z * 0.2,
  250. }
  251. self.old_velocity = self.velocity
  252. return
  253. end
  254. for _,y in ipairs({0,-1,1}) do
  255. for _,z in ipairs({1,-1}) do
  256. if cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), {x=0, y=y, z=z}), {x=0, y=y, z=z}) then
  257. self.velocity = {
  258. x = 0,
  259. y = 0.2*y,
  260. z = 0.2*z,
  261. }
  262. self.old_velocity = self.velocity
  263. return
  264. end
  265. end
  266. for _,x in ipairs({1,-1}) do
  267. if cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), {x=x, y=y, z=0}), {x=x, y=y, z=0}) then
  268. self.velocity = {
  269. x = 0.2*x,
  270. y = 0.2*y,
  271. z = 0,
  272. }
  273. self.old_velocity = self.velocity
  274. return
  275. end
  276. end
  277. end
  278. end
  279.  
  280. self.velocity = {x=0, y=0, z=0}
  281. self.object:setvelocity(self.velocity)
  282. self.old_velocity = self.velocity
  283. self.old_pos = self.object:getpos()
  284. return
  285. end
  286. end
  287.  
  288. --
  289. -- Set the new moving direction
  290. --
  291.  
  292. -- Recalcualte the rails that are passed since the last server step
  293. local old_dir = cart_func:velocity_to_dir(self.old_velocity)
  294. if old_dir.x ~= 0 then
  295. local sign = cart_func:get_sign(pos.x-self.old_pos.x)
  296. while true do
  297. if sign ~= cart_func:get_sign(pos.x-self.old_pos.x) or pos.x == self.old_pos.x then
  298. break
  299. end
  300. self.old_pos.x = self.old_pos.x + cart_func:get_sign(pos.x-self.old_pos.x)*0.1
  301. self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.x-self.old_pos.x)*0.1*old_dir.y
  302. self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
  303. old_dir = cart_func:velocity_to_dir(self.old_velocity)
  304. if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
  305. self.velocity = self.old_velocity
  306. pos = self.old_pos
  307. self.object:setpos(self.old_pos)
  308. break
  309. end
  310. end
  311. elseif old_dir.z ~= 0 then
  312. local sign = cart_func:get_sign(pos.z-self.old_pos.z)
  313. while true do
  314. if sign ~= cart_func:get_sign(pos.z-self.old_pos.z) or pos.z == self.old_pos.z then
  315. break
  316. end
  317. self.old_pos.z = self.old_pos.z + cart_func:get_sign(pos.z-self.old_pos.z)*0.1
  318. self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.z-self.old_pos.z)*0.1*old_dir.y
  319. self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
  320. old_dir = cart_func:velocity_to_dir(self.old_velocity)
  321. if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
  322. self.velocity = self.old_velocity
  323. pos = self.old_pos
  324. self.object:setpos(self.old_pos)
  325. break
  326. end
  327. end
  328. end
  329.  
  330. -- Calculate the new step
  331. self.velocity, pos = self:calc_rail_direction(pos, self.velocity)
  332. self.object:setpos(pos)
  333. dir = cart_func:velocity_to_dir(self.velocity)
  334.  
  335. -- Accelerate or decelerate the cart according to the pitch and acceleration of the rail node
  336. local a = tonumber(minetest.env:get_meta(pos):get_string("cart_acceleration"))
  337. if not a then
  338. a = 0
  339. end
  340. if self.velocity.y < 0 then
  341. self.velocity = {
  342. x = self.velocity.x + (a+0.13)*cart_func:get_sign(self.velocity.x),
  343. y = self.velocity.y + (a+0.13)*cart_func:get_sign(self.velocity.y),
  344. z = self.velocity.z + (a+0.13)*cart_func:get_sign(self.velocity.z),
  345. }
  346. elseif self.velocity.y > 0 then
  347. self.velocity = {
  348. x = self.velocity.x + (a-0.1)*cart_func:get_sign(self.velocity.x),
  349. y = self.velocity.y + (a-0.1)*cart_func:get_sign(self.velocity.y),
  350. z = self.velocity.z + (a-0.1)*cart_func:get_sign(self.velocity.z),
  351. }
  352. else
  353. self.velocity = {
  354. x = self.velocity.x + (a-0.03)*cart_func:get_sign(self.velocity.x),
  355. y = self.velocity.y + (a-0.03)*cart_func:get_sign(self.velocity.y),
  356. z = self.velocity.z + (a-0.03)*cart_func:get_sign(self.velocity.z),
  357. }
  358.  
  359. -- Place the cart exactly on top of the rail
  360. if cart_func:is_rail(cart_func.v3:round(pos)) then
  361. self.object:setpos({x=pos.x, y=math.floor(pos.y+0.5), z=pos.z})
  362. pos = self.object:getpos()
  363. end
  364. end
  365.  
  366. -- Dont switch moving direction
  367. -- Only if on flat railway
  368. if dir.y == 0 then
  369. if cart_func:get_sign(dir.x) ~= cart_func:get_sign(self.velocity.x) then
  370. self.velocity.x = 0
  371. end
  372. if cart_func:get_sign(dir.y) ~= cart_func:get_sign(self.velocity.y) then
  373. self.velocity.y = 0
  374. end
  375. if cart_func:get_sign(dir.z) ~= cart_func:get_sign(self.velocity.z) then
  376. self.velocity.z = 0
  377. end
  378. end
  379.  
  380. -- Allow only one moving direction (multiply the other one with 0)
  381. dir = cart_func:velocity_to_dir(self.velocity)
  382. self.velocity = {
  383. x = math.abs(self.velocity.x) * dir.x,
  384. y = self.velocity.y,
  385. z = math.abs(self.velocity.z) * dir.z,
  386. }
  387.  
  388. -- Move cart exactly on the rail
  389. if dir.x ~= 0 and not cart_func:is_int(pos.z) then
  390. pos.z = math.floor(0.5+pos.z)
  391. self.object:setpos(pos)
  392. elseif dir.z ~= 0 and not cart_func:is_int(pos.x) then
  393. pos.x = math.floor(0.5+pos.x)
  394. self.object:setpos(pos)
  395. end
  396.  
  397. -- Limit the velocity
  398. if math.abs(self.velocity.x) > self.MAX_V then
  399. self.velocity.x = self.MAX_V*cart_func:get_sign(self.velocity.x)
  400. end
  401. if math.abs(self.velocity.y) > self.MAX_V then
  402. self.velocity.y = self.MAX_V*cart_func:get_sign(self.velocity.y)
  403. end
  404. if math.abs(self.velocity.z) > self.MAX_V then
  405. self.velocity.z = self.MAX_V*cart_func:get_sign(self.velocity.z)
  406. end
  407.  
  408. self.object:setvelocity(self.velocity)
  409.  
  410. self.old_pos = self.object:getpos()
  411. self.old_velocity = cart_func.v3:copy(self.velocity)
  412.  
  413. if dir.x < 0 then
  414. self.object:setyaw(math.pi/2)
  415. elseif dir.x > 0 then
  416. self.object:setyaw(3*math.pi/2)
  417. elseif dir.z < 0 then
  418. self.object:setyaw(math.pi)
  419. elseif dir.z > 0 then
  420. self.object:setyaw(0)
  421. end
  422.  
  423. if dir.y == -1 then
  424. self.object:set_animation({x=1, y=1}, 1, 0)
  425. elseif dir.y == 1 then
  426. self.object:set_animation({x=2, y=2}, 1, 0)
  427. else
  428. self.object:set_animation({x=0, y=0}, 1, 0)
  429. end
  430.  
  431. end
  432.  
  433. minetest.register_entity("carts:cart", cart)
  434.  
  435.  
  436. minetest.register_craftitem("carts:cart", {
  437. description = "Minecart",
  438. inventory_image = minetest.inventorycube("cart_top.png", "cart_side.png", "cart_side.png"),
  439. wield_image = "cart_side.png",
  440.  
  441. on_place = function(itemstack, placer, pointed_thing)
  442. if not pointed_thing.type == "node" then
  443. return
  444. end
  445. if cart_func:is_rail(pointed_thing.under) then
  446. minetest.env:add_entity(pointed_thing.under, "carts:cart")
  447. if not minetest.setting_getbool("creative_mode") then
  448. itemstack:take_item()
  449. end
  450. return itemstack
  451. elseif cart_func:is_rail(pointed_thing.above) then
  452. minetest.env:add_entity(pointed_thing.above, "carts:cart")
  453. if not minetest.setting_getbool("creative_mode") then
  454. itemstack:take_item()
  455. end
  456. return itemstack
  457. end
  458. end,
  459. })
  460.  
  461. minetest.register_craft({
  462. output = "carts:cart",
  463. recipe = {
  464. {"", "", ""},
  465. {"default:steel_ingot", "", "default:steel_ingot"},
  466. {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
  467. },
  468. })
  469.  
  470. --
  471. -- Mesecon support
  472. --
  473.  
  474. minetest.register_node(":default:rail", {
  475. description = "Rail",
  476. drawtype = "raillike",
  477. tiles = {"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
  478. inventory_image = "default_rail.png",
  479. wield_image = "default_rail.png",
  480. paramtype = "light",
  481. is_ground_content = true,
  482. walkable = false,
  483. selection_box = {
  484. type = "fixed",
  485. -- but how to specify the dimensions for curved and sideways rails?
  486. fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
  487. },
  488. groups = {bendy=2,snappy=1,dig_immediate=2,attached_node=1,rail=1,connect_to_raillike=1},
  489. })
  490.  
  491. minetest.register_node("carts:powerrail", {
  492. description = "Powered Rail",
  493. drawtype = "raillike",
  494. tiles = {"carts_rail_pwr.png", "carts_rail_curved_pwr.png", "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"},
  495. inventory_image = "carts_rail_pwr.png",
  496. wield_image = "carts_rail_pwr.png",
  497. paramtype = "light",
  498. is_ground_content = true,
  499. walkable = false,
  500. selection_box = {
  501. type = "fixed",
  502. -- but how to specify the dimensions for curved and sideways rails?
  503. fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
  504. },
  505. groups = {bendy=2,snappy=1,dig_immediate=2,attached_node=1,rail=1,connect_to_raillike=1},
  506.  
  507. after_place_node = function(pos, placer, itemstack)
  508. if not mesecon then
  509. minetest.env:get_meta(pos):set_string("cart_acceleration", "0.5")
  510. end
  511. end,
  512.  
  513. mesecons = {
  514. effector = {
  515. action_on = function(pos, node)
  516. minetest.env:get_meta(pos):set_string("cart_acceleration", "0.5")
  517. end,
  518.  
  519. action_off = function(pos, node)
  520. minetest.env:get_meta(pos):set_string("cart_acceleration", "0")
  521. end,
  522. },
  523. },
  524. })
  525.  
  526. minetest.register_node("carts:brakerail", {
  527. description = "Brake Rail",
  528. drawtype = "raillike",
  529. tiles = {"carts_rail_brk.png", "carts_rail_curved_brk.png", "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"},
  530. inventory_image = "carts_rail_brk.png",
  531. wield_image = "carts_rail_brk.png",
  532. paramtype = "light",
  533. is_ground_content = true,
  534. walkable = false,
  535. selection_box = {
  536. type = "fixed",
  537. -- but how to specify the dimensions for curved and sideways rails?
  538. fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
  539. },
  540. groups = {bendy=2,snappy=1,dig_immediate=2,attached_node=1,rail=1,connect_to_raillike=1},
  541.  
  542. after_place_node = function(pos, placer, itemstack)
  543. if not mesecon then
  544. minetest.env:get_meta(pos):set_string("cart_acceleration", "-0.2")
  545. end
  546. end,
  547.  
  548. mesecons = {
  549. effector = {
  550. action_on = function(pos, node)
  551. minetest.env:get_meta(pos):set_string("cart_acceleration", "-0.2")
  552. end,
  553.  
  554. action_off = function(pos, node)
  555. minetest.env:get_meta(pos):set_string("cart_acceleration", "0")
  556. end,
  557. },
  558. },
  559. })
  560.  
  561. minetest.register_craft({
  562. output = "carts:powerrail 2",
  563. recipe = {
  564. {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
  565. {"default:steel_ingot", "default:stick", "default:steel_ingot"},
  566. {"default:steel_ingot", "", "default:steel_ingot"},
  567. }
  568. })
  569.  
  570. minetest.register_craft({
  571. output = "carts:powerrail 2",
  572. recipe = {
  573. {"default:steel_ingot", "", "default:steel_ingot"},
  574. {"default:steel_ingot", "default:stick", "default:steel_ingot"},
  575. {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
  576. }
  577. })
  578.  
  579. minetest.register_craft({
  580. output = "carts:brakerail 2",
  581. recipe = {
  582. {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
  583. {"default:steel_ingot", "default:stick", "default:steel_ingot"},
  584. {"default:steel_ingot", "", "default:steel_ingot"},
  585. }
  586. })
  587.  
  588. minetest.register_craft({
  589. output = "carts:brakerail 2",
  590. recipe = {
  591. {"default:steel_ingot", "", "default:steel_ingot"},
  592. {"default:steel_ingot", "default:stick", "default:steel_ingot"},
  593. {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
  594. }
  595. })
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement