Committing these because it seems to be the only way to get rid of them ever.

This commit is contained in:
Shadowmech88
2016-01-12 14:46:12 -06:00
parent 48128950c9
commit 8de9a63e78
10 changed files with 5501 additions and 5501 deletions

View File

@@ -1,54 +1,54 @@
/*
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
(2012)
*/
var/list/config_stream = list()
var/list/servers = list()
var/list/servernames = list()
var/list/adminfiles = list()
var/list/adminkeys = list()
proc/gen_configs()
config_stream = dd_file2list("config.txt")
var/server_gen = 0 // if the stream is looking for servers
var/admin_gen = 0 // if the stream is looking for admins
for(var/line in config_stream)
if(line == "\[SERVERS\]")
server_gen = 1
if(admin_gen)
admin_gen = 0
else if(line == "\[ADMINS\]")
admin_gen = 1
if(server_gen)
server_gen = 0
else
if(findtext(line, ".") && !findtext(line, "##"))
if(server_gen)
var/filterline = replacetext(line, " ", "")
var/serverlink = copytext(filterline, findtext( filterline, ")") + 1)
servers.Add(serverlink)
servernames.Add( copytext(line, findtext(line, "("), findtext(line, ")") + 1))
else if(admin_gen)
adminfiles.Add(line)
/*
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
(2012)
*/
var/list/config_stream = list()
var/list/servers = list()
var/list/servernames = list()
var/list/adminfiles = list()
var/list/adminkeys = list()
proc/gen_configs()
config_stream = dd_file2list("config.txt")
var/server_gen = 0 // if the stream is looking for servers
var/admin_gen = 0 // if the stream is looking for admins
for(var/line in config_stream)
if(line == "\[SERVERS\]")
server_gen = 1
if(admin_gen)
admin_gen = 0
else if(line == "\[ADMINS\]")
admin_gen = 1
if(server_gen)
server_gen = 0
else
if(findtext(line, ".") && !findtext(line, "##"))
if(server_gen)
var/filterline = replacetext(line, " ", "")
var/serverlink = copytext(filterline, findtext( filterline, ")") + 1)
servers.Add(serverlink)
servernames.Add( copytext(line, findtext(line, "("), findtext(line, ")") + 1))
else if(admin_gen)
adminfiles.Add(line)
to_chat(world, line)
// Generate the list of admins now
for(var/file in adminfiles)
var/admin_config_stream = dd_file2list(file)
for(var/line in admin_config_stream)
var/akey = copytext(line, 1, findtext(line, " "))
adminkeys.Add(akey)
// Generate the list of admins now
for(var/file in adminfiles)
var/admin_config_stream = dd_file2list(file)
for(var/line in admin_config_stream)
var/akey = copytext(line, 1, findtext(line, " "))
adminkeys.Add(akey)

View File

@@ -1,21 +1,21 @@
// DM Environment file for Redirect_Tgstation.dme.
// All manual changes should be made outside the BEGIN_ and END_ blocks.
// New source code should be placed in .dm files: choose File/New --> Code File.
// BEGIN_INTERNALS
// END_INTERNALS
// BEGIN_FILE_DIR
#define FILE_DIR .
// END_FILE_DIR
// BEGIN_PREFERENCES
// END_PREFERENCES
// BEGIN_INCLUDE
#include "Configurations.dm"
#include "Redirector.dm"
#include "textprocs.dm"
#include "skin.dmf"
// END_INCLUDE
// DM Environment file for Redirect_Tgstation.dme.
// All manual changes should be made outside the BEGIN_ and END_ blocks.
// New source code should be placed in .dm files: choose File/New --> Code File.
// BEGIN_INTERNALS
// END_INTERNALS
// BEGIN_FILE_DIR
#define FILE_DIR .
// END_FILE_DIR
// BEGIN_PREFERENCES
// END_PREFERENCES
// BEGIN_INCLUDE
#include "Configurations.dm"
#include "Redirector.dm"
#include "textprocs.dm"
#include "skin.dmf"
// END_INCLUDE

View File

@@ -1,88 +1,88 @@
/*
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
(2012)
*/
/* TODO: work on server selection for detected admins */
#define ADMINS 1
#define PLAYERS 0
var/player_weight = 1 // players are more likely to join a server with less players
var/admin_weight = 5 // admins are more likely to join a server with less admins
var/player_substr = "players=" // search for this substring to locate # of players
var/admin_substr = "admins=" // search for this to locate # of admins
world
name = "TGstation Redirector"
New()
..()
gen_configs()
/datum/server
var/players = 0
var/admins = 0
var/weight = 0 // lower weight is good; highet weight is bad
var/link = ""
mob/Login()
..()
var/list/weights = list()
var/list/servers = list()
for(var/x in global.servers)
/*
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
(2012)
*/
/* TODO: work on server selection for detected admins */
#define ADMINS 1
#define PLAYERS 0
var/player_weight = 1 // players are more likely to join a server with less players
var/admin_weight = 5 // admins are more likely to join a server with less admins
var/player_substr = "players=" // search for this substring to locate # of players
var/admin_substr = "admins=" // search for this to locate # of admins
world
name = "TGstation Redirector"
New()
..()
gen_configs()
/datum/server
var/players = 0
var/admins = 0
var/weight = 0 // lower weight is good; highet weight is bad
var/link = ""
mob/Login()
..()
var/list/weights = list()
var/list/servers = list()
for(var/x in global.servers)
to_chat(world, "[x] [servernames[ global.servers.Find(x) ]]")
var/info = world.Export("[x]?status")
var/datum/server/S = new()
S.players = extract(info, PLAYERS)
S.admins = extract(info, ADMINS)
S.weight += player_weight * S.players
S.link = x
var/info = world.Export("[x]?status")
var/datum/server/S = new()
S.players = extract(info, PLAYERS)
S.admins = extract(info, ADMINS)
S.weight += player_weight * S.players
S.link = x
to_chat(world, S.players)
to_chat(world, S.admins)
weights.Add(S.weight)
servers.Add(S)
var/lowest = min(weights)
var/serverlink
for(var/datum/server/S in servers)
if(S.weight == lowest)
serverlink = S.link
weights.Add(S.weight)
servers.Add(S)
var/lowest = min(weights)
var/serverlink
for(var/datum/server/S in servers)
if(S.weight == lowest)
serverlink = S.link
to_chat(src, link(serverlink))
proc/extract(var/data, var/type = PLAYERS)
var/nextpos = 0
if(type == PLAYERS)
nextpos = findtextEx(data, player_substr)
nextpos += length(player_substr)
else
nextpos = findtextEx(data, admin_substr)
nextpos += length(admin_substr)
var/returnval = ""
for(var/i = 1, i <= 10, i++)
var/interval = copytext(data, nextpos + (i-1), nextpos + i)
if(interval == "&")
break
else
returnval += interval
return returnval
proc/extract(var/data, var/type = PLAYERS)
var/nextpos = 0
if(type == PLAYERS)
nextpos = findtextEx(data, player_substr)
nextpos += length(player_substr)
else
nextpos = findtextEx(data, admin_substr)
nextpos += length(admin_substr)
var/returnval = ""
for(var/i = 1, i <= 10, i++)
var/interval = copytext(data, nextpos + (i-1), nextpos + i)
if(interval == "&")
break
else
returnval += interval
return returnval

