From bc8c04d146cea83e6b7c6e63c1778abff6cd0b68 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Wed, 12 Apr 2023 21:31:14 +0200 Subject: Trackmap: get started --- advtrains_trackmap/fsrender.lua | 23 +++++++++++ advtrains_trackmap/grid.lua | 90 +++++++++++++++++++++++++++++++++++++++++ advtrains_trackmap/init.lua | 14 +++++++ advtrains_trackmap/mod.conf | 6 +++ advtrains_trackmap/viewer.lua | 44 ++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 advtrains_trackmap/fsrender.lua create mode 100644 advtrains_trackmap/grid.lua create mode 100644 advtrains_trackmap/init.lua create mode 100644 advtrains_trackmap/mod.conf create mode 100644 advtrains_trackmap/viewer.lua diff --git a/advtrains_trackmap/fsrender.lua b/advtrains_trackmap/fsrender.lua new file mode 100644 index 0000000..607f3cd --- /dev/null +++ b/advtrains_trackmap/fsrender.lua @@ -0,0 +1,23 @@ +-- fsrender.lua +-- Rendering of a grid of characters into a formspec + +local tm = advtrains.trackmap + +function tm.render_grid(grid, origin_pos, width, height) + local s = {"label[0,0;"} + for z=height-1, 0, -1 do + -- render a row + for x=0,width-1 do + local apos_x = origin_pos.x + x + local apos_z = origin_pos.z + z + local chr = "░" + if grid[apos_x] and grid[apos_x][apos_z] then + chr = grid[apos_x][apos_z] + end + table.insert(s, chr) + end + table.insert(s,"\n") + end + table.insert(s, "]") + return table.concat(s) +end \ No newline at end of file diff --git a/advtrains_trackmap/grid.lua b/advtrains_trackmap/grid.lua new file mode 100644 index 0000000..9f367cb --- /dev/null +++ b/advtrains_trackmap/grid.lua @@ -0,0 +1,90 @@ +-- grid.lua +-- routines taking the tracks and building a grid out of them + +local tm = advtrains.trackmap + +-- Maximum scan length for track iterator +local TS_MAX_SCAN = 1000 + +-- Get a character matching the class requested by chr, in the correct orientation for conndir +-- The characters will be chosen from the unicode frame set if appropriate +-- valid character classes -, =, | +local char_equiv = { + ["-"] = {"│", "/", "─", "\\"}, -- single-line + ["="] = {"║", "/", "═", "\\"}, -- double-line + ["|"] = {"─", "\\", "│", "/"}, -- break (i.e. TCB, perpendicular to orientation) +} +local dir_to_charmap = { + [15] = 1, + [ 0] = 1, + [ 1] = 1, + [ 2] = 2, + [ 3] = 3, + [ 4] = 3, + [ 5] = 3, + [ 6] = 4, + [ 7] = 1, + [ 8] = 1, + [ 9] = 1, + [10] = 2, + [11] = 3, + [12] = 3, + [13] = 3, + [14] = 4, +} +function tm.rotate_char_class_by_conn(chr, conndir) + return char_equiv[chr][dir_to_charmap[conndir]] +end + +-- Generate a grid map by walking tracks starting from the given position start_pos +-- For every track that is visited, node_callback is called. +-- signature: node_callback(pos, conns, connid) +-- should return a table as follows: +-- { +-- char = "X" -- the character to use in this place, defaults to guessing a fitting frame character +-- stop = false -- if true, the iterator will stop following this branch +-- } +-- Returning nil will assume defaults. +-- return value: a table: +-- { +-- grid = - access abs_grid[x][y] - contains one character per cell +-- min_pos = - the minimum pos contained in this grid +-- max_pos = - the maximum pos +-- } +function tm.generate_grid_map(start_pos, node_callback) + local ti = advtrains.get_track_iterator(start_pos, nil, TS_MAX_SCAN, true) + local grid = {} -- grid[x][y] + local gminx, gmaxx, gminz, gmaxz = start_pos.x, start_pos.x, start_pos.z, start_pos.z + + while ti:has_next_branch() do + pos, connid = ti:next_branch() + repeat + local ok, conns = advtrains.get_rail_info_at(pos) + local c = node_callback(pos, conns, connid) + local chr = c and c.char + if not chr then + chr = tm.rotate_char_class_by_conn("=", conns[connid]) + end + + -- add the char to the grid + if not grid[pos.x] then + grid[pos.x] = {} + end + grid[pos.x][pos.z] = chr + + gminx = math.min(gminx, pos.x) + gmaxx = math.max(gmaxx, pos.x) + gminz = math.min(gminz, pos.z) + gmaxz = math.max(gmaxz, pos.z) + + if c and c.stop then break end + pos, connid = ti:next_track() + until not pos + end + return { + grid = grid, + min_pos = {x=gminx, z=gminz}, + max_pos = {x=gmaxx, z=gmaxz}, + } +end + diff --git a/advtrains_trackmap/init.lua b/advtrains_trackmap/init.lua new file mode 100644 index 0000000..060e597 --- /dev/null +++ b/advtrains_trackmap/init.lua @@ -0,0 +1,14 @@ +-- Advtrains track map +-- Replacement of itrainmap + +advtrains.trackmap = {} + + +local modpath = minetest.get_modpath(minetest.get_current_modname()) .. DIR_DELIM + + +dofile(modpath.."grid.lua") +dofile(modpath.."fsrender.lua") +dofile(modpath.."viewer.lua") + + diff --git a/advtrains_trackmap/mod.conf b/advtrains_trackmap/mod.conf new file mode 100644 index 0000000..633f1e2 --- /dev/null +++ b/advtrains_trackmap/mod.conf @@ -0,0 +1,6 @@ +name=advtrains_trackmap +title=Advanced Trains Track Map +description=Formspec-based map to display track layouts +author=orwell96 + +depends=advtrains diff --git a/advtrains_trackmap/viewer.lua b/advtrains_trackmap/viewer.lua new file mode 100644 index 0000000..d1921d8 --- /dev/null +++ b/advtrains_trackmap/viewer.lua @@ -0,0 +1,44 @@ +-- viewer.lua +-- standalone chatcommand/tool trackmap viewer window + +local tm = advtrains.trackmap + +local function node_left_click(pos, pname) + local node_ok, conns, rail_y=advtrains.get_rail_info_at(pos) + if not node_ok then + minetest.chat_send_player(pname, "Node is not a track!") + return + end + + local function node_callback() + return nil + end + + local gridtbl = tm.generate_grid_map(pos, node_callback) + local fslabel = tm.render_grid(gridtbl.grid, gridtbl.min_pos, 100, 100) + + minetest.show_formspec(pname, "advtrains_trackmap:test", "size[20,20]"..fslabel) +end + + +minetest.register_craftitem("advtrains_trackmap:tool",{ + description = "Trackmap Tool\nPunch: Show map", + groups = {cracky=1}, -- key=name, value=rating; rating=1..3. + inventory_image = "at_il_tool.png", + wield_image = "at_il_tool.png", + stack_max = 1, + on_use = function(itemstack, player, pointed_thing) + local pname = player:get_player_name() + if not pname then + return + end + if not minetest.check_player_privs(pname, {interlocking=true}) then + minetest.chat_send_player(pname, "Insufficient privileges to use this!") + return + end + if pointed_thing.type=="node" then + local pos=pointed_thing.under + node_left_click(pos, pname) + end + end +}) \ No newline at end of file -- cgit v1.2.3