diff --git a/README.txt b/README.txt index 4ec9bb8..7440b15 100644 --- a/README.txt +++ b/README.txt @@ -1,6 +1,19 @@ -Minetest mod: boost_cart -======================= -Based on the mod "carts" by PilzAdam +Minetest mod: carts for MFF +=========================== + +Based on boost_cart and modified to fully *replace* carts (@Coethium) + - desactivate mesecons + - power_rail: accelerate, max_speed set in init.lua + - brake_rail: deccelerate, min_speed set in init.lua (so the cart doesn't stop and runs at very low speed) + - default:rail / rail_cooper : no friction, keep the current speed + - no collision (avoid the "walled_in" bug) + + + +Boost_cart +========== + +Based on (and fully compatible with) the mod "carts" by PilzAdam Target: Run smoothly and do not use too much CPU License of source code: diff --git a/depends.txt b/depends.txt index 331d858..bfb43df 100644 --- a/depends.txt +++ b/depends.txt @@ -1 +1,3 @@ -default \ No newline at end of file +default +mesecons? +moreores? \ No newline at end of file diff --git a/detector.lua b/detector.lua new file mode 100644 index 0000000..a218254 --- /dev/null +++ b/detector.lua @@ -0,0 +1,58 @@ +local mesecons_rules = mesecon.rules.flat + +function carts:turnoff_detector_rail(pos) + local node = minetest.get_node(pos) + if minetest.get_item_group(node.name, "detector_rail") == 1 then + if node.name == "carts:detectorrail_on" then --has not been dug + minetest.swap_node(pos, {name = "carts:detectorrail", param2=node.param2}) + end + mesecon.receptor_off(pos, mesecons_rules) + end +end + +function carts:signal_detector_rail(pos) + local node = minetest.get_node(pos) + if minetest.get_item_group(node.name, "detector_rail") ~= 1 then + return + end + + if node.name == "carts:detectorrail" then + minetest.swap_node(pos, {name = "carts:detectorrail_on", param2=node.param2}) + end + mesecon.receptor_on(pos, mesecons_rules) + minetest.after(0.5, carts.turnoff_detector_rail, carts, pos) +end + +carts:register_rail("carts:detectorrail", { + description = "Detector rail", + tiles = { + "carts_rail_dtc.png", "carts_rail_curved_dtc.png", + "carts_rail_t_junction_dtc.png", "carts_rail_crossing_dtc.png" + }, + groups = carts:get_rail_groups({detector_rail = 1}), + + mesecons = {receptor = {state = "off", rules = mesecons_rules}}, +}) + +carts:register_rail("carts:detectorrail_on", { + description = "Detector rail ON (you hacker you)", + tiles = { + "carts_rail_dtc_on.png", "carts_rail_curved_dtc_on.png", + "carts_rail_t_junction_dtc_on.png", "carts_rail_crossing_dtc_on.png" + }, + groups = carts:get_rail_groups({ + detector_rail = 1, not_in_creative_inventory = 1 + }), + drop = "carts:detectorrail", + + mesecons = {receptor = {state = "on", rules = mesecons_rules}}, +}) + +minetest.register_craft({ + output = "carts:detectorrail 6", + recipe = { + {"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"}, + {"default:steel_ingot", "group:stick", "default:steel_ingot"}, + {"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"}, + }, +}) diff --git a/functions.lua b/functions.lua index b6bab4e..6d8a972 100644 --- a/functions.lua +++ b/functions.lua @@ -1,4 +1,4 @@ -function boost_cart:get_sign(z) +function carts:get_sign(z) if z == 0 then return 0 else @@ -6,98 +6,221 @@ function boost_cart:get_sign(z) end end -function boost_cart:velocity_to_dir(v) - if math.abs(v.x) > math.abs(v.z) then - return {x=boost_cart:get_sign(v.x), y=boost_cart:get_sign(v.y), z=0} +function carts:manage_attachment(player, status, obj) + if not player then + return + end + local player_name = player:get_player_name() + if default.player_attached[player_name] == status then + return + end + default.player_attached[player_name] = status + + if status then + player:set_attach(obj, "", {x=0, y=6, z=0}, {x=0, y=0, z=0}) + player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0}) else - return {x=0, y=boost_cart:get_sign(v.y), z=boost_cart:get_sign(v.z)} + player:set_detach() + player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0}) end end -function boost_cart:is_rail(pos) - local node = minetest.get_node(pos).name - return minetest.get_item_group(node, "rail") ~= 0 +function carts:velocity_to_dir(v) + if math.abs(v.x) > math.abs(v.z) then + return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0} + else + return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)} + end end -function boost_cart:get_rail_direction(pos_, dir_) - local pos = vector.round(pos_) +function carts:is_rail(pos, railtype) + local node = minetest.get_node(pos).name + if node == "ignore" then + local vm = minetest.get_voxel_manip() + local emin, emax = vm:read_from_map(pos, pos) + local area = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax, + } + local data = vm:get_data() + local vi = area:indexp(pos) + node = minetest.get_name_from_content_id(data[vi]) + end + if minetest.get_item_group(node, "rail") == 0 then + return false + end + if not railtype then + return true + end + return minetest.get_item_group(node, "connect_to_raillike") == railtype +end + +function carts:check_front_up_down(pos, dir_, check_up, railtype) local dir = vector.new(dir_) local cur = nil - + -- Front dir.y = 0 cur = vector.add(pos, dir) - if boost_cart:is_rail(cur) then + if carts:is_rail(cur, railtype) then return dir end - - -- Down - dir.y = -1 - cur = vector.add(pos, dir) - if boost_cart:is_rail(cur) then - return dir - end - -- Up - dir.y = 1 + if check_up then + dir.y = 1 + cur = vector.add(pos, dir) + if carts:is_rail(cur, railtype) then + return dir + end + end + -- Down + dir.y = -1 cur = vector.add(pos, dir) - if boost_cart:is_rail(cur) then + if carts:is_rail(cur, railtype) then return dir end - - -- Left, right - dir.y = 0 - + return nil +end + +function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype) + local pos = vector.round(pos_) + local cur = nil + local left_check, right_check = true, true + -- Check left and right - local view, opposite, val - - if dir.x == 0 and dir.z ~= 0 then - view = "z" - other = "x" - if dir.z < 0 then - val = {1, -1} - else - val = {-1, 1} + local left = {x=0, y=0, z=0} + local right = {x=0, y=0, z=0} + if dir.z ~= 0 and dir.x == 0 then + left.x = -dir.z + right.x = dir.z + elseif dir.x ~= 0 and dir.z == 0 then + left.z = dir.x + right.z = -dir.x + end + + if ctrl then + if old_switch == 1 then + left_check = false + elseif old_switch == 2 then + right_check = false end - elseif dir.z == 0 and dir.x ~= 0 then - view = "x" - other = "z" - if dir.x > 0 then - val = {1, -1} - else - val = {-1, 1} + if ctrl.left and left_check then + cur = carts:check_front_up_down(pos, left, false, railtype) + if cur then + return cur, 1 + end + left_check = false + end + if ctrl.right and right_check then + cur = carts:check_front_up_down(pos, right, false, railtype) + if cur then + return cur, 2 + end + right_check = true end - else - return {x=0, y=0, z=0} end - - dir[view] = 0 - dir[other] = val[1] - cur = vector.add(pos, dir) - if boost_cart:is_rail(cur) then - return dir + + -- Normal + cur = carts:check_front_up_down(pos, dir, true, railtype) + if cur then + return cur end - - -- Down - dir.y = -1 - cur = vector.add(pos, dir) - if boost_cart:is_rail(cur) then - return dir + + -- Left, if not already checked + if left_check then + cur = carts:check_front_up_down(pos, left, false, railtype) + if cur then + return cur + end end - dir.y = 0 - - dir[other] = val[2] - cur = vector.add(pos, dir) - if boost_cart:is_rail(cur) then - return dir + + -- Right, if not already checked + if right_check then + cur = carts:check_front_up_down(pos, right, false, railtype) + if cur then + return cur + end end - - -- Down - dir.y = -1 - cur = vector.add(pos, dir) - if boost_cart:is_rail(cur) then - return dir + + -- Backwards + if not old_switch then + cur = carts:check_front_up_down(pos, { + x = -dir.x, + y = dir.y, + z = -dir.z + }, true, railtype) + if cur then + return cur + end end - + return {x=0, y=0, z=0} end + +function carts:pathfinder(pos_, expected_pos, old_dir, ctrl, pf_switch, railtype) + local pos = vector.round(pos_) + local pf_pos = vector.round(expected_pos) + local pf_dir = vector.new(old_dir) + + for i = 1, 3 do + if vector.equals(pf_pos, pos) then + -- Success! Cart moved on correctly + return true + end + + pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype) + if vector.equals(pf_dir, {x=0, y=0, z=0}) then + -- No way forwards + return false + end + + pf_pos = vector.add(pf_pos, pf_dir) + end + -- Cart not found + return false +end + +function carts:boost_rail(pos, amount) + minetest.get_meta(pos):set_string("cart_acceleration", tostring(amount)) + for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 0.5)) do + if not obj_:is_player() and + obj_:get_luaentity() and + obj_:get_luaentity().name == "carts:cart" then + obj_:get_luaentity():on_punch() + end + end +end + +function carts:register_rail(name, def) + local def_default = { + drawtype = "raillike", + paramtype = "light", + sunlight_propagates = true, + is_ground_content = true, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, + } + } + for k, v in pairs(def_default) do + def[k] = v + end + if not def.inventory_image then + def.wield_image = def.tiles[1] + def.inventory_image = def.tiles[1] + end + + minetest.register_node(name, def) +end + +function carts:get_rail_groups(additional_groups) + -- Get the default rail groups and add more when a table is given + local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1} + if type(additional_groups) == "table" then + for k, v in pairs(additional_groups) do + groups[k] = v + end + end + return groups +end diff --git a/init.lua b/init.lua index ca4adbb..e5e7c22 100644 --- a/init.lua +++ b/init.lua @@ -1,208 +1,410 @@ --- TODO: --- Fix way-up --- Add rail-cross switching --- Prevent from floating carts --- Speed up and brake rails -boost_cart = {} -boost_cart.modpath = minetest.get_modpath("boost_cart") -boost_cart.speed_max = 8 +carts = {} +carts.modpath = minetest.get_modpath("carts") -dofile(boost_cart.modpath.."/functions.lua") -dofile(boost_cart.modpath.."/rails.lua") +-- Maximal speed of the cart in m/s +carts.speed_max = minetest.setting_get("movement_speed_walk")*3*0.9 +-- Minimal speed of the cart on brake rail +carts.brake_speed_min = minetest.setting_get("movement_speed_walk")/2 +-- Set to nil to disable punching the cart from inside (min = -1) +carts.punch_speed_min = 7 +-- 1 disable mesecons / 0 enable mesecons +carts.mesecon_disabled = 1 -boost_cart.cart = { + +if not carts.modpath then + error("\nWrong mod directory name! Please change it to 'carts'.\n" .. + "See also: http://dev.minetest.net/Installing_Mods") +end + +function vector.floor(v) + return { + x = math.floor(v.x), + y = math.floor(v.y), + z = math.floor(v.z) + } +end + +dofile(carts.modpath.."/functions.lua") +dofile(carts.modpath.."/rails.lua") + +if not carts.mesecon_disabled and mesecon then + dofile(carts.modpath.."/detector.lua") +end + +-- Support for non-default games +if not default.player_attached then + default.player_attached = {} +end + +carts.cart = { physical = false, collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, visual = "mesh", mesh = "cart.x", visual_size = {x=1, y=1}, textures = {"cart.png"}, - + driver = nil, - punch = false, -- used to re-send velocity and position + punched = false, -- used to re-send velocity and position velocity = {x=0, y=0, z=0}, -- only used on punch - old_dir = {x=0, y=0, z=0}, - old_pos = nil + old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch + old_pos = nil, + old_switch = 0, + railtype = nil, + attached_items = {} } -function boost_cart.cart:on_rightclick(clicker) +function carts.cart:on_rightclick(clicker) if not clicker or not clicker:is_player() then return end local player_name = clicker:get_player_name() if self.driver and player_name == self.driver then self.driver = nil - clicker:set_detach() + carts:manage_attachment(clicker, false) + self.object:setacceleration({x=0, y=0, z=0}) -- Stops the cart when we leave it + self.object:setvelocity({x=0, y=0, z=0}) elseif not self.driver then self.driver = player_name - clicker:set_attach(self.object, "", {x=0,y=5,z=0}, {x=0,y=0,z=0}) + carts:manage_attachment(clicker, true, self.object) end end -function boost_cart.cart:on_activate(staticdata, dtime_s) +function carts.cart:on_activate(staticdata, dtime_s) self.object:set_armor_groups({immortal=1}) - self.old_pos = self.object:getpos() + if string.sub(staticdata, 1, string.len("return")) ~= "return" then + return + end + local data = minetest.deserialize(staticdata) + if not data or type(data) ~= "table" then + return + end + self.railtype = data.railtype + if data.old_dir then + self.old_dir = data.old_dir + end end -function boost_cart.cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) +function carts.cart:get_staticdata() + return minetest.serialize({ + railtype = self.railtype, + old_dir = self.old_dir + }) +end + +function carts.cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) + local pos = self.object:getpos() + if not self.railtype then + local bar = vector.floor(vector.add(pos, 0.1)) + local node = minetest.get_node(bar).name + self.railtype = minetest.get_item_group(node, "connect_to_raillike") + end + if not puncher or not puncher:is_player() then + local cart_dir = carts:get_rail_direction(pos, self.old_dir, nil, nil, self.railtype) + if vector.equals(cart_dir, {x=0, y=0, z=0}) then + return + end + self.velocity = vector.multiply(cart_dir, 3) + self.old_pos = nil + self.punched = true return end if puncher:get_player_control().sneak then + -- Pick up cart: Drop all attachments if self.driver then + if self.old_pos then + self.object:setpos(self.old_pos) + end local player = minetest.get_player_by_name(self.driver) - if player then - player:set_detach() + carts:manage_attachment(player, false) + end + for _,obj_ in ipairs(self.attached_items) do + if obj_ then + obj_:set_detach() end end - self.object:remove() - puncher:get_inventory():add_item("main", "boost_cart:cart") + + local leftover = puncher:get_inventory():add_item("main", "carts:cart") + if not leftover:is_empty() then + minetest.add_item(self.object:getpos(), leftover) + end + self.object:remove() return end - - local vel = self.velocity + + local vel = self.object:getvelocity() if puncher:get_player_name() == self.driver then - if math.abs(vel.x) > 2 or math.abs(vel.z) > 2 then + if math.abs(vel.x + vel.z) > carts.punch_speed_min then + return + end + --end --Only the driver can punch + + local punch_dir = carts:velocity_to_dir(puncher:get_look_dir()) + punch_dir.y = 0 + local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype) + if vector.equals(cart_dir, {x=0, y=0, z=0}) then + return + end + + local punch_interval = 1 + if tool_capabilities and tool_capabilities.full_punch_interval then + punch_interval = tool_capabilities.full_punch_interval + end + time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval) + local f = 3 * (time_from_last_punch / punch_interval) + + self.velocity = vector.multiply(cart_dir, f) + self.old_dir = cart_dir + self.old_pos = nil + self.punched = true + end +end + +function carts.cart:on_step(dtime) + local vel = self.object:getvelocity() + local update = {} + if self.punched then + vel = vector.add(vel, self.velocity) + self.object:setvelocity(vel) + self.old_dir.y = 0 + elseif vector.equals(vel, {x=0, y=0, z=0}) then + return + end + + -- dir: New moving direction of the cart + -- last_switch: Currently pressed L/R key, used to ignore the key on the next rail node + local dir, last_switch + local pos = self.object:getpos() + local is_slow = ((vel.x ~= 0 and math.abs(vel.x) <= carts.brake_speed_min) or + (vel.y ~= 0 and math.abs(vel.y) <= carts.brake_speed_min) or + (vel.z ~= 0 and math.abs(vel.z) <= carts.brake_speed_min)) and + string.match(minetest.get_node(pos).name, "brake") + + if self.old_pos and not self.punched then + local flo_pos = vector.round(pos) + local flo_old = vector.round(self.old_pos) + if vector.equals(flo_pos, flo_old) and not is_slow then -- Do not check one node multiple times (but check if low speed) return end end - - local cart_dir = boost_cart:velocity_to_dir(direction) - if cart_dir.x == 0 and cart_dir.z == 0 then - local fd = minetest.dir_to_facedir(puncher:get_look_dir()) - if fd == 0 then - cart_dir.x = 1 - elseif fd == 1 then - cart_dir.z = -1 - elseif fd == 2 then - cart_dir.x = -1 - elseif fd == 3 then - cart_dir.z = 1 + + + local ctrl, player + + -- Get player controls + if self.driver then + player = minetest.get_player_by_name(self.driver) + if player then + ctrl = player:get_player_control() end end - if time_from_last_punch > tool_capabilities.full_punch_interval then - time_from_last_punch = tool_capabilities.full_punch_interval - end - local dir = boost_cart:get_rail_direction(self.object:getpos(), cart_dir) - - local f = 3 * (time_from_last_punch / tool_capabilities.full_punch_interval) - vel.x = dir.x * f - vel.z = dir.y * f - vel.z = dir.z * f - self.velocity = vel - self.punch = true -end + if self.old_pos then + -- Detection for "skipping" nodes + local expected_pos = vector.add(self.old_pos, self.old_dir) + local found_path = carts:pathfinder( + pos, expected_pos, self.old_dir, ctrl, self.old_switch, self.railtype + ) -function boost_cart.cart:on_step(dtime) - local vel = self.object:getvelocity() - if self.punch then - vel = vector.add(vel, self.velocity) - self.velocity = {x=0,y=0,z=0} - elseif vector.equals(vel, {x=0,y=0,z=0}) then - return + if not found_path and not is_slow then + -- No rail found: reset back to the expected position + pos = expected_pos + update.pos = true + end end - - local pos = self.object:getpos() - local fpos, fold_pos = vector.round(pos), vector.round(self.old_pos) - if vector.equals(fpos, fold_pos) and not self.punch then - return + + local cart_dir = carts:velocity_to_dir(vel) + local max_vel = carts.speed_max + if not dir then + dir, last_switch = carts:get_rail_direction( + pos, cart_dir, ctrl, self.old_switch, self.railtype + ) end - self.old_pos = vector.new(pos) - - local cart_dir = { - x = boost_cart:get_sign(vel.x), - y = boost_cart:get_sign(vel.y), - z = boost_cart:get_sign(vel.z) - } - local dir = boost_cart:get_rail_direction(pos, cart_dir) + + local new_acc = {x=0, y=0, z=0} + local speed_mod = 0 if vector.equals(dir, {x=0, y=0, z=0}) then vel = {x=0, y=0, z=0} - self.object:setacceleration({x=0, y=0, z=0}) - self.punch = true + pos = vector.round(pos) + update.pos = true + update.vel = true else -- If the direction changed if dir.x ~= 0 and self.old_dir.z ~= 0 then vel.x = dir.x * math.abs(vel.z) vel.z = 0 pos.z = math.floor(pos.z + 0.5) - self.punch = true + update.pos = true end if dir.z ~= 0 and self.old_dir.x ~= 0 then vel.z = dir.z * math.abs(vel.x) vel.x = 0 pos.x = math.floor(pos.x + 0.5) - self.punch = true + update.pos = true end -- Up, down? if dir.y ~= self.old_dir.y then - vel.y = dir.y * (math.abs(vel.x) + math.abs(vel.z)) - pos.y = math.floor(pos.y + 0.5) - self.punch = true + vel.y = dir.y * math.abs(vel.x + vel.z) + pos = vector.round(pos) + update.pos = true + end + + -- Slow down or speed up in slopes.. + local acc = dir.y * -1.8 + + -- MFF : Some rails have bad acceleration property, reinit them ! + -- this code would be commented when all rails will be corrected + local rail = minetest.get_node(pos) + if string.match(rail.name, "power") + then minetest.get_meta(pos):set_string("cart_acceleration", "1") + elseif string.match(rail.name, "brake") then minetest.get_meta(pos):set_string("cart_acceleration", "-1") + else minetest.get_meta(pos):set_string("cart_acceleration", "0") + end + + -- Change acceleration by rail (power/brake) + local speed_mod_string = minetest.get_meta(pos):get_string("cart_acceleration") + if speed_mod_string and speed_mod_string ~= "" + then speed_mod = tonumber(speed_mod_string) + else speed_mod = 0 end - -- Slow down or speed up.. - local acc = -2 * dir.y - 0.4 - self.object:setacceleration({ - x = dir.x * acc, - y = dir.y * (math.abs(dir.x) + math.abs(dir.z)) * acc, - z = dir.z * acc - }) + if speed_mod > 0 then speed_mod = 2 + elseif speed_mod < 0 then speed_mod = -2 + else speed_mod = 0 + end + + + --[[if speed_mod_string == "halt" then --stop rail, not used in MFF + vel = {x=0, y=0, z=0} + acc = 0 + pos = vector.round(pos) + update.pos = true + update.vel = true + else--]]if speed_mod and speed_mod ~= 0 then + acc = acc + (speed_mod * 10) + else + --acc = acc - 0.4 --No friction (to be set as an option) + -- Handbrake + if ctrl and ctrl.down then + acc = acc - 1.2 + end + end + + if self.old_dir.y == 0 and not self.punched then + -- Stop the cart swing between two rail parts (handbrake) + if vector.equals(vector.multiply(self.old_dir, -1), dir) then + vel = {x=0, y=0, z=0} + acc = 0 + if self.old_pos then + pos = vector.new(self.old_pos) + update.pos = true + end + dir = vector.new(self.old_dir) + update.vel = true + end + end + + new_acc = vector.multiply(dir, acc) + end + + if not carts.mesecon_disabled and mesecon then + carts:signal_detector_rail(vector.round(pos)) end - self.old_dir = vector.new(dir) - + -- Limits for _,v in ipairs({"x","y","z"}) do - if math.abs(vel[v]) > boost_cart.speed_max then - vel[v] = boost_cart:get_sign(vel[v]) * boost_cart.speed_max - self.punch = true + if speed_mod > 0 and math.abs(vel[v]) > max_vel then + vel[v] = carts:get_sign(vel[v]) * max_vel + new_acc[v] = 0 + update.vel = true + elseif speed_mod < 0 and vel[v] ~= 0 and math.abs(vel[v]) <= carts.brake_speed_min then + vel[v] = carts:get_sign(vel[v]) * carts.brake_speed_min + new_acc[v] = 0 + update.vel = true end end - - if dir.x < 0 then - self.object:setyaw(math.pi / 2) - elseif dir.x > 0 then - self.object:setyaw(3 * math.pi / 2) - elseif dir.z < 0 then - self.object:setyaw(math.pi) - elseif dir.z > 0 then - self.object:setyaw(0) + + self.object:setacceleration(new_acc) + self.old_pos = vector.new(pos) + if not vector.equals(dir, {x=0, y=0, z=0}) then + self.old_dir = vector.new(dir) + end + self.old_switch = last_switch + + + if self.punched then + -- Collect dropped items + for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 1)) do + if not obj_:is_player() and + obj_:get_luaentity() and + not obj_:get_luaentity().physical_state and + obj_:get_luaentity().name == "__builtin:item" then + + obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}) + self.attached_items[#self.attached_items + 1] = obj_ + end + end + self.punched = false + update.vel = true -- update player animation end + if not (update.vel or update.pos) then + return + end + + local yaw = 0 + if self.old_dir.x < 0 then + yaw = 0.5 + elseif self.old_dir.x > 0 then + yaw = 1.5 + elseif self.old_dir.z < 0 then + yaw = 1 + end + self.object:setyaw(yaw * math.pi) + + local anim = {x=0, y=0} if dir.y == -1 then - self.object:set_animation({x=1, y=1}, 1, 0) + anim = {x=1, y=1} elseif dir.y == 1 then - self.object:set_animation({x=2, y=2}, 1, 0) - else - self.object:set_animation({x=0, y=0}, 1, 0) + anim = {x=2, y=2} end - if self.punch then - self.object:setvelocity(vel) + self.object:set_animation(anim, 1, 0) + + self.object:setvelocity(vel) + if update.pos then self.object:setpos(pos) - self.old_pos = {x=0, y=0, z=0} end - self.punch = false + update = nil end -minetest.register_entity("boost_cart:cart", boost_cart.cart) -minetest.register_craftitem("boost_cart:cart", { - description = "Cart", +minetest.register_entity(":carts:cart", carts.cart) +minetest.register_craftitem(":carts:cart", { + description = "Cart (Sneak+Click to pick up)", inventory_image = minetest.inventorycube("cart_top.png", "cart_side.png", "cart_side.png"), wield_image = "cart_side.png", on_place = function(itemstack, placer, pointed_thing) if not pointed_thing.type == "node" then return end - if boost_cart:is_rail(pointed_thing.under) then - minetest.add_entity(pointed_thing.under, "boost_cart:cart") - elseif boost_cart:is_rail(pointed_thing.above) then - minetest.add_entity(pointed_thing.above, "boost_cart:cart") + if carts:is_rail(pointed_thing.under) then + minetest.add_entity(pointed_thing.under, "carts:cart") + elseif carts:is_rail(pointed_thing.above) then + minetest.add_entity(pointed_thing.above, "carts:cart") else return end - + itemstack:take_item() return itemstack end, -}) \ No newline at end of file +}) + +minetest.register_craft({ + output = "carts:cart", + recipe = { + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + }, +}) diff --git a/rails.lua b/rails.lua index 0cdac7a..bf70abe 100644 --- a/rails.lua +++ b/rails.lua @@ -1,7 +1,10 @@ minetest.register_node(":default:rail", { description = "Rail", drawtype = "raillike", - tiles = {"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"}, + tiles = { + "default_rail.png", "default_rail_curved.png", + "default_rail_t_junction.png", "default_rail_crossing.png" + }, inventory_image = "default_rail.png", wield_image = "default_rail.png", paramtype = "light", @@ -12,5 +15,146 @@ minetest.register_node(":default:rail", { type = "fixed", fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, }, - groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1}, -}) \ No newline at end of file + groups = carts:get_rail_groups(), +}) + + +-- Copper rail + +if minetest.get_modpath("moreores") then + -- Moreores' copper rail + minetest.register_alias("carts:rail_copper", "moreores:copper_rail") +else + carts:register_rail(":carts:rail_copper", { + description = "Copper rail", + tiles = { + "carts_rail_cp.png", "carts_rail_curved_cp.png", + "carts_rail_t_junction_cp.png", "carts_rail_crossing_cp.png" + }, + groups = carts:get_rail_groups(), + }) + + minetest.register_craft({ + output = "carts:rail_copper 16", + recipe = { + {"default:copper_ingot", "group:stick", "default:copper_ingot"}, + {"default:copper_ingot", "group:stick", "default:copper_ingot"}, + {"default:copper_ingot", "group:stick", "default:copper_ingot"}, + } + }) +end + +-- Speed up + +-- Rail Power + +carts:register_rail(":carts:rail_power", { + description = "Powered rail", + tiles = { + "carts_rail_pwr.png", "carts_rail_curved_pwr.png", + "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png" + }, + groups = carts:get_rail_groups(), + + after_place_node = function(pos, placer, itemstack) + if not mesecon then + minetest.get_meta(pos):set_string("cart_acceleration", "1") + end + end, + + mesecons = { + effector = { + action_on = function(pos, node) + carts:boost_rail(pos, 1) + end, + + action_off = function(pos, node) + minetest.get_meta(pos):set_string("cart_acceleration", "0") + end, + }, + }, +}) + +minetest.register_craft({ + type = "shapeless", + output = "carts:rail_power", + recipe = {"group:rail", "default:mese_crystal_fragment"}, +}) + + +-- Rail Brake + +carts:register_rail(":carts:rail_brake", { + description = "Brake rail", + tiles = { + "carts_rail_brk.png", "carts_rail_curved_brk.png", + "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png" + }, + groups = carts:get_rail_groups(), + + after_place_node = function(pos, placer, itemstack) + if not mesecon then + minetest.get_meta(pos):set_string("cart_acceleration", "-1") + end + end, + + mesecons = { + effector = { + action_on = function(pos, node) + minetest.get_meta(pos):set_string("cart_acceleration", "-1") + end, + + action_off = function(pos, node) + minetest.get_meta(pos):set_string("cart_acceleration", "0") + end, + }, + }, +}) + +minetest.register_craft({ + type = "shapeless", + output = "carts:rail_brake", + recipe = {"group:rail", "default:coal_lump"}, +}) + +-- Start stop rail (temporary removed for mff) + +--[[carts:register_rail("carts:startstoprail", { + description = "Start-stop rail", + tiles = { + "carts_rail_ss.png", "carts_rail_curved_ss.png", + "carts_rail_t_junction_ss.png", "carts_rail_crossing_ss.png" + }, + groups = carts:get_rail_groups(), + + after_place_node = function(pos, placer, itemstack) + if not mesecon then + minetest.get_meta(pos):set_string("cart_acceleration", "halt") + end + end, + + mesecons = { + effector = { + action_on = function(pos, node) + carts:boost_rail(pos, 0.5) + end, + + action_off = function(pos, node) + minetest.get_meta(pos):set_string("cart_acceleration", "halt") + end, + }, + }, +}) + +minetest.register_craft({ + type = "shapeless", + output = "carts:startstoprail 2", + recipe = {"carts:powerrail", "carts:brakerail"}, +})--]] + +--Alias + +minetest.register_alias("carts:powerrail", "carts:rail_power") +minetest.register_alias("carts:power_rail", "carts:rail_power") +minetest.register_alias("carts:brakerail", "carts:rail_brake") +minetest.register_alias("carts:brake_rail", "carts:rail_brake") diff --git a/textures/carts_rail_brk.png b/textures/carts_rail_brk.png new file mode 100644 index 0000000..2717bd5 Binary files /dev/null and b/textures/carts_rail_brk.png differ diff --git a/textures/carts_rail_cp.png b/textures/carts_rail_cp.png new file mode 100644 index 0000000..119461f Binary files /dev/null and b/textures/carts_rail_cp.png differ diff --git a/textures/carts_rail_crossing_brk.png b/textures/carts_rail_crossing_brk.png new file mode 100644 index 0000000..f9ce303 Binary files /dev/null and b/textures/carts_rail_crossing_brk.png differ diff --git a/textures/carts_rail_crossing_cp.png b/textures/carts_rail_crossing_cp.png new file mode 100644 index 0000000..b04aa63 Binary files /dev/null and b/textures/carts_rail_crossing_cp.png differ diff --git a/textures/carts_rail_crossing_dtc.png b/textures/carts_rail_crossing_dtc.png new file mode 100644 index 0000000..cf04f0f Binary files /dev/null and b/textures/carts_rail_crossing_dtc.png differ diff --git a/textures/carts_rail_crossing_dtc_on.png b/textures/carts_rail_crossing_dtc_on.png new file mode 100644 index 0000000..b6f5b87 Binary files /dev/null and b/textures/carts_rail_crossing_dtc_on.png differ diff --git a/textures/carts_rail_crossing_pwr.png b/textures/carts_rail_crossing_pwr.png new file mode 100644 index 0000000..dc317cf Binary files /dev/null and b/textures/carts_rail_crossing_pwr.png differ diff --git a/textures/carts_rail_crossing_ss.png b/textures/carts_rail_crossing_ss.png new file mode 100644 index 0000000..69ee070 Binary files /dev/null and b/textures/carts_rail_crossing_ss.png differ diff --git a/textures/carts_rail_curved_brk.png b/textures/carts_rail_curved_brk.png new file mode 100644 index 0000000..c55183d Binary files /dev/null and b/textures/carts_rail_curved_brk.png differ diff --git a/textures/carts_rail_curved_cp.png b/textures/carts_rail_curved_cp.png new file mode 100644 index 0000000..004ef56 Binary files /dev/null and b/textures/carts_rail_curved_cp.png differ diff --git a/textures/carts_rail_curved_dtc.png b/textures/carts_rail_curved_dtc.png new file mode 100644 index 0000000..8117c27 Binary files /dev/null and b/textures/carts_rail_curved_dtc.png differ diff --git a/textures/carts_rail_curved_dtc_on.png b/textures/carts_rail_curved_dtc_on.png new file mode 100644 index 0000000..032630f Binary files /dev/null and b/textures/carts_rail_curved_dtc_on.png differ diff --git a/textures/carts_rail_curved_pwr.png b/textures/carts_rail_curved_pwr.png new file mode 100644 index 0000000..4aef5dd Binary files /dev/null and b/textures/carts_rail_curved_pwr.png differ diff --git a/textures/carts_rail_curved_ss.png b/textures/carts_rail_curved_ss.png new file mode 100644 index 0000000..504e31f Binary files /dev/null and b/textures/carts_rail_curved_ss.png differ diff --git a/textures/carts_rail_dtc.png b/textures/carts_rail_dtc.png new file mode 100644 index 0000000..5e2ccef Binary files /dev/null and b/textures/carts_rail_dtc.png differ diff --git a/textures/carts_rail_dtc_on.png b/textures/carts_rail_dtc_on.png new file mode 100644 index 0000000..e81dbe1 Binary files /dev/null and b/textures/carts_rail_dtc_on.png differ diff --git a/textures/carts_rail_pwr.png b/textures/carts_rail_pwr.png new file mode 100644 index 0000000..f346a02 Binary files /dev/null and b/textures/carts_rail_pwr.png differ diff --git a/textures/carts_rail_ss.png b/textures/carts_rail_ss.png new file mode 100644 index 0000000..489e7fe Binary files /dev/null and b/textures/carts_rail_ss.png differ diff --git a/textures/carts_rail_t_junction_brk.png b/textures/carts_rail_t_junction_brk.png new file mode 100644 index 0000000..5689ffe Binary files /dev/null and b/textures/carts_rail_t_junction_brk.png differ diff --git a/textures/carts_rail_t_junction_cp.png b/textures/carts_rail_t_junction_cp.png new file mode 100644 index 0000000..3da9094 Binary files /dev/null and b/textures/carts_rail_t_junction_cp.png differ diff --git a/textures/carts_rail_t_junction_dtc.png b/textures/carts_rail_t_junction_dtc.png new file mode 100644 index 0000000..b154f43 Binary files /dev/null and b/textures/carts_rail_t_junction_dtc.png differ diff --git a/textures/carts_rail_t_junction_dtc_on.png b/textures/carts_rail_t_junction_dtc_on.png new file mode 100644 index 0000000..9fda111 Binary files /dev/null and b/textures/carts_rail_t_junction_dtc_on.png differ diff --git a/textures/carts_rail_t_junction_pwr.png b/textures/carts_rail_t_junction_pwr.png new file mode 100644 index 0000000..d7edaf1 Binary files /dev/null and b/textures/carts_rail_t_junction_pwr.png differ diff --git a/textures/carts_rail_t_junction_ss.png b/textures/carts_rail_t_junction_ss.png new file mode 100644 index 0000000..c1a2cb1 Binary files /dev/null and b/textures/carts_rail_t_junction_ss.png differ diff --git a/textures/default_rail_t_junction.png b/textures/default_rail_t_junction.png new file mode 100644 index 0000000..fe62905 Binary files /dev/null and b/textures/default_rail_t_junction.png differ