View File

@@ -1,12 +1,12 @@
[SERVERS]
## Simply enter a list of servers to poll. Be sure to specify a server name in parentheses.
(Sibyl #1) byond://game.nanotrasen.com:1337
(Sibyl #2) byond://game.nanotrasen.com:2337
[ADMINS]
## Specify some standard Windows filepaths (you may use relative paths) for admin txt lists to poll.
C:\SS13\config\admins.txt
[SERVERS]
## Simply enter a list of servers to poll. Be sure to specify a server name in parentheses.
(Sibyl #1) byond://game.nanotrasen.com:1337
(Sibyl #2) byond://game.nanotrasen.com:2337
[ADMINS]
## Specify some standard Windows filepaths (you may use relative paths) for admin txt lists to poll.
C:\SS13\config\admins.txt

View File

@@ -1,149 +1,149 @@
macro "macro"
elem
name = "North+REP"
command = ".north"
is-disabled = false
elem
name = "South+REP"
command = ".south"
is-disabled = false
elem
name = "East+REP"
command = ".east"
is-disabled = false
elem
name = "West+REP"
command = ".west"
is-disabled = false
elem
name = "Northeast+REP"
command = ".northeast"
is-disabled = false
elem
name = "Northwest+REP"
command = ".northwest"
is-disabled = false
elem
name = "Southeast+REP"
command = ".southeast"
is-disabled = false
elem
name = "Southwest+REP"
command = ".southwest"
is-disabled = false
elem
name = "Center+REP"
command = ".center"
is-disabled = false
menu "menu"
elem
name = "&Quit"
command = ".quit"
category = "&File"
is-checked = false
can-check = false
group = ""
is-disabled = false
saved-params = "is-checked"
window "window"
elem "window"
type = MAIN
pos = 281,0
size = 594x231
anchor1 = none
anchor2 = none
font-family = ""
font-size = 0
font-style = ""
text-color = #000000
background-color = #000000
is-visible = false
is-disabled = false
is-transparent = false
is-default = true
border = none
drop-zone = false
right-click = false
saved-params = "pos;size;is-minimized;is-maximized"
on-size = ""
title = ""
titlebar = true
statusbar = false
can-close = true
can-minimize = true
can-resize = true
is-pane = false
is-minimized = false
is-maximized = false
can-scroll = none
icon = ""
image = ""
image-mode = stretch
keep-aspect = false
transparent-color = none
alpha = 255
macro = "macro"
menu = ""
on-close = ""
elem "servers"
type = GRID
pos = 8,8
size = 576x152
anchor1 = none
anchor2 = none
font-family = ""
font-size = 0
font-style = ""
text-color = #ffffff
background-color = #000000
is-visible = true
is-disabled = false
is-transparent = false
is-default = false
border = none
drop-zone = true
right-click = false
saved-params = ""
on-size = ""
cells = 1x1
current-cell = 1,1
show-lines = none
small-icons = true
show-names = true
enable-http-images = false
link-color = #0000ff
visited-color = #ff00ff
line-color = #c0c0c0
style = ""
is-list = false
elem "output1"
type = OUTPUT
pos = 8,168
size = 576x56
anchor1 = none
anchor2 = none
font-family = ""
font-size = 0
font-style = ""
text-color = #ffffff
background-color = #000000
is-visible = true
is-disabled = false
is-transparent = false
is-default = true
border = none
drop-zone = false
right-click = false
saved-params = "max-lines"
on-size = ""
link-color = #0000ff
visited-color = #ff00ff
style = ""
enable-http-images = false
max-lines = 1000
image = ""
macro "macro"
elem
name = "North+REP"
command = ".north"
is-disabled = false
elem
name = "South+REP"
command = ".south"
is-disabled = false
elem
name = "East+REP"
command = ".east"
is-disabled = false
elem
name = "West+REP"
command = ".west"
is-disabled = false
elem
name = "Northeast+REP"
command = ".northeast"
is-disabled = false
elem
name = "Northwest+REP"
command = ".northwest"
is-disabled = false
elem
name = "Southeast+REP"
command = ".southeast"
is-disabled = false
elem
name = "Southwest+REP"
command = ".southwest"
is-disabled = false
elem
name = "Center+REP"
command = ".center"
is-disabled = false
menu "menu"
elem
name = "&Quit"
command = ".quit"
category = "&File"
is-checked = false
can-check = false
group = ""
is-disabled = false
saved-params = "is-checked"
window "window"
elem "window"
type = MAIN
pos = 281,0
size = 594x231
anchor1 = none
anchor2 = none
font-family = ""
font-size = 0
font-style = ""
text-color = #000000
background-color = #000000
is-visible = false
is-disabled = false
is-transparent = false
is-default = true
border = none
drop-zone = false
right-click = false
saved-params = "pos;size;is-minimized;is-maximized"
on-size = ""
title = ""
titlebar = true
statusbar = false
can-close = true
can-minimize = true
can-resize = true
is-pane = false
is-minimized = false
is-maximized = false
can-scroll = none
icon = ""
image = ""
image-mode = stretch
keep-aspect = false
transparent-color = none
alpha = 255
macro = "macro"
menu = ""
on-close = ""
elem "servers"
type = GRID
pos = 8,8
size = 576x152
anchor1 = none
anchor2 = none
font-family = ""
font-size = 0
font-style = ""
text-color = #ffffff
background-color = #000000
is-visible = true
is-disabled = false
is-transparent = false
is-default = false
border = none
drop-zone = true
right-click = false
saved-params = ""
on-size = ""
cells = 1x1
current-cell = 1,1
show-lines = none
small-icons = true
show-names = true
enable-http-images = false
link-color = #0000ff
visited-color = #ff00ff
line-color = #c0c0c0
style = ""
is-list = false
elem "output1"
type = OUTPUT
pos = 8,168
size = 576x56
anchor1 = none
anchor2 = none
font-family = ""
font-size = 0
font-style = ""
text-color = #ffffff
background-color = #000000
is-visible = true
is-disabled = false
is-transparent = false
is-default = true
border = none
drop-zone = false
right-click = false
saved-params = "max-lines"
on-size = ""
link-color = #0000ff
visited-color = #ff00ff
style = ""
enable-http-images = false
max-lines = 1000
image = ""

View File

@@ -1,150 +1,150 @@
/*
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
(2012)
NOTE: The below functions are part of BYOND user Deadron's "TextHandling" library.
[ http://www.byond.com/developer/Deadron/TextHandling ]
*/
proc
///////////////////
// Reading files //
///////////////////
dd_file2list(file_path, separator = "\n")
var/file
if (isfile(file_path))
file = file_path
else
file = file(file_path)
return dd_text2list(file2text(file), separator)
////////////////////
// Replacing text //
////////////////////
dd_replacetext(text, search_string, replacement_string)
// A nice way to do this is to split the text into an array based on the search_string,
// then put it back together into text using replacement_string as the new separator.
var/list/textList = dd_text2list(text, search_string)
return dd_list2text(textList, replacement_string)
dd_replaceText(text, search_string, replacement_string)
var/list/textList = dd_text2List(text, search_string)
return dd_list2text(textList, replacement_string)
/////////////////////
// Prefix checking //
/////////////////////
dd_hasprefix(text, prefix)
var/start = 1
var/end = lentext(prefix) + 1
return findtext(text, prefix, start, end)
dd_hasPrefix(text, prefix)
var/start = 1
var/end = lentext(prefix) + 1
return findtextEx(text, prefix, start, end)
/////////////////////
// Suffix checking //
/////////////////////
dd_hassuffix(text, suffix)
var/start = length(text) - length(suffix)
if (start) return findtext(text, suffix, start)
dd_hasSuffix(text, suffix)
var/start = length(text) - length(suffix)
if (start) return findtextEx(text, suffix, start)
/////////////////////////////
// Turning text into lists //
/////////////////////////////
dd_text2list(text, separator)
var/textlength = lentext(text)
var/separatorlength = lentext(separator)
var/list/textList = new /list()
var/searchPosition = 1
var/findPosition = 1
var/buggyText
while (1) // Loop forever.
findPosition = findtext(text, separator, searchPosition, 0)
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
searchPosition = findPosition + separatorlength // Skip over separator.
if (findPosition == 0) // Didn't find anything at end of string so stop here.
return textList
else
if (searchPosition > textlength) // Found separator at very end of string.
textList += "" // So add empty element.
return textList
dd_text2List(text, separator)
var/textlength = lentext(text)
var/separatorlength = lentext(separator)
var/list/textList = new /list()
var/searchPosition = 1
var/findPosition = 1
var/buggyText
while (1) // Loop forever.
findPosition = findtextEx(text, separator, searchPosition, 0)
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
searchPosition = findPosition + separatorlength // Skip over separator.
if (findPosition == 0) // Didn't find anything at end of string so stop here.
return textList
else
if (searchPosition > textlength) // Found separator at very end of string.
textList += "" // So add empty element.
return textList
dd_list2text(list/the_list, separator)
var/total = the_list.len
if (total == 0) // Nothing to work with.
return
var/newText = "[the_list[1]]" // Treats any object/number as text also.
var/count
for (count = 2, count <= total, count++)
if (separator) newText += separator
newText += "[the_list[count]]"
return newText
dd_centertext(message, length)
var/new_message = message
var/size = length(message)
if (size == length)
return new_message
if (size > length)
return copytext(new_message, 1, length + 1)
// Need to pad text to center it.
var/delta = length - size
if (delta == 1)
// Add one space after it.
return new_message + " "
// Is this an odd number? If so, add extra space to front.
if (delta % 2)
new_message = " " + new_message
delta--
// Divide delta in 2, add those spaces to both ends.
delta = delta / 2
var/spaces = ""
for (var/count = 1, count <= delta, count++)
spaces += " "
return spaces + new_message + spaces
dd_limittext(message, length)
// Truncates text to limit if necessary.
var/size = length(message)
if (size <= length)
return message
else
/*
Written by contributor Doohl for the /tg/station Open Source project, hosted on Google Code.
(2012)
NOTE: The below functions are part of BYOND user Deadron's "TextHandling" library.
[ http://www.byond.com/developer/Deadron/TextHandling ]
*/
proc
///////////////////
// Reading files //
///////////////////
dd_file2list(file_path, separator = "\n")
var/file
if (isfile(file_path))
file = file_path
else
file = file(file_path)
return dd_text2list(file2text(file), separator)
////////////////////
// Replacing text //
////////////////////
dd_replacetext(text, search_string, replacement_string)
// A nice way to do this is to split the text into an array based on the search_string,
// then put it back together into text using replacement_string as the new separator.
var/list/textList = dd_text2list(text, search_string)
return dd_list2text(textList, replacement_string)
dd_replaceText(text, search_string, replacement_string)
var/list/textList = dd_text2List(text, search_string)
return dd_list2text(textList, replacement_string)
/////////////////////
// Prefix checking //
/////////////////////
dd_hasprefix(text, prefix)
var/start = 1
var/end = lentext(prefix) + 1
return findtext(text, prefix, start, end)
dd_hasPrefix(text, prefix)
var/start = 1
var/end = lentext(prefix) + 1
return findtextEx(text, prefix, start, end)
/////////////////////
// Suffix checking //
/////////////////////
dd_hassuffix(text, suffix)
var/start = length(text) - length(suffix)
if (start) return findtext(text, suffix, start)
dd_hasSuffix(text, suffix)
var/start = length(text) - length(suffix)
if (start) return findtextEx(text, suffix, start)
/////////////////////////////
// Turning text into lists //
/////////////////////////////
dd_text2list(text, separator)
var/textlength = lentext(text)
var/separatorlength = lentext(separator)
var/list/textList = new /list()
var/searchPosition = 1
var/findPosition = 1
var/buggyText
while (1) // Loop forever.
findPosition = findtext(text, separator, searchPosition, 0)
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
searchPosition = findPosition + separatorlength // Skip over separator.
if (findPosition == 0) // Didn't find anything at end of string so stop here.
return textList
else
if (searchPosition > textlength) // Found separator at very end of string.
textList += "" // So add empty element.
return textList
dd_text2List(text, separator)
var/textlength = lentext(text)
var/separatorlength = lentext(separator)
var/list/textList = new /list()
var/searchPosition = 1
var/findPosition = 1
var/buggyText
while (1) // Loop forever.
findPosition = findtextEx(text, separator, searchPosition, 0)
buggyText = copytext(text, searchPosition, findPosition) // Everything from searchPosition to findPosition goes into a list element.
textList += "[buggyText]" // Working around weird problem where "text" != "text" after this copytext().
searchPosition = findPosition + separatorlength // Skip over separator.
if (findPosition == 0) // Didn't find anything at end of string so stop here.
return textList
else
if (searchPosition > textlength) // Found separator at very end of string.
textList += "" // So add empty element.
return textList
dd_list2text(list/the_list, separator)
var/total = the_list.len
if (total == 0) // Nothing to work with.
return
var/newText = "[the_list[1]]" // Treats any object/number as text also.
var/count
for (count = 2, count <= total, count++)
if (separator) newText += separator
newText += "[the_list[count]]"
return newText
dd_centertext(message, length)
var/new_message = message
var/size = length(message)
if (size == length)
return new_message
if (size > length)
return copytext(new_message, 1, length + 1)
// Need to pad text to center it.
var/delta = length - size
if (delta == 1)
// Add one space after it.
return new_message + " "
// Is this an odd number? If so, add extra space to front.
if (delta % 2)
new_message = " " + new_message
delta--
// Divide delta in 2, add those spaces to both ends.
delta = delta / 2
var/spaces = ""
for (var/count = 1, count <= delta, count++)
spaces += " "
return spaces + new_message + spaces
dd_limittext(message, length)
// Truncates text to limit if necessary.
var/size = length(message)
if (size <= length)
return message
else
return copytext(message, 1, length + 1)

File diff suppressed because it is too large Load Diff

View File

@@ -1,314 +1,314 @@
/* Runtime Condenser by Nodrak
* This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance
* of the runtime will log the proc, source, usr and src, the rest will just add to the total. Infinite loops will
* also be caught and displayed (if any) above the list of runtimes.
*
* How to use:
* 1) Copy and paste your list of runtimes from Dream Daemon into input.exe
* 2) Run RuntimeCondenser.exe
* 3) Open output.txt for a condensed report of the runtimes
*/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//Make all of these global. It's bad yes, but it's a small program so it really doesn't affect anything.
//Because hardcoded numbers are bad :(
const unsigned short maxStorage = 99; //100 - 1
//What we use to read input
string currentLine = "Blank";
string nextLine = "Blank";
//Stores lines we want to keep to print out
string storedRuntime[maxStorage+1];
string storedProc[maxStorage+1];
string storedSource[maxStorage+1];
string storedUsr[maxStorage+1];
string storedSrc[maxStorage+1];
//Stat tracking stuff for output
unsigned int totalRuntimes = 0;
unsigned int totalUniqueRuntimes = 0;
unsigned int totalInfiniteLoops = 0;
unsigned int totalUniqueInfiniteLoops = 0;
//Misc
unsigned int numRuntime[maxStorage+1]; //Number of times a specific runtime has occured
bool checkNextLines = false; //Used in case byond has condensed a large number of similar runtimes
int storedIterator = 0; //Used to remember where we stored the runtime
bool readFromFile()
{
//Open file to read
ifstream inputFile("input.txt");
if(inputFile.is_open())
{
while(!inputFile.eof()) //Until end of file
{
//If we've run out of storage
if(storedRuntime[maxStorage] != "Blank") break;
//Update our lines
currentLine = nextLine;
getline(inputFile, nextLine);
//After finding a new runtime, check to see if there are extra values to store
if(checkNextLines)
{
//Skip ahead
currentLine = nextLine;
getline(inputFile, nextLine);
//If we find this, we have new stuff to store
if(nextLine.find("usr:") != std::string::npos)
{
//Store more info
storedSource[storedIterator] = currentLine;
storedUsr[storedIterator] = nextLine;
//Skip ahead again
currentLine = nextLine;
getline(inputFile, nextLine);
//Store the last of the info
storedSrc[storedIterator] = nextLine;
}
checkNextLines = false;
}
//Found an infinite loop!
if(currentLine.find("Infinite loop suspected") != std::string::npos || currentLine.find("Maximum recursion level reached") != std::string::npos)
{
totalInfiniteLoops++;
for(int i=0; i <= maxStorage; i++)
{
//We've already encountered this
if(currentLine == storedRuntime[i])
{
numRuntime[i]++;
break;
}
//We've never encoutnered this
if(storedRuntime[i] == "Blank")
{
storedRuntime[i] = currentLine;
currentLine = nextLine;
getline(inputFile, nextLine); //Skip the "if this is not an infinite loop" line
storedProc[i] = nextLine;
numRuntime[i] = 1;
checkNextLines = true;
storedIterator = i;
totalUniqueInfiniteLoops++;
break;
}
}
}
//Found a runtime!
else if(currentLine.find("runtime error:") != std::string::npos)
{
totalRuntimes++;
for(int i=0; i <= maxStorage; i++)
{
//We've already encountered this
if(currentLine == storedRuntime[i])
{
numRuntime[i]++;
break;
}
//We've never encoutnered this
if(storedRuntime[i] == "Blank")
{
storedRuntime[i] = currentLine;
storedProc[i] = nextLine;
numRuntime[i] = 1;
checkNextLines = true;
storedIterator = i;
totalUniqueRuntimes++;
break;
}
}
}
}
}
else
{
return false;
}
return true;
}
bool writeToFile()
{
//Open and clear the file
ofstream outputFile("Output.txt", ios::trunc);
if(outputFile.is_open())
{
outputFile << "Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n";
if(totalUniqueInfiniteLoops > 0)
{
outputFile << "Total unique infinite loops: " << totalUniqueInfiniteLoops << endl;
}
if(totalInfiniteLoops > 0)
{
outputFile << "Total infinite loops: " << totalInfiniteLoops << endl;
}
outputFile << "Total unique runtimes: " << totalUniqueRuntimes << endl;
outputFile << "Total runtimes: " << totalRuntimes << endl << endl;
//Display a warning if we've hit the maximum space we've allocated for storage
if(totalUniqueRuntimes + totalUniqueInfiniteLoops >= maxStorage)
{
outputFile << "Warning: The maximum number of unique runtimes has been hit. If there were more, they have been cropped out.\n\n";
}
//If we have infinite loops, display them first.
if(totalInfiniteLoops > 0)
{
outputFile << "** Infinite loops **";
for(int i=0; i <= maxStorage; i++)
{
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos)
{
if(numRuntime[i] != 0) outputFile << endl << endl << "The following infinite loop has occured " << numRuntime[i] << " time(s).\n";
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
}
}
outputFile << endl << endl; //For spacing
}
//Do runtimes next
outputFile << "** Runtimes **";
for(int i=0; i <= maxStorage; i++)
{
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos) continue;
if(numRuntime[i] != 0) outputFile << endl << endl << "The following runtime has occured " << numRuntime[i] << " time(s).\n";
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
}
outputFile.close();
}
else
{
return false;
}
return true;
}
void sortRuntimes()
{
string tempRuntime[maxStorage+1];
string tempProc[maxStorage+1];
string tempSource[maxStorage+1];
string tempUsr[maxStorage+1];
string tempSrc[maxStorage+1];
unsigned int tempNumRuntime[maxStorage+1];
unsigned int highestCount = 0; //Used for descending order
// int keepLooping = 0;
//Move all of our data into temporary arrays. Also clear the stored data (not necessary but.. just incase)
for(int i=0; i <= maxStorage; i++)
{
//Get the largest occurance of a single runtime
if(highestCount < numRuntime[i])
{
highestCount = numRuntime[i];
}
tempRuntime[i] = storedRuntime[i]; storedRuntime[i] = "Blank";
tempProc[i] = storedProc[i]; storedProc[i] = "Blank";
tempSource[i] = storedSource[i]; storedSource[i] = "Blank";
tempUsr[i] = storedUsr[i]; storedUsr[i] = "Blank";
tempSrc[i] = storedSrc[i]; storedSrc[i] = "Blank";
tempNumRuntime[i] = numRuntime[i]; numRuntime[i] = 0;
}
while(highestCount > 0)
{
for(int i=0; i <= maxStorage; i++) //For every runtime
{
if(tempNumRuntime[i] == highestCount) //If the number of occurances of that runtime is equal to our current highest
{
for(int j=0; j <= maxStorage; j++) //Find the next available slot and store the info
{
if(storedRuntime[j] == "Blank") //Found an empty spot
{
storedRuntime[j] = tempRuntime[i];
storedProc[j] = tempProc[i];
storedSource[j] = tempSource[i];
storedUsr[j] = tempUsr[i];
storedSrc[j] = tempSrc[i];
numRuntime[j] = tempNumRuntime[i];
break;
}
}
}
}
highestCount--; //Lower our 'highest' by one and continue
}
}
int main() {
char exit; //Used to stop the program from immediatly exiting
//Start everything fresh. "Blank" should never occur in the runtime logs on its own.
for(int i=0; i <= maxStorage; i++)
{
storedRuntime[i] = "Blank";
storedProc[i] = "Blank";
storedSource[i] = "Blank";
storedUsr[i] = "Blank";
storedSrc[i] = "Blank";
numRuntime[i] = 0;
}
if(readFromFile())
{
cout << "Input read successfully!\n";
}
else
{
cout << "Input failed to open, shutting down.\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 1;
}
sortRuntimes();
if(writeToFile())
{
cout << "Output was successful!\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 0;
}
else
{
cout << "The output file could not be opened, shutting down.\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 0;
}
return 0;
}
/* Runtime Condenser by Nodrak
* This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance
* of the runtime will log the proc, source, usr and src, the rest will just add to the total. Infinite loops will
* also be caught and displayed (if any) above the list of runtimes.
*
* How to use:
* 1) Copy and paste your list of runtimes from Dream Daemon into input.exe
* 2) Run RuntimeCondenser.exe
* 3) Open output.txt for a condensed report of the runtimes
*/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//Make all of these global. It's bad yes, but it's a small program so it really doesn't affect anything.
//Because hardcoded numbers are bad :(
const unsigned short maxStorage = 99; //100 - 1
//What we use to read input
string currentLine = "Blank";
string nextLine = "Blank";
//Stores lines we want to keep to print out
string storedRuntime[maxStorage+1];
string storedProc[maxStorage+1];
string storedSource[maxStorage+1];
string storedUsr[maxStorage+1];
string storedSrc[maxStorage+1];
//Stat tracking stuff for output
unsigned int totalRuntimes = 0;
unsigned int totalUniqueRuntimes = 0;
unsigned int totalInfiniteLoops = 0;
unsigned int totalUniqueInfiniteLoops = 0;
//Misc
unsigned int numRuntime[maxStorage+1]; //Number of times a specific runtime has occured
bool checkNextLines = false; //Used in case byond has condensed a large number of similar runtimes
int storedIterator = 0; //Used to remember where we stored the runtime
bool readFromFile()
{
//Open file to read
ifstream inputFile("input.txt");
if(inputFile.is_open())
{
while(!inputFile.eof()) //Until end of file
{
//If we've run out of storage
if(storedRuntime[maxStorage] != "Blank") break;
//Update our lines
currentLine = nextLine;
getline(inputFile, nextLine);
//After finding a new runtime, check to see if there are extra values to store
if(checkNextLines)
{
//Skip ahead
currentLine = nextLine;
getline(inputFile, nextLine);
//If we find this, we have new stuff to store
if(nextLine.find("usr:") != std::string::npos)
{
//Store more info
storedSource[storedIterator] = currentLine;
storedUsr[storedIterator] = nextLine;
//Skip ahead again
currentLine = nextLine;
getline(inputFile, nextLine);
//Store the last of the info
storedSrc[storedIterator] = nextLine;
}
checkNextLines = false;
}
//Found an infinite loop!
if(currentLine.find("Infinite loop suspected") != std::string::npos || currentLine.find("Maximum recursion level reached") != std::string::npos)
{
totalInfiniteLoops++;
for(int i=0; i <= maxStorage; i++)
{
//We've already encountered this
if(currentLine == storedRuntime[i])
{
numRuntime[i]++;
break;
}
//We've never encoutnered this
if(storedRuntime[i] == "Blank")
{
storedRuntime[i] = currentLine;
currentLine = nextLine;
getline(inputFile, nextLine); //Skip the "if this is not an infinite loop" line
storedProc[i] = nextLine;
numRuntime[i] = 1;
checkNextLines = true;
storedIterator = i;
totalUniqueInfiniteLoops++;
break;
}
}
}
//Found a runtime!
else if(currentLine.find("runtime error:") != std::string::npos)
{
totalRuntimes++;
for(int i=0; i <= maxStorage; i++)
{
//We've already encountered this
if(currentLine == storedRuntime[i])
{
numRuntime[i]++;
break;
}
//We've never encoutnered this
if(storedRuntime[i] == "Blank")
{
storedRuntime[i] = currentLine;
storedProc[i] = nextLine;
numRuntime[i] = 1;
checkNextLines = true;
storedIterator = i;
totalUniqueRuntimes++;
break;
}
}
}
}
}
else
{
return false;
}
return true;
}
bool writeToFile()
{
//Open and clear the file
ofstream outputFile("Output.txt", ios::trunc);
if(outputFile.is_open())
{
outputFile << "Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n";
if(totalUniqueInfiniteLoops > 0)
{
outputFile << "Total unique infinite loops: " << totalUniqueInfiniteLoops << endl;
}
if(totalInfiniteLoops > 0)
{
outputFile << "Total infinite loops: " << totalInfiniteLoops << endl;
}
outputFile << "Total unique runtimes: " << totalUniqueRuntimes << endl;
outputFile << "Total runtimes: " << totalRuntimes << endl << endl;
//Display a warning if we've hit the maximum space we've allocated for storage
if(totalUniqueRuntimes + totalUniqueInfiniteLoops >= maxStorage)
{
outputFile << "Warning: The maximum number of unique runtimes has been hit. If there were more, they have been cropped out.\n\n";
}
//If we have infinite loops, display them first.
if(totalInfiniteLoops > 0)
{
outputFile << "** Infinite loops **";
for(int i=0; i <= maxStorage; i++)
{
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos)
{
if(numRuntime[i] != 0) outputFile << endl << endl << "The following infinite loop has occured " << numRuntime[i] << " time(s).\n";
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
}
}
outputFile << endl << endl; //For spacing
}
//Do runtimes next
outputFile << "** Runtimes **";
for(int i=0; i <= maxStorage; i++)
{
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos) continue;
if(numRuntime[i] != 0) outputFile << endl << endl << "The following runtime has occured " << numRuntime[i] << " time(s).\n";
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
}
outputFile.close();
}
else
{
return false;
}
return true;
}
void sortRuntimes()
{
string tempRuntime[maxStorage+1];
string tempProc[maxStorage+1];
string tempSource[maxStorage+1];
string tempUsr[maxStorage+1];
string tempSrc[maxStorage+1];
unsigned int tempNumRuntime[maxStorage+1];
unsigned int highestCount = 0; //Used for descending order
// int keepLooping = 0;
//Move all of our data into temporary arrays. Also clear the stored data (not necessary but.. just incase)
for(int i=0; i <= maxStorage; i++)
{
//Get the largest occurance of a single runtime
if(highestCount < numRuntime[i])
{
highestCount = numRuntime[i];
}
tempRuntime[i] = storedRuntime[i]; storedRuntime[i] = "Blank";
tempProc[i] = storedProc[i]; storedProc[i] = "Blank";
tempSource[i] = storedSource[i]; storedSource[i] = "Blank";
tempUsr[i] = storedUsr[i]; storedUsr[i] = "Blank";
tempSrc[i] = storedSrc[i]; storedSrc[i] = "Blank";
tempNumRuntime[i] = numRuntime[i]; numRuntime[i] = 0;
}
while(highestCount > 0)
{
for(int i=0; i <= maxStorage; i++) //For every runtime
{
if(tempNumRuntime[i] == highestCount) //If the number of occurances of that runtime is equal to our current highest
{
for(int j=0; j <= maxStorage; j++) //Find the next available slot and store the info
{
if(storedRuntime[j] == "Blank") //Found an empty spot
{
storedRuntime[j] = tempRuntime[i];
storedProc[j] = tempProc[i];
storedSource[j] = tempSource[i];
storedUsr[j] = tempUsr[i];
storedSrc[j] = tempSrc[i];
numRuntime[j] = tempNumRuntime[i];
break;
}
}
}
}
highestCount--; //Lower our 'highest' by one and continue
}
}
int main() {
char exit; //Used to stop the program from immediatly exiting
//Start everything fresh. "Blank" should never occur in the runtime logs on its own.
for(int i=0; i <= maxStorage; i++)
{
storedRuntime[i] = "Blank";
storedProc[i] = "Blank";
storedSource[i] = "Blank";
storedUsr[i] = "Blank";
storedSrc[i] = "Blank";
numRuntime[i] = 0;
}
if(readFromFile())
{
cout << "Input read successfully!\n";
}
else
{
cout << "Input failed to open, shutting down.\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 1;
}
sortRuntimes();
if(writeToFile())
{
cout << "Output was successful!\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 0;
}
else
{
cout << "The output file could not be opened, shutting down.\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 0;
}
return 0;
}

