aboutsummaryrefslogtreecommitdiff
path: root/advtrains_trackmap
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains_trackmap')
-rw-r--r--advtrains_trackmap/fsrender.lua41
-rw-r--r--advtrains_trackmap/grid.lua107
-rw-r--r--advtrains_trackmap/init.lua14
-rw-r--r--advtrains_trackmap/mod.conf6
-rw-r--r--advtrains_trackmap/viewer.lua43
5 files changed, 211 insertions, 0 deletions
diff --git a/advtrains_trackmap/fsrender.lua b/advtrains_trackmap/fsrender.lua
new file mode 100644
index 0000000..340b08c
--- /dev/null
+++ b/advtrains_trackmap/fsrender.lua
@@ -0,0 +1,41 @@
+-- fsrender.lua
+-- Rendering of a grid of characters into a formspec
+
+local tm = advtrains.trackmap
+
+function tm.render_grid_formspec(formsize_x, formsize_y, gridtbl, origin_pos, width, height)
+ local grid = gridtbl.grid
+ local gcolor = gridtbl.gcolor
+ local s = {
+ "formspec_version[3]",
+ "size["..formsize_x..","..formsize_y.."]",
+ "no_prepend[]",
+ "bgcolor[white;false;white]",
+ "style_type[label;font=mono]",
+ "label[0,0;",
+ minetest.get_color_escape_sequence("black")
+ }
+ local last_color = nil
+ 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
+ local color = gcolor[apos_x][apos_z]
+ if color ~= last_color then
+ -- change the color of the text
+ table.insert(s, minetest.get_color_escape_sequence(color or "black"))
+ last_color = color
+ end
+ chr = grid[apos_x][apos_z]
+ end
+ table.insert(s, chr)
+ end
+ table.insert(s,"\n")
+ end
+ table.insert(s, "]")
+ table.insert(s, "style_type[label;font=]") -- reset font style
+ 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..4c98b2f
--- /dev/null
+++ b/advtrains_trackmap/grid.lua
@@ -0,0 +1,107 @@
+-- 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)
+ --atdebug("rotatechar", chr, conndir, "dircharmap", dir_to_charmap[conndir], "charequiv", char_equiv[chr])
+ 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
+-- color = "colorstring" or nil -- the color to render the character with
+-- stop = false -- if true, the iterator will stop following this branch
+-- }
+-- Returning nil will assume defaults.
+-- return value: a table:
+-- {
+-- grid = <grid> - access abs_grid[x][y] - contains one character per cell
+-- min_pos = <pos> - the minimum pos contained in this grid
+-- max_pos = <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 gcolor = {} -- grid[x][y]
+ local gylev = {} -- 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
+ --atdebug("init",pos.x,pos.z,chr,"")
+ if not chr then
+ chr = tm.rotate_char_class_by_conn("=", conns[connid].c)
+ end
+
+ -- add the char to the grid
+ if not grid[pos.x] then
+ grid[pos.x] = {}
+ gcolor[pos.x] = {}
+ gylev[pos.x] = {}
+ end
+
+ -- ensure that higher rails are rendered on top
+ local prev_ylev = gylev[pos.x][pos.z]
+ if not prev_ylev or prev_ylev < pos.y then
+ grid[pos.x][pos.z] = chr
+ gylev[pos.x][pos.z] = pos.y
+ if c and c.color then
+ gcolor[pos.x][pos.z] = c.color
+ end
+ end
+
+ 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,
+ gcolor = gcolor,
+ 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..b7205c8
--- /dev/null
+++ b/advtrains_trackmap/viewer.lua
@@ -0,0 +1,43 @@
+-- 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(npos, conns, connid)
+ if vector.equals(pos, npos) then
+ return {color = "red"}
+ end
+ return nil
+ end
+
+ local gridtbl = tm.generate_grid_map(pos, node_callback)
+ local fslabel = tm.render_grid_formspec(20, 20, gridtbl, {x=pos.x-35, z=pos.z-22}, 70, 44)
+
+ minetest.show_formspec(pname, "advtrains_trackmap:test", 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 pointed_thing.type=="node" then
+ local pos=pointed_thing.under
+ node_left_click(pos, pname)
+ end
+ end
+}) \ No newline at end of file