Skip to content

Commit 1e691c4

Browse files
sofarparamat
authored andcommittedNov 21, 2016
Carts: Merge boost_cart as "carts" mod
This is all the working code from SmallJoker's boost_cart, poored into a more suitable form for minetest_game. - Mesecons and moreores stuff was removed entirely. - Textures were all renamed and moved out of default/ - Updated license, readme.txt, attribution - Changed code license to MIT, left artwork at CC0 - removed default:rail and made aliases for it - :carts:rail is now carts:rail. - localized entity def - removed copper rail entirely - startstop rail was removed, as well as detector rail - remodeled to b3d using stujones11 excellent blend model, but sizes of cart adjusted to make pixel sizes consistent (0.625) everywhere. - slightly more complex texture map for the cart (front/side visibly different) - rail parameters are passed as a separate def table, and stored in a private list. This avoids having to call `get_meta` on every node. In return, we need the node name, though. - adds metal sounds (based on default metal sound function) and cart moving sound. - reduced cart speeds to max 7, 5 by pushing. - Added on_step() rail event handler, gets called when a cart is on a rail. - Added various rebased updates from upstream (thanks Krock) - Included a fix that removes the 'reverse jiggle' when stopping. - Included reworked textures by sofar. The mod namespace is still public, but I'm NOT declaring it an API. I'd rather see it localized instead, for now. Any public interface in this code is *experimental* at best, and should be considered non-stable and unsupported for now.
1 parent 75caa91 commit 1e691c4

35 files changed

+780
-33
lines changed
 

‎game_api.txt

+22
Original file line numberDiff line numberDiff line change
@@ -650,3 +650,25 @@ Trees
650650

651651
* `default.grow_new_snowy_pine_tree(pos)`
652652
* Grows a new design snowy pine tree at pos
653+
654+
Carts
655+
-----
656+
657+
carts.register_rail(
658+
"mycarts:myrail", -- Rail name
659+
nodedef, -- standard nodedef
660+
railparams -- rail parameter struct (optional)
661+
)
662+
663+
railparams = {
664+
on_step(obj, dtime), -- Event handler called when
665+
-- cart is on rail
666+
acceleration, -- integer acceleration factor (negative
667+
-- values to brake)
668+
}
669+
670+
The event handler is called after all default calculations
671+
are made, so the custom on_step handler can override things
672+
like speed, acceleration, player attachment. The handler will
673+
likely be called many times per second, so the function needs
674+
to make sure that the event is handled properly.

‎mods/carts/README.txt

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Carts (formerly boost_cart)
2+
==========================
3+
4+
Cleaned up for merge based almost entirely on SmallJoker's boost_cart
5+
mod (github.com/smalljoker/boost_cart).
6+
7+
That in turn was based on (and fully compatible with) the mod "carts"
8+
by PilzAdam
9+
10+
The model was redone, but based on github.com/stujones11/railcart, CC-0
11+
12+
Cart Textures are based on original work from PixelBOX (WTFPL).
13+
14+
15+
Features
16+
----------
17+
- A fast cart for your railway or roller coaster (up to 7 m/s!)
18+
- Boost and brake rails
19+
- Rail junction switching with the 'right-left' walking keys
20+
- Handbrake with the 'back' key

‎mods/carts/depends.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
default

‎mods/carts/functions.lua