View File

@@ -1,190 +1,190 @@
Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.
Total unique runtimes: 25
Total runtimes: 767
** Runtimes **
The following runtime has occured 269 time(s).
runtime error: Cannot read null.viruses
proc name: cure (/datum/disease/proc/cure)
source file: disease.dm,156
usr: null
src: Space Retrovirus (/datum/disease/dnaspread)
The following runtime has occured 199 time(s).
runtime error: Cannot read null.has_gravity
proc name: throw at (/atom/movable/proc/throw_at)
source file: throwing.dm,194
usr: Reese Marcotte (/mob/living/carbon/human)
src: Reese Marcotte (/mob/living/carbon/human)
The following runtime has occured 165 time(s).
runtime error: Cannot read null.slot_flags
proc name: db click (/mob/living/carbon/human/db_click)
source file: inventory.dm,1083
usr: Puke Chunks (/mob/living/carbon/human)
src: Puke Chunks (/mob/living/carbon/human)
The following runtime has occured 25 time(s).
runtime error: Cannot read null.flags
proc name: relaymove (/obj/effect/dummy/spell_jaunt/relaymove)
The following runtime has occured 24 time(s).
runtime error: Cannot read null.len
proc name: mergeRecordLists (/proc/mergeRecordLists)
source file: helpers.dm,260
usr: Wintermute (/mob/living/silicon/ai)
src: null
The following runtime has occured 20 time(s).
runtime error: Cannot read null.total_volume
proc name: attackby (/obj/machinery/reagentgrinder/attackby)
source file: Chemistry-Machinery.dm,751
usr: Reese Marcotte (/mob/living/carbon/human)
src: All-In-One Grinder (/obj/machinery/reagentgrinder)
The following runtime has occured 16 time(s).
runtime error: Cannot read null.broadcasting
proc name: radio menu (/mob/living/silicon/robot/proc/radio_menu)
source file: robot.dm,857
usr: Engineering Cyborg -432 (/mob/living/silicon/robot)
src: Engineering Cyborg -432 (/mob/living/silicon/robot)
The following runtime has occured 7 time(s).
runtime error: unexpected stat
proc name: Stat (/mob/living/silicon/robot/Stat)
source file: robot.dm,227
usr: Michigan Slim (/mob/living/carbon/human)
src: Engineering Cyborg -133 (/mob/living/silicon/robot)
The following runtime has occured 7 time(s).
runtime error: Cannot read null.current
proc name: check completion (/datum/objective/download/check_completion)
source file: objective.dm,411
usr: null
src: /datum/objective/download (/datum/objective/download)
The following runtime has occured 6 time(s).
runtime error: Cannot create objects of type null.
proc name: Topic (/obj/machinery/computer/rdconsole/Topic)
source file: rdconsole.dm,381
usr: Matthew Hoff (/mob/living/carbon/human)
src: Core R&D Console (/obj/machinery/computer/rdconsole/core)
The following runtime has occured 6 time(s).
runtime error: Cannot read null.fields
proc name: mergeRecordLists (/proc/mergeRecordLists)
source file: helpers.dm,263
usr: Wintermute (/mob/living/silicon/ai)
src: null
The following runtime has occured 3 time(s).
runtime error: undefined variable /client/var/loc
proc name: get turf (/proc/get_turf)
source file: helper_procs.dm,38
usr: the ghost (/mob/dead/observer)
src: null
The following runtime has occured 3 time(s).
runtime error: Cannot read null.nodes
proc name: merge powernets (/datum/powernet/proc/merge_powernets)
source file: power.dm,401
usr: Darin Keppel (/mob/living/carbon/human)
src: /datum/powernet (/datum/powernet)
The following runtime has occured 3 time(s).
runtime error: Cannot read null.reagents
proc name: fire syringe (/obj/item/weapon/gun/syringe/proc/fire_syringe)
The following runtime has occured 2 time(s).
runtime error: undefined proc or verb /obj/machinery/space_heater/attack().
The following runtime has occured 2 time(s).
runtime error: list index out of bounds
proc name: mergeConnectedNetworksOnTurf (/obj/structure/cable/proc/mergeConnectedNetworksOnTurf)
source file: cable.dm,520
usr: Josue Sandford (/mob/living/carbon/human)
src: the power cable (/obj/structure/cable)
The following runtime has occured 2 time(s).
runtime error: Cannot read null.loc
proc name: Life (/mob/living/simple_animal/corgi/Ian/Life)
source file: corgi.dm,304
usr: null
src: Captain Ian (/mob/living/simple_animal/corgi/Ian)
The following runtime has occured 1 time(s).
runtime error: undefined proc or verb /obj/machinery/portable_atmospherics/canister/toxins/attack().
The following runtime has occured 1 time(s).
runtime error: undefined variable /datum/preferences/var/fields
proc name: Topic (/obj/machinery/computer/cloning/Topic)
source file: cloning.dm,370
usr: Logan Graves (/mob/living/carbon/human)
src: Cloning console (/obj/machinery/computer/cloning)
The following runtime has occured 1 time(s).
runtime error: undefined variable /turf/simulated/floor/plating/var/mineral
proc name: attackby (/turf/simulated/wall/attackby)
source file: turf.dm,600
usr: Monte Smail (/mob/living/carbon/human)
src: the plating (176,172,5) (/turf/simulated/floor/plating)
The following runtime has occured 1 time(s).
runtime error: Cannot read null.blood_DNA
proc name: update inv w uniform (/mob/living/carbon/human/update_inv_w_uniform)
source file: update_icons.dm,372
usr: null
src: Chip Harshman (/mob/living/carbon/human)
The following runtime has occured 1 time(s).
runtime error: Cannot execute null.dropped().
proc name: drop l hand (/mob/proc/drop_l_hand)
source file: inventory.dm,104
usr: Jeb Stone (/mob/living/carbon/human)
src: Jeb Stone (/mob/living/carbon/human)
The following runtime has occured 1 time(s).
runtime error: Cannot read null.w_class
proc name: attackby (/obj/item/weapon/storage/attackby)
source file: storage.dm,187
usr: Samuel York (/mob/living/carbon/human)
src: the backpack (/obj/item/weapon/storage/backpack)
The following runtime has occured 1 time(s).
runtime error: Cannot read null.amount
proc name: attackby (/obj/machinery/constructable_frame/machine_frame/attackby)
source file: constructable_frame.dm,27
usr: Quinton Bould (/mob/living/carbon/human)
src: the machine frame (/obj/machinery/constructable_frame/machine_frame)
The following runtime has occured 1 time(s).
runtime error: Cannot modify null.status.
proc name: death (/mob/living/silicon/robot/death)
Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.
Total unique runtimes: 25
Total runtimes: 767
** Runtimes **
The following runtime has occured 269 time(s).
runtime error: Cannot read null.viruses
proc name: cure (/datum/disease/proc/cure)
source file: disease.dm,156
usr: null
src: Space Retrovirus (/datum/disease/dnaspread)
The following runtime has occured 199 time(s).
runtime error: Cannot read null.has_gravity
proc name: throw at (/atom/movable/proc/throw_at)
source file: throwing.dm,194
usr: Reese Marcotte (/mob/living/carbon/human)
src: Reese Marcotte (/mob/living/carbon/human)
The following runtime has occured 165 time(s).
runtime error: Cannot read null.slot_flags
proc name: db click (/mob/living/carbon/human/db_click)
source file: inventory.dm,1083
usr: Puke Chunks (/mob/living/carbon/human)
src: Puke Chunks (/mob/living/carbon/human)
The following runtime has occured 25 time(s).
runtime error: Cannot read null.flags
proc name: relaymove (/obj/effect/dummy/spell_jaunt/relaymove)
The following runtime has occured 24 time(s).
runtime error: Cannot read null.len
proc name: mergeRecordLists (/proc/mergeRecordLists)
source file: helpers.dm,260
usr: Wintermute (/mob/living/silicon/ai)
src: null
The following runtime has occured 20 time(s).
runtime error: Cannot read null.total_volume
proc name: attackby (/obj/machinery/reagentgrinder/attackby)
source file: Chemistry-Machinery.dm,751
usr: Reese Marcotte (/mob/living/carbon/human)
src: All-In-One Grinder (/obj/machinery/reagentgrinder)
The following runtime has occured 16 time(s).
runtime error: Cannot read null.broadcasting
proc name: radio menu (/mob/living/silicon/robot/proc/radio_menu)
source file: robot.dm,857
usr: Engineering Cyborg -432 (/mob/living/silicon/robot)
src: Engineering Cyborg -432 (/mob/living/silicon/robot)
The following runtime has occured 7 time(s).
runtime error: unexpected stat
proc name: Stat (/mob/living/silicon/robot/Stat)
source file: robot.dm,227
usr: Michigan Slim (/mob/living/carbon/human)
src: Engineering Cyborg -133 (/mob/living/silicon/robot)
The following runtime has occured 7 time(s).
runtime error: Cannot read null.current
proc name: check completion (/datum/objective/download/check_completion)
source file: objective.dm,411
usr: null
src: /datum/objective/download (/datum/objective/download)
The following runtime has occured 6 time(s).
runtime error: Cannot create objects of type null.
proc name: Topic (/obj/machinery/computer/rdconsole/Topic)
source file: rdconsole.dm,381
usr: Matthew Hoff (/mob/living/carbon/human)
src: Core R&D Console (/obj/machinery/computer/rdconsole/core)
The following runtime has occured 6 time(s).
runtime error: Cannot read null.fields
proc name: mergeRecordLists (/proc/mergeRecordLists)
source file: helpers.dm,263
usr: Wintermute (/mob/living/silicon/ai)
src: null
The following runtime has occured 3 time(s).
runtime error: undefined variable /client/var/loc
proc name: get turf (/proc/get_turf)
source file: helper_procs.dm,38
usr: the ghost (/mob/dead/observer)
src: null
The following runtime has occured 3 time(s).
runtime error: Cannot read null.nodes
proc name: merge powernets (/datum/powernet/proc/merge_powernets)
source file: power.dm,401
usr: Darin Keppel (/mob/living/carbon/human)
src: /datum/powernet (/datum/powernet)
The following runtime has occured 3 time(s).
runtime error: Cannot read null.reagents
proc name: fire syringe (/obj/item/weapon/gun/syringe/proc/fire_syringe)
The following runtime has occured 2 time(s).
runtime error: undefined proc or verb /obj/machinery/space_heater/attack().
The following runtime has occured 2 time(s).
runtime error: list index out of bounds
proc name: mergeConnectedNetworksOnTurf (/obj/structure/cable/proc/mergeConnectedNetworksOnTurf)
source file: cable.dm,520
usr: Josue Sandford (/mob/living/carbon/human)
src: the power cable (/obj/structure/cable)
The following runtime has occured 2 time(s).
runtime error: Cannot read null.loc
proc name: Life (/mob/living/simple_animal/corgi/Ian/Life)
source file: corgi.dm,304
usr: null
src: Captain Ian (/mob/living/simple_animal/corgi/Ian)
The following runtime has occured 1 time(s).
runtime error: undefined proc or verb /obj/machinery/portable_atmospherics/canister/toxins/attack().
The following runtime has occured 1 time(s).
runtime error: undefined variable /datum/preferences/var/fields
proc name: Topic (/obj/machinery/computer/cloning/Topic)
source file: cloning.dm,370
usr: Logan Graves (/mob/living/carbon/human)
src: Cloning console (/obj/machinery/computer/cloning)
The following runtime has occured 1 time(s).
runtime error: undefined variable /turf/simulated/floor/plating/var/mineral
proc name: attackby (/turf/simulated/wall/attackby)
source file: turf.dm,600
usr: Monte Smail (/mob/living/carbon/human)
src: the plating (176,172,5) (/turf/simulated/floor/plating)
The following runtime has occured 1 time(s).
runtime error: Cannot read null.blood_DNA
proc name: update inv w uniform (/mob/living/carbon/human/update_inv_w_uniform)
source file: update_icons.dm,372
usr: null
src: Chip Harshman (/mob/living/carbon/human)
The following runtime has occured 1 time(s).
runtime error: Cannot execute null.dropped().
proc name: drop l hand (/mob/proc/drop_l_hand)
source file: inventory.dm,104
usr: Jeb Stone (/mob/living/carbon/human)
src: Jeb Stone (/mob/living/carbon/human)
The following runtime has occured 1 time(s).
runtime error: Cannot read null.w_class
proc name: attackby (/obj/item/weapon/storage/attackby)
source file: storage.dm,187
usr: Samuel York (/mob/living/carbon/human)
src: the backpack (/obj/item/weapon/storage/backpack)
The following runtime has occured 1 time(s).
runtime error: Cannot read null.amount
proc name: attackby (/obj/machinery/constructable_frame/machine_frame/attackby)
source file: constructable_frame.dm,27
usr: Quinton Bould (/mob/living/carbon/human)
src: the machine frame (/obj/machinery/constructable_frame/machine_frame)
The following runtime has occured 1 time(s).
runtime error: Cannot modify null.status.
proc name: death (/mob/living/silicon/robot/death)

