diff options
Diffstat (limited to 'railtrack')
24 files changed, 567 insertions, 0 deletions
diff --git a/railtrack/LICENSE.txt b/railtrack/LICENSE.txt new file mode 100644 index 0000000..c43348a --- /dev/null +++ b/railtrack/LICENSE.txt @@ -0,0 +1,13 @@ +Minetest Mod - Railtrack [railtrack] +==================================== + +License Source Code: LGPL v2.1 + +License of media (textures, sounds and models): CC-0 + +Authors of media files: +----------------------- + +rarkenin: + cart_rail_*.png + diff --git a/railtrack/README.txt b/railtrack/README.txt new file mode 100644 index 0000000..b371e29 --- /dev/null +++ b/railtrack/README.txt @@ -0,0 +1,72 @@ +Minetest Mod - Railtrack [railtrack] +==================================== + +Minetest version: 0.4.13 + +Depends: default + +Proof of concept rail networking system which enables rail-carts to travel +through unloaded map chunks. + +Please note, this mod makes heavy use of metadata so that much of the processing +gets done as tracks are laid, for this reason a 'rails' privilege is required in +order to place rails when using multiplayer mode. + +Crafting +-------- + +R = Rail [default:rail] +F = Mese Crystal Fragment [default:mese_crystal_fragment] +C = Coal Lump [default:coal_lump] +D = Diamond [default:diamond] +M = Mese Block [default:mese] + +Powered Rail: [railtrack:powerrail] + +By default these rails apply a positive acceleration during the time a cart +remains on a given section of track. When used with the mesecons mod the rails +will require power from a mesecon source to become active. + ++---+---+---+ +| R | F | R | ++---+---+---+ + +Braking Rail: [railtrack:brakerail] + +By default these rails apply a negative acceleration during the time a cart +remains on a given section of track. When used with the mesecons mod the rails +will require power from a mesecon source to become active. + ++---+---+---+ +| R | C | R | ++---+---+---+ + +Superconducting Rail: [railtrack:superrail] + +Zero friction rails that are easier to manage and are also a little less +cpu-intensive by avoiding the use of square root calculations. + ++---+---+---+ +| R | D | R | ++---+---+---+ + +Switching Rail: [railtrack:switchrail] + +Currently depends on mesecons to do much other than provide a convenient, zero +friction union to join long sections of superconducting rails. + ++---+---+---+ +| R | M | R | ++---+---+---+ + +Misc Items +---------- + +Rail Fixer: [railtrack:fixer] + +Only available in creative menu or with give(me) privileges. + +Rail Inspector [railtrack:inspector] + +Only available in creative menu or with give(me) privileges. + diff --git a/railtrack/depends.txt b/railtrack/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/railtrack/depends.txt @@ -0,0 +1 @@ +default diff --git a/railtrack/init.lua b/railtrack/init.lua new file mode 100644 index 0000000..373fcaa --- /dev/null +++ b/railtrack/init.lua @@ -0,0 +1,197 @@ +local modpath = minetest.get_modpath(minetest.get_current_modname()) + +dofile(modpath.."/railtrack.lua") + +railtrack:register_rail(":default:rail", { + description = "Rail", + tiles = {"default_rail.png", "default_rail_curved.png", + "default_rail_t_junction.png", "default_rail_crossing.png"}, + railtype = "rail", +}) + +railtrack:register_rail("railtrack:superrail", { + description = "Superconducting Rail", + tiles = {"carts_rail_sup.png", "carts_rail_curved_sup.png", + "carts_rail_t_junction_sup.png", "carts_rail_crossing_sup.png"}, + railtype = "superrail", + acceleration = 0, +}) + +railtrack:register_rail("railtrack:powerrail", { + description = "Powered Rail", + tiles = {"carts_rail_pwr.png", "carts_rail_curved_pwr.png", + "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"}, + railtype = "powerrail", + acceleration = 4, + mesecons = { + effector = { + action_on = function(pos, node) + railtrack:set_acceleration(pos, 4) + end, + action_off = function(pos, node) + railtrack:set_acceleration(pos, RAILTRACK_FRICTION_FLAT) + end, + }, + }, +}) + +railtrack:register_rail("railtrack:brakerail", { + description = "Braking Rail", + tiles = {"carts_rail_brk.png", "carts_rail_curved_brk.png", + "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"}, + railtype = "brakerail", + acceleration = -4, + mesecons = { + effector = { + action_on = function(pos, node) + railtrack:set_acceleration(pos, -4) + end, + action_off = function(pos, node) + railtrack:set_acceleration(pos, RAILTRACK_FRICTION_FLAT) + end, + }, + }, +}) + +railtrack:register_rail("railtrack:switchrail", { + description = "Switching Rail", + tiles = {"carts_rail_swt.png", "carts_rail_curved_swt.png", + "carts_rail_t_junction_swt.png", "carts_rail_crossing_swt.png"}, + railtype = "switchrail", + acceleration = 0, + mesecons = { + effector = { + action_on = function(pos, node) + local meta = minetest.get_meta(pos) + meta:set_string("rotations", "RFLB") + end, + action_off = function(pos, node) + local meta = minetest.get_meta(pos) + meta:set_string("rotations", nil) + end, + }, + }, +}) + +minetest.register_privilege("rails", "Player can dig and place rails.") + +minetest.register_tool("railtrack:fixer", { + description = "Rail Fixer", + inventory_image = "railtrack_fixer.png", + wield_image = "railtrack_fixer.png", + on_use = function(itemstack, user, pointed_thing) + local pos = minetest.get_pointed_thing_position(pointed_thing, false) + local name = user:get_player_name() + if not pos or not name or pointed_thing.type ~= "node" then + return + end + if not railtrack:is_railnode(pos) then + minetest.chat_send_player(name, "Not a rail node!") + return + end + if not minetest.is_singleplayer() then + if not minetest.check_player_privs(name, {rails=true}) then + minetest.chat_send_player(name, "Requires rails privilege") + return + end + end + local node = minetest.get_node(pos) + minetest.remove_node(pos) + set_node(pos, node) + local def = minetest.registered_items[node.name] or {} + if type(def.after_place_node) == "function" then + def.after_place_node(pos, user, node) + end + end, +}) + +minetest.register_tool("railtrack:inspector", { + description = "Rail Inspector", + inventory_image = "railtrack_inspector.png", + wield_image = "railtrack_inspector.png", + on_use = function(itemstack, user, pointed_thing) + local name = user:get_player_name() + local pos = minetest.get_pointed_thing_position(pointed_thing, false) + if not name or not pos then + return + end + local node = minetest.get_node(pos) or {} + if not railtrack:is_railnode(pos) or not node.name then + minetest.chat_send_player(name, "Not a rail node!") + return + end + local ref = minetest.registered_items[node.name] or {} + local meta = minetest.get_meta(pos) + local form = "" + local size = 2.5 + form = form.."label[0.5,0.5;POS: "..minetest.pos_to_string(pos).."]" + local railtype = ref.railtype or "NIL" + form = form.."label[0.5,1.0;RAILTYPE: "..railtype.."]" + local contype = meta:get_string("contype") or "NIL" + form = form.."label[0.5,1.5;CONTYPE: "..contype.."]" + local accel = meta:get_string("acceleration") or "NIL" + form = form.."label[0.5,2.0;ACCEL: "..accel.."]" + local s_junc = meta:get_string("junctions") + if s_junc then + local junctions = minetest.deserialize(s_junc) + if junctions then + form = form.."label[0.5,2.5;JUNCTIONS:]" + for i, p in ipairs(junctions) do + size = size + 0.5 + form = form.."label[0.5,"..size..";#"..i.." " + ..minetest.pos_to_string(p).."]" + end + end + end + local s_cons = meta:get_string("connections") + if s_cons then + local cons = minetest.deserialize(s_cons) + if cons then + size = size + 0.5 + form = form.."label[0.5,"..size..";CONNECTIONS:]" + for i, p in pairs(cons) do + size = size + 0.5 + form = form.."label[0.5,"..size..";#"..i.." " + ..minetest.pos_to_string(p).."]" + end + end + end + local s_rots = meta:get_string("rotations") + if s_rots then + size = size + 0.5 + form = form.."label[0.5,"..size..";ROTATIONS: "..s_rots.."]" + end + form = form.."button_exit[3.0,"..(size + 1)..";2,0.5;;Ok]" + form = "size[8,"..(size + 2).."]"..form + minetest.show_formspec(name, "info", form) + end, +}) + +minetest.register_craft({ + output = "railtrack:powerrail 2", + recipe = { + {"default:rail", "default:mese_crystal_fragment", "default:rail"}, + } +}) + +minetest.register_craft({ + output = "railtrack:brakerail 2", + recipe = { + {"default:rail", "default:coal_lump", "default:rail"}, + } +}) + +minetest.register_craft({ + output = "railtrack:switchrail 2", + recipe = { + {"default:rail", "default:mese", "default:rail"}, + } +}) + +minetest.register_craft({ + output = "railtrack:superrail 2", + recipe = { + {"default:rail", "default:diamond", "default:rail"}, + } +}) + diff --git a/railtrack/railtrack.lua b/railtrack/railtrack.lua new file mode 100644 index 0000000..3a1f714 --- /dev/null +++ b/railtrack/railtrack.lua @@ -0,0 +1,284 @@ +RAILTRACK_WARN_SECTION_LEN = 20 +RAILTRACK_ROTATIONS = "FLR" +RAILTRACK_ACCEL_FLAT = -0.5 +RAILTRACK_ACCEL_UP = -2 +RAILTRACK_ACCEL_DOWN = 2 + +railtrack = {} + +railtrack.default_rail = { + description = "Rail", + drawtype = "raillike", + tiles = {"default_rail.png", "default_rail_curved.png", + "default_rail_t_junction.png", "default_rail_crossing.png"}, + paramtype = "light", + sunlight_propagates = true, + walkable = false, + is_ground_content = false, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, + }, + groups = {bendy = 2, dig_immediate = 2, attached_node = 1, + connect_to_raillike = minetest.raillike_group("rail")}, + railtype = "rail", + on_place = function(itemstack, placer, pointed_thing) + local name = placer:get_player_name() + if not name or pointed_thing.type ~= "node" then + return + end + if not minetest.is_singleplayer() then + if not minetest.check_player_privs(name, {rails=true}) then + minetest.chat_send_player(name, "Requires rails privilege") + return + end + end + end, + after_place_node = function(pos, placer, itemstack) + local meta = minetest.get_meta(pos) + local def = itemstack:get_definition() or {} + if def.acceleration then + meta:set_string("acceleration", def.acceleration) + end + local junc = {} + local contype = meta:get_string("contype") or "" + local s_cons = meta:get_string("connections") or "" + if contype == "section" then + railtrack:warn_section_len(placer, pos, meta) + elseif s_cons ~= "" then + local cons = minetest.deserialize(s_cons) + for _, con in pairs(cons) do + if railtrack:warn_section_len(placer, con) then + break + end + end + end + end, + on_construct = function(pos) + railtrack:update_rails(pos) + end, + after_destruct = function(pos) + local cons = railtrack:get_connections(pos) + for _, p in pairs(cons) do + railtrack:update_rails(p) + end + end, +} + +function railtrack:register_rail(name, def) + for k, v in pairs(railtrack.default_rail) do + if not def[k] then + def[k] = v + end + end + def.inventory_image = def.inventory_image or def.tiles[1] + def.wield_image = def.wield_image or def.tiles[1] + minetest.register_node(name, def) +end + +function railtrack:warn_section_len(player, pos, meta) + meta = meta or minetest.get_meta(pos) + local contype = meta:get_string("contype") or "" + if contype == "section" then + local s_junc = meta:get_string("junctions") or "" + if s_junc ~= "" then + local junc = minetest.deserialize(s_junc) + if #junc == 2 then + local dist = railtrack:get_distance(junc[1], junc[2]) + if dist > RAILTRACK_WARN_SECTION_LEN then + local name = player:get_player_name() + if name then + minetest.chat_send_player(name, "Warning, section" + .." length "..dist.." exceeds the recommended" + .." maximum of "..RAILTRACK_WARN_SECTION_LEN) + return true + end + end + end + end + end +end + +function railtrack:is_railnode(pos) + local node = minetest.get_node(pos) + if node then + return minetest.get_item_group(node.name, "connect_to_raillike") > 0 + end +end + +function railtrack:get_sign(z) + if z == 0 then + return 0 + else + return z / math.abs(z) + end +end + +function railtrack:get_rotations(s_rots, dir) + local rots = {} + for i = 1, string.len(s_rots) do + local r = string.sub(s_rots, i, i) + local rot = nil + if r == "F" then + rot = {x=dir.x, z=dir.z} + elseif r == "L" then + rot = {x=-dir.z, z=dir.x} + elseif r == "R" then + rot = {x=dir.z, z=-dir.x} + elseif r == "B" then + rot = {x=-dir.x, z=-dir.z} + end + if rot then + table.insert(rots, rot) + end + end + return rots +end + +function railtrack:get_acceleration(pos) + local meta = minetest.get_meta(pos) + local accel = meta:get_string("acceleration") or "" + if accel ~= "" then + return tonumber(accel) + end +end + +function railtrack:get_direction(p1, p2) + local v = vector.subtract(p1, p2) + return { + x = railtrack:get_sign(v.x), + y = railtrack:get_sign(v.y), + z = railtrack:get_sign(v.z), + } +end + +function railtrack:get_distance(p1, p2) + local dx = p1.x - p2.x + local dz = p1.z - p2.z + return math.abs(dx) + math.abs(dz) +end + + +function railtrack:get_railtype(pos) + local node = minetest.get_node(pos) or {} + if node.name then + local ref = minetest.registered_items[node.name] or {} + return ref.railtype + end +end + +function railtrack:get_connection_type(pos, cons) + local railtype = railtrack:get_railtype(pos) + if #cons == 0 then + return "single" + elseif #cons == 1 then + return "junction" + elseif #cons == 2 then + if cons[1].x == cons[2].x or cons[1].z == cons[2].z then + if (cons[1].y == cons[2].y and cons[1].y == pos.y) or + (math.abs(cons[1].y - cons[2].y) == 2) then + if railtype == railtrack:get_railtype(cons[1]) and + railtype == railtrack:get_railtype(cons[2]) then + return "section" + end + end + end + end + return "junction" +end + +function railtrack:get_connections(pos) + local connections = {} + for y = -1, 1 do + for x = -1, 1 do + for z = -1, 1 do + if math.abs(x) ~= math.abs(z) then + local p = vector.add(pos, {x=x, y=y, z=z}) + if railtrack:is_railnode(p) then + table.insert(connections, p) + end + end + end + end + end + return connections +end + +function railtrack:get_junctions(pos, last_pos, junctions) + junctions = junctions or {} + local cons = railtrack:get_connections(pos) + local contype = railtrack:get_connection_type(pos, cons) + if contype == "junction" then + table.insert(junctions, pos) + elseif contype == "section" then + if last_pos then + for i, p in pairs(cons) do + if vector.equals(p, last_pos) then + cons[i] = nil + end + end + end + for _, p in pairs(cons) do + railtrack:get_junctions(p, pos, junctions) + end + end + return junctions +end + +function railtrack:set_acceleration(pos, accel) + local meta = minetest.get_meta(pos) + local contype = meta:get_string("contype") + if contype == "section" then + local s_junc = meta:get_string("junctions") or "" + local junc = minetest.deserialize(s_junc) or {} + if #junc == 2 then + local p = vector.new(junc[2]) + local dir = railtrack:get_direction(junc[1], junc[2]) + local dist = railtrack:get_distance(junc[1], junc[2]) + for i = 0, dist do + local m = minetest.get_meta(p) + if m then + m:set_string("acceleration", tostring(accel)) + end + p = vector.add(dir, p) + end + end + else + meta:set_string("acceleration", tostring(accel)) + end +end + +function railtrack:update_rails(pos, last_pos, level) + local connections = {} + local junctions = {} + local meta = minetest.get_meta(pos) + local cons = railtrack:get_connections(pos) + local contype = railtrack:get_connection_type(pos, cons) + level = level or 0 + for i, p in pairs(cons) do + connections[i] = p + end + if contype == "junction" then + level = level + 1 + end + if contype == "section" or level < 2 then + if last_pos then + for i, p in pairs(cons) do + if vector.equals(p, last_pos) then + cons[i] = nil + end + end + end + for _, p in pairs(cons) do + railtrack:update_rails(p, pos, level) + end + end + if contype == "section" then + junctions = railtrack:get_junctions(pos) + connections = {} + end + meta:set_string("connections", minetest.serialize(connections)) + meta:set_string("junctions", minetest.serialize(junctions)) + meta:set_string("contype", contype) +end + diff --git a/railtrack/textures/carts_rail_brk.png b/railtrack/textures/carts_rail_brk.png Binary files differnew file mode 100644 index 0000000..f3e0ff9 --- /dev/null +++ b/railtrack/textures/carts_rail_brk.png diff --git a/railtrack/textures/carts_rail_crossing_brk.png b/railtrack/textures/carts_rail_crossing_brk.png Binary files differnew file mode 100644 index 0000000..3ace508 --- /dev/null +++ b/railtrack/textures/carts_rail_crossing_brk.png diff --git a/railtrack/textures/carts_rail_crossing_pwr.png b/railtrack/textures/carts_rail_crossing_pwr.png Binary files differnew file mode 100644 index 0000000..d63f133 --- /dev/null +++ b/railtrack/textures/carts_rail_crossing_pwr.png diff --git a/railtrack/textures/carts_rail_crossing_sup.png b/railtrack/textures/carts_rail_crossing_sup.png Binary files differnew file mode 100644 index 0000000..b51467d --- /dev/null +++ b/railtrack/textures/carts_rail_crossing_sup.png diff --git a/railtrack/textures/carts_rail_crossing_swt.png b/railtrack/textures/carts_rail_crossing_swt.png Binary files differnew file mode 100644 index 0000000..a780cf2 --- /dev/null +++ b/railtrack/textures/carts_rail_crossing_swt.png diff --git a/railtrack/textures/carts_rail_curved_brk.png b/railtrack/textures/carts_rail_curved_brk.png Binary files differnew file mode 100644 index 0000000..5a84918 --- /dev/null +++ b/railtrack/textures/carts_rail_curved_brk.png diff --git a/railtrack/textures/carts_rail_curved_pwr.png b/railtrack/textures/carts_rail_curved_pwr.png Binary files differnew file mode 100644 index 0000000..e2ac67a --- /dev/null +++ b/railtrack/textures/carts_rail_curved_pwr.png diff --git a/railtrack/textures/carts_rail_curved_sup.png b/railtrack/textures/carts_rail_curved_sup.png Binary files differnew file mode 100644 index 0000000..326d544 --- /dev/null +++ b/railtrack/textures/carts_rail_curved_sup.png diff --git a/railtrack/textures/carts_rail_curved_swt.png b/railtrack/textures/carts_rail_curved_swt.png Binary files differnew file mode 100644 index 0000000..0ed9287 --- /dev/null +++ b/railtrack/textures/carts_rail_curved_swt.png diff --git a/railtrack/textures/carts_rail_pwr.png b/railtrack/textures/carts_rail_pwr.png Binary files differnew file mode 100644 index 0000000..95f33f6 --- /dev/null +++ b/railtrack/textures/carts_rail_pwr.png diff --git a/railtrack/textures/carts_rail_sup.png b/railtrack/textures/carts_rail_sup.png Binary files differnew file mode 100644 index 0000000..4c812a9 --- /dev/null +++ b/railtrack/textures/carts_rail_sup.png diff --git a/railtrack/textures/carts_rail_swt.png b/railtrack/textures/carts_rail_swt.png Binary files differnew file mode 100644 index 0000000..b7da323 --- /dev/null +++ b/railtrack/textures/carts_rail_swt.png diff --git a/railtrack/textures/carts_rail_t_junction_brk.png b/railtrack/textures/carts_rail_t_junction_brk.png Binary files differnew file mode 100644 index 0000000..0c2c1cb --- /dev/null +++ b/railtrack/textures/carts_rail_t_junction_brk.png diff --git a/railtrack/textures/carts_rail_t_junction_pwr.png b/railtrack/textures/carts_rail_t_junction_pwr.png Binary files differnew file mode 100644 index 0000000..7f97fc7 --- /dev/null +++ b/railtrack/textures/carts_rail_t_junction_pwr.png diff --git a/railtrack/textures/carts_rail_t_junction_sup.png b/railtrack/textures/carts_rail_t_junction_sup.png Binary files differnew file mode 100644 index 0000000..fbdc89c --- /dev/null +++ b/railtrack/textures/carts_rail_t_junction_sup.png diff --git a/railtrack/textures/carts_rail_t_junction_swt.png b/railtrack/textures/carts_rail_t_junction_swt.png Binary files differnew file mode 100644 index 0000000..b03844d --- /dev/null +++ b/railtrack/textures/carts_rail_t_junction_swt.png diff --git a/railtrack/textures/default_rail.png b/railtrack/textures/default_rail.png Binary files differnew file mode 100644 index 0000000..26fed02 --- /dev/null +++ b/railtrack/textures/default_rail.png diff --git a/railtrack/textures/railtrack_fixer.png b/railtrack/textures/railtrack_fixer.png Binary files differnew file mode 100644 index 0000000..17af383 --- /dev/null +++ b/railtrack/textures/railtrack_fixer.png diff --git a/railtrack/textures/railtrack_inspector.png b/railtrack/textures/railtrack_inspector.png Binary files differnew file mode 100644 index 0000000..671fd38 --- /dev/null +++ b/railtrack/textures/railtrack_inspector.png |