summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/m_spanningtree.cpp62
1 files changed, 43 insertions, 19 deletions
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index abdb6d798..1c35ecad0 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -971,54 +971,78 @@ class ModuleSpanningTree : public Module
return;
}
- void ShowMap(TreeServer* Current, userrec* user, int depth, char matrix[32][80])
+ // WARNING: NOT THREAD SAFE - DONT GET ANY SMART IDEAS.
+
+ void ShowMap(TreeServer* Current, userrec* user, int depth, char matrix[128][80])
{
- for (int t = 0; t < depth; t++)
+ if (line < 128)
{
- matrix[line][t] = ' ';
- }
- strlcpy(&matrix[line][depth],Current->GetName().c_str(),80);
- line++;
- //WriteServ(user->fd,"006 %s :%s%s",user->nick,header,Current->GetName().c_str());
- for (unsigned int q = 0; q < Current->ChildCount(); q++)
- {
- ShowMap(Current->GetChild(q),user,depth+2,matrix);
+ for (int t = 0; t < depth; t++)
+ {
+ matrix[line][t] = ' ';
+ }
+ strlcpy(&matrix[line][depth],Current->GetName().c_str(),80);
+ line++;
+ for (unsigned int q = 0; q < Current->ChildCount(); q++)
+ {
+ ShowMap(Current->GetChild(q),user,depth+2,matrix);
+ }
}
}
- // Yes, this is smart (and odd). You may all praise me now.
- // After looking over how others did this, with tons of ugly
- // maths combined with lots of recursion, i decided to approach
- // this in a very different way. To cut down on the recursion,
- // as users may be able to trigger this command, the algorithm
- // renders the map 'backwards' without recursion after it has
- // correctly placed the servers into the lines.
+ // Ok, prepare to be confused.
+ // After much mulling over how to approach this, it struck me that
+ // the 'usual' way of doing a /MAP isnt the best way. Instead of
+ // keeping track of a ton of ascii characters, and line by line
+ // under recursion working out where to place them using multiplications
+ // and divisons, we instead render the map onto a backplane of characters
+ // (a character matrix), then draw the branches as a series of "L" shapes
+ // from the nodes. This is not only friendlier on CPU it uses less stack.
+
void HandleMap(char** parameters, int pcnt, userrec* user)
{
- char matrix[32][80];
- for (unsigned int t = 0; t < 32; t++)
+ // This array represents a virtual screen which we will
+ // "scratch" draw to, as the console device of an irc
+ // client does not provide for a proper terminal.
+ char matrix[128][80];
+ for (unsigned int t = 0; t < 128; t++)
{
matrix[line][0] = '\0';
}
line = 0;
+ // The only recursive bit is called here.
ShowMap(TreeRoot,user,0,matrix);
+ // Process each line one by one. The algorithm has a limit of
+ // 128 servers (which is far more than a spanning tree should have
+ // anyway, so we're ok). This limit can be raised simply by making
+ // the character matrix deeper, 128 rows taking 10k of memory.
for (int l = 1; l < line; l++)
{
+ // scan across the line looking for the start of the
+ // servername (the recursive part of the algorithm has placed
+ // the servers at indented positions depending on what they
+ // are related to)
int first_nonspace = 0;
while (matrix[l][first_nonspace] == ' ')
{
first_nonspace++;
}
first_nonspace--;
+ // Draw the `- (corner) section: this may be overwritten by
+ // another L shape passing along the same vertical pane, becoming
+ // a |- (branch) section instead.
matrix[l][first_nonspace] = '-';
matrix[l][first_nonspace-1] = '`';
int l2 = l - 1;
+ // Draw upwards until we hit the parent server, causing possibly
+ // other corners (`-) to become branches (|-)
while ((matrix[l2][first_nonspace-1] == ' ') || (matrix[l2][first_nonspace-1] == '`'))
{
matrix[l2][first_nonspace-1] = '|';
l2--;
}
}
+ // dump the whole lot to the user. This is the easy bit, honest.
for (int t = 0; t < line; t++)
{
WriteServ(user->fd,"006 %s :%s",user->nick,&matrix[t][0]);