procrealms-client
Version:
A web/terminal hybrid client for Procedural Realms
346 lines (285 loc) • 6.96 kB
JavaScript
const colorTable = {
k: '\u001b[30m',
K: '\u001b[90m',
0: '\u001b[40m',
')': '\u001b[100m',
r: '\u001b[31m',
R: '\u001b[91m',
1: '\u001b[41m',
'!': '\u001b[101m',
g: '\u001b[32m',
G: '\u001b[92m',
2: '\u001b[42m',
'@': '\u001b[102m',
y: '\u001b[33m',
Y: '\u001b[93m',
3: '\u001b[43m',
'#': '\u001b[103m',
b: '\u001b[34m',
B: '\u001b[94m',
4: '\u001b[44m',
'$': '\u001b[104m',
m: '\u001b[35m',
M: '\u001b[95m',
5: '\u001b[45m',
'%': '\u001b[105m',
c: '\u001b[36m',
C: '\u001b[96m',
6: '\u001b[46m',
'^': '\u001b[106m',
w: '\u001b[37m',
W: '\u001b[97m',
7: '\u001b[47m',
'&': '\u001b[107m',
'<': '\u001b[97m',
'>': '\u001b[37m',
'{': '{',
'Z': '\u001b[0m'
}
exports.parseAnsi = function (str) {
return exports.parseColor(str.replace(/\\u001b/g, '\u001b'))
}
exports.parseColor = function (str) {
str = str || ''
let pieces = str.split(/({{[a-zA-Z0-9)!@#$%^<>{])/g)
let out = ''
for (let i = 0; i < pieces.length; i++) {
let color = false
let colorKey = ''
if (pieces[i].substr(0, 2) == '{{') {
colorKey = pieces[i].substr(2, 1)
color = colorTable[colorKey]
if (color) {
i++
}
}
if (color) {
out += color + pieces[i]
} else {
out += pieces[i]
}
}
return out
}
exports.wordWrap = function (str, maxWidth) {
let newStr = ''
let visibleCharsThisLine = 0
let totalCharsThisLine = 0
let newLineStart = 0
let lastColor
if (!str) {
return ''
}
let insideAnsiCode = false
for (let i = 0; i < str.length; i++) {
newStr += str[i]
totalCharsThisLine++
if (str[i] == "\u001b") {
insideAnsiCode = true
continue
}
if (insideAnsiCode) {
if (str[i] == 'm') {
insideAnsiCode = false
}
continue
}
if (str[i-2] == '{' && str[i-1] == '{') {
if (!['<', '>'].includes(str[i])) {
lastColor = '{{' + str[i]
}
}
if (str[i] == '{' || str[i-1] == '{') {
continue
}
if (str[i] == '\r' || str[i] == '\n') {
visibleCharsThisLine = 0
continue
}
visibleCharsThisLine++
if (visibleCharsThisLine >= maxWidth) {
let checkForSpace = newStr.substring(newLineStart, newLineStart + totalCharsThisLine)
let overflow = ''
let newline = ''
if (checkForSpace.match(/\s/)) {
newline = '\n'
for (let j = newStr.length - 1; j > 0; j--) {
overflow = `${newStr[j]}${overflow}`
newStr = newStr.substring(0, newStr.length - 1)
if (newStr[j-1].match(/\s/)) {
newStr = newStr.substring(0, newStr.length - 1)
break
}
}
}
newStr += newline
newLineStart = newStr.length
if (lastColor) {
newStr += lastColor
lastColor = null
}
newStr += overflow
visibleCharsThisLine = exports.numVisibleChars(overflow)
totalCharsThisLine = overflow.length
}
}
return newStr
}
exports.numVisibleChars = function (str) {
let insideAnsiCode = false
let visibleChars = 0
for (let i = 0; i < str.length; i++) {
if (str[i] == "\u001b") {
insideAnsiCode = true
continue
}
if (insideAnsiCode) {
if (str[i] == 'm') {
insideAnsiCode = false
}
continue
}
if (str[i] == '{' || str[i-1] == '{') {
continue
}
visibleChars++
}
return visibleChars
}
exports.listToString = function (list, seperator='and') {
if (!list) {
return ''
}
list = list.filter(it => it)
if (!list.length) {
return ''
}
if (list.length == 1) {
return list.pop()
}
let final = list.pop()
return `${list.join(', ')} ${seperator} ${final}`
}
exports.objectToString = function (obj) {
return JSON.stringify(obj, function(key, value) {
if (typeof value == "string") {
return "{{C" + value + "{{w"
}
if (typeof value == "number") {
return "{{G" + value + "{{w"
}
if (typeof value == "boolean") {
return "{{R" + value + "{{w"
}
return value
}, 2).replace(/\"/g, '') + '\n'
}
exports.renderBar = function (label, amt, max, size, colors, centered = true, brackets = false) {
label = '' + label
let bars = Math.ceil(amt / max * size)
let labelStart = 0
if (centered) {
labelStart = size / 2 - label.length / 2
}
let bar = ''
let color = colors[0]
if (bars >= size * 0.80) {
color = colors[4]
} else if (bars >= size * 0.60) {
color = colors[3]
} else if (bars >= size * 0.40) {
color = colors[2]
} else if (bars >= size * 0.20) {
color = colors[1]
}
for (let i = 0; i < size; i++) {
let char
let clr
if (i < bars) {
char = ` `
clr = color
} else {
char = ' '
clr = '{{0{{w'
}
if (i >= labelStart && i < labelStart + label.length) {
char = `${clr}${label.substr(i - labelStart, 1)}`
}
if (brackets) {
if (i == 0 && char == ' ') {
char = '['
} else if (i == size - 1 && char == ' ') {
char = ']'
}
}
bar += `${clr}${char}`
}
return bar + '{{0{{w'
}
exports.renderMoney = function (amount, brief = false) {
let copper = amount % 100
let silver = Math.floor(amount / 100) % 100
let gold = Math.floor(amount / 10000)
let str = ''
if (gold) {
if (brief) {
str += `{{Y${gold}g`
} else {
str += `{{Y${gold} gold`
}
}
if (silver) {
str += ' '
if (brief) {
str += `{{W${silver}s`
} else {
str += `{{W${silver} silver`
}
}
if (copper || amount == 0) {
str += ' '
if (brief) {
str += `{{C${copper}c`
} else {
str += `{{C${copper} copper`
}
}
return str + '{{w'
}
exports.timeLeft = (time) => {
let out = ''
let minutes = Math.floor(time / 60)
let hours = Math.floor(minutes / 60)
if (hours > 0) {
out += `${hours}h `
}
if (minutes > 0) {
out += `${minutes % 60}m `
} else {
out += `${time % 60}s`
}
return out.trim()
}
exports.ucfirst = function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
exports.centerText = function (str, size) {
let padAmount = Math.max(0, Math.floor((size - exports.stripColorCodes(str).length) / 2))
return ' '.repeat(padAmount) + str
}
exports.padLeft = function (str, length) {
return ' '.repeat(length - Math.min(length, exports.stripColorCodes('' + str).length)) + str
}
exports.padRight = function (str, length) {
return str + ' '.repeat(length - Math.min(length, exports.stripColorCodes('' + str).length))
}
exports.stripColorCodes = function (str) {
return str.replace(/\u001b[^\s]+m/g, '').replace(/{{./g, '')
}
exports.renderNumber = function (value, digits = 2) {
if (value == Math.floor(value)) return Math.round(value) + ''
return value.toFixed(digits)
}
exports.inBrowser = function () {
return typeof window != 'undefined'
}