@ -0,0 +1,44 @@ | |||
# Mediocre Mapper Multi-Mapper Server setup | |||
## What you need to start | |||
* install node.js from https://nodejs.org/en/ | |||
* move your song into the /Songs/ directory | |||
* port forward a TCP port of your choosing. 17425 is default. | |||
* create a song in MediocreMapper and set up difficulties, offset and BPM | |||
## Setting up the server | |||
### config.json setup | |||
``` | |||
"folder" - Folder name of the song | |||
"characteristic" - Characteristic to be used (Standard/No Arrows/One Saber) | |||
"difficulty": - Difficulty to be used (Easy/Normal/Hard/Expert/ExpertPlus) | |||
"port": - Port you'll be using | |||
"password": - Password to the server, can be left empty for no password | |||
``` | |||
### config.json example | |||
``` | |||
{ | |||
"folder": "The Other Side", | |||
"characteristic": "Standard", | |||
"difficulty": "ExpertPlus", | |||
"port": 17425, | |||
"password": "967" | |||
} | |||
``` | |||
## Starting the server | |||
* copy the song from your Mediocre Mapper's /CustomSongs/ Directory into your Server's /Songs/ directory | |||
* set up the config.json as above | |||
* open up a command line and navigate to the folder containing server.js. Or shift + right click in the folder in Windows Explorer to and open up PowerShell | |||
* run command: `npm install` | |||
* run command: `node ./server.js` | |||
* all done! | |||
## Other info | |||
Server saves every 5 minutes, so at most 5 minutes of progress is lost in the case of a crash. | |||
No more than one person using the same name can be in a session. sometimes this bugs out and there's an improper disconnect. Have server restarted after a save if you're unable to join with the same name and really don't wanna change it. or just change it. | |||
Full or partial information can be supplied to the server by typing for example `node ./server.js --difficulty "ExpertPlus"` | |||
@ -0,0 +1,7 @@ | |||
{ | |||
"folder": "Song", | |||
"characteristic": "Standard", | |||
"difficulty": "ExpertPlus", | |||
"port": 17425, | |||
"password": "" | |||
} |
@ -0,0 +1,346 @@ | |||
{ | |||
"name": "mediocremapperserver", | |||
"version": "1.0.0", | |||
"lockfileVersion": 1, | |||
"requires": true, | |||
"dependencies": { | |||
"ajv": { | |||
"version": "6.6.2", | |||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", | |||
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", | |||
"requires": { | |||
"fast-deep-equal": "^2.0.1", | |||
"fast-json-stable-stringify": "^2.0.0", | |||
"json-schema-traverse": "^0.4.1", | |||
"uri-js": "^4.2.2" | |||
} | |||
}, | |||
"asn1": { | |||
"version": "0.2.4", | |||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", | |||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", | |||
"requires": { | |||
"safer-buffer": "~2.1.0" | |||
} | |||
}, | |||
"assert-plus": { | |||
"version": "1.0.0", | |||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", | |||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" | |||
}, | |||
"asynckit": { | |||
"version": "0.4.0", | |||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", | |||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" | |||
}, | |||
"aws-sign2": { | |||
"version": "0.7.0", | |||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", | |||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" | |||
}, | |||
"aws4": { | |||
"version": "1.8.0", | |||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", | |||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" | |||
}, | |||
"bcrypt-pbkdf": { | |||
"version": "1.0.2", | |||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", | |||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", | |||
"requires": { | |||
"tweetnacl": "^0.14.3" | |||
} | |||
}, | |||
"caseless": { | |||
"version": "0.12.0", | |||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", | |||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" | |||
}, | |||
"combined-stream": { | |||
"version": "1.0.7", | |||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", | |||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", | |||
"requires": { | |||
"delayed-stream": "~1.0.0" | |||
} | |||
}, | |||
"core-util-is": { | |||
"version": "1.0.2", | |||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", | |||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" | |||
}, | |||
"dashdash": { | |||
"version": "1.14.1", | |||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", | |||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", | |||
"requires": { | |||
"assert-plus": "^1.0.0" | |||
} | |||
}, | |||
"delayed-stream": { | |||
"version": "1.0.0", | |||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", | |||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" | |||
}, | |||
"ecc-jsbn": { | |||
"version": "0.1.2", | |||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", | |||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", | |||
"requires": { | |||
"jsbn": "~0.1.0", | |||
"safer-buffer": "^2.1.0" | |||
} | |||
}, | |||
"extend": { | |||
"version": "3.0.2", | |||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", | |||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" | |||
}, | |||
"extsprintf": { | |||
"version": "1.3.0", | |||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", | |||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" | |||
}, | |||
"fast-deep-equal": { | |||
"version": "2.0.1", | |||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", | |||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" | |||
}, | |||
"fast-json-stable-stringify": { | |||
"version": "2.0.0", | |||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", | |||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" | |||
}, | |||
"forever-agent": { | |||
"version": "0.6.1", | |||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", | |||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" | |||
}, | |||
"form-data": { | |||
"version": "2.3.3", | |||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", | |||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", | |||
"requires": { | |||
"asynckit": "^0.4.0", | |||
"combined-stream": "^1.0.6", | |||
"mime-types": "^2.1.12" | |||
} | |||
}, | |||
"getpass": { | |||
"version": "0.1.7", | |||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", | |||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", | |||
"requires": { | |||
"assert-plus": "^1.0.0" | |||
} | |||
}, | |||
"har-schema": { | |||
"version": "2.0.0", | |||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", | |||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" | |||
}, | |||
"har-validator": { | |||
"version": "5.1.3", | |||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", | |||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", | |||
"requires": { | |||
"ajv": "^6.5.5", | |||
"har-schema": "^2.0.0" | |||
} | |||
}, | |||
"http-signature": { | |||
"version": "1.2.0", | |||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", | |||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", | |||
"requires": { | |||
"assert-plus": "^1.0.0", | |||
"jsprim": "^1.2.2", | |||
"sshpk": "^1.7.0" | |||
} | |||
}, | |||
"is-typedarray": { | |||
"version": "1.0.0", | |||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", | |||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" | |||
}, | |||
"isstream": { | |||
"version": "0.1.2", | |||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", | |||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" | |||
}, | |||
"jsbn": { | |||
"version": "0.1.1", | |||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", | |||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" | |||
}, | |||
"json-schema": { | |||
"version": "0.2.3", | |||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", | |||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" | |||
}, | |||
"json-schema-traverse": { | |||
"version": "0.4.1", | |||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | |||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" | |||
}, | |||
"json-stringify-safe": { | |||
"version": "5.0.1", | |||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", | |||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" | |||
}, | |||
"jsprim": { | |||
"version": "1.4.1", | |||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", | |||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", | |||
"requires": { | |||
"assert-plus": "1.0.0", | |||
"extsprintf": "1.3.0", | |||
"json-schema": "0.2.3", | |||
"verror": "1.10.0" | |||
} | |||
}, | |||
"mime-db": { | |||
"version": "1.37.0", | |||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", | |||
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" | |||
}, | |||
"mime-types": { | |||
"version": "2.1.21", | |||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", | |||
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", | |||
"requires": { | |||
"mime-db": "~1.37.0" | |||
} | |||
}, | |||
"oauth-sign": { | |||
"version": "0.9.0", | |||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", | |||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" | |||
}, | |||
"performance-now": { | |||
"version": "2.1.0", | |||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", | |||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" | |||
}, | |||
"psl": { | |||
"version": "1.1.31", | |||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", | |||
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" | |||
}, | |||
"punycode": { | |||
"version": "2.1.1", | |||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", | |||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" | |||
}, | |||
"qs": { | |||
"version": "6.5.2", | |||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", | |||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" | |||
}, | |||
"request": { | |||
"version": "2.88.0", | |||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", | |||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", | |||
"requires": { | |||
"aws-sign2": "~0.7.0", | |||
"aws4": "^1.8.0", | |||
"caseless": "~0.12.0", | |||
"combined-stream": "~1.0.6", | |||
"extend": "~3.0.2", | |||
"forever-agent": "~0.6.1", | |||
"form-data": "~2.3.2", | |||
"har-validator": "~5.1.0", | |||
"http-signature": "~1.2.0", | |||
"is-typedarray": "~1.0.0", | |||
"isstream": "~0.1.2", | |||
"json-stringify-safe": "~5.0.1", | |||
"mime-types": "~2.1.19", | |||
"oauth-sign": "~0.9.0", | |||
"performance-now": "^2.1.0", | |||
"qs": "~6.5.2", | |||
"safe-buffer": "^5.1.2", | |||
"tough-cookie": "~2.4.3", | |||
"tunnel-agent": "^0.6.0", | |||
"uuid": "^3.3.2" | |||
} | |||
}, | |||
"safe-buffer": { | |||
"version": "5.1.2", | |||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", | |||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" | |||
}, | |||
"safer-buffer": { | |||
"version": "2.1.2", | |||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", | |||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" | |||
}, | |||
"sshpk": { | |||
"version": "1.15.2", | |||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", | |||
"integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", | |||
"requires": { | |||
"asn1": "~0.2.3", | |||
"assert-plus": "^1.0.0", | |||
"bcrypt-pbkdf": "^1.0.0", | |||
"dashdash": "^1.12.0", | |||
"ecc-jsbn": "~0.1.1", | |||
"getpass": "^0.1.1", | |||
"jsbn": "~0.1.0", | |||
"safer-buffer": "^2.0.2", | |||
"tweetnacl": "~0.14.0" | |||
} | |||
}, | |||
"tough-cookie": { | |||
"version": "2.4.3", | |||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", | |||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", | |||
"requires": { | |||
"psl": "^1.1.24", | |||
"punycode": "^1.4.1" | |||
}, | |||
"dependencies": { | |||
"punycode": { | |||
"version": "1.4.1", | |||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", | |||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" | |||
} | |||
} | |||
}, | |||
"tunnel-agent": { | |||
"version": "0.6.0", | |||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", | |||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", | |||
"requires": { | |||
"safe-buffer": "^5.0.1" | |||
} | |||
}, | |||
"tweetnacl": { | |||
"version": "0.14.5", | |||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", | |||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" | |||
}, | |||
"uri-js": { | |||
"version": "4.2.2", | |||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", | |||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", | |||
"requires": { | |||
"punycode": "^2.1.0" | |||
} | |||
}, | |||
"uuid": { | |||
"version": "3.3.2", | |||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", | |||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" | |||
}, | |||
"verror": { | |||
"version": "1.10.0", | |||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", | |||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", | |||
"requires": { | |||
"assert-plus": "^1.0.0", | |||
"core-util-is": "1.0.2", | |||
"extsprintf": "^1.2.0" | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,15 @@ | |||
{ | |||
"name": "mediocremapperserver", | |||
"version": "1.0.0", | |||
"description": "Server for Mediocre Mapper Multi-Mapper", | |||
"main": "server.js", | |||
"scripts": { | |||
"test": "start", | |||
"start": "node server.js" | |||
}, | |||
"author": "squeaksies", | |||
"license": "ISC", | |||
"dependencies": { | |||
"request": "^2.88.0" | |||
} | |||
} |
@ -0,0 +1,730 @@ | |||
"use strict"; | |||
const fs = require("fs"); | |||
var clients = []; | |||
var net = require('net'); | |||
try{ | |||
var request = require('request'); | |||
} | |||
catch(err){ | |||
console.log(err); | |||
console.log('Go read the damn readme. Run "npm install" or install the request module in some other way.'); | |||
process.exit() | |||
} | |||
var https = require('https'); | |||
var config = {}; | |||
var diff; | |||
var fileSize; | |||
var diffIndex; | |||
var charIndex; | |||
var diffFound = false; | |||
var charFound = false; | |||
var changesMade = false; | |||
var downloadURL = ""; | |||
console.log("\n\n\n"); | |||
// Loading up json files and such that you need | |||
try{ | |||
config = require('./config.json'); | |||
} | |||
catch(err){ | |||
} | |||
process.argv.shift(); | |||
process.argv.shift(); | |||
var type = ""; | |||
while(process.argv.length > 0) | |||
{ | |||
var input = process.argv.shift() | |||
if (input.startsWith("--")) | |||
{ | |||
type = input.replace('--',''); | |||
} | |||
else | |||
{ | |||
if (type == "") | |||
{ | |||
console.log('you fucked up'); | |||
process.exit() | |||
} | |||
else | |||
{ | |||
config[type] = input; | |||
} | |||
} | |||
} | |||
// Check and display relevant info | |||
try{ | |||
if(config.folder !== "" && config.folder !== undefined){ | |||
console.log(' Song folder: ' + config.folder); | |||
} | |||
else{ | |||
console.log('\nError: Fill in folder field'); | |||
process.exit() | |||
} | |||
if(config.difficulty !== "" && config.characteristic !== undefined){ | |||
console.log(' Song characteristic: ' + config.characteristic); | |||
} | |||
else{ | |||
console.log(' Song characteristic: Standard'); | |||
} | |||
if(config.difficulty !== "" && config.difficulty !== undefined){ | |||
console.log(' Song difficulty: ' + config.difficulty); | |||
} | |||
else{ | |||
console.log('\nError: Fill in difficulty field'); | |||
process.exit() | |||
} | |||
if(config.port !== "" && config.port !== undefined){ | |||
console.log(' Port: ' + config.port); | |||
} | |||
else{ | |||
console.log('\nError: Fill in port field'); | |||
process.exit() | |||
} | |||
if(config.password != "" && config.password !== undefined){ | |||
console.log(' Password: ' + config.password); | |||
} | |||
else{ | |||
config.password = ""; | |||
console.log(' Password: no password being used'); | |||
} | |||
if(config.download !== "" && config.download !== undefined){ | |||
console.log(' Song download: ' + config.download); | |||
downloadURL = config.download; | |||
} | |||
} | |||
catch(err){ | |||
console.log('config file is not formatted correctly'); | |||
process.exit() | |||
} | |||
var data = fs.readFileSync('./Songs/' + config.folder + '/info.dat'); | |||
// Loading stuff | |||
try{ | |||
var info = loadJSON('./Songs/' + config.folder + '/info.dat'); | |||
} | |||
catch(err){ | |||
console.log('Could not find file: Songs/' + config.folder + '/info.dat'); | |||
process.exit() | |||
} | |||
if (!config.characteristic) | |||
{ | |||
config.characteristic = "Standard"; | |||
} | |||
for (var i = 0; i < info._difficultyBeatmapSets.length; i++) | |||
{ | |||
if (info._difficultyBeatmapSets[i]._beatmapCharacteristicName == config.characteristic) | |||
{ | |||
for(var j = 0; j < info._difficultyBeatmapSets[i]._difficultyBeatmaps.length; j++) | |||
{ | |||
if (info._difficultyBeatmapSets[i]._difficultyBeatmaps[j]._difficulty == config.difficulty) | |||
{ | |||
diff = loadJSON('./Songs/' + config.folder + '/' + info._difficultyBeatmapSets[i]._difficultyBeatmaps[j]._beatmapFilename); | |||
try{ | |||
fileSize = fs.statSync('./Songs/' + config.folder + '/' + info._songFilename); | |||
}catch(err) | |||
{ | |||
//console.log('\nFailed to find '+info.difficultyLevels[i].audioPath+'. now using fileSize argument'); | |||
if(!config.hasOwnProperty('fileSize')) | |||
{ | |||
//console.log('could not use fileSize argument, finding from download URL'); | |||
request({ | |||
url: downloadURL, | |||
method: "HEAD" | |||
}, function(err, response, body) { | |||
var downloadResponse = response.headers; | |||
if (downloadResponse.hasOwnProperty('content-length')) | |||
{ | |||
fileSize = downloadResponse['content-length']; | |||
} | |||
else | |||
{ | |||
console.log('Unable to get file size. Please specify fileSize in config.json or as an argument'); | |||
process.exit(); | |||
} | |||
}); | |||
} | |||
fileSize = config['content-length']; | |||
} | |||
diffIndex = j; | |||
charIndex = i; | |||
diffFound = true; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
if (diff === null) | |||
{ | |||
console.log('No proper difficulty found.'); | |||
process.exit(); | |||
} | |||
if (diffFound == false) | |||
{ | |||
console.log('Difficulty/Characteristic not found'); | |||
process.exit(); | |||
} | |||
setInterval(saveFile, 300000);//save every 5 minutes | |||
// if(config.download === "") | |||
// { | |||
// config.download = 'none'; | |||
// } | |||
var server = net.createServer(function(socket){ | |||
socket.name = "wait"; | |||
socket.send = false; | |||
//add new client to the list | |||
clients.push(socket); | |||
// Handle incoming messages from clients. | |||
socket.on('data', function (data) { | |||
if(socket.name == "wait") | |||
{ | |||
if (config.password !== "" && data.toString().includes(";|;")) | |||
{ | |||
console.log("attempted connection: " + data.toString().split(";|;")[1] + "\nPassword: " +data.toString().split(";|;")[0]); | |||
if (config.password == data.toString().split(";|;")[0]) | |||
{ | |||
for (var i = 0; i < clients.length; i++) | |||
{ | |||
if (clients[i].name == data.toString().split(";|;")[1] || "wait" == data.toString().split(";|;")[1]) | |||
{ | |||
if (socket.address == clients[i].address) | |||
{ | |||
console.log('duplicate from same client. Destroying old client.') | |||
clients[i].destroy(); | |||
clients.splice(i, 1); | |||
} | |||
else | |||
{ | |||
socket.write('dc:duplicate name'); | |||
clients.splice(clients.indexOf(socket), 1); | |||
socket.destroy(); | |||
return; | |||
} | |||
} | |||
} | |||
socket.name = data.toString().split(";|;")[1]; | |||
// Send a nice welcome message and announce | |||
socket.write(config.folder.split('/').pop()+"::"+diffIndex*100+ charIndex+";;;"); //0 | |||
socket.write(JSON.stringify(info)+";;;"); //1 | |||
socket.write(info._difficultyBeatmapSets[charIndex]._difficultyBeatmaps[diffIndex]._beatmapFilename+";;;"); //2 | |||
socket.write(JSON.stringify(diff)+";;;");//3 | |||
socket.write(info._songFilename+";;;"+fileSize+";;;");//4 & 5 | |||
socket.write(downloadURL +";;;" );//6 | |||
socket.send = true; | |||
} | |||
else | |||
{ | |||
socket.write('dc:wrong password'); | |||
clients.splice(clients.indexOf(socket), 1); | |||
socket.destroy(); | |||
return; | |||
} | |||
} | |||
else if (config.password === "") | |||
{ | |||
if(data.toString().includes(";|;")) | |||
{ | |||
data = data.toString().split(";|;")[1]; | |||
} | |||
console.log("attempted connection: " + data); | |||
for (var i = 0; i < clients.length; i++) | |||
{ | |||
if (clients[i].name == data || "wait" == data) | |||
{ | |||
socket.write('dc:duplicate name'); | |||
clients.splice(clients.indexOf(socket), 1); | |||
socket.destroy(); | |||
return; | |||
} | |||
} | |||
socket.name = data.toString(); | |||
// Send a nice welcome message and announce | |||
socket.write(config.folder.split('/').pop()+"::"+diffIndex*100+ charIndex+";;;"); //0 | |||
socket.write(JSON.stringify(info)+";;;"); //1 | |||
socket.write(info._difficultyBeatmapSets[charIndex]._difficultyBeatmaps[diffIndex]._beatmapFilename+";;;"); //2 | |||
socket.write(JSON.stringify(diff)+";;;");//3 | |||
socket.write(info._songFilename+";;;"+fileSize+";;;");//4 & 5 | |||
socket.write(downloadURL +";;;" );//6 | |||
socket.send = true; | |||
} | |||
else if (config.password !== "" && !data.toString().includes(";|;")) | |||
{ | |||
socket.write('dc:password required'); | |||
clients.splice(clients.indexOf(socket), 1); | |||
socket.destroy(); | |||
return; | |||
} | |||
else | |||
{ | |||
socket.write('dc:uhhh something else'); | |||
clients.splice(clients.indexOf(socket), 1); | |||
socket.destroy(); | |||
return; | |||
} | |||
console.log(socket.name + " joined the session."); | |||
broadcast("System:,:sy:,:"+ socket.name + " joined the session.;:;"); | |||
} | |||
else | |||
{ | |||
broadcast(data.toString(), socket); | |||
var commands = data.toString().split(";:;"); | |||
for (var i = 0; i < commands.length; i++) | |||
{ | |||
readMessage(commands[i]); | |||
} | |||
} | |||
}); | |||
// Remove the client from the list when it leaves | |||
socket.on('end', function () { | |||
try | |||
{ | |||
clients.splice(clients.indexOf(socket), 1); | |||
console.log(socket.name + " left the session."); | |||
broadcast("System:,:sy:,:"+ socket.name + " left the session.;:;"); | |||
broadcast(socket.name + ":,:rc;:;"); | |||
} | |||
catch(err) | |||
{ | |||
console.log(err); | |||
} | |||
}); | |||
socket.on('error',function () { | |||
try | |||
{ | |||
clients.splice(clients.indexOf(socket), 1); | |||
broadcast("System:,:sy:,:"+ socket.name + " left the session.;:;"); | |||
broadcast(socket.name + ":,:rc;:;"); | |||
} | |||
catch(err) | |||
{ | |||
console.log(err); | |||
} | |||
}); | |||
// Send a message to all clients | |||
function broadcast(message, sender) { | |||
clients.forEach(function (client) { | |||
// Don't want to send it to sender | |||
if (client === sender) | |||
{ | |||
return; | |||
} | |||
if (client.send == false) | |||
{ | |||
return; | |||
} | |||
client.write(message); | |||
}); | |||
} | |||
}); | |||
//Get IP address | |||
console.log('\n\n\n'); | |||
if (downloadURL === undefined || downloadURL === "") | |||
{ | |||
var req = request.post('https://catbox.moe/user/api.php', function (err, resp, body) { | |||
if (err) { | |||
console.log(err); | |||
} else { | |||
// var downloadInfo = JSON.parse(body) | |||
downloadURL = body; | |||
console.log('Download URL generated: ' + body); | |||
https.get('https://ifconfig.co/ip', function(res){ | |||
res.setEncoding('utf8'); | |||
res.on('data', function(chunk){ | |||
server.listen(config.port, '0.0.0.0'); | |||
process.stdout.write("Server Started on IP address: ") | |||
console.log(chunk); | |||
}); | |||
res.on('error', function(err) { | |||
server.listen(config.port, '0.0.0.0'); | |||
process.stdout.write("Server Started"); | |||
}); | |||
}); | |||
} | |||
}); | |||
var form = req.form(); | |||
form.append('reqtype', 'fileupload'); | |||
form.append('fileToUpload', fs.createReadStream('./Songs/'+config.folder+'/'+info._songFilename)); | |||
}else | |||
{ | |||
https.get('https://ifconfig.co/ip', function(res){ | |||
res.setEncoding('utf8'); | |||
res.on('data', function(chunk){ | |||
server.listen(config.port, '0.0.0.0'); | |||
process.stdout.write("Server Started on IP address: ") | |||
console.log(chunk); | |||
}); | |||
res.on('error', function(err) { | |||
server.listen(config.port, '0.0.0.0'); | |||
process.stdout.write("Server Started"); | |||
}); | |||
}); | |||
} | |||
function readMessage(message) | |||
{ | |||
changesMade = true; | |||
var type = message.split(":,:")[1]; | |||
switch(type) | |||
{ | |||
case 'an': | |||
try{ | |||
addNote(message.split(':,:')[2].split(" ")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
case 'rn': | |||
try{ | |||
removeNote(message.split(':,:')[2].split(" ")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
case 'ae': | |||
try{ | |||
addEvent(message.split(':,:')[2].split(" ")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
case 're': | |||
try{ | |||
removeEvent(message.split(':,:')[2].split(" ")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
case 'aw': | |||
try{ | |||
addWall(message.split(':,:')[2].split(" ")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
case 'rw': | |||
try{ | |||
removeWall(message.split(':,:')[2].split(" ")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
case 'ab': | |||
try{ | |||
addBookmark(message.split(':,:')[2].split("|||")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
case 'rb': | |||
try{ | |||
removeBookmark(message.split(':,:')[2].split(" ")); | |||
} | |||
catch(err){ | |||
} | |||
break; | |||
default: | |||
//console.log(message); | |||
break; | |||
} | |||
} | |||
function addNote(data) | |||
{ | |||
var note = stringToNote(data) | |||
if (!hasNull(note)) | |||
{ | |||
diff._notes.push(note); | |||
} | |||
} | |||
function removeNote(data) | |||
{ | |||
for (var j = diff._notes.length -1 ; j >= 0; j--) | |||
{ | |||
if (sameNote(diff._notes[j],stringToNote(data))) | |||
{ | |||
diff._notes.splice(j,1); | |||
break; | |||
} | |||
} | |||
} | |||
function stringToNote(data) | |||
{ | |||
return {_time: parseFloat(data[0]), | |||
_lineIndex: parseInt(data[1]), | |||
_lineLayer: parseInt(data[2]), | |||
_type: parseInt(data[3]), | |||
_cutDirection: parseInt(data[4])}; | |||
} | |||
function sameNote(note1,note2) | |||
{ | |||
if (Math.abs(note1._time - note2._time) > 0.001) | |||
return false; | |||
if (note1._lineIndex != note2._lineIndex) | |||
return false; | |||
if (note1._lineLayer != note2._lineLayer) | |||
return false; | |||
if (note1._type != note2._type) | |||
return false; | |||
if (note1._cutDirection != note2._cutDirection) | |||
return false; | |||
return true; | |||
} | |||
function addEvent(data) | |||
{ | |||
if (data.length == 3) | |||
{ | |||
var event = stringToEvent(data) | |||
if (!hasNull(event)) | |||
{ | |||
diff._events.push(event); | |||
} | |||
} | |||
else | |||
{ | |||
var event = stringToEvent(data) | |||
if (!hasNull(event)) | |||
{ | |||
diff._BPMChanges.push(stringToBPM(data)); | |||
} | |||
} | |||
} | |||
function removeEvent(data) | |||
{ | |||
if (data.length == 3) | |||
{ | |||
for (var j = diff._events.length -1 ; j >= 0; j--) | |||
{ | |||
if (sameEvent(diff._events[j],stringToEvent(data))) | |||
{ | |||
diff._events.splice(j,1); | |||
break; | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
for (var j = diff._BPMChanges.length -1 ; j >= 0; j--) | |||
{ | |||
if (sameBPM(stringToBPM(data), diff._BPMChanges[j])) | |||
{ | |||
diff._BPMChanges.splice(j,1); | |||
} | |||
} | |||
} | |||
} | |||
function sameEvent(event1,event2) | |||
{ | |||
if (Math.abs(event1._time - event2._time) > 0.001) | |||
return false; | |||
if (event1._type != event2._type) | |||
return false; | |||
if (event1._value != event2._value) | |||
return false; | |||
return true; | |||
} | |||
function sameBPM(event1,event2) | |||
{ | |||
if (Math.abs(event1._BPM - event2._BPM) > 0.02) | |||
return false; | |||
if (Math.abs(event1._time - event2._time) > 0.001) | |||
return false; | |||
return true; | |||
} | |||
function stringToEvent(data) | |||
{ | |||
return { | |||
_time: parseFloat(data[0]), | |||
_type: parseInt(data[1]), | |||
_value: parseInt(data[2]) | |||
}; | |||
} | |||
function stringToBPM(data) | |||
{ | |||
return { | |||
_BPM:parseFloat(data[0]), | |||
_time:parseFloat(data[1]), | |||
_beatsPerBar:parseFloat(data[2]), | |||
_metronomeOffset:parseFloat(data[3])} | |||
} | |||
function addWall(data) | |||
{ | |||
var wall = stringToWall(data) | |||
if (!hasNull(wall)) | |||
{ | |||
diff._obstacles.push(wall); | |||
} | |||
} | |||
function removeWall(data) | |||
{ | |||
for (var j = diff._obstacles.length -1 ; j >= 0; j--) | |||
{ | |||
if (sameWall(diff._obstacles[j],stringToWall(data))) | |||
{ | |||
diff._obstacles.splice(j,1); | |||
break; | |||
} | |||
} | |||
} | |||
function stringToWall(data) | |||
{ | |||
return {_time: parseFloat(data[0]), | |||
_lineIndex: parseInt(data[1]), | |||
_type: parseInt(data[2]), | |||
_duration: parseFloat(data[3]), | |||
_width: parseInt(data[4]) | |||
}; | |||
} | |||
function sameWall(wall1,wall2) | |||
{ | |||
if (Math.abs(wall1._time - wall2._time) > 0.001) | |||
return false; | |||
if (wall1._lineIndex != wall2._lineIndex) | |||
return false; | |||
if (wall1._type != wall2._type) | |||
return false; | |||
if (Math.abs(wall1._duration - wall2._duration) > 0.001) | |||
return false; | |||
if (wall1._width != wall2._width) | |||
return false; | |||
return true; | |||
} | |||
function addBookmark(data) | |||
{ | |||
diff._bookmarks.push(stringToBookmark(data)); | |||
} | |||
function removeBookmark(data) | |||
{ | |||
for (var j = diff._bookmarks.length - 1; j >= 0; j--) | |||
{ | |||
if (Math.abs(diff._bookmarks[j]._time - stringToBookmark(data)._time) < 0.001) | |||
{ | |||
diff._bookmarks.splice(j,1); | |||
break; | |||
} | |||
} | |||
} | |||
function stringToBookmark(data) | |||
{ | |||
return { | |||
_time: parseFloat(data[0]), | |||
_name: data[1] | |||
}; | |||
} | |||
function saveFile() | |||
{ | |||
if (changesMade) | |||
{ | |||
fs.writeFile('./Songs/' + config.folder + '/' + info._difficultyBeatmapSets[charIndex]._difficultyBeatmaps[diffIndex]._beatmapFilename, JSON.stringify(diff), function(err) { | |||
if (err) | |||
console.log(err); | |||
else | |||
{ | |||
console.log ("file successfully saved.\nNote Count: "+ diff._notes.length+"\nEvent Count: "+diff._events.length); | |||
} | |||
}); | |||
} | |||
changesMade = false; | |||
} | |||
// server.getConnections(function(err,count){ | |||
// console.log(count); | |||
// }); | |||
function disconnectSoon(socket) | |||
{ | |||
if(socket.name == "wait" || socket.name.length > 30) | |||
{ | |||
clients.splice(clients.indexOf(socket), 1); | |||
socket.destroy(); | |||
return; | |||
} | |||
} | |||
function hasNull(object) | |||
{ | |||
for(var key in object) { | |||
if (object[key] === null) | |||
{ | |||
try | |||
{ | |||
console.log("null object detected at :" + object._time); | |||
} | |||
catch(err) | |||
{ | |||
console.log("null object detected") | |||
} | |||
return true; | |||
} | |||
} | |||
} | |||
function loadJSON(file) { | |||
var data = fs.readFileSync(file); | |||
return JSON.parse(data); | |||
} |