View File

@@ -1,90 +1,90 @@
#!/usr/bin/env python
import re, os, sys, fnmatch
# Regex pattern to extract the directory path in a #define FILE_DIR
filedir_pattern = re.compile(r'^#define\s*FILE_DIR\s*"(.*?)"')
# Regex pattern to extract any single quoted piece of text. This can also
# match single quoted strings inside of double quotes, which is part of a
# regular text string and should not be replaced. The replacement function
# however will any match that doesn't appear to be a filename so these
# extra matches should not be a problem.
rename_pattern = re.compile(r"'(.+?)'")
# Only filenames matching this pattern will have their resources renamed
source_pattern = re.compile(r"^.*?\.(dm|dmm)$")
# Open the .dme file and return a list of all FILE_DIR paths in it
def read_filedirs(filename):
result = []
with open(filename, "rt") as dme_file:
# Read each line from the file and check for regex pattern match
for row in dme_file:
match = filedir_pattern.match(row)
if match:
result.append(match.group(1))
return result
# Search through a list of directories, and build a dictionary which
# maps every file to its full pathname (relative to the .dme file)
# If the same filename appears in more than one directory, the earlier
# directory in the list takes preference.
def index_files(file_dirs):
result = {}
# Reverse the directory list so the earlier directories take precedence
# by replacing the previously indexed file of the same name
for directory in reversed(file_dirs):
for name in os.listdir(directory):
# Replace backslash path separators on Windows with forward slash
# Force "name" to lowercase when used as a key since BYOND resource
# names are case insensitive, even on Linux.
if name.find(".") == -1:
continue
result[name.lower()] = directory.replace('\\', '/') + '/' + name
return result
# Recursively search for every .dm/.dmm file in the .dme file directory. For
# each file, search it for any resource names in single quotes, and replace
# them with the full path previously found by index_files()
def rewrite_sources(resources):
# Create a closure for the regex replacement function to capture the
# resources dictionary which can't be passed directly to this function
def replace_func(name):
key = name.group(1).lower()
if key in resources:
replacement = resources[key]
else:
replacement = name.group(1)
return "'" + replacement + "'"
# Search recursively for all .dm and .dmm files
for (dirpath, dirs, files) in os.walk("."):
for name in files:
if source_pattern.match(name):
path = dirpath + '/' + name
source_file = open(path, "rt")
output_file = open(path + ".tmp", "wt")
# Read file one line at a time and perform replacement of all
# single quoted resource names with the fullpath to that resource
# file. Write the updated text back out to a temporary file.
for row in source_file:
row = rename_pattern.sub(replace_func, row)
output_file.write(row)
output_file.close()
source_file.close()
# Delete original source file and replace with the temporary
# output. On Windows, an atomic rename() operation is not
# possible like it is under POSIX.
os.remove(path)
os.rename(path + ".tmp", path)
dirs = read_filedirs("vgstation13.dme");
resources = index_files(dirs)
rewrite_sources(resources)
#!/usr/bin/env python
import re, os, sys, fnmatch
# Regex pattern to extract the directory path in a #define FILE_DIR
filedir_pattern = re.compile(r'^#define\s*FILE_DIR\s*"(.*?)"')
# Regex pattern to extract any single quoted piece of text. This can also
# match single quoted strings inside of double quotes, which is part of a
# regular text string and should not be replaced. The replacement function
# however will any match that doesn't appear to be a filename so these
# extra matches should not be a problem.
rename_pattern = re.compile(r"'(.+?)'")
# Only filenames matching this pattern will have their resources renamed
source_pattern = re.compile(r"^.*?\.(dm|dmm)$")
# Open the .dme file and return a list of all FILE_DIR paths in it
def read_filedirs(filename):
result = []
with open(filename, "rt") as dme_file:
# Read each line from the file and check for regex pattern match
for row in dme_file:
match = filedir_pattern.match(row)
if match:
result.append(match.group(1))
return result
# Search through a list of directories, and build a dictionary which
# maps every file to its full pathname (relative to the .dme file)
# If the same filename appears in more than one directory, the earlier
# directory in the list takes preference.
def index_files(file_dirs):
result = {}
# Reverse the directory list so the earlier directories take precedence
# by replacing the previously indexed file of the same name
for directory in reversed(file_dirs):
for name in os.listdir(directory):
# Replace backslash path separators on Windows with forward slash
# Force "name" to lowercase when used as a key since BYOND resource
# names are case insensitive, even on Linux.
if name.find(".") == -1:
continue
result[name.lower()] = directory.replace('\\', '/') + '/' + name
return result
# Recursively search for every .dm/.dmm file in the .dme file directory. For
# each file, search it for any resource names in single quotes, and replace
# them with the full path previously found by index_files()
def rewrite_sources(resources):
# Create a closure for the regex replacement function to capture the
# resources dictionary which can't be passed directly to this function
def replace_func(name):
key = name.group(1).lower()
if key in resources:
replacement = resources[key]
else:
replacement = name.group(1)
return "'" + replacement + "'"
# Search recursively for all .dm and .dmm files
for (dirpath, dirs, files) in os.walk("."):
for name in files:
if source_pattern.match(name):
path = dirpath + '/' + name
source_file = open(path, "rt")
output_file = open(path + ".tmp", "wt")
# Read file one line at a time and perform replacement of all
# single quoted resource names with the fullpath to that resource
# file. Write the updated text back out to a temporary file.
for row in source_file:
row = rename_pattern.sub(replace_func, row)
output_file.write(row)
output_file.close()
source_file.close()
# Delete original source file and replace with the temporary
# output. On Windows, an atomic rename() operation is not
# possible like it is under POSIX.
os.remove(path)
os.rename(path + ".tmp", path)
dirs = read_filedirs("vgstation13.dme");
resources = index_files(dirs)
rewrite_sources(resources)