+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
function carts:get_sign(z)
2+
if z == 0 then
3+
return 0
4+
else
5+
return z / math.abs(z)
6+
end
7+
end
8+
9+
function carts:manage_attachment(player, obj)
10+
if not player then
11+
return
12+
end
13+
local status = obj ~= nil
14+
local player_name = player:get_player_name()
15+
if default.player_attached[player_name] == status then
16+
return
17+
end
18+
default.player_attached[player_name] = status
19+
20+
if status then
21+
player:set_attach(obj, "", {x=0, y=6, z=0}, {x=0, y=0, z=0})
22+
player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
23+
else
24+
player:set_detach()
25+
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
26+
end
27+
end
28+
29+
function carts:velocity_to_dir(v)
30+
if math.abs(v.x) > math.abs(v.z) then
31+
return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0}
32+
else
33+
return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)}
34+
end
35+
end
36+
37+
function carts:is_rail(pos, railtype)
38+
local node = minetest.get_node(pos).name
39+
if node == "ignore" then
40+
local vm = minetest.get_voxel_manip()
41+
local emin, emax = vm:read_from_map(pos, pos)
42+
local area = VoxelArea:new{
43+
MinEdge = emin,
44+
MaxEdge = emax,
45+
}
46+
local data = vm:get_data()
47+
local vi = area:indexp(pos)
48+
node = minetest.get_name_from_content_id(data[vi])
49+
end
50+
if minetest.get_item_group(node, "rail") == 0 then
51+
return false
52+
end
53+
if not railtype then
54+
return true
55+
end
56+
return minetest.get_item_group(node, "connect_to_raillike") == railtype
57+
end
58+
59+
function carts:check_front_up_down(pos, dir_, check_up, railtype)
60+
local dir = vector.new(dir_)
61+
local cur
62+
63+
-- Front
64+
dir.y = 0
65+
cur = vector.add(pos, dir)
66+
if carts:is_rail(cur, railtype) then
67+
return dir
68+
end
69+
-- Up
70+
if check_up then
71+
dir.y = 1
72+
cur = vector.add(pos, dir)
73+
if carts:is_rail(cur, railtype) then
74+
return dir
75+
end
76+
end
77+
-- Down
78+
dir.y = -1
79+
cur = vector.add(pos, dir)
80+
if carts:is_rail(cur, railtype) then
81+
return dir
82+
end
83+
return nil
84+
end
85+
86+
function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
87+
local pos = vector.round(pos_)
88+
local cur
89+
local left_check, right_check = true, true
90+
91+
-- Check left and right
92+
local left = {x=0, y=0, z=0}
93+
local right = {x=0, y=0, z=0}
94+
if dir.z ~= 0 and dir.x == 0 then
95+
left.x = -dir.z
96+
right.x = dir.z
97+
elseif dir.x ~= 0 and dir.z == 0 then
98+
left.z = dir.x
99+
right.z = -dir.x
100+
end
101+
102+
if ctrl then
103+
if old_switch == 1 then
104+
left_check = false
105+
elseif old_switch == 2 then
106+
right_check = false
107+
end
108+
if ctrl.left and left_check then
109+
cur = carts:check_front_up_down(pos, left, false, railtype)
110+
if cur then
111+
return cur, 1
112+
end
113+
left_check = false
114+
end
115+
if ctrl.right and right_check then
116+
cur = carts:check_front_up_down(pos, right, false, railtype)
117+
if cur then
118+
return cur, 2
119+
end
120+
right_check = true
121+
end
122+
end
123+
124+
-- Normal
125+
cur = carts:check_front_up_down(pos, dir, true, railtype)
126+
if cur then
127+
return cur
128+
end
129+
130+
-- Left, if not already checked
131+
if left_check then
132+
cur = carts:check_front_up_down(pos, left, false, railtype)
133+
if cur then
134+
return cur
135+
end
136+
end
137+
138+
-- Right, if not already checked
139+
if right_check then
140+
cur = carts:check_front_up_down(pos, right, false, railtype)
141+
if cur then
142+
return cur
143+
end
144+
end
145+
146+
-- Backwards
147+
if not old_switch then
148+
cur = carts:check_front_up_down(pos, {
149+
x = -dir.x,
150+
y = dir.y,
151+
z = -dir.z
152+
}, true, railtype)
153+
if cur then
154+
return cur
155+
end
156+
end
157+
158+
return {x=0, y=0, z=0}
159+
end
160+
161+
function carts:pathfinder(pos_, expected_pos, old_dir, ctrl, pf_switch, railtype)
162+
local pos = vector.round(pos_)
163+
local pf_pos = vector.round(expected_pos)
164+
local pf_dir = vector.new(old_dir)
165+
166+
for i = 1, 3 do
167+
if vector.equals(pf_pos, pos) then
168+
-- Success! Cart moved on correctly
169+
return true
170+
end
171+
172+
pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype)
173+
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
174+
-- No way forwards
175+
return false
176+
end
177+
178+
pf_pos = vector.add(pf_pos, pf_dir)
179+
end
180+
-- Cart not found
181+
return false
182+
end
183+
184+
function carts:register_rail(name, def, railparams)
185+
local def_default = {
186+
drawtype = "raillike",
187+
paramtype = "light",
188+
sunlight_propagates = true,
189+
is_ground_content = true,
190+
walkable = false,
191+
selection_box = {
192+
type = "fixed",
193+
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
194+
},
195+
sounds = default.node_sound_metal_defaults()
196+
}
197+
for k, v in pairs(def_default) do
198+
def[k] = v
199+
end
200+
if not def.inventory_image then
201+
def.wield_image = def.tiles[1]
202+
def.inventory_image = def.tiles[1]
203+
end
204+
205+
if railparams then
206+
carts.railparams[name] = table.copy(railparams)
207+
end
208+
209+
minetest.register_node(name, def)
210+
end
211+
212+
function carts:get_rail_groups(additional_groups)
213+
-- Get the default rail groups and add more when a table is given
214+
local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1}
215+
if type(additional_groups) == "table" then
216+
for k, v in pairs(additional_groups) do
217+
groups[k] = v
218+
end
219+
end
220+
return groups
221+
end

0 commit comments

Comments
 (0)
Please sign in to comment.