├── .gitignore ├── README.md ├── cart_entity.lua ├── detector.lua ├── doc └── mod_api.txt ├── functions.lua ├── init.lua ├── mod.conf ├── models ├── cart.png └── cart.x ├── rails.lua ├── screenshot.png ├── settingtypes.txt ├── sounds ├── cart_rail.1.ogg ├── cart_rail.2.ogg └── cart_rail.3.ogg └── textures ├── cart_bottom.png ├── cart_side.png ├── cart_top.png ├── carts_rail_crossing.png ├── carts_rail_crossing_brk.png ├── carts_rail_crossing_cp.png ├── carts_rail_crossing_dtc.png ├── carts_rail_crossing_dtc_on.png ├── carts_rail_crossing_pwr.png ├── carts_rail_crossing_ss.png ├── carts_rail_curved.png ├── carts_rail_curved_brk.png ├── carts_rail_curved_cp.png ├── carts_rail_curved_dtc.png ├── carts_rail_curved_dtc_on.png ├── carts_rail_curved_pwr.png ├── carts_rail_curved_ss.png ├── carts_rail_straight.png ├── carts_rail_straight_brk.png ├── carts_rail_straight_cp.png ├── carts_rail_straight_dtc.png ├── carts_rail_straight_dtc_on.png ├── carts_rail_straight_pwr.png ├── carts_rail_straight_ss.png ├── carts_rail_t_junction.png ├── carts_rail_t_junction_brk.png ├── carts_rail_t_junction_cp.png ├── carts_rail_t_junction_dtc.png ├── carts_rail_t_junction_dtc_on.png ├── carts_rail_t_junction_pwr.png ├── carts_rail_t_junction_ss.png └── templates ├── crossing.png ├── curved.png ├── straight.png └── t_junction.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | *.diff 3 | *.patch 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Boost Cart 2 | Based on (and fully compatible with) the mod "carts" by PilzAdam 3 | and the one contained in the subgame "minetest_game". 4 | Target: Run smoothly as possible, even on laggy servers. 5 | 6 | ## Features 7 | - A fast cart for your railway or roller coaster 8 | - Easily configurable cart speed using the Advanced Settings 9 | - Boost and brake rails 10 | - By mesecons controlled Start-Stop rails 11 | - Detector rails that send a mesecons signal when the cart drives over them 12 | - Rail junction switching with the 'right/left' walking keys 13 | - Handbrake with the 'back' key 14 | - Support for non-minetest_game subgames 15 | - Descend from cart using the `sneak` key 16 | 17 | ## Settings 18 | This mod can be adjusted to fit the preference of a player or server. Use the `Settings -> All Settings` dialog in the main menu or tune your 19 | minetest.conf file manually: 20 | 21 | #### `boost_cart.speed_max = 10` 22 | * Maximal speed of the cart in m/s 23 | * Possible values: 1 ... 100 24 | 25 | #### `boost_cart.punch_speed_max = 7` 26 | * Maximal speed to which the driving player can accelerate the cart by punching from inside the cart. 27 | * Possible values: -1 ... 100 28 | * Value `-1` will disable this feature. 29 | 30 | ## License for everything 31 | CC-0, if not specified otherwise below 32 | 33 | 34 | Authors 35 | --------- 36 | Various authors 37 | - carts_rail_*.png 38 | 39 | kddekadenz 40 | - cart_bottom.png 41 | - cart_side.png 42 | - cart_top.png 43 | 44 | klankbeeld (CC-BY 3.0) 45 | - http://freesound.org/people/klankbeeld/sounds/174042/ 46 | - cart_rail.*.ogg 47 | 48 | Zeg9 49 | - cart.x 50 | - cart.png -------------------------------------------------------------------------------- /cart_entity.lua: -------------------------------------------------------------------------------- 1 | 2 | function boost_cart:on_rail_step(entity, pos, distance) 3 | -- Play rail sound 4 | if entity.sound_counter <= 0 then 5 | minetest.sound_play("cart_rail", { 6 | pos = pos, 7 | max_hear_distance = 40, 8 | gain = 0.5 9 | }) 10 | entity.sound_counter = math.random(4, 15) 11 | end 12 | entity.sound_counter = entity.sound_counter - distance 13 | 14 | if boost_cart.MESECONS then 15 | boost_cart:signal_detector_rail(pos) 16 | end 17 | end 18 | 19 | local cart_entity = { 20 | initial_properties = { 21 | physical = false, 22 | collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, 23 | visual = "mesh", 24 | mesh = "cart.x", 25 | visual_size = {x=1, y=1}, 26 | textures = {"cart.png"}, 27 | }, 28 | 29 | driver = nil, 30 | punched = false, -- used to re-send velocity and position 31 | velocity = {x=0, y=0, z=0}, -- only used on punch 32 | old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch 33 | old_pos = nil, 34 | old_switch = 0, 35 | sound_counter = 0, 36 | railtype = nil, 37 | attached_items = {} 38 | } 39 | 40 | -- Model and textures 41 | if boost_cart.MTG_CARTS then 42 | cart_entity.initial_properties.mesh = "carts_cart.b3d" 43 | cart_entity.initial_properties.textures = {"carts_cart.png"} 44 | end 45 | 46 | function cart_entity:on_rightclick(clicker) 47 | if not clicker or not clicker:is_player() then 48 | return 49 | end 50 | local player_name = clicker:get_player_name() 51 | if self.driver and player_name == self.driver then 52 | boost_cart:manage_attachment(clicker, nil) 53 | elseif not self.driver then 54 | boost_cart:manage_attachment(clicker, self.object) 55 | self.driver = player_name 56 | end 57 | end 58 | 59 | function cart_entity:on_activate(staticdata, dtime_s) 60 | self.object:set_armor_groups({immortal=1}) 61 | self.sound_counter = math.random(4, 15) 62 | 63 | if string.sub(staticdata, 1, string.len("return")) ~= "return" then 64 | return 65 | end 66 | local data = minetest.deserialize(staticdata) 67 | if type(data) ~= "table" then 68 | return 69 | end 70 | self.railtype = data.railtype 71 | self.old_dir = data.old_dir or self.old_dir 72 | self.old_pos = data.old_pos or self.old_pos 73 | -- Correct the position when the cart drives further after the last 'step()' 74 | if self.old_pos and boost_cart:is_rail(self.old_pos, self.railtype) then 75 | self.object:set_pos(self.old_pos) 76 | end 77 | end 78 | 79 | function cart_entity:get_staticdata() 80 | return minetest.serialize({ 81 | railtype = self.railtype, 82 | old_dir = self.old_dir, 83 | old_pos = self.old_pos 84 | }) 85 | end 86 | 87 | -- 0.5.x and later: When the driver leaves 88 | function cart_entity:on_detach_child(child) 89 | if child and child:get_player_name() == self.driver then 90 | boost_cart:manage_attachment(child, nil) 91 | self.driver = nil 92 | end 93 | end 94 | 95 | function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) 96 | local pos = self.object:get_pos() 97 | local vel = self.object:get_velocity() 98 | if not self.railtype or vector.equals(vel, {x=0, y=0, z=0}) then 99 | local node = minetest.get_node(pos).name 100 | self.railtype = minetest.get_item_group(node, "connect_to_raillike") 101 | end 102 | 103 | if not puncher or not puncher:is_player() then 104 | local cart_dir = boost_cart:get_rail_direction(pos, self.old_dir, nil, nil, self.railtype) 105 | if vector.equals(cart_dir, {x=0, y=0, z=0}) then 106 | return 107 | end 108 | self.velocity = vector.multiply(cart_dir, 3) 109 | self.punched = true 110 | return 111 | end 112 | 113 | if puncher:get_player_control().sneak then 114 | -- Pick up cart: Drop all attachments 115 | if self.driver then 116 | if self.old_pos then 117 | self.object:set_pos(self.old_pos) 118 | end 119 | local player = minetest.get_player_by_name(self.driver) 120 | boost_cart:manage_attachment(player, nil) 121 | end 122 | for _, obj_ in pairs(self.attached_items) do 123 | local ent = obj_ and obj_:get_luaentity() 124 | if ent then 125 | obj_:set_detach() 126 | -- Attention! Internal item API 127 | if ent.enable_physics then 128 | ent:enable_physics() 129 | end 130 | end 131 | end 132 | 133 | local leftover = puncher:get_inventory():add_item("main", "carts:cart") 134 | if not leftover:is_empty() then 135 | minetest.add_item(pos, leftover) 136 | end 137 | 138 | self.object:remove() 139 | return 140 | end 141 | 142 | -- Driver punches to accelerate the cart 143 | if puncher:get_player_name() == self.driver then 144 | if math.abs(vel.x + vel.z) > boost_cart.punch_speed_max then 145 | return 146 | end 147 | end 148 | 149 | local punch_dir = boost_cart:velocity_to_dir(puncher:get_look_dir()) 150 | punch_dir.y = 0 151 | local cart_dir = boost_cart:get_rail_direction(pos, punch_dir, nil, nil, self.railtype) 152 | if vector.equals(cart_dir, {x=0, y=0, z=0}) then 153 | return 154 | end 155 | 156 | local punch_interval = 1 157 | -- Faulty tool registrations may cause the interval to be set to 0 ! 158 | if tool_capabilities and (tool_capabilities.full_punch_interval or 0) > 0 then 159 | punch_interval = tool_capabilities.full_punch_interval 160 | end 161 | time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval) 162 | local f = 3 * (time_from_last_punch / punch_interval) 163 | 164 | self.velocity = vector.multiply(cart_dir, f) 165 | self.old_dir = cart_dir 166 | self.punched = true 167 | end 168 | 169 | local v3_len = vector.length 170 | function cart_entity:on_step(dtime) 171 | local vel = self.object:get_velocity() 172 | if self.punched then 173 | vel = vector.add(vel, self.velocity) 174 | self.object:set_velocity(vel) 175 | self.old_dir.y = 0 176 | elseif vector.equals(vel, {x=0, y=0, z=0}) then 177 | return 178 | end 179 | 180 | local pos = self.object:get_pos() 181 | local dir = boost_cart:velocity_to_dir(vel) 182 | local dir_changed = not vector.equals(dir, self.old_dir) 183 | local update = {} 184 | 185 | if self.old_pos and not self.punched and not dir_changed then 186 | local flo_pos = vector.round(pos) 187 | local flo_old = vector.round(self.old_pos) 188 | if vector.equals(flo_pos, flo_old) then 189 | -- Do not check one node multiple times 190 | return 191 | end 192 | end 193 | 194 | local ctrl, player 195 | local distance = 1 196 | 197 | -- Get player controls 198 | if self.driver then 199 | player = minetest.get_player_by_name(self.driver) 200 | if player then 201 | ctrl = player:get_player_control() 202 | end 203 | end 204 | 205 | local stop_wiggle = false 206 | if self.old_pos and not dir_changed then 207 | -- Detection for "skipping" nodes (perhaps use average dtime?) 208 | -- It's sophisticated enough to take the acceleration in account 209 | local acc = self.object:get_acceleration() 210 | distance = dtime * (v3_len(vel) + 0.5 * dtime * v3_len(acc)) 211 | 212 | local new_pos, new_dir = boost_cart:pathfinder( 213 | pos, self.old_pos, self.old_dir, distance, ctrl, 214 | self.old_switch, self.railtype 215 | ) 216 | 217 | if new_pos then 218 | -- No rail found: set to the expected position 219 | pos = new_pos 220 | update.pos = true 221 | dir = new_dir 222 | end 223 | elseif self.old_pos and self.old_dir.y ~= 1 and not self.punched then 224 | -- Stop wiggle 225 | stop_wiggle = true 226 | end 227 | 228 | -- dir: New moving direction of the cart 229 | -- switch_keys: Currently pressed L(1) or R(2) key, 230 | -- used to ignore the key on the next rail node 231 | local switch_keys 232 | dir, switch_keys = boost_cart:get_rail_direction( 233 | pos, dir, ctrl, self.old_switch, self.railtype 234 | ) 235 | dir_changed = not vector.equals(dir, self.old_dir) 236 | 237 | local acc = 0 238 | if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then 239 | dir = vector.new(self.old_dir) 240 | vel = {x=0, y=0, z=0} 241 | local pos_r = vector.round(pos) 242 | if not boost_cart:is_rail(pos_r, self.railtype) 243 | and self.old_pos then 244 | pos = self.old_pos 245 | elseif not stop_wiggle then 246 | -- End of rail: Smooth out. 247 | pos = pos_r 248 | dir_changed = false 249 | dir.y = 0 250 | else 251 | pos.y = math.floor(pos.y + 0.5) 252 | end 253 | update.pos = true 254 | update.vel = true 255 | else 256 | -- Direction change detected 257 | if dir_changed then 258 | vel = vector.multiply(dir, math.abs(vel.x + vel.z)) 259 | update.vel = true 260 | if dir.y ~= self.old_dir.y then 261 | pos = vector.round(pos) 262 | update.pos = true 263 | end 264 | end 265 | -- Center on the rail 266 | if dir.z ~= 0 and math.floor(pos.x + 0.5) ~= pos.x then 267 | pos.x = math.floor(pos.x + 0.5) 268 | update.pos = true 269 | end 270 | if dir.x ~= 0 and math.floor(pos.z + 0.5) ~= pos.z then 271 | pos.z = math.floor(pos.z + 0.5) 272 | update.pos = true 273 | end 274 | 275 | -- Calculate current cart acceleration 276 | acc = nil 277 | 278 | local acc_meta = minetest.get_meta(pos):get_string("cart_acceleration") 279 | if acc_meta == "halt" and not self.punched then 280 | -- Stop rail 281 | vel = {x=0, y=0, z=0} 282 | acc = false 283 | pos = vector.round(pos) 284 | update.pos = true 285 | update.vel = true 286 | end 287 | if acc == nil then 288 | -- Meta speed modifier 289 | local speed_mod = tonumber(acc_meta) 290 | if speed_mod and speed_mod ~= 0 then 291 | -- Try to make it similar to the original carts mod 292 | acc = speed_mod * 10 293 | end 294 | end 295 | if acc == nil and boost_cart.MTG_CARTS then 296 | -- MTG Cart API adaption 297 | local rail_node = minetest.get_node(vector.round(pos)) 298 | local railparam = carts.railparams[rail_node.name] 299 | if railparam and railparam.acceleration then 300 | acc = railparam.acceleration 301 | end 302 | end 303 | if acc ~= false then 304 | -- Handbrake 305 | if ctrl and ctrl.down then 306 | acc = (acc or 0) - 2 307 | elseif acc == nil then 308 | acc = -0.4 309 | end 310 | end 311 | if ctrl and ctrl.sneak then 312 | -- Descend when sneak is pressed 313 | boost_cart:manage_attachment(player, nil) 314 | player = nil 315 | ctrl = nil 316 | end 317 | 318 | if acc then 319 | -- Slow down or speed up, depending on Y direction 320 | acc = acc + dir.y * -4 321 | else 322 | acc = 0 323 | end 324 | end 325 | 326 | -- Limit cart speed 327 | local vel_len = vector.length(vel) 328 | if vel_len > boost_cart.speed_max then 329 | vel = vector.multiply(vel, boost_cart.speed_max / vel_len) 330 | update.vel = true 331 | end 332 | if vel_len >= boost_cart.speed_max and acc > 0 then 333 | acc = 0 334 | end 335 | 336 | self.object:set_acceleration(vector.multiply(dir, acc)) 337 | 338 | self.old_pos = vector.round(pos) 339 | local old_y_dir = self.old_dir.y -- For player tilt 340 | self.old_dir = vector.new(dir) 341 | self.old_switch = switch_keys 342 | 343 | boost_cart:on_rail_step(self, self.old_pos, distance) 344 | 345 | if self.punched then 346 | -- Collect dropped items 347 | for _, obj_ in pairs(minetest.get_objects_inside_radius(pos, 1)) do 348 | local ent = obj_:get_luaentity() 349 | -- Attention! Physics must be disabled prior to attach 350 | if ent and ent.name == "__builtin:item" and not obj_:get_attach() then 351 | -- Check API to support 5.2.0 and older 352 | if ent.disable_physics then 353 | ent:disable_physics() 354 | end 355 | 356 | obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}) 357 | self.attached_items[#self.attached_items + 1] = obj_ 358 | end 359 | end 360 | self.punched = false 361 | update.vel = true 362 | end 363 | 364 | if not (update.vel or update.pos) then 365 | return 366 | end 367 | 368 | local yaw = 0 369 | if dir.x < 0 then 370 | yaw = 0.5 371 | elseif dir.x > 0 then 372 | yaw = 1.5 373 | elseif dir.z < 0 then 374 | yaw = 1 375 | end 376 | self.object:set_yaw(yaw * math.pi) 377 | 378 | local anim = {x=0, y=0} 379 | if dir.y == -1 then 380 | anim = {x=1, y=1} 381 | elseif dir.y == 1 then 382 | anim = {x=2, y=2} 383 | end 384 | self.object:set_animation(anim, 1, 0) 385 | 386 | -- Change player model rotation, depending on the Y direction 387 | if player and dir.y ~= old_y_dir then 388 | local feet = {x=0, y=-4, z=0} 389 | local eye = {x=0, y=-4, z=0} 390 | 391 | if dir.y ~= 0 then 392 | -- TODO: Find a better way to calculate this 393 | feet.y = feet.y + 4 394 | feet.z = -dir.y * 2 395 | 396 | eye.z = -dir.y * 8 397 | end 398 | player:set_attach(self.object, "", feet, 399 | {x=dir.y * -30, y=0, z=0}) 400 | player:set_eye_offset(eye, eye) 401 | end 402 | 403 | if update.vel then 404 | self.object:set_velocity(vel) 405 | end 406 | if update.pos then 407 | if dir_changed then 408 | self.object:set_pos(pos) 409 | else 410 | self.object:move_to(pos) 411 | end 412 | end 413 | end 414 | 415 | minetest.register_entity(":carts:cart", cart_entity) 416 | 417 | -- Register item to place the entity 418 | if not boost_cart.MTG_CARTS then 419 | minetest.register_craftitem(":carts:cart", { 420 | description = "Cart (Sneak+Click to pick up)", 421 | inventory_image = minetest.inventorycube( 422 | "cart_top.png", 423 | "cart_side.png", 424 | "cart_side.png" 425 | ), 426 | wield_image = "cart_side.png", 427 | on_place = function(itemstack, placer, pointed_thing) 428 | if not pointed_thing.type == "node" then 429 | return 430 | end 431 | if boost_cart:is_rail(pointed_thing.under) then 432 | minetest.add_entity(pointed_thing.under, "carts:cart") 433 | elseif boost_cart:is_rail(pointed_thing.above) then 434 | minetest.add_entity(pointed_thing.above, "carts:cart") 435 | else 436 | return 437 | end 438 | 439 | if not minetest.settings:get_bool("creative_mode") then 440 | itemstack:take_item() 441 | end 442 | return itemstack 443 | end, 444 | }) 445 | 446 | minetest.register_craft({ 447 | output = "carts:cart", 448 | recipe = { 449 | {"default:steel_ingot", "", "default:steel_ingot"}, 450 | {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, 451 | }, 452 | }) 453 | end 454 | -------------------------------------------------------------------------------- /detector.lua: -------------------------------------------------------------------------------- 1 | local mesecons_rules = mesecon.rules.flat 2 | 3 | function boost_cart:turnoff_detector_rail(pos) 4 | local node = minetest.get_node(pos) 5 | if minetest.get_item_group(node.name, "detector_rail") == 1 then 6 | if node.name == "boost_cart:detectorrail_on" then --has not been dug 7 | minetest.swap_node(pos, {name = "boost_cart:detectorrail", param2=node.param2}) 8 | end 9 | mesecon.receptor_off(pos, mesecons_rules) 10 | end 11 | end 12 | 13 | function boost_cart:signal_detector_rail(pos) 14 | local node = minetest.get_node(pos) 15 | if minetest.get_item_group(node.name, "detector_rail") ~= 1 then 16 | return 17 | end 18 | 19 | if node.name == "boost_cart:detectorrail" then 20 | minetest.swap_node(pos, {name = "boost_cart:detectorrail_on", param2=node.param2}) 21 | end 22 | mesecon.receptor_on(pos, mesecons_rules) 23 | minetest.after(0.5, boost_cart.turnoff_detector_rail, boost_cart, pos) 24 | end 25 | 26 | boost_cart:register_rail("boost_cart:detectorrail", { 27 | description = "Detector rail", 28 | tiles = { 29 | "carts_rail_straight_dtc.png", "carts_rail_curved_dtc.png", 30 | "carts_rail_t_junction_dtc.png", "carts_rail_crossing_dtc.png" 31 | }, 32 | groups = boost_cart:get_rail_groups({detector_rail = 1}), 33 | 34 | mesecons = {receptor = {state = "off", rules = mesecons_rules}}, 35 | }) 36 | 37 | boost_cart:register_rail("boost_cart:detectorrail_on", { 38 | description = "Detector rail ON (you hacker you)", 39 | tiles = { 40 | "carts_rail_straight_dtc_on.png", "carts_rail_curved_dtc_on.png", 41 | "carts_rail_t_junction_dtc_on.png", "carts_rail_crossing_dtc_on.png" 42 | }, 43 | groups = boost_cart:get_rail_groups({ 44 | detector_rail = 1, not_in_creative_inventory = 1 45 | }), 46 | drop = "boost_cart:detectorrail", 47 | 48 | mesecons = {receptor = {state = "on", rules = mesecons_rules}}, 49 | }) 50 | 51 | minetest.register_craft({ 52 | output = "boost_cart:detectorrail 6", 53 | recipe = { 54 | {"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"}, 55 | {"default:steel_ingot", "group:stick", "default:steel_ingot"}, 56 | {"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"}, 57 | }, 58 | }) 59 | -------------------------------------------------------------------------------- /doc/mod_api.txt: -------------------------------------------------------------------------------- 1 | boost_cart API 2 | ============== 3 | 4 | This file provides information about the API of boost_cart for the use in 5 | mods. The API might change slightly when the development goes on, so avoid 6 | using internal tables or functions which are not documented here. 7 | 8 | 9 | Types 10 | ----- 11 | 12 | * `SwitchIgnore` -> `number/nil` 13 | * Specifies which player control was pressed. This value is used to prefer 14 | straight rails instead of preferring left and right rail checks. 15 | * `1`: Ignore left rail 16 | * `2`: Ignore right rail 17 | * `nil`: Ignore no rail 18 | 19 | 20 | Entity movement 21 | --------------- 22 | These functions are grouped so that they make sense and then sorted alphabetically. 23 | 24 | * `boost_cart:manage_attachment(player, obj)` 25 | * Attaches or detaches the player to/from an object, depending on what is 26 | supplied to `obj`. 27 | * `player`: `ObjectRef` of the player 28 | * `obj`: `ObjectRef` (to attach) or `nil` (to detach) 29 | * `boost_cart:get_sign(n)` -> `number` 30 | * Returns the sign for the given number. Values: `-1`, `0`, `1` 31 | * `n`: any `number` 32 | * `boost_cart:velocity_to_dir(vel)` -> `vector` 33 | * Returns the cart direction depending on `vel`. Each coordinate can have 34 | one of the `get_sign()` return values. 35 | * `vel`: velocity as `vector` 36 | * `boost_cart:boost_rail(pos, amount)` 37 | * Sets the rail acceleration for the given position to `amount` and punches 38 | carts which are at the given position. 39 | * `pos`: `vector`, rail position 40 | * `amount`: `number`, negative to brake, positive to boost 41 | * `boost_cart:get_rail_direction(pos, dir, ctrl, old_switch, railtype)` 42 | -> `vector, SwitchIgnore` 43 | * Returns the direction to where the next rail is, and which player control that 44 | should be ignored in the next call. 45 | * `pos`: `vector`, position of the cart 46 | * `dir`: `vector`, movement direction of the cart (see `velocity_to_dir()`) 47 | * `ctrl`: Player controls table or `nil` (no player) 48 | * `old_switch`: `SwitchIgnore` 49 | * `railtype`: (optional) `number`, gets passed indirectly to `is_rail()` 50 | 51 | 52 | Rail helper functions 53 | --------------------- 54 | * `boost_cart:get_rail_groups(groups)` -> `table` 55 | * Returns a group table with preset values for a common rail node 56 | * `groups`: (optional) `table`, additional groups append (or overwrite) 57 | * Hint: To register an incompatible rail type, set the group 58 | `connect_to_raillike` to the value returned by 59 | `minetest.raillike_group(new_rail_type)` 60 | * `boost_cart:is_rail(pos, [railtype])` -> `boolean` 61 | * Returns whether the node at `pos` is a rail. When `railtype` is specified, 62 | `true` is only returned when the node is in the same rail group. 63 | * `pos`: `vector` of the node to check 64 | * `railtype`: (optional) `number`, rail group number 65 | * `boost_cart:register_rail(name, def)` 66 | * Registers a new rail with preset node definition defaults as fallback 67 | * `name`: `string`, node name of the new rail 68 | * `def`: Node definition table, containing at least the following keys: 69 | * `description` 70 | * `groups` 71 | * `tiles` 72 | -------------------------------------------------------------------------------- /functions.lua: -------------------------------------------------------------------------------- 1 | function boost_cart: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 boost_cart:manage_attachment(player, obj) 10 | if not player then 11 | return 12 | end 13 | local do_attach = obj ~= nil 14 | 15 | if obj and player:get_attach() == obj then 16 | return 17 | end 18 | 19 | if boost_cart.PLAYER_API then 20 | local player_name = player:get_player_name() 21 | player_api.player_attached[player_name] = do_attach 22 | end 23 | 24 | if do_attach then 25 | player:set_attach(obj, "", {x=0, y=-4, z=0}, {x=0, y=0, z=0}) 26 | player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0}) 27 | 28 | if boost_cart.PLAYER_API then 29 | -- player_api does not update the animation 30 | -- when the player is attached, reset to default animation 31 | player_api.set_animation(player, "stand") 32 | end 33 | else 34 | player:set_detach() 35 | player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0}) 36 | -- HACK in effect! Force updating the attachment rotation 37 | player:set_properties({}) 38 | end 39 | end 40 | 41 | function boost_cart:velocity_to_dir(v) 42 | if math.abs(v.x) > math.abs(v.z) then 43 | return {x=self:get_sign(v.x), y=self:get_sign(v.y), z=0} 44 | else 45 | return {x=0, y=self:get_sign(v.y), z=self:get_sign(v.z)} 46 | end 47 | end 48 | 49 | local get_node = minetest.get_node 50 | local get_item_group = minetest.get_item_group 51 | function boost_cart:is_rail(pos, railtype) 52 | local node = get_node(pos).name 53 | if node == "ignore" then 54 | local vm = minetest.get_voxel_manip() 55 | local emin, emax = vm:read_from_map(pos, pos) 56 | local area = VoxelArea:new{ 57 | MinEdge = emin, 58 | MaxEdge = emax, 59 | } 60 | local data = vm:get_data() 61 | local vi = area:indexp(pos) 62 | node = minetest.get_name_from_content_id(data[vi]) 63 | end 64 | if get_item_group(node, "rail") == 0 then 65 | return false 66 | end 67 | if not railtype then 68 | return true 69 | end 70 | return get_item_group(node, "connect_to_raillike") == railtype 71 | end 72 | 73 | function boost_cart:check_front_up_down(pos, dir_, check_up, railtype) 74 | local dir = vector.new(dir_) 75 | local cur = nil 76 | 77 | -- Front 78 | dir.y = 0 79 | cur = vector.add(pos, dir) 80 | if self:is_rail(cur, railtype) then 81 | return dir 82 | end 83 | -- Up 84 | if check_up then 85 | dir.y = 1 86 | cur = vector.add(pos, dir) 87 | if self:is_rail(cur, railtype) then 88 | return dir 89 | end 90 | end 91 | -- Down 92 | dir.y = -1 93 | cur = vector.add(pos, dir) 94 | if self:is_rail(cur, railtype) then 95 | return dir 96 | end 97 | return nil 98 | end 99 | 100 | function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype) 101 | local pos = vector.round(pos_) 102 | local cur = nil 103 | local left_check, right_check = true, true 104 | 105 | -- Check left and right 106 | local left = {x=0, y=0, z=0} 107 | local right = {x=0, y=0, z=0} 108 | if dir.z ~= 0 and dir.x == 0 then 109 | left.x = -dir.z 110 | right.x = dir.z 111 | elseif dir.x ~= 0 and dir.z == 0 then 112 | left.z = dir.x 113 | right.z = -dir.x 114 | end 115 | 116 | local straight_priority = ctrl and dir.y ~= 0 117 | 118 | -- Normal, to disallow rail switching up- & downhill 119 | if straight_priority then 120 | cur = self:check_front_up_down(pos, dir, true, railtype) 121 | if cur then 122 | return cur 123 | end 124 | end 125 | 126 | if ctrl then 127 | if old_switch == 1 then 128 | left_check = false 129 | elseif old_switch == 2 then 130 | right_check = false 131 | end 132 | if ctrl.left and left_check then 133 | cur = self:check_front_up_down(pos, left, false, railtype) 134 | if cur then 135 | return cur, 1 136 | end 137 | left_check = false 138 | end 139 | if ctrl.right and right_check then 140 | cur = self:check_front_up_down(pos, right, false, railtype) 141 | if cur then 142 | return cur, 2 143 | end 144 | right_check = true 145 | end 146 | end 147 | 148 | -- Normal 149 | if not straight_priority then 150 | cur = self:check_front_up_down(pos, dir, true, railtype) 151 | if cur then 152 | return cur 153 | end 154 | end 155 | 156 | -- Left, if not already checked 157 | if left_check then 158 | cur = self:check_front_up_down(pos, left, false, railtype) 159 | if cur then 160 | return cur 161 | end 162 | end 163 | 164 | -- Right, if not already checked 165 | if right_check then 166 | cur = self:check_front_up_down(pos, right, false, railtype) 167 | if cur then 168 | return cur 169 | end 170 | end 171 | 172 | -- Backwards 173 | if not old_switch then 174 | cur = self:check_front_up_down(pos, { 175 | x = -dir.x, 176 | y = dir.y, 177 | z = -dir.z 178 | }, true, railtype) 179 | if cur then 180 | return cur 181 | end 182 | end 183 | 184 | return {x=0, y=0, z=0} 185 | end 186 | 187 | function boost_cart:pathfinder(pos_, old_pos, old_dir, distance, ctrl, 188 | pf_switch, railtype) 189 | 190 | local pos = vector.round(pos_) 191 | if vector.equals(old_pos, pos) then 192 | return 193 | end 194 | 195 | local pf_pos = vector.round(old_pos) 196 | local pf_dir = vector.new(old_dir) 197 | distance = math.min(boost_cart.path_distance_max, 198 | math.floor(distance + 1)) 199 | 200 | for i = 1, distance do 201 | pf_dir, pf_switch = self:get_rail_direction( 202 | pf_pos, pf_dir, ctrl, pf_switch or 0, railtype) 203 | 204 | if vector.equals(pf_dir, {x=0, y=0, z=0}) then 205 | -- No way forwards 206 | return pf_pos, pf_dir 207 | end 208 | 209 | pf_pos = vector.add(pf_pos, pf_dir) 210 | 211 | if vector.equals(pf_pos, pos) then 212 | -- Success! Cart moved on correctly 213 | return 214 | end 215 | end 216 | -- Not found. Put cart to predicted position 217 | return pf_pos, pf_dir 218 | end 219 | 220 | function boost_cart:boost_rail(pos, amount) 221 | minetest.get_meta(pos):set_string("cart_acceleration", tostring(amount)) 222 | for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 0.5)) do 223 | if not obj_:is_player() and 224 | obj_:get_luaentity() and 225 | obj_:get_luaentity().name == "carts:cart" then 226 | obj_:get_luaentity():on_punch() 227 | end 228 | end 229 | end 230 | 231 | function boost_cart:register_rail(name, def_overwrite) 232 | local sound_func = default.node_sound_metal_defaults 233 | or default.node_sound_defaults 234 | 235 | local def = { 236 | drawtype = "raillike", 237 | paramtype = "light", 238 | sunlight_propagates = true, 239 | is_ground_content = false, 240 | walkable = false, 241 | selection_box = { 242 | type = "fixed", 243 | fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, 244 | }, 245 | sounds = sound_func() 246 | } 247 | for k, v in pairs(def_overwrite) do 248 | def[k] = v 249 | end 250 | if not def.inventory_image then 251 | def.wield_image = def.tiles[1] 252 | def.inventory_image = def.tiles[1] 253 | end 254 | 255 | minetest.register_node(name, def) 256 | end 257 | 258 | function boost_cart:get_rail_groups(additional_groups) 259 | -- Get the default rail groups and add more when a table is given 260 | local groups = { 261 | dig_immediate = 2, 262 | attached_node = 1, 263 | rail = 1, 264 | connect_to_raillike = 1 265 | } 266 | if minetest.raillike_group then 267 | groups.connect_to_raillike = minetest.raillike_group("rail") 268 | end 269 | if type(additional_groups) == "table" then 270 | for k, v in pairs(additional_groups) do 271 | groups[k] = v 272 | end 273 | end 274 | return groups 275 | end 276 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | 2 | if not minetest.features.object_use_texture_alpha then 3 | error("[boost_cart] Your Minetest version is no longer supported." 4 | .. " (Version < 5.0.0)") 5 | end 6 | 7 | boost_cart = {} 8 | boost_cart.modpath = minetest.get_modpath("boost_cart") 9 | boost_cart.MESECONS = minetest.global_exists("mesecon") 10 | boost_cart.MTG_CARTS = minetest.global_exists("carts") and carts.pathfinder 11 | boost_cart.PLAYER_API = minetest.global_exists("player_api") 12 | 13 | local function getNum(setting) 14 | return tonumber(minetest.settings:get(setting)) 15 | end 16 | 17 | -- Maximal speed of the cart in m/s 18 | boost_cart.speed_max = getNum("boost_cart.speed_max") or 10 19 | -- Set to -1 to disable punching the cart from inside 20 | boost_cart.punch_speed_max = getNum("boost_cart.punch_speed_max") or 7 21 | -- Maximal distance for the path correction (for dtime peaks) 22 | boost_cart.path_distance_max = 4 23 | 24 | 25 | dofile(boost_cart.modpath.."/functions.lua") 26 | dofile(boost_cart.modpath.."/rails.lua") 27 | 28 | if boost_cart.MESECONS then 29 | dofile(boost_cart.modpath.."/detector.lua") 30 | --else 31 | -- minetest.register_alias("carts:powerrail", "boost_cart:detectorrail") 32 | -- minetest.register_alias("carts:powerrail", "boost_cart:detectorrail_on") 33 | end 34 | 35 | if boost_cart.MTG_CARTS then 36 | minetest.log("action", "[boost_cart] Overwriting definitions of similar carts mod") 37 | end 38 | dofile(boost_cart.modpath.."/cart_entity.lua") 39 | -------------------------------------------------------------------------------- /mod.conf: -------------------------------------------------------------------------------- 1 | name = boost_cart 2 | description = """ 3 | Boost Cart 4 | The mod that add a cart and new kinds of rails to your world. 5 | """ 6 | depends = default 7 | optional_depends = mesecons, moreores, carts, player_api 8 | -------------------------------------------------------------------------------- /models/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/models/cart.png -------------------------------------------------------------------------------- /models/cart.x: -------------------------------------------------------------------------------- 1 | xof 0303txt 0032 2 | 3 | Frame Root { 4 | FrameTransformMatrix { 5 | 1.000000, 0.000000, 0.000000, 0.000000, 6 | 0.000000, 0.000000, 1.000000, 0.000000, 7 | 0.000000, 1.000000,-0.000000, 0.000000, 8 | 0.000000, 0.000000, 0.000000, 1.000000;; 9 | } 10 | Frame Cube { 11 | FrameTransformMatrix { 12 | 5.000000, 0.000000,-0.000000, 0.000000, 13 | -0.000000, 3.535534, 3.535534, 0.000000, 14 | 0.000000,-3.535534, 3.535534, 0.000000, 15 | 0.000000,-3.000000, 3.000000, 1.000000;; 16 | } 17 | Mesh { //Cube_001 Mesh 18 | 72; 19 | -1.000000; 1.000000;-1.000000;, 20 | -1.000000;-1.000000;-1.000000;, 21 | 1.000000;-1.000000;-1.000000;, 22 | 1.000000; 1.000000;-1.000000;, 23 | -0.833334;-1.000000; 1.000000;, 24 | -1.000000;-1.000000; 1.000000;, 25 | -1.000000;-0.833333; 1.000000;, 26 | -0.833334;-0.833333; 1.000000;, 27 | -1.000000;-1.000000;-1.000000;, 28 | -1.000000;-1.000000; 1.000000;, 29 | 0.999999;-1.000001; 1.000000;, 30 | 1.000000;-1.000000;-1.000000;, 31 | 0.999999;-1.000001; 1.000000;, 32 | 0.833332;-1.000000; 1.000000;, 33 | 0.833333;-0.833334; 1.000000;, 34 | 1.000000;-0.833334; 1.000000;, 35 | 0.833332;-1.000000; 1.000000;, 36 | -0.833334;-1.000000; 1.000000;, 37 | -0.833334;-0.833333; 1.000000;, 38 | 0.833333;-0.833334; 1.000000;, 39 | 1.000000; 0.833333; 1.000000;, 40 | 0.833334; 0.833333; 1.000000;, 41 | 0.833334; 1.000000; 1.000000;, 42 | 1.000000; 0.999999; 1.000000;, 43 | 1.000000;-0.833334; 1.000000;, 44 | 0.833333;-0.833334; 1.000000;, 45 | 0.833334; 0.833333; 1.000000;, 46 | 1.000000; 0.833333; 1.000000;, 47 | 0.833334; 0.833333; 1.000000;, 48 | -0.833333; 0.833333; 1.000000;, 49 | -0.833333; 1.000000; 1.000000;, 50 | 0.833334; 1.000000; 1.000000;, 51 | 0.833334; 0.833333;-0.800000;, 52 | -0.833333; 0.833333;-0.800000;, 53 | -0.833333; 0.833333; 1.000000;, 54 | 0.833334; 0.833333; 1.000000;, 55 | -0.833333; 0.833333; 1.000000;, 56 | -1.000000; 0.833333; 1.000000;, 57 | -1.000000; 1.000000; 1.000000;, 58 | -0.833333; 1.000000; 1.000000;, 59 | -0.833334;-0.833333; 1.000000;, 60 | -1.000000;-0.833333; 1.000000;, 61 | -1.000000; 0.833333; 1.000000;, 62 | -0.833333; 0.833333; 1.000000;, 63 | 0.833333;-0.833334;-0.800000;, 64 | -0.833334;-0.833333;-0.800000;, 65 | -0.833333; 0.833333;-0.800000;, 66 | 0.833334; 0.833333;-0.800000;, 67 | -0.833333; 0.833333;-0.800000;, 68 | -0.833334;-0.833333;-0.800000;, 69 | -0.833334;-0.833333; 1.000000;, 70 | -0.833333; 0.833333; 1.000000;, 71 | -0.833334;-0.833333;-0.800000;, 72 | 0.833333;-0.833334;-0.800000;, 73 | 0.833333;-0.833334; 1.000000;, 74 | -0.833334;-0.833333; 1.000000;, 75 | 0.833333;-0.833334;-0.800000;, 76 | 0.833334; 0.833333;-0.800000;, 77 | 0.833334; 0.833333; 1.000000;, 78 | 0.833333;-0.833334; 1.000000;, 79 | -1.000000; 1.000000;-1.000000;, 80 | -1.000000; 1.000000; 1.000000;, 81 | -1.000000;-1.000000; 1.000000;, 82 | -1.000000;-1.000000;-1.000000;, 83 | -1.000000; 1.000000; 1.000000;, 84 | -1.000000; 1.000000;-1.000000;, 85 | 1.000000; 1.000000;-1.000000;, 86 | 1.000000; 0.999999; 1.000000;, 87 | 1.000000;-1.000000;-1.000000;, 88 | 0.999999;-1.000001; 1.000000;, 89 | 1.000000; 0.999999; 1.000000;, 90 | 1.000000; 1.000000;-1.000000;; 91 | 18; 92 | 4;0;1;2;3;, 93 | 4;4;5;6;7;, 94 | 4;8;9;10;11;, 95 | 4;12;13;14;15;, 96 | 4;16;17;18;19;, 97 | 4;20;21;22;23;, 98 | 4;24;25;26;27;, 99 | 4;28;29;30;31;, 100 | 4;32;33;34;35;, 101 | 4;36;37;38;39;, 102 | 4;40;41;42;43;, 103 | 4;44;45;46;47;, 104 | 4;48;49;50;51;, 105 | 4;52;53;54;55;, 106 | 4;56;57;58;59;, 107 | 4;60;61;62;63;, 108 | 4;64;65;66;67;, 109 | 4;68;69;70;71;; 110 | MeshNormals { //Cube_001 Normals 111 | 72; 112 | 0.000000; 0.000000;-1.000000;, 113 | 0.000000; 0.000000;-1.000000;, 114 | 0.000000; 0.000000;-1.000000;, 115 | 0.000000; 0.000000;-1.000000;, 116 | 0.000000;-0.000000; 1.000000;, 117 | 0.000000;-0.000000; 1.000000;, 118 | 0.000000;-0.000000; 1.000000;, 119 | 0.000000;-0.000000; 1.000000;, 120 | -0.000000;-1.000000;-0.000000;, 121 | -0.000000;-1.000000;-0.000000;, 122 | -0.000000;-1.000000;-0.000000;, 123 | -0.000000;-1.000000;-0.000000;, 124 | 0.000000;-0.000000; 1.000000;, 125 | 0.000000;-0.000000; 1.000000;, 126 | 0.000000;-0.000000; 1.000000;, 127 | 0.000000;-0.000000; 1.000000;, 128 | 0.000000;-0.000000; 1.000000;, 129 | 0.000000;-0.000000; 1.000000;, 130 | 0.000000;-0.000000; 1.000000;, 131 | 0.000000;-0.000000; 1.000000;, 132 | 0.000000;-0.000000; 1.000000;, 133 | 0.000000;-0.000000; 1.000000;, 134 | 0.000000;-0.000000; 1.000000;, 135 | 0.000000;-0.000000; 1.000000;, 136 | 0.000000;-0.000000; 1.000000;, 137 | 0.000000;-0.000000; 1.000000;, 138 | 0.000000;-0.000000; 1.000000;, 139 | 0.000000;-0.000000; 1.000000;, 140 | 0.000000;-0.000000; 1.000000;, 141 | 0.000000;-0.000000; 1.000000;, 142 | 0.000000;-0.000000; 1.000000;, 143 | 0.000000;-0.000000; 1.000000;, 144 | -0.000000;-1.000000; 0.000000;, 145 | -0.000000;-1.000000; 0.000000;, 146 | -0.000000;-1.000000; 0.000000;, 147 | -0.000000;-1.000000; 0.000000;, 148 | 0.000000;-0.000000; 1.000000;, 149 | 0.000000;-0.000000; 1.000000;, 150 | 0.000000;-0.000000; 1.000000;, 151 | 0.000000;-0.000000; 1.000000;, 152 | 0.000000;-0.000000; 1.000000;, 153 | 0.000000;-0.000000; 1.000000;, 154 | 0.000000;-0.000000; 1.000000;, 155 | 0.000000;-0.000000; 1.000000;, 156 | 0.000000;-0.000000; 1.000000;, 157 | 0.000000;-0.000000; 1.000000;, 158 | 0.000000;-0.000000; 1.000000;, 159 | 0.000000;-0.000000; 1.000000;, 160 | 1.000000;-0.000000; 0.000000;, 161 | 1.000000;-0.000000; 0.000000;, 162 | 1.000000;-0.000000; 0.000000;, 163 | 1.000000;-0.000000; 0.000000;, 164 | 0.000000; 1.000000; 0.000000;, 165 | 0.000000; 1.000000; 0.000000;, 166 | 0.000000; 1.000000; 0.000000;, 167 | 0.000000; 1.000000; 0.000000;, 168 | -1.000000; 0.000000; 0.000000;, 169 | -1.000000; 0.000000; 0.000000;, 170 | -1.000000; 0.000000; 0.000000;, 171 | -1.000000; 0.000000; 0.000000;, 172 | -1.000000; 0.000000;-0.000000;, 173 | -1.000000; 0.000000;-0.000000;, 174 | -1.000000; 0.000000;-0.000000;, 175 | -1.000000; 0.000000;-0.000000;, 176 | 0.000000; 1.000000; 0.000000;, 177 | 0.000000; 1.000000; 0.000000;, 178 | 0.000000; 1.000000; 0.000000;, 179 | 0.000000; 1.000000; 0.000000;, 180 | 1.000000;-0.000000; 0.000000;, 181 | 1.000000;-0.000000; 0.000000;, 182 | 1.000000;-0.000000; 0.000000;, 183 | 1.000000;-0.000000; 0.000000;; 184 | 18; 185 | 4;0;1;2;3;, 186 | 4;4;5;6;7;, 187 | 4;8;9;10;11;, 188 | 4;12;13;14;15;, 189 | 4;16;17;18;19;, 190 | 4;20;21;22;23;, 191 | 4;24;25;26;27;, 192 | 4;28;29;30;31;, 193 | 4;32;33;34;35;, 194 | 4;36;37;38;39;, 195 | 4;40;41;42;43;, 196 | 4;44;45;46;47;, 197 | 4;48;49;50;51;, 198 | 4;52;53;54;55;, 199 | 4;56;57;58;59;, 200 | 4;60;61;62;63;, 201 | 4;64;65;66;67;, 202 | 4;68;69;70;71;; 203 | } //End of Cube_001 Normals 204 | MeshMaterialList { //Cube_001 Material List 205 | 1; 206 | 18; 207 | 0, 208 | 0, 209 | 0, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | 0, 215 | 0, 216 | 0, 217 | 0, 218 | 0, 219 | 0, 220 | 0, 221 | 0, 222 | 0, 223 | 0, 224 | 0;; 225 | Material Material { 226 | 0.640000; 0.640000; 0.640000; 1.000000;; 227 | 96.078431; 228 | 0.500000; 0.500000; 0.500000;; 229 | 0.000000; 0.000000; 0.000000;; 230 | TextureFilename {"cart.png";} 231 | } 232 | } //End of Cube_001 Material List 233 | MeshTextureCoords { //Cube_001 UV Coordinates 234 | 72; 235 | 0.000000; 0.500000;, 236 | 0.500000; 0.500000;, 237 | 0.500000; 1.000000;, 238 | 0.000000; 1.000000;, 239 | 0.031250; 0.500000;, 240 | -0.000000; 0.500000;, 241 | -0.000000; 0.468750;, 242 | 0.031250; 0.468750;, 243 | 0.500000; 0.500000;, 244 | 0.500000; 0.000000;, 245 | 1.000000; 0.000000;, 246 | 1.000000; 0.500000;, 247 | 0.468750; 0.468750;, 248 | 0.500000; 0.468750;, 249 | 0.500000; 0.500000;, 250 | 0.468750; 0.500000;, 251 | 0.031250; 0.468750;, 252 | 0.468750; 0.468750;, 253 | 0.468750; 0.500000;, 254 | 0.031250; 0.500000;, 255 | 0.468750; 0.000000;, 256 | 0.500000; 0.000000;, 257 | 0.500000; 0.031250;, 258 | 0.468750; 0.031250;, 259 | 0.468750; 0.031250;, 260 | 0.500000; 0.031250;, 261 | 0.500000; 0.468750;, 262 | 0.468750; 0.468750;, 263 | 0.468750; 0.031250;, 264 | 0.031250; 0.031250;, 265 | 0.031250; 0.000000;, 266 | 0.468750; 0.000000;, 267 | 1.000000; 0.500000;, 268 | 0.500000; 0.500000;, 269 | 0.500000; 0.000000;, 270 | 1.000000; 0.000000;, 271 | 0.031250; 0.031250;, 272 | 0.000000; 0.031250;, 273 | 0.000000; 0.000000;, 274 | 0.031250; 0.000000;, 275 | 0.031250; 0.468750;, 276 | -0.000000; 0.468750;, 277 | 0.000000; 0.031250;, 278 | 0.031250; 0.031250;, 279 | 0.000000; 0.500000;, 280 | 0.500000; 0.500000;, 281 | 0.500000; 1.000000;, 282 | 0.000000; 1.000000;, 283 | 1.000000; 0.500000;, 284 | 0.500000; 0.500000;, 285 | 0.500000; 0.000000;, 286 | 1.000000; 0.000000;, 287 | 1.000000; 0.500000;, 288 | 0.500000; 0.500000;, 289 | 0.500000; 0.000000;, 290 | 1.000000; 0.000000;, 291 | 1.000000; 0.500000;, 292 | 0.500000; 0.500000;, 293 | 0.500000; 0.000000;, 294 | 1.000000; 0.000000;, 295 | 0.500000; 0.500000;, 296 | 0.500000; 0.000000;, 297 | 1.000000; 0.000000;, 298 | 1.000000; 0.500000;, 299 | 1.000000; 0.000000;, 300 | 1.000000; 0.500000;, 301 | 0.500000; 0.500000;, 302 | 0.500000; 0.000000;, 303 | 0.500000; 0.500000;, 304 | 0.500000; 0.000000;, 305 | 1.000000; 0.000000;, 306 | 1.000000; 0.500000;; 307 | } //End of Cube_001 UV Coordinates 308 | } //End of Cube_001 Mesh 309 | } //End of Cube 310 | } //End of Root Frame 311 | AnimationSet { 312 | Animation { 313 | {Cube} 314 | AnimationKey { //Position 315 | 2; 316 | 4; 317 | 0;3; 0.000000, 0.000000, 0.000000;;, 318 | 1;3; 0.000000, 3.000000, 3.000000;;, 319 | 2;3; 0.000000,-3.000000, 3.000000;;, 320 | 3;3; 0.000000,-3.000000, 3.000000;;; 321 | } 322 | AnimationKey { //Rotation 323 | 0; 324 | 4; 325 | 0;4; -1.000000, 0.000000, 0.000000, 0.000000;;, 326 | 1;4; -0.923880,-0.382683,-0.000000, 0.000000;;, 327 | 2;4; -0.923880, 0.382683, 0.000000, 0.000000;;, 328 | 3;4; -0.923880, 0.382683, 0.000000, 0.000000;;; 329 | } 330 | AnimationKey { //Scale 331 | 1; 332 | 4; 333 | 0;3; 5.000000, 5.000000, 5.000000;;, 334 | 1;3; 5.000000, 5.000000, 5.000000;;, 335 | 2;3; 5.000000, 5.000000, 5.000000;;, 336 | 3;3; 5.000000, 5.000000, 5.000000;;; 337 | } 338 | } 339 | } //End of AnimationSet 340 | -------------------------------------------------------------------------------- /rails.lua: -------------------------------------------------------------------------------- 1 | -- Common rail registrations 2 | 3 | local regular_rail_itemname = "default:rail" 4 | if minetest.registered_nodes["carts:rail"] then 5 | -- MTG Compatibility 6 | regular_rail_itemname = "carts:rail" 7 | end 8 | 9 | boost_cart:register_rail(":"..regular_rail_itemname, { 10 | description = "Rail", 11 | tiles = { 12 | "carts_rail_straight.png", "carts_rail_curved.png", 13 | "carts_rail_t_junction.png", "carts_rail_crossing.png" 14 | }, 15 | groups = boost_cart:get_rail_groups() 16 | }) 17 | 18 | -- Moreores' copper rail 19 | local copperrail_registered = false 20 | if minetest.get_modpath("moreores") then 21 | minetest.register_alias("carts:copperrail", "moreores:copper_rail") 22 | 23 | local raildef = minetest.registered_nodes["moreores:copper_rail"] 24 | if raildef and minetest.raillike_group then 25 | -- Ensure that this rail uses the same connect_to_raillike 26 | raildef.groups.connect_to_raillike = minetest.raillike_group("rail") 27 | minetest.override_item("moreores:copper_rail", { 28 | groups = raildef.groups 29 | }) 30 | copperrail_registered = true 31 | end 32 | end 33 | if not copperrail_registered then 34 | boost_cart:register_rail(":carts:copperrail", { 35 | description = "Copper rail", 36 | tiles = { 37 | "carts_rail_straight_cp.png", "carts_rail_curved_cp.png", 38 | "carts_rail_t_junction_cp.png", "carts_rail_crossing_cp.png" 39 | }, 40 | groups = boost_cart:get_rail_groups() 41 | }) 42 | 43 | minetest.register_craft({ 44 | output = "carts:copperrail 12", 45 | recipe = { 46 | {"default:copper_ingot", "", "default:copper_ingot"}, 47 | {"default:copper_ingot", "group:stick", "default:copper_ingot"}, 48 | {"default:copper_ingot", "", "default:copper_ingot"}, 49 | } 50 | }) 51 | end 52 | 53 | -- Power rail 54 | boost_cart:register_rail(":carts:powerrail", { 55 | description = "Powered rail", 56 | tiles = { 57 | "carts_rail_straight_pwr.png", "carts_rail_curved_pwr.png", 58 | "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png" 59 | }, 60 | groups = boost_cart:get_rail_groups(), 61 | after_place_node = function(pos, placer, itemstack) 62 | if not mesecon then 63 | minetest.get_meta(pos):set_string("cart_acceleration", "0.5") 64 | end 65 | end, 66 | mesecons = { 67 | effector = { 68 | action_on = function(pos, node) 69 | boost_cart:boost_rail(pos, 0.5) 70 | end, 71 | action_off = function(pos, node) 72 | minetest.get_meta(pos):set_string("cart_acceleration", "0") 73 | end, 74 | }, 75 | }, 76 | }) 77 | 78 | minetest.register_craft({ 79 | output = "carts:powerrail 6", 80 | recipe = { 81 | {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"}, 82 | {"default:steel_ingot", "group:stick", "default:steel_ingot"}, 83 | {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"}, 84 | } 85 | }) 86 | 87 | -- Brake rail 88 | boost_cart:register_rail(":carts:brakerail", { 89 | description = "Brake rail", 90 | tiles = { 91 | "carts_rail_straight_brk.png", "carts_rail_curved_brk.png", 92 | "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png" 93 | }, 94 | groups = boost_cart:get_rail_groups(), 95 | after_place_node = function(pos, placer, itemstack) 96 | if not mesecon then 97 | minetest.get_meta(pos):set_string("cart_acceleration", "-0.3") 98 | end 99 | end, 100 | mesecons = { 101 | effector = { 102 | action_on = function(pos, node) 103 | minetest.get_meta(pos):set_string("cart_acceleration", "-0.3") 104 | end, 105 | action_off = function(pos, node) 106 | minetest.get_meta(pos):set_string("cart_acceleration", "0") 107 | end, 108 | }, 109 | }, 110 | }) 111 | 112 | minetest.register_craft({ 113 | output = "carts:brakerail 6", 114 | recipe = { 115 | {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"}, 116 | {"default:steel_ingot", "group:stick", "default:steel_ingot"}, 117 | {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"}, 118 | } 119 | }) 120 | 121 | boost_cart:register_rail("boost_cart:startstoprail", { 122 | description = "Start-stop rail", 123 | tiles = { 124 | "carts_rail_straight_ss.png", "carts_rail_curved_ss.png", 125 | "carts_rail_t_junction_ss.png", "carts_rail_crossing_ss.png" 126 | }, 127 | groups = boost_cart:get_rail_groups(), 128 | after_place_node = function(pos, placer, itemstack) 129 | if not mesecon then 130 | minetest.get_meta(pos):set_string("cart_acceleration", "halt") 131 | end 132 | end, 133 | mesecons = { 134 | effector = { 135 | action_on = function(pos, node) 136 | boost_cart:boost_rail(pos, 0.5) 137 | end, 138 | action_off = function(pos, node) 139 | minetest.get_meta(pos):set_string("cart_acceleration", "halt") 140 | end, 141 | }, 142 | }, 143 | }) 144 | 145 | minetest.register_craft({ 146 | type = "shapeless", 147 | output = "boost_cart:startstoprail 2", 148 | recipe = {"carts:powerrail", "carts:brakerail"}, 149 | }) 150 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/screenshot.png -------------------------------------------------------------------------------- /settingtypes.txt: -------------------------------------------------------------------------------- 1 | # Maximal speed of the cart in m/s (min=1, max=100) 2 | boost_cart.speed_max (Maximal speed) int 10 1 100 3 | 4 | # Maximal speed to which the driving player can accelerate the cart by punching 5 | # from inside the cart. -1 will disable this feature. (min=-1, max=100) 6 | boost_cart.punch_speed_max (Maximal punch speed) int 7 -1 100 -------------------------------------------------------------------------------- /sounds/cart_rail.1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/sounds/cart_rail.1.ogg -------------------------------------------------------------------------------- /sounds/cart_rail.2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/sounds/cart_rail.2.ogg -------------------------------------------------------------------------------- /sounds/cart_rail.3.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/sounds/cart_rail.3.ogg -------------------------------------------------------------------------------- /textures/cart_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/cart_bottom.png -------------------------------------------------------------------------------- /textures/cart_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/cart_side.png -------------------------------------------------------------------------------- /textures/cart_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/cart_top.png -------------------------------------------------------------------------------- /textures/carts_rail_crossing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_crossing.png -------------------------------------------------------------------------------- /textures/carts_rail_crossing_brk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_crossing_brk.png -------------------------------------------------------------------------------- /textures/carts_rail_crossing_cp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_crossing_cp.png -------------------------------------------------------------------------------- /textures/carts_rail_crossing_dtc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_crossing_dtc.png -------------------------------------------------------------------------------- /textures/carts_rail_crossing_dtc_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_crossing_dtc_on.png -------------------------------------------------------------------------------- /textures/carts_rail_crossing_pwr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_crossing_pwr.png -------------------------------------------------------------------------------- /textures/carts_rail_crossing_ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_crossing_ss.png -------------------------------------------------------------------------------- /textures/carts_rail_curved.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_curved.png -------------------------------------------------------------------------------- /textures/carts_rail_curved_brk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_curved_brk.png -------------------------------------------------------------------------------- /textures/carts_rail_curved_cp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_curved_cp.png -------------------------------------------------------------------------------- /textures/carts_rail_curved_dtc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_curved_dtc.png -------------------------------------------------------------------------------- /textures/carts_rail_curved_dtc_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_curved_dtc_on.png -------------------------------------------------------------------------------- /textures/carts_rail_curved_pwr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_curved_pwr.png -------------------------------------------------------------------------------- /textures/carts_rail_curved_ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_curved_ss.png -------------------------------------------------------------------------------- /textures/carts_rail_straight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_straight.png -------------------------------------------------------------------------------- /textures/carts_rail_straight_brk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_straight_brk.png -------------------------------------------------------------------------------- /textures/carts_rail_straight_cp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_straight_cp.png -------------------------------------------------------------------------------- /textures/carts_rail_straight_dtc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_straight_dtc.png -------------------------------------------------------------------------------- /textures/carts_rail_straight_dtc_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_straight_dtc_on.png -------------------------------------------------------------------------------- /textures/carts_rail_straight_pwr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_straight_pwr.png -------------------------------------------------------------------------------- /textures/carts_rail_straight_ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_straight_ss.png -------------------------------------------------------------------------------- /textures/carts_rail_t_junction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_t_junction.png -------------------------------------------------------------------------------- /textures/carts_rail_t_junction_brk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_t_junction_brk.png -------------------------------------------------------------------------------- /textures/carts_rail_t_junction_cp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_t_junction_cp.png -------------------------------------------------------------------------------- /textures/carts_rail_t_junction_dtc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_t_junction_dtc.png -------------------------------------------------------------------------------- /textures/carts_rail_t_junction_dtc_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_t_junction_dtc_on.png -------------------------------------------------------------------------------- /textures/carts_rail_t_junction_pwr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_t_junction_pwr.png -------------------------------------------------------------------------------- /textures/carts_rail_t_junction_ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/carts_rail_t_junction_ss.png -------------------------------------------------------------------------------- /textures/templates/crossing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/templates/crossing.png -------------------------------------------------------------------------------- /textures/templates/curved.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/templates/curved.png -------------------------------------------------------------------------------- /textures/templates/straight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/templates/straight.png -------------------------------------------------------------------------------- /textures/templates/t_junction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmallJoker/boost_cart/e458734cc54745fa7b8e19fbcfd038a1ad2b4946/textures/templates/t_junction.png --------------------------------------------------------------------------------