[
  {
    "path": ".gitignore",
    "content": "#MacOSX Stuffs\n.DS_Store\n.DS_Store?\n\n#public folder\npublic\n\n#Configuration Folder\nserver/configurations/config.js\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules\njspm_packages\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# MV Online Version 0.2.0 Release Notes:\n\n## Summary\nThere are 2 main points that are different from 0.1.0\n\n- package.json has been updated with new versions of all the project's dependencies.  To update all dependencies simply run the install command again after updating the server:\n```bash\nnpm install\n```\n\n- With these newer packages the default method for registration and login have been changed.  Registration and login by default now use sha256 encryption.  This will not allow you to use the database already there unless you decide not to update your package.json and stick with previous versions.\n\n## IMPORTANT!!!! YOU MUST CLEAR YOUR DATABASE AND START OVER OR FOLLOW THE INSTRUCTIONS BELOW:\n\n- Keep the original package.json in your project or change the `passport-local-mongoose` entry to `^1.0.0\"` as this will keep the original sha1 encryption.\n\n- You'll also need to change line 103 to:\n\n```js\ncrypto.pbkdf2(req.body.password, account.salt, 25000, 512, 'sha1', function(err, hashRaw){\n```\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Matthew Cipriano (Nelderson)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Procfile",
    "content": "web: node server.js"
  },
  {
    "path": "README.md",
    "content": "MV Online Core Documentation\n==========================\n\nRequirements\n-------------\nNode.js and RPGMaker MV\n\nInstallation\n-------------\n\nDeploy to Heroku here:\n\n[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://dashboard.heroku.com/new?template=https://github.com/Nelderson/MV_Online/tree/master)\n\nUse `git clone` or download and unzip to the directory of your choice.\n\nRun `npm install` to download all dependencies for the server. Use `npm install -d` for windows users\n\nAfter configuring the server run `npm start` to start the server\n\n\nServer Configuration\n-------------\n\nInside the  `server/configurations/config.js` file, there are several things to configure:\n\n`port` defines which port the server will run on (Default `8000`)\n\n`jwtSecret` defines the secret the JWT is signed.  Please change this for security reasons in a production environment\n\n`firstHash` is the initial hashing secret for login system.  This is the same as the client plugin first hash.  Recommended that this be changed before putting in a production environment\n\n\n`mailFrom` when a user registers they recieve an email from this address.\n`smtps://username@gmail.com:password@smtp.gmail.com`  (Additional steps are required if you want to use gmail.)\n\n`mongoDBconnect` Link and credentials to MongoDB Database. `mongodb://username:password@linktomongodb.com:39504/collection`\n\n\nClient Configuration (RPGMaker MV)\n-------------\n\nAdd the `css` folder to the root of your project directory\n\nAdd the files in `game_resources/js/plugns` that you want for your plugins to your own `js/plugins` folder of your game. (`Online_Main_Core.js` is manditory for all other plugins)\n\nAdd the files from the `game_resources/js/libs` folder to your own `js/libs` folder\n\nModify your `index.html` file in your game to add this in the header:\n\n```html\n<!-- Nel Add -->\n<link rel=\"stylesheet\" type=\"text/css\" href=\"./css/bootstrap3.3.5.min.css\" >\n<link rel=\"stylesheet\" type=\"text/css\" href=\"./css/fontawesome4.4.0.min.css\" >\n<link rel=\"stylesheet\" type=\"text/css\" href=\"./css/MMO.css\">\n<!-- Nel Add -->\n```\n\nAnd this in the body, dont forget the change localhost for your IP or Domain :\n\n```html\n<!-- Nel Add -->\n<script type=\"text/javascript\" src=\"./js/libs/jquery-2.1.4.min.js\"></script>\n<script type=\"text/javascript\" src=\"./js/libs/jquerymobile1.4.5.min.js\"></script>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"./css/jquerymobile1.4.5.min.css\">\n<script type=\"text/javascript\" src=\"./js/libs/crypto.sha1.js\"></script>\n<script type=\"text/javascript\" src=\"./js/libs/socket.io-2.2.0.js\"></script>\n<!-- Nel Add -->\n```\n"
  },
  {
    "path": "READMEs/Chat.md",
    "content": "MV Online Chat Documentation\n==========================\n\nIntroduction\n-------------\n\nThe Online Chat Socket Module allows you to communicate with other players in your game using an in game chat window.\n\nInstallation\n-------------\n\nMake sure you have the `chat.js` file in your `socket_modules` folder.\n\nAdd this line to the `ADD SOCKET IO MODULES HERE` section in the `server.js` file:\n\n`var chat = require('./socket_modules/chat');`\n\nAdd this line to the `BIND SOCKET IO MODULES HERE` section in the `server.js` file:\n\n`chat(io);`\n"
  },
  {
    "path": "READMEs/CloudSave.md",
    "content": "MV Cloud Save Documentation\n==========================\n\nIntroduction\n-------------\n\n`Cloud Save` allows you to store game data that you can use to project and show trends within your game\n\nConfiguration\n-------------\n\nAdd this line to the `Authentication required` section in the `server.js` file:\n\n`app.use('/cloudsave',require('./api_routes/cloudsave.js'));`\n"
  },
  {
    "path": "READMEs/Cors.md",
    "content": "MV Cors Documentation\n==========================\n\nIntroduction\n-------------\n\n`api_routes/Cors.js` allows you to your server cors cross domain\n`configurations/Cors.js` Configuration your cors domain\n\nConfiguration\n-------------\n\nAdd this line to the `API SECTION` section in the `server.js` file:\n\n`app.use('AllowCrossDomain',require('./api_routes/cors'));`\n\n"
  },
  {
    "path": "READMEs/GlobalVariables.md",
    "content": "MV Online Global Variables Documentation\n==========================\n\nIntroduction\n-------------\n\nThe Online Global Variables Socket Module allows you to send Variable and Switch data to other players connected.\n\nInstallation\n-------------\n\nMake sure you have the `globalvar.js` file in your `socket_modules` folder.\n\nAdd this line to the `ADD SOCKET IO MODULES HERE` section in the `server.js` file:\n\n`var globalvar = require('./socket_modules/globalvar');`\n\nAdd this line to the `BIND SOCKET IO MODULES HERE` section in the `server.js` file:\n\n`globalvar(io);`\n"
  },
  {
    "path": "READMEs/Metrics.md",
    "content": "MV Online Metrics Documentation\n==========================\n\nIntroduction\n-------------\n\n`Metrics` allows you to store game data that you can use to project\nand show trends within your game\n\nConfiguration\n-------------\n\nAdd this line to the `Authentication required` section in the `server.js` file:\n\n`app.use('/metrics',require('./api_routes/metrics'));`\n\nThe `metrics.js ` has only one configuration in the file for an anonymous flag.\nThis flag determines if you want the metrics to be anonymous, or the player has\nto be signed into an account.\n"
  },
  {
    "path": "READMEs/NetPlayers.md",
    "content": "MV Net Players Documentation\n==========================\n\nIntroduction\n-------------\n\nThe Online Net Players Socket Module allows you to see other players on the same map\n\nInstallation\n-------------\n\nMake sure you have the `netplayer.js` file in your `socket_modules` folder.\n\nAdd this line to the `ADD SOCKET IO MODULES HERE` section in the `server.js` file:\n\n`var netplayers = require('./socket_modules/netplayer');`\n\nAdd this line to the `BIND SOCKET IO MODULES HERE` section in the `server.js` file:\n\n`netplayers(io);`\n"
  },
  {
    "path": "api_routes/LoginSchema/Account.js",
    "content": "//Version 0.1.0 - Added fields for password reset logic\n\nvar mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar passportLocalMongoose = require('passport-local-mongoose');\n\nvar allFields = 'id salt hash username email activated actCode rank socketId lostPasswordFlag lostPasswordTemp lostPasswordExpires';\n\nvar Account = new Schema({\n    username: {type: String, required: true, index: { unique: true}},\n    email: {type: String, required: true, index: { unique: true}},\n    activated: Boolean,\n    actCode: String,\n    socketId: String, //Current assigned socket\n    lostPasswordFlag: Boolean,\n    lostPasswordTemp: String,\n    lostPasswordExpires: Date,\n    rank: Number //0 - player, 1 - moderator, 2 - admin\n});\n\nAccount.statics.findByName = function(name, cb) {\n\treturn this.findOne({ username: name}, allFields, cb);\n};\n\nAccount.statics.findByEmail = function(email, cb) {\n\treturn this.findOne({ email: email}, allFields, cb);\n};\n\nAccount.statics.activate = function(actCode, cb) {\n\treturn this.findOneAndUpdate({ 'actCode': actCode }, { activated: true }, cb);\n};\n\nAccount.plugin(passportLocalMongoose, {\n\tusernameQueryFields: ['username']\n});\n\n\nmodule.exports = mongoose.model('Account', Account);\n"
  },
  {
    "path": "api_routes/cloudsave.js",
    "content": "var mongoose = require(\"mongoose\");\nvar express = require('express');\nvar authAPI = require('../auth.js').authAPI;\nvar router = express.Router();\nvar config = require('../configurations/config');\nvar log = require('tracer').colorConsole(config.loggingConfig);\n\nvar Save = new mongoose.Schema({\n    username: {type: String, required: true, index: { unique: true}},\n    email: {type: String, required: true, index: { unique: true}},\n    savedata: {type: String, required: true},\n    globaldata: {type: String, required: false}\n});\n\nvar Saves = mongoose.model('Saves', Save);\n\n//Need to have a valid token for all routes\nrouter.use(authAPI);\n\nrouter.get('/loadfromcloud', function(req, res){\n  var name = req.decoded.name;\n  Saves.findOne({username: name}, function(err,account){\n    if (err) log.error(err);\n    if (account){\n      return res.status(200).send(account.savedata);\n    }else{\n      return res.status(200).send(\"No account\");\n    }\n  });\n});\n\n\nrouter.post('/savetocloud', function(req, res){\n  //Save to the database....\n  var name = req.decoded.name;\n  var email = req.decoded.email;\n  var savedata = req.body.savedata;\n  Saves.findOne({username: name}, function(err,account){\n    if (err) log.error(err);\n    if (account){\n      //Update save data to database\n        Saves.findOneAndUpdate({username: name}, {$set: {savedata:savedata}},function(err,data1){\n          if (err) log.error(err);\n          return res.status(200).send();\n        });\n    }else{\n      //Make New Account with save data\n      var newUser = new Saves({\n        username: name,\n        email: email,\n        savedata: savedata,\n      });\n      newUser.save(function(err,data){\n        if (err) log.error(err);\n        return res.status(200).send();\n      });\n    }\n  });\n});\n\nmodule.exports = router;\n"
  },
  {
    "path": "api_routes/cors.js",
    "content": "//----------------------------------\n// Require file & Router :\n//----------------------------------\nvar config = require('./../configurations/cors');\nvar server = require('../server');\nvar express = require('express');\nvar router = express.Router();\n\n//----------------------------------\n// Var Config :\n//----------------------------------\nvar MyCorsHost = 'OriginDomain'\nvar MyMethods = 'MethodsCors'\nvar MyHeader = 'HeaderCors'\nvar AllowCrossDomain = 'CrossDomain'\n\n//----------------------------------\n// Allow Cors Domain:\n//----------------------------------\n\n\n\nvar CrossDomain = function(req, res, next) {\n    res.header('Access-Control-Allow-Origin', 'OriginDomain');\n    res.header('Access-Control-Allow-Methods', 'MethodsCors');\n    res.header('Access-Control-Allow-Headers', 'HeaderCors');\n    if (req.method === \"OPTIONS\") \n        res.send(200);\n    else \n        next();\n}\n\n\nmodule.exports = router;\n"
  },
  {
    "path": "api_routes/example.js",
    "content": "var express = require('express');\nvar authAPI = require('../auth.js').authAPI;\nvar router = express.Router();\n\n\n//Need to have a valid token for all routes\nrouter.use(authAPI);\n\nrouter.get('/testing',function(req,res){\n  res.status(200).send('Dude....this is totally awesome');\n});\n\n\nmodule.exports = router;\n"
  },
  {
    "path": "api_routes/loginDBConnection.js",
    "content": "module.exports = function(){\n  var config = require('../configurations/config');\n  var mongoose = require('mongoose');\n  var log = require('tracer').colorConsole(config.loggingConfig);\n\n  //Mongo DB Database Connection\n  mongoose.connect(config.mongoDBconnect, { useNewUrlParser: true, useCreateIndex: true }, function(err) {\n      if (err) {\n        log.error(err);\n      }\n    });\n};\n"
  },
  {
    "path": "api_routes/login_routes.js",
    "content": "var crypto = require('crypto');\nvar express = require('express');\nvar config = require('../configurations/config');\nvar log = require('tracer').colorConsole(config.loggingConfig);\nvar nodemailer = require('nodemailer');\nvar transporter = nodemailer.createTransport(config.mailFrom);\nvar Account = require('./LoginSchema/Account');\nvar jwt = require('jsonwebtoken');\nvar router = express.Router();\nvar authAPI = require('../auth.js').authAPI;\nvar sgMail = null;\n\nif (process.env.SENDGRID_API_KEY){\n  sgMail = require('@sendgrid/mail');\n  sgMail.setApiKey(process.env.SENDGRID_API_KEY);\n}\n\nrouter.get('/', function (req, res) {\n  res.status(203).json({});\n});\n\n\nrouter.get('/verify-token', function (req, res, next) {\n  authAPI(req,res,next)\n}, function (req, res, next) {\n  res.status(203).json({token: req.decoded});\n});\n\nrouter.get('/register', function(req, res) {\n    res.status(403).json({});\n});\n\nrouter.post('/register', function(req, res) {\n    //Check if email not already used\n    Account.findByEmail(req.body.email, function(err, account){\n        if (err) {\n            return res.status(203).json({\n                pageData: {\n                    err : err.message\n                }\n            });\n        }\n        if (account)\n            return res.status(203).json({\n                pageData: {\n                    err : \"Email '\"+account.email+\"' already registered\"\n                }\n            });\n\n        //Create hash for activation code\n        var shasum = crypto.createHash('sha1');\n        shasum.update(req.body.username+req.body.email);\n        actCode = shasum.digest('hex');\n\n        //Hash the password a first time in sha1\n        var shapwd = crypto.createHash('sha1').update(req.body.password + config.firstHash).digest('hex');\n\n        Account.register(new Account({\n            username : req.body.username,\n            email : req.body.email,\n            activated : false,\n            actCode: actCode,\n            socketId: null,\n            rank: 0\n        }), shapwd, function(err, account) {\n            if (err) {\n                return res.status(203).json({\n                    pageData: {\n                        err : err.message\n                    }\n                });\n            }\n\n            actUrl = `http://${req.headers.host}/activate/${actCode}`;\n\n            const messageBody = {\n              from: 'Team <no-reply@myserver.com>',\n              to: req.body.email,\n              subject: \"RPGMaker MV MMO\",\n              text: \"Hello \"+req.body.username+' and welcome to RPGMaker MV MMO!\\nYour account has been registrated, but you need to activate it by following this link :\\n'+actUrl+'\\n\\nEnjoy!\\n\\t-- Nelderson'\n            }\n\n            if (sgMail){\n              sgMail.send(messageBody)\n              .then(()=>{\n                log.info('Yes?');\n                return res.status(200).json({\n                  pageData: {\n                      msg : 'An activation link has been send to your email address.'\n                  }\n                });\n              })\n              .catch(error => {\n                log.error(err);\n                  return res.status(203).json({\n                    pageData: {\n                        err : 'Error sending email'\n                    }\n                  });\n              })  \n            }\n            else{\n              transporter.sendMail({\n                  ...messageBody\n              },function(err,info){\n                if (err){\n                  log.error(err);\n                  return res.status(203).json({\n                    pageData: {\n                        err : 'Error sending email'\n                    }\n                  });\n                }else{\n                  log.info(info);\n                  return res.status(200).json({\n                    pageData: {\n                        msg : 'An activation link has been send to your email address.'\n                    }\n                });\n                }\n              });\n            }\n        });\n    });\n});\n\nrouter.get('/login', function(req, res) {\n    res.status(203).json({});\n});\n\nrouter.post('/login', function(req, res){\n  Account.findByName(req.body.username, function(err, account){\n    if (err) {\n      return res.status(203).json({\n        err: err.msg\n      });\n    }\n    if (!account) {\n      return res.status(203).json({\n        err: \"Invalid username\"\n      });\n    }\n\n    var profile = {\n      name: account.username,\n      email: account.email,\n      id: account._id,\n      rank: account.rank\n    };\n\n    //Check for lost password flag and temp password\n     if (account.lostPasswordFlag===true){\n      var tempPasswordHash = crypto.createHash('sha1').update(account.lostPasswordTemp + config.firstHash).digest('hex');\n      if (tempPasswordHash===req.body.password){\n        //Check lostPasswordExpires\n        if (Date.now() > account.lostPasswordExpires){\n          return res.status(203).json({\n            err: \"Temporary Password is Expired!\"\n          });\n        }\n        return res.status(200).json({\n          temp:tempPasswordHash,\n          name:account.username\n         });\n        }\n       }\n\n    //Check for normal password\n    crypto.pbkdf2(req.body.password, account.salt, 25000, 512, 'sha256', function(err, hashRaw){\n      var hpass = new Buffer(hashRaw, 'binary').toString('hex');\n      if (account.hash == hpass) {\n        if (!account.activated){\n          return res.status(203).json({\n          err: \"Account Not Activated\"\n          });\n        }\n          var token = jwt.sign(profile, config.jwtSecret, { expiresIn: 60*config.tokenExpiresIn});\n          return res.status(200).json({token: token});\n      }\n      return res.status(203).json({\n        err: \"Invalid password\"\n      });\n    });\n  });\n});\n\n\nrouter.get('/activate/:actCode', function(req, res) {\n    var actCode = req.params.actCode;\n\n    Account.activate(actCode, function(err, account){\n        if (err) {\n            return res.status(203).json('activation', {\n                pageData: {\n                    err: err.message\n                }\n            });\n        }\n        if (!account) {\n            return res.status(203).json('activation', {\n                pageData: {\n                    err: \"Can't activate account : Unknown token '<b>\"+actCode+\"</b>'.\"\n                }\n            });\n        }\n        return res.status(200).json('activation');\n    });\n});\n\nrouter.post('/lostpassword', function(req, res){\n  var randomPass=crypto.randomBytes(config.lostPasswordComplexity).toString('hex');\n  Account.findOneAndUpdate({email:req.body.email},\n    {lostPasswordFlag:true,lostPasswordTemp:randomPass,lostPasswordExpires:Date.now() + config.tempPasswordExpires},\n    function(err, account){\n    if (!account.activated){\n      return res.status(203).json({\n      err: \"Account Not Activated\"\n      });\n    }\n    if (err) {\n      return res.status(203).json({\n        err: err.msg\n      });\n    }\n    if (!account) {\n      return res.status(203).json({\n        err: \"Email not found\"\n      });\n    }\n\n    // Send Email with random temporary password\n    transporter.sendMail({\n        from: 'Team <no-reply@myserver.com>',\n        to: account.email,\n        subject: \"RPGMaker MV MMO\",\n        text: \"Hello \"+account.username+' \\nyour temporary account password is: '+randomPass,\n        html: \"Hello \"+account.username+' \\nyour temporary account password is: '+randomPass,\n    },function(err,info){\n      if (err){\n        log.error(err);\n      }else{\n        log.info(info);\n      }\n    });\n    return res.status(200).json({});\n  });\n});\n\nrouter.post('/resetpassword', function(req, res){\n  Account.findByName(req.body.tempName, function(err,account){\n    if (err){\n      return res.status(203).json({\n        err: err.msg\n        });\n    }\n    if (!account) {\n      return res.status(203).json({\n        err: \"Error Occured (Account Not Found)\"\n      });\n    }\n    if (!account.lostPasswordFlag){\n      return res.status(203).json({\n        err: \"Please go through the password reset process the normal way....\"\n      });\n    }\n\n    var tempPasswordHash = crypto.createHash('sha1').update(account.lostPasswordTemp + config.firstHash).digest('hex');\n    if (req.body.tempHash!==tempPasswordHash){\n      return res.status(203).json({\n        err: \"Please go through the password reset process the normal way....\"\n      });\n    }\n\n    if (Date.now() > account.lostPasswordExpires){\n      return res.status(203).json({\n        err: \"Temporary Password is Expired!\"\n      });\n    }\n\n    account.setPassword(req.body.password, function(err,data){\n      if (err){\n        return res.status(203).json({\n          err: err.message\n        });\n      }\n      if (data){\n        account.lostPasswordFlag = false;\n        account.save().then(function(error,data){\n          if (err) log.error(err);\n          return res.status(200).json({});\n        });\n      }\n    });\n  });\n});\n\nmodule.exports = router;\n"
  },
  {
    "path": "api_routes/metrics.js",
    "content": "var mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\nvar express = require('express');\nvar authAPI = require('../auth.js').authAPI;\nvar router = express.Router();\nvar config = require('../configurations/config');\nvar log = require('tracer').colorConsole(config.loggingConfig);\n\n//============Config Section=============//\n//Set this the same as client anonymous flag\nvar anonymous = process.env.MV_METRICS_ANONYMOUS || false;\n//======================================//\n\n if (!anonymous){\n  var Metric = new Schema({\n      username: {type: String, required: true, index: { unique: true}},\n      email: {type: String, required: true, index: { unique: true}},\n      data: [{body: [], date: Date }],\n  });\n}else{\n  var Metric = new Schema({\n      data: [{body: [], date: Date }],\n  });\n}\n\nvar Metrics = mongoose.model('Metrics', Metric);\n\nif (!anonymous){\n  //Need to have a valid token for all routes\n  router.use(authAPI);\n}\n\nrouter.post('/datadump', function(req, res) {\n  var name, email, id;\n  if (!anonymous){\n    id  = req.body.id;\n    name = req.decoded.name;\n    email = req.decoded.email;\n  }\n  var data = {\n    body: [req.body],\n    date: Date.now()\n  };\n\n\nif (!anonymous){\n  Metrics.findOne({username: name}, 'username', function(err,account){\n    if (account){\n      //Metrics collection started\n      Metrics.findOneAndUpdate({username: name}, {$push: {data:data}},function(err,data1){\n        if (err) log.error(err);\n        return res.status(200).send('Done');\n      });\n    }else{\n      //Metrics collection NOT started\n      var newUser = new Metrics({\n        username: name,\n        email: email,\n        data: [data]\n      });\n      newUser.save(function(err,data){\n        if (err) log.error(err);\n        return res.status(200).send('Done');\n      });\n    }\n  });\n}else{\n  //Anonymous Metrics\n  Metrics.findOne({_id: id}, function(err,account){\n    if (account){\n      //Metrics collection started\n      Metrics.findOneAndUpdate({_id: id}, {$push: {data:data}},function(err,data1){\n        if (err) log.error(err);\n        return res.status(200).send(id);\n      });\n    }else{\n      //Metrics collection NOT started\n      var newUser = new Metrics({\n        username: 'null',\n        email: 'null',\n        data: [data]\n      });\n      newUser.save(function(err,data){\n        var uid = newUser._id;\n        if (err) log.error(err);\n        return res.status(200).send(uid);\n      });\n    }\n  });\n}\n});\n\nmodule.exports = router;\n"
  },
  {
    "path": "app.json",
    "content": "{\n  \"name\": \"MV Online\",\n  \"description\": \"MV Online system created by Nelderson\",\n  \"repository\": \"https://github.com/Nelderson/MV_Online\",\n  \"logo\": \"https://i.imgur.com/I0fAzpx.png\",\n  \"keywords\": [\"node\", \"express\", \"static\"],\n  \"env\": {\n    \"MV_JWT_SECRET\": {\n      \"description\": \"A secret key for verifying the integrity of signed JSON Web Tokens.\",\n      \"generator\": \"secret\"\n    },\n    \"MV_FIRST_HASH\": {\n      \"description\": \"The first hash to pass all passwords through\",\n      \"generator\": \"secret\"\n    },\n    \"MV_TOKEN_EXPIRES_MIN\": {\n      \"description\": \"The amount of minutes before token expires (20160 = 14 Days)\",\n      \"value\": \"20160\"\n    },\n    \"MV_WORKER_COUNT\" :{\n      \"description\": \"The amount of workers the cluster will use\",\n      \"value\": \"4\"\n    },\n    \"MV_ENFORCE_ONE_USER\" :{\n      \"description\": \"Allow only one login per user\",\n      \"value\": \"false\"\n    },\n    \"MV_LOST_PASSWORD_COMPLEXITY\" :{\n      \"description\": \"Complexity of lost password (Default 2)\",\n      \"value\": \"2\"\n    },\n    \"MV_LOST_PASSWORD_EXPIRES\" :{\n      \"description\": \"Temporary Password Expiration in Milliseconds (3600000 = 1hr)\",\n      \"value\": \"3600000\"\n    },\n    \"MV_CHAT_ENABLE_LOGGING\" :{\n      \"description\": \"Enable logging on all chat windows\",\n      \"value\": \"false\"\n    },\n    \"MV_CHAT_PROFANITY_FILTER\" :{\n      \"description\": \"Enable profanity filter on all chat windows\",\n      \"value\": \"false\"\n    },\n    \"MV_METRICS_ANONYMOUS\" :{\n      \"description\": \"Make metrics anonymous\",\n      \"value\": \"false\"\n    }\n  },\n  \"addons\": [\n    {\n      \"plan\": \"mongolab:sandbox\",\n      \"as\": \"MV_MONGO\"\n    },\n    {\n      \"plan\": \"heroku-redis:hobby-dev\",\n      \"as\": \"MV_REDIS_HOST\"\n    },\n    {\n      \"plan\": \"sendgrid:starter\"\n    }\n  ]\n}"
  },
  {
    "path": "auth.js",
    "content": "var jwt = require('jsonwebtoken');\nvar config = require('./configurations/config');\n\n var authAPI = function(req, res, next){\n\n\t// check header or url parameters or post parameters for token\n\tvar token = req.body.token || req.param('token') || req.headers['x-access-token'];\n\n\t// decode token\n\tif (token) {\n\n\t\t// verifies secret and checks exp\n\t\tjwt.verify(token, config.jwtSecret, function(err, decoded) {\n\t\t\tif (err) {\n\t\t\t\treturn res.status(403).json({ success: false, message: 'Failed to authenticate token.' });\n\t\t\t} else {\n\t\t\t\t// if everything is good, save to request for use in other routes\n\t\t\t\treq.decoded = decoded;\n\t\t\t\tnext();\n\t\t\t}\n\t\t});\n\n\t} else {\n\n\t\t// if there is no token\n\t\t// return an error\n\t\treturn res.status(403).send({\n\t\t\tsuccess: false,\n\t\t\tmessage: 'Not Authenticated'\n\t\t});\n\n\t}\n};\n\n var authSocket = function(socket, next){\n\tvar { token } = socket.handshake.query;\n\n\t// decode token\n\tif (token) {\n\n\t\t// verifies secret and checks exp\n\t\tjwt.verify(token, config.jwtSecret, function(err, decoded) {\n\t\t\tif (err) {\n\t\t\t\treturn next(err);\n\t\t\t} else {\n\t\t\t\t// set user to decoded token \n\t\t\t\t// for use throughout app\n\t\t\t\tsocket.user = decoded;\n\t\t\t\tnext(null);\n\t\t\t}\n\t\t});\n\n\t} else {\n\t\t// if there is no token\n\t\t// return an error\n\t\treturn next('Not Authenticated')\n\t}\n};\n\n\nmodule.exports.authAPI = authAPI;\nmodule.exports.authSocket = authSocket;\n"
  },
  {
    "path": "configurations/chat.js",
    "content": "var Config = module.exports = {\n\t//---------------------\n\t//Main Configurations\n\t//---------------------\n\tenableLogging: process.env.MV_CHAT_ENABLE_LOGGING || false,\n\tprofanityFilter: process.env.MV_CHAT_PROFANITY_FILTER || false,\n};\n"
  },
  {
    "path": "configurations/config.js",
    "content": "var Config = module.exports = {\n  //---------------------\n  //Main Configurations\n  //---------------------\n  port:  process.env.PORT || 8000,\n\n  jwtSecret: process.env.MV_JWT_SECRET || 'aeha8j4h20adn92k10nkav0sjf90sleicazvyi54j39jfqasfjk9',\n\n  loggingConfig: {\n    format : [\n              \"{{timestamp}} <{{title}}> {{message}}\", //default format\n              {\n                error : \"{{timestamp}} <{{title}}> {{message}} (in {{file}}:{{line}})\\nCall Stack:\\n{{stack}}\" // error format\n              }\n    ],\n    dateformat : \"HH:MM:ss.L\",\n    preprocess :  function(data){\n      data.title = data.title.toUpperCase();\n    },\n    level: 'debug'\n  },\n\n  redisConnection: process.env.MV_REDIS_HOST_URL || 'redis://localhost',\n\n  //---------------------\n  //Login Configurations\n  //---------------------\n\n  //Needs to be the same as Client firstHash\n  firstHash: process.env.MV_FIRST_HASH||'d28cb767c4272d8ab91000283c67747cb2ef7cd1',\n\n  //Mail to send activation codes from\n  mailFrom: process.env.MV_MAILFROM || 'smtps://username@gmail.com:password@smtp.gmail.com',\n\n  //Time until token expires (in minutes)\n  tokenExpiresIn: process.env.MV_TOKEN_EXPIRES_MIN || 60 * 24 * 14,\n\n  //Allows only one logged in user at a time.\n  enforceOneUser: process.env.MV_ENFORCE_ONE_USER || false,\n\n  //Temporary Password Complexity for lost Passwords\n  lostPasswordComplexity: process.env.MV_LOST_PASSWORD_COMPLEXITY || 2,\n\n  //Temporary Password Expiration in Milliseconds\n  tempPasswordExpires: process.env.MV_LOST_PASSWORD_EXPIRES || 3600000, //1 hour\n\n  //------------------------\n  //Database Configurations\n  //------------------------\n\n  mongoDBconnect: process.env.MV_MONGO_URI || 'mongodb://username:password@linktomongodb.com:39504/collection'\n};\n"
  },
  {
    "path": "configurations/cors.js",
    "content": "var Config = module.exports = {\n  //---------------------\n  //Cors Configurations\n  //---------------------\n\n  MyCorsHost: '*',\n  MyMethods: 'GET,PUT,POST',\n  MyHeader: 'DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range, X-Acces-Token, Accept-Type'\n\n};\n"
  },
  {
    "path": "game_resources/css/MMO.css",
    "content": "/*\n* @Author: Vinxce\n* @Date:   2015-10-27 10:55:44\n* @Last Modified by:   Vinxce\n* @Last Modified time: 2015-10-27 21:31:32\n*/\n\n@keyframes fadeIn {\n\tfrom \t{ opacity: 0; }\n\tto \t\t{ opacity: 1; }\n}\n\n#LoginForm {\n\tmargin: auto;\n\ttext-shadow: none !important;\n\tposition: relative;\n\tbottom: 50px;\n\tanimation: fadeIn 1 ease-in;\n}\n\n#RegisterForm{\n\tmargin: auto;\n\ttext-shadow: none !important;\n\tposition: relative;\n\tbottom: 50px;\n\tanimation: fadeIn 1 ease-in;\n}\n\n#ActivationForm{\n\tmargin: auto;\n\ttext-shadow: none !important;\n\tposition: relative;\n\tbottom: 50px;\n\tanimation: fadeIn 1 ease-in;\n}\n"
  },
  {
    "path": "game_resources/js/libs/crypto.sha1.js",
    "content": "/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto-js/wiki/License\n*/\nvar CryptoJS=CryptoJS||function(e,m){var p={},j=p.lib={},l=function(){},f=j.Base={extend:function(a){l.prototype=this;var c=new l;a&&c.mixIn(a);c.hasOwnProperty(\"init\")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty(\"toString\")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},\nn=j.WordArray=f.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=m?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var c=this.words,q=a.words,d=this.sigBytes;a=a.sigBytes;this.clamp();if(d%4)for(var b=0;b<a;b++)c[d+b>>>2]|=(q[b>>>2]>>>24-8*(b%4)&255)<<24-8*((d+b)%4);else if(65535<q.length)for(b=0;b<a;b+=4)c[d+b>>>2]=q[b>>>2];else c.push.apply(c,q);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<\n32-8*(c%4);a.length=e.ceil(c/4)},clone:function(){var a=f.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b<a;b+=4)c.push(4294967296*e.random()|0);return new n.init(c,a)}}),b=p.enc={},h=b.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++){var f=c[d>>>2]>>>24-8*(d%4)&255;b.push((f>>>4).toString(16));b.push((f&15).toString(16))}return b.join(\"\")},parse:function(a){for(var c=a.length,b=[],d=0;d<c;d+=2)b[d>>>3]|=parseInt(a.substr(d,\n2),16)<<24-4*(d%8);return new n.init(b,c/2)}},g=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++)b.push(String.fromCharCode(c[d>>>2]>>>24-8*(d%4)&255));return b.join(\"\")},parse:function(a){for(var c=a.length,b=[],d=0;d<c;d++)b[d>>>2]|=(a.charCodeAt(d)&255)<<24-8*(d%4);return new n.init(b,c)}},r=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(g.stringify(a)))}catch(c){throw Error(\"Malformed UTF-8 data\");}},parse:function(a){return g.parse(unescape(encodeURIComponent(a)))}},\nk=j.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new n.init;this._nDataBytes=0},_append:function(a){\"string\"==typeof a&&(a=r.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,b=c.words,d=c.sigBytes,f=this.blockSize,h=d/(4*f),h=a?e.ceil(h):e.max((h|0)-this._minBufferSize,0);a=h*f;d=e.min(4*a,d);if(a){for(var g=0;g<a;g+=f)this._doProcessBlock(b,g);g=b.splice(0,a);c.sigBytes-=d}return new n.init(g,d)},clone:function(){var a=f.clone.call(this);\na._data=this._data.clone();return a},_minBufferSize:0});j.Hasher=k.extend({cfg:f.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){k.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(c,b){return(new a.init(b)).finalize(c)}},_createHmacHelper:function(a){return function(b,f){return(new s.HMAC.init(a,\nf)).finalize(b)}}});var s=p.algo={};return p}(Math);\n(function(){var e=CryptoJS,m=e.lib,p=m.WordArray,j=m.Hasher,l=[],m=e.algo.SHA1=j.extend({_doReset:function(){this._hash=new p.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(f,n){for(var b=this._hash.words,h=b[0],g=b[1],e=b[2],k=b[3],j=b[4],a=0;80>a;a++){if(16>a)l[a]=f[n+a]|0;else{var c=l[a-3]^l[a-8]^l[a-14]^l[a-16];l[a]=c<<1|c>>>31}c=(h<<5|h>>>27)+j+l[a];c=20>a?c+((g&e|~g&k)+1518500249):40>a?c+((g^e^k)+1859775393):60>a?c+((g&e|g&k|e&k)-1894007588):c+((g^e^\nk)-899497514);j=k;k=e;e=g<<30|g>>>2;g=h;h=c}b[0]=b[0]+h|0;b[1]=b[1]+g|0;b[2]=b[2]+e|0;b[3]=b[3]+k|0;b[4]=b[4]+j|0},_doFinalize:function(){var f=this._data,e=f.words,b=8*this._nDataBytes,h=8*f.sigBytes;e[h>>>5]|=128<<24-h%32;e[(h+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(h+64>>>9<<4)+15]=b;f.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=j.clone.call(this);e._hash=this._hash.clone();return e}});e.SHA1=j._createHelper(m);e.HmacSHA1=j._createHmacHelper(m)})();"
  },
  {
    "path": "game_resources/js/libs/socket.io-2.2.0.js",
    "content": "/*!\n * Socket.IO v2.2.0\n * (c) 2014-2018 Guillermo Rauch\n * Released under the MIT License.\n */\n!function(t,e){\"object\"==typeof exports&&\"object\"==typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define([],e):\"object\"==typeof exports?exports.io=e():t.io=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p=\"\",e(0)}([function(t,e,n){\"use strict\";function r(t,e){\"object\"===(\"undefined\"==typeof t?\"undefined\":o(t))&&(e=t,t=void 0),e=e||{};var n,r=i(t),s=r.source,u=r.id,h=r.path,f=p[u]&&h in p[u].nsps,l=e.forceNew||e[\"force new connection\"]||!1===e.multiplex||f;return l?(c(\"ignoring socket cache for %s\",s),n=a(s,e)):(p[u]||(c(\"new io instance for %s\",s),p[u]=a(s,e)),n=p[u]),r.query&&!e.query&&(e.query=r.query),n.socket(r.path,e)}var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},i=n(1),s=n(7),a=n(12),c=n(3)(\"socket.io-client\");t.exports=e=r;var p=e.managers={};e.protocol=s.protocol,e.connect=r,e.Manager=n(12),e.Socket=n(36)},function(t,e,n){\"use strict\";function r(t,e){var n=t;e=e||\"undefined\"!=typeof location&&location,null==t&&(t=e.protocol+\"//\"+e.host),\"string\"==typeof t&&(\"/\"===t.charAt(0)&&(t=\"/\"===t.charAt(1)?e.protocol+t:e.host+t),/^(https?|wss?):\\/\\//.test(t)||(i(\"protocol-less url %s\",t),t=\"undefined\"!=typeof e?e.protocol+\"//\"+t:\"https://\"+t),i(\"parse %s\",t),n=o(t)),n.port||(/^(http|ws)$/.test(n.protocol)?n.port=\"80\":/^(http|ws)s$/.test(n.protocol)&&(n.port=\"443\")),n.path=n.path||\"/\";var r=n.host.indexOf(\":\")!==-1,s=r?\"[\"+n.host+\"]\":n.host;return n.id=n.protocol+\"://\"+s+\":\"+n.port,n.href=n.protocol+\"://\"+s+(e&&e.port===n.port?\"\":\":\"+n.port),n}var o=n(2),i=n(3)(\"socket.io-client:url\");t.exports=r},function(t,e){var n=/^(?:(?![^:@]+:[^:@\\/]*@)(http|https|ws|wss):\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/,r=[\"source\",\"protocol\",\"authority\",\"userInfo\",\"user\",\"password\",\"host\",\"port\",\"relative\",\"path\",\"directory\",\"file\",\"query\",\"anchor\"];t.exports=function(t){var e=t,o=t.indexOf(\"[\"),i=t.indexOf(\"]\");o!=-1&&i!=-1&&(t=t.substring(0,o)+t.substring(o,i).replace(/:/g,\";\")+t.substring(i,t.length));for(var s=n.exec(t||\"\"),a={},c=14;c--;)a[r[c]]=s[c]||\"\";return o!=-1&&i!=-1&&(a.source=e,a.host=a.host.substring(1,a.host.length-1).replace(/;/g,\":\"),a.authority=a.authority.replace(\"[\",\"\").replace(\"]\",\"\").replace(/;/g,\":\"),a.ipv6uri=!0),a}},function(t,e,n){(function(r){function o(){return!(\"undefined\"==typeof window||!window.process||\"renderer\"!==window.process.type)||(\"undefined\"==typeof navigator||!navigator.userAgent||!navigator.userAgent.toLowerCase().match(/(edge|trident)\\/(\\d+)/))&&(\"undefined\"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||\"undefined\"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||\"undefined\"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/)&&parseInt(RegExp.$1,10)>=31||\"undefined\"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\\/(\\d+)/))}function i(t){var n=this.useColors;if(t[0]=(n?\"%c\":\"\")+this.namespace+(n?\" %c\":\" \")+t[0]+(n?\"%c \":\" \")+\"+\"+e.humanize(this.diff),n){var r=\"color: \"+this.color;t.splice(1,0,r,\"color: inherit\");var o=0,i=0;t[0].replace(/%[a-zA-Z%]/g,function(t){\"%%\"!==t&&(o++,\"%c\"===t&&(i=o))}),t.splice(i,0,r)}}function s(){return\"object\"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function a(t){try{null==t?e.storage.removeItem(\"debug\"):e.storage.debug=t}catch(n){}}function c(){var t;try{t=e.storage.debug}catch(n){}return!t&&\"undefined\"!=typeof r&&\"env\"in r&&(t=r.env.DEBUG),t}function p(){try{return window.localStorage}catch(t){}}e=t.exports=n(5),e.log=s,e.formatArgs=i,e.save=a,e.load=c,e.useColors=o,e.storage=\"undefined\"!=typeof chrome&&\"undefined\"!=typeof chrome.storage?chrome.storage.local:p(),e.colors=[\"#0000CC\",\"#0000FF\",\"#0033CC\",\"#0033FF\",\"#0066CC\",\"#0066FF\",\"#0099CC\",\"#0099FF\",\"#00CC00\",\"#00CC33\",\"#00CC66\",\"#00CC99\",\"#00CCCC\",\"#00CCFF\",\"#3300CC\",\"#3300FF\",\"#3333CC\",\"#3333FF\",\"#3366CC\",\"#3366FF\",\"#3399CC\",\"#3399FF\",\"#33CC00\",\"#33CC33\",\"#33CC66\",\"#33CC99\",\"#33CCCC\",\"#33CCFF\",\"#6600CC\",\"#6600FF\",\"#6633CC\",\"#6633FF\",\"#66CC00\",\"#66CC33\",\"#9900CC\",\"#9900FF\",\"#9933CC\",\"#9933FF\",\"#99CC00\",\"#99CC33\",\"#CC0000\",\"#CC0033\",\"#CC0066\",\"#CC0099\",\"#CC00CC\",\"#CC00FF\",\"#CC3300\",\"#CC3333\",\"#CC3366\",\"#CC3399\",\"#CC33CC\",\"#CC33FF\",\"#CC6600\",\"#CC6633\",\"#CC9900\",\"#CC9933\",\"#CCCC00\",\"#CCCC33\",\"#FF0000\",\"#FF0033\",\"#FF0066\",\"#FF0099\",\"#FF00CC\",\"#FF00FF\",\"#FF3300\",\"#FF3333\",\"#FF3366\",\"#FF3399\",\"#FF33CC\",\"#FF33FF\",\"#FF6600\",\"#FF6633\",\"#FF9900\",\"#FF9933\",\"#FFCC00\",\"#FFCC33\"],e.formatters.j=function(t){try{return JSON.stringify(t)}catch(e){return\"[UnexpectedJSONParseError]: \"+e.message}},e.enable(c())}).call(e,n(4))},function(t,e){function n(){throw new Error(\"setTimeout has not been defined\")}function r(){throw new Error(\"clearTimeout has not been defined\")}function o(t){if(u===setTimeout)return setTimeout(t,0);if((u===n||!u)&&setTimeout)return u=setTimeout,setTimeout(t,0);try{return u(t,0)}catch(e){try{return u.call(null,t,0)}catch(e){return u.call(this,t,0)}}}function i(t){if(h===clearTimeout)return clearTimeout(t);if((h===r||!h)&&clearTimeout)return h=clearTimeout,clearTimeout(t);try{return h(t)}catch(e){try{return h.call(null,t)}catch(e){return h.call(this,t)}}}function s(){y&&l&&(y=!1,l.length?d=l.concat(d):m=-1,d.length&&a())}function a(){if(!y){var t=o(s);y=!0;for(var e=d.length;e;){for(l=d,d=[];++m<e;)l&&l[m].run();m=-1,e=d.length}l=null,y=!1,i(t)}}function c(t,e){this.fun=t,this.array=e}function p(){}var u,h,f=t.exports={};!function(){try{u=\"function\"==typeof setTimeout?setTimeout:n}catch(t){u=n}try{h=\"function\"==typeof clearTimeout?clearTimeout:r}catch(t){h=r}}();var l,d=[],y=!1,m=-1;f.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];d.push(new c(t,e)),1!==d.length||y||o(a)},c.prototype.run=function(){this.fun.apply(null,this.array)},f.title=\"browser\",f.browser=!0,f.env={},f.argv=[],f.version=\"\",f.versions={},f.on=p,f.addListener=p,f.once=p,f.off=p,f.removeListener=p,f.removeAllListeners=p,f.emit=p,f.prependListener=p,f.prependOnceListener=p,f.listeners=function(t){return[]},f.binding=function(t){throw new Error(\"process.binding is not supported\")},f.cwd=function(){return\"/\"},f.chdir=function(t){throw new Error(\"process.chdir is not supported\")},f.umask=function(){return 0}},function(t,e,n){function r(t){var n,r=0;for(n in t)r=(r<<5)-r+t.charCodeAt(n),r|=0;return e.colors[Math.abs(r)%e.colors.length]}function o(t){function n(){if(n.enabled){var t=n,r=+new Date,i=r-(o||r);t.diff=i,t.prev=o,t.curr=r,o=r;for(var s=new Array(arguments.length),a=0;a<s.length;a++)s[a]=arguments[a];s[0]=e.coerce(s[0]),\"string\"!=typeof s[0]&&s.unshift(\"%O\");var c=0;s[0]=s[0].replace(/%([a-zA-Z%])/g,function(n,r){if(\"%%\"===n)return n;c++;var o=e.formatters[r];if(\"function\"==typeof o){var i=s[c];n=o.call(t,i),s.splice(c,1),c--}return n}),e.formatArgs.call(t,s);var p=n.log||e.log||console.log.bind(console);p.apply(t,s)}}var o;return n.namespace=t,n.enabled=e.enabled(t),n.useColors=e.useColors(),n.color=r(t),n.destroy=i,\"function\"==typeof e.init&&e.init(n),e.instances.push(n),n}function i(){var t=e.instances.indexOf(this);return t!==-1&&(e.instances.splice(t,1),!0)}function s(t){e.save(t),e.names=[],e.skips=[];var n,r=(\"string\"==typeof t?t:\"\").split(/[\\s,]+/),o=r.length;for(n=0;n<o;n++)r[n]&&(t=r[n].replace(/\\*/g,\".*?\"),\"-\"===t[0]?e.skips.push(new RegExp(\"^\"+t.substr(1)+\"$\")):e.names.push(new RegExp(\"^\"+t+\"$\")));for(n=0;n<e.instances.length;n++){var i=e.instances[n];i.enabled=e.enabled(i.namespace)}}function a(){e.enable(\"\")}function c(t){if(\"*\"===t[t.length-1])return!0;var n,r;for(n=0,r=e.skips.length;n<r;n++)if(e.skips[n].test(t))return!1;for(n=0,r=e.names.length;n<r;n++)if(e.names[n].test(t))return!0;return!1}function p(t){return t instanceof Error?t.stack||t.message:t}e=t.exports=o.debug=o[\"default\"]=o,e.coerce=p,e.disable=a,e.enable=s,e.enabled=c,e.humanize=n(6),e.instances=[],e.names=[],e.skips=[],e.formatters={}},function(t,e){function n(t){if(t=String(t),!(t.length>100)){var e=/^((?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(t);if(e){var n=parseFloat(e[1]),r=(e[2]||\"ms\").toLowerCase();switch(r){case\"years\":case\"year\":case\"yrs\":case\"yr\":case\"y\":return n*u;case\"days\":case\"day\":case\"d\":return n*p;case\"hours\":case\"hour\":case\"hrs\":case\"hr\":case\"h\":return n*c;case\"minutes\":case\"minute\":case\"mins\":case\"min\":case\"m\":return n*a;case\"seconds\":case\"second\":case\"secs\":case\"sec\":case\"s\":return n*s;case\"milliseconds\":case\"millisecond\":case\"msecs\":case\"msec\":case\"ms\":return n;default:return}}}}function r(t){return t>=p?Math.round(t/p)+\"d\":t>=c?Math.round(t/c)+\"h\":t>=a?Math.round(t/a)+\"m\":t>=s?Math.round(t/s)+\"s\":t+\"ms\"}function o(t){return i(t,p,\"day\")||i(t,c,\"hour\")||i(t,a,\"minute\")||i(t,s,\"second\")||t+\" ms\"}function i(t,e,n){if(!(t<e))return t<1.5*e?Math.floor(t/e)+\" \"+n:Math.ceil(t/e)+\" \"+n+\"s\"}var s=1e3,a=60*s,c=60*a,p=24*c,u=365.25*p;t.exports=function(t,e){e=e||{};var i=typeof t;if(\"string\"===i&&t.length>0)return n(t);if(\"number\"===i&&isNaN(t)===!1)return e[\"long\"]?o(t):r(t);throw new Error(\"val is not a non-empty string or a valid number. val=\"+JSON.stringify(t))}},function(t,e,n){function r(){}function o(t){var n=\"\"+t.type;if(e.BINARY_EVENT!==t.type&&e.BINARY_ACK!==t.type||(n+=t.attachments+\"-\"),t.nsp&&\"/\"!==t.nsp&&(n+=t.nsp+\",\"),null!=t.id&&(n+=t.id),null!=t.data){var r=i(t.data);if(r===!1)return g;n+=r}return f(\"encoded %j as %s\",t,n),n}function i(t){try{return JSON.stringify(t)}catch(e){return!1}}function s(t,e){function n(t){var n=d.deconstructPacket(t),r=o(n.packet),i=n.buffers;i.unshift(r),e(i)}d.removeBlobs(t,n)}function a(){this.reconstructor=null}function c(t){var n=0,r={type:Number(t.charAt(0))};if(null==e.types[r.type])return h(\"unknown packet type \"+r.type);if(e.BINARY_EVENT===r.type||e.BINARY_ACK===r.type){for(var o=\"\";\"-\"!==t.charAt(++n)&&(o+=t.charAt(n),n!=t.length););if(o!=Number(o)||\"-\"!==t.charAt(n))throw new Error(\"Illegal attachments\");r.attachments=Number(o)}if(\"/\"===t.charAt(n+1))for(r.nsp=\"\";++n;){var i=t.charAt(n);if(\",\"===i)break;if(r.nsp+=i,n===t.length)break}else r.nsp=\"/\";var s=t.charAt(n+1);if(\"\"!==s&&Number(s)==s){for(r.id=\"\";++n;){var i=t.charAt(n);if(null==i||Number(i)!=i){--n;break}if(r.id+=t.charAt(n),n===t.length)break}r.id=Number(r.id)}if(t.charAt(++n)){var a=p(t.substr(n)),c=a!==!1&&(r.type===e.ERROR||y(a));if(!c)return h(\"invalid payload\");r.data=a}return f(\"decoded %s as %j\",t,r),r}function p(t){try{return JSON.parse(t)}catch(e){return!1}}function u(t){this.reconPack=t,this.buffers=[]}function h(t){return{type:e.ERROR,data:\"parser error: \"+t}}var f=n(3)(\"socket.io-parser\"),l=n(8),d=n(9),y=n(10),m=n(11);e.protocol=4,e.types=[\"CONNECT\",\"DISCONNECT\",\"EVENT\",\"ACK\",\"ERROR\",\"BINARY_EVENT\",\"BINARY_ACK\"],e.CONNECT=0,e.DISCONNECT=1,e.EVENT=2,e.ACK=3,e.ERROR=4,e.BINARY_EVENT=5,e.BINARY_ACK=6,e.Encoder=r,e.Decoder=a;var g=e.ERROR+'\"encode error\"';r.prototype.encode=function(t,n){if(f(\"encoding packet %j\",t),e.BINARY_EVENT===t.type||e.BINARY_ACK===t.type)s(t,n);else{var r=o(t);n([r])}},l(a.prototype),a.prototype.add=function(t){var n;if(\"string\"==typeof t)n=c(t),e.BINARY_EVENT===n.type||e.BINARY_ACK===n.type?(this.reconstructor=new u(n),0===this.reconstructor.reconPack.attachments&&this.emit(\"decoded\",n)):this.emit(\"decoded\",n);else{if(!m(t)&&!t.base64)throw new Error(\"Unknown type: \"+t);if(!this.reconstructor)throw new Error(\"got binary data when not reconstructing a packet\");n=this.reconstructor.takeBinaryData(t),n&&(this.reconstructor=null,this.emit(\"decoded\",n))}},a.prototype.destroy=function(){this.reconstructor&&this.reconstructor.finishedReconstruction()},u.prototype.takeBinaryData=function(t){if(this.buffers.push(t),this.buffers.length===this.reconPack.attachments){var e=d.reconstructPacket(this.reconPack,this.buffers);return this.finishedReconstruction(),e}return null},u.prototype.finishedReconstruction=function(){this.reconPack=null,this.buffers=[]}},function(t,e,n){function r(t){if(t)return o(t)}function o(t){for(var e in r.prototype)t[e]=r.prototype[e];return t}t.exports=r,r.prototype.on=r.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks[\"$\"+t]=this._callbacks[\"$\"+t]||[]).push(e),this},r.prototype.once=function(t,e){function n(){this.off(t,n),e.apply(this,arguments)}return n.fn=e,this.on(t,n),this},r.prototype.off=r.prototype.removeListener=r.prototype.removeAllListeners=r.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var n=this._callbacks[\"$\"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks[\"$\"+t],this;for(var r,o=0;o<n.length;o++)if(r=n[o],r===e||r.fn===e){n.splice(o,1);break}return this},r.prototype.emit=function(t){this._callbacks=this._callbacks||{};var e=[].slice.call(arguments,1),n=this._callbacks[\"$\"+t];if(n){n=n.slice(0);for(var r=0,o=n.length;r<o;++r)n[r].apply(this,e)}return this},r.prototype.listeners=function(t){return this._callbacks=this._callbacks||{},this._callbacks[\"$\"+t]||[]},r.prototype.hasListeners=function(t){return!!this.listeners(t).length}},function(t,e,n){function r(t,e){if(!t)return t;if(s(t)){var n={_placeholder:!0,num:e.length};return e.push(t),n}if(i(t)){for(var o=new Array(t.length),a=0;a<t.length;a++)o[a]=r(t[a],e);return o}if(\"object\"==typeof t&&!(t instanceof Date)){var o={};for(var c in t)o[c]=r(t[c],e);return o}return t}function o(t,e){if(!t)return t;if(t&&t._placeholder)return e[t.num];if(i(t))for(var n=0;n<t.length;n++)t[n]=o(t[n],e);else if(\"object\"==typeof t)for(var r in t)t[r]=o(t[r],e);return t}var i=n(10),s=n(11),a=Object.prototype.toString,c=\"function\"==typeof Blob||\"undefined\"!=typeof Blob&&\"[object BlobConstructor]\"===a.call(Blob),p=\"function\"==typeof File||\"undefined\"!=typeof File&&\"[object FileConstructor]\"===a.call(File);e.deconstructPacket=function(t){var e=[],n=t.data,o=t;return o.data=r(n,e),o.attachments=e.length,{packet:o,buffers:e}},e.reconstructPacket=function(t,e){return t.data=o(t.data,e),t.attachments=void 0,t},e.removeBlobs=function(t,e){function n(t,a,u){if(!t)return t;if(c&&t instanceof Blob||p&&t instanceof File){r++;var h=new FileReader;h.onload=function(){u?u[a]=this.result:o=this.result,--r||e(o)},h.readAsArrayBuffer(t)}else if(i(t))for(var f=0;f<t.length;f++)n(t[f],f,t);else if(\"object\"==typeof t&&!s(t))for(var l in t)n(t[l],l,t)}var r=0,o=t;n(o),r||e(o)}},function(t,e){var n={}.toString;t.exports=Array.isArray||function(t){return\"[object Array]\"==n.call(t)}},function(t,e){function n(t){return r&&Buffer.isBuffer(t)||o&&(t instanceof ArrayBuffer||i(t))}t.exports=n;var r=\"function\"==typeof Buffer&&\"function\"==typeof Buffer.isBuffer,o=\"function\"==typeof ArrayBuffer,i=function(t){return\"function\"==typeof ArrayBuffer.isView?ArrayBuffer.isView(t):t.buffer instanceof ArrayBuffer}},function(t,e,n){\"use strict\";function r(t,e){if(!(this instanceof r))return new r(t,e);t&&\"object\"===(\"undefined\"==typeof t?\"undefined\":o(t))&&(e=t,t=void 0),e=e||{},e.path=e.path||\"/socket.io\",this.nsps={},this.subs=[],this.opts=e,this.reconnection(e.reconnection!==!1),this.reconnectionAttempts(e.reconnectionAttempts||1/0),this.reconnectionDelay(e.reconnectionDelay||1e3),this.reconnectionDelayMax(e.reconnectionDelayMax||5e3),this.randomizationFactor(e.randomizationFactor||.5),this.backoff=new l({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()}),this.timeout(null==e.timeout?2e4:e.timeout),this.readyState=\"closed\",this.uri=t,this.connecting=[],this.lastPing=null,this.encoding=!1,this.packetBuffer=[];var n=e.parser||c;this.encoder=new n.Encoder,this.decoder=new n.Decoder,this.autoConnect=e.autoConnect!==!1,this.autoConnect&&this.open()}var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},i=n(13),s=n(36),a=n(8),c=n(7),p=n(38),u=n(39),h=n(3)(\"socket.io-client:manager\"),f=n(35),l=n(40),d=Object.prototype.hasOwnProperty;t.exports=r,r.prototype.emitAll=function(){this.emit.apply(this,arguments);for(var t in this.nsps)d.call(this.nsps,t)&&this.nsps[t].emit.apply(this.nsps[t],arguments)},r.prototype.updateSocketIds=function(){for(var t in this.nsps)d.call(this.nsps,t)&&(this.nsps[t].id=this.generateId(t))},r.prototype.generateId=function(t){return(\"/\"===t?\"\":t+\"#\")+this.engine.id},a(r.prototype),r.prototype.reconnection=function(t){return arguments.length?(this._reconnection=!!t,this):this._reconnection},r.prototype.reconnectionAttempts=function(t){return arguments.length?(this._reconnectionAttempts=t,this):this._reconnectionAttempts},r.prototype.reconnectionDelay=function(t){return arguments.length?(this._reconnectionDelay=t,this.backoff&&this.backoff.setMin(t),this):this._reconnectionDelay},r.prototype.randomizationFactor=function(t){return arguments.length?(this._randomizationFactor=t,this.backoff&&this.backoff.setJitter(t),this):this._randomizationFactor},r.prototype.reconnectionDelayMax=function(t){return arguments.length?(this._reconnectionDelayMax=t,this.backoff&&this.backoff.setMax(t),this):this._reconnectionDelayMax},r.prototype.timeout=function(t){return arguments.length?(this._timeout=t,this):this._timeout},r.prototype.maybeReconnectOnOpen=function(){!this.reconnecting&&this._reconnection&&0===this.backoff.attempts&&this.reconnect()},r.prototype.open=r.prototype.connect=function(t,e){if(h(\"readyState %s\",this.readyState),~this.readyState.indexOf(\"open\"))return this;h(\"opening %s\",this.uri),this.engine=i(this.uri,this.opts);var n=this.engine,r=this;this.readyState=\"opening\",this.skipReconnect=!1;var o=p(n,\"open\",function(){r.onopen(),t&&t()}),s=p(n,\"error\",function(e){if(h(\"connect_error\"),r.cleanup(),r.readyState=\"closed\",r.emitAll(\"connect_error\",e),t){var n=new Error(\"Connection error\");n.data=e,t(n)}else r.maybeReconnectOnOpen()});if(!1!==this._timeout){var a=this._timeout;h(\"connect attempt will timeout after %d\",a);var c=setTimeout(function(){h(\"connect attempt timed out after %d\",a),o.destroy(),n.close(),n.emit(\"error\",\"timeout\"),r.emitAll(\"connect_timeout\",a)},a);this.subs.push({destroy:function(){clearTimeout(c)}})}return this.subs.push(o),this.subs.push(s),this},r.prototype.onopen=function(){h(\"open\"),this.cleanup(),this.readyState=\"open\",this.emit(\"open\");var t=this.engine;this.subs.push(p(t,\"data\",u(this,\"ondata\"))),this.subs.push(p(t,\"ping\",u(this,\"onping\"))),this.subs.push(p(t,\"pong\",u(this,\"onpong\"))),this.subs.push(p(t,\"error\",u(this,\"onerror\"))),this.subs.push(p(t,\"close\",u(this,\"onclose\"))),this.subs.push(p(this.decoder,\"decoded\",u(this,\"ondecoded\")))},r.prototype.onping=function(){this.lastPing=new Date,this.emitAll(\"ping\")},r.prototype.onpong=function(){this.emitAll(\"pong\",new Date-this.lastPing)},r.prototype.ondata=function(t){this.decoder.add(t)},r.prototype.ondecoded=function(t){this.emit(\"packet\",t)},r.prototype.onerror=function(t){h(\"error\",t),this.emitAll(\"error\",t)},r.prototype.socket=function(t,e){function n(){~f(o.connecting,r)||o.connecting.push(r)}var r=this.nsps[t];if(!r){r=new s(this,t,e),this.nsps[t]=r;var o=this;r.on(\"connecting\",n),r.on(\"connect\",function(){r.id=o.generateId(t)}),this.autoConnect&&n()}return r},r.prototype.destroy=function(t){var e=f(this.connecting,t);~e&&this.connecting.splice(e,1),this.connecting.length||this.close()},r.prototype.packet=function(t){h(\"writing packet %j\",t);var e=this;t.query&&0===t.type&&(t.nsp+=\"?\"+t.query),e.encoding?e.packetBuffer.push(t):(e.encoding=!0,this.encoder.encode(t,function(n){for(var r=0;r<n.length;r++)e.engine.write(n[r],t.options);e.encoding=!1,e.processPacketQueue()}))},r.prototype.processPacketQueue=function(){if(this.packetBuffer.length>0&&!this.encoding){var t=this.packetBuffer.shift();this.packet(t)}},r.prototype.cleanup=function(){h(\"cleanup\");for(var t=this.subs.length,e=0;e<t;e++){var n=this.subs.shift();n.destroy()}this.packetBuffer=[],this.encoding=!1,this.lastPing=null,this.decoder.destroy()},r.prototype.close=r.prototype.disconnect=function(){h(\"disconnect\"),this.skipReconnect=!0,this.reconnecting=!1,\"opening\"===this.readyState&&this.cleanup(),this.backoff.reset(),this.readyState=\"closed\",this.engine&&this.engine.close()},r.prototype.onclose=function(t){h(\"onclose\"),this.cleanup(),this.backoff.reset(),this.readyState=\"closed\",this.emit(\"close\",t),this._reconnection&&!this.skipReconnect&&this.reconnect()},r.prototype.reconnect=function(){if(this.reconnecting||this.skipReconnect)return this;var t=this;if(this.backoff.attempts>=this._reconnectionAttempts)h(\"reconnect failed\"),this.backoff.reset(),this.emitAll(\"reconnect_failed\"),this.reconnecting=!1;else{var e=this.backoff.duration();h(\"will wait %dms before reconnect attempt\",e),this.reconnecting=!0;var n=setTimeout(function(){t.skipReconnect||(h(\"attempting reconnect\"),t.emitAll(\"reconnect_attempt\",t.backoff.attempts),t.emitAll(\"reconnecting\",t.backoff.attempts),t.skipReconnect||t.open(function(e){e?(h(\"reconnect attempt error\"),t.reconnecting=!1,t.reconnect(),t.emitAll(\"reconnect_error\",e.data)):(h(\"reconnect success\"),t.onreconnect())}))},e);this.subs.push({destroy:function(){clearTimeout(n)}})}},r.prototype.onreconnect=function(){var t=this.backoff.attempts;this.reconnecting=!1,this.backoff.reset(),this.updateSocketIds(),this.emitAll(\"reconnect\",t)}},function(t,e,n){t.exports=n(14),t.exports.parser=n(21)},function(t,e,n){function r(t,e){return this instanceof r?(e=e||{},t&&\"object\"==typeof t&&(e=t,t=null),t?(t=u(t),e.hostname=t.host,e.secure=\"https\"===t.protocol||\"wss\"===t.protocol,e.port=t.port,t.query&&(e.query=t.query)):e.host&&(e.hostname=u(e.host).host),this.secure=null!=e.secure?e.secure:\"undefined\"!=typeof location&&\"https:\"===location.protocol,e.hostname&&!e.port&&(e.port=this.secure?\"443\":\"80\"),this.agent=e.agent||!1,this.hostname=e.hostname||(\"undefined\"!=typeof location?location.hostname:\"localhost\"),this.port=e.port||(\"undefined\"!=typeof location&&location.port?location.port:this.secure?443:80),this.query=e.query||{},\"string\"==typeof this.query&&(this.query=h.decode(this.query)),this.upgrade=!1!==e.upgrade,this.path=(e.path||\"/engine.io\").replace(/\\/$/,\"\")+\"/\",this.forceJSONP=!!e.forceJSONP,this.jsonp=!1!==e.jsonp,this.forceBase64=!!e.forceBase64,this.enablesXDR=!!e.enablesXDR,this.timestampParam=e.timestampParam||\"t\",this.timestampRequests=e.timestampRequests,this.transports=e.transports||[\"polling\",\"websocket\"],this.transportOptions=e.transportOptions||{},this.readyState=\"\",this.writeBuffer=[],this.prevBufferLen=0,this.policyPort=e.policyPort||843,this.rememberUpgrade=e.rememberUpgrade||!1,this.binaryType=null,this.onlyBinaryUpgrades=e.onlyBinaryUpgrades,this.perMessageDeflate=!1!==e.perMessageDeflate&&(e.perMessageDeflate||{}),!0===this.perMessageDeflate&&(this.perMessageDeflate={}),this.perMessageDeflate&&null==this.perMessageDeflate.threshold&&(this.perMessageDeflate.threshold=1024),this.pfx=e.pfx||null,this.key=e.key||null,this.passphrase=e.passphrase||null,this.cert=e.cert||null,this.ca=e.ca||null,this.ciphers=e.ciphers||null,this.rejectUnauthorized=void 0===e.rejectUnauthorized||e.rejectUnauthorized,this.forceNode=!!e.forceNode,this.isReactNative=\"undefined\"!=typeof navigator&&\"string\"==typeof navigator.product&&\"reactnative\"===navigator.product.toLowerCase(),(\"undefined\"==typeof self||this.isReactNative)&&(e.extraHeaders&&Object.keys(e.extraHeaders).length>0&&(this.extraHeaders=e.extraHeaders),e.localAddress&&(this.localAddress=e.localAddress)),this.id=null,this.upgrades=null,this.pingInterval=null,this.pingTimeout=null,this.pingIntervalTimer=null,this.pingTimeoutTimer=null,void this.open()):new r(t,e)}function o(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}var i=n(15),s=n(8),a=n(3)(\"engine.io-client:socket\"),c=n(35),p=n(21),u=n(2),h=n(29);t.exports=r,r.priorWebsocketSuccess=!1,s(r.prototype),r.protocol=p.protocol,r.Socket=r,r.Transport=n(20),r.transports=n(15),r.parser=n(21),r.prototype.createTransport=function(t){a('creating transport \"%s\"',t);var e=o(this.query);e.EIO=p.protocol,e.transport=t;var n=this.transportOptions[t]||{};this.id&&(e.sid=this.id);var r=new i[t]({query:e,socket:this,agent:n.agent||this.agent,hostname:n.hostname||this.hostname,port:n.port||this.port,secure:n.secure||this.secure,path:n.path||this.path,forceJSONP:n.forceJSONP||this.forceJSONP,jsonp:n.jsonp||this.jsonp,forceBase64:n.forceBase64||this.forceBase64,enablesXDR:n.enablesXDR||this.enablesXDR,timestampRequests:n.timestampRequests||this.timestampRequests,timestampParam:n.timestampParam||this.timestampParam,policyPort:n.policyPort||this.policyPort,pfx:n.pfx||this.pfx,key:n.key||this.key,passphrase:n.passphrase||this.passphrase,cert:n.cert||this.cert,ca:n.ca||this.ca,ciphers:n.ciphers||this.ciphers,rejectUnauthorized:n.rejectUnauthorized||this.rejectUnauthorized,perMessageDeflate:n.perMessageDeflate||this.perMessageDeflate,extraHeaders:n.extraHeaders||this.extraHeaders,forceNode:n.forceNode||this.forceNode,localAddress:n.localAddress||this.localAddress,requestTimeout:n.requestTimeout||this.requestTimeout,protocols:n.protocols||void 0,isReactNative:this.isReactNative});return r},r.prototype.open=function(){var t;if(this.rememberUpgrade&&r.priorWebsocketSuccess&&this.transports.indexOf(\"websocket\")!==-1)t=\"websocket\";else{if(0===this.transports.length){var e=this;return void setTimeout(function(){e.emit(\"error\",\"No transports available\")},0)}t=this.transports[0]}this.readyState=\"opening\";try{t=this.createTransport(t)}catch(n){return this.transports.shift(),void this.open()}t.open(),this.setTransport(t)},r.prototype.setTransport=function(t){a(\"setting transport %s\",t.name);var e=this;this.transport&&(a(\"clearing existing transport %s\",this.transport.name),this.transport.removeAllListeners()),this.transport=t,t.on(\"drain\",function(){e.onDrain()}).on(\"packet\",function(t){e.onPacket(t)}).on(\"error\",function(t){e.onError(t)}).on(\"close\",function(){e.onClose(\"transport close\")})},r.prototype.probe=function(t){function e(){if(f.onlyBinaryUpgrades){var e=!this.supportsBinary&&f.transport.supportsBinary;h=h||e}h||(a('probe transport \"%s\" opened',t),u.send([{type:\"ping\",data:\"probe\"}]),u.once(\"packet\",function(e){if(!h)if(\"pong\"===e.type&&\"probe\"===e.data){if(a('probe transport \"%s\" pong',t),f.upgrading=!0,f.emit(\"upgrading\",u),!u)return;r.priorWebsocketSuccess=\"websocket\"===u.name,a('pausing current transport \"%s\"',f.transport.name),f.transport.pause(function(){h||\"closed\"!==f.readyState&&(a(\"changing transport and sending upgrade packet\"),p(),f.setTransport(u),u.send([{type:\"upgrade\"}]),f.emit(\"upgrade\",u),u=null,f.upgrading=!1,f.flush())})}else{a('probe transport \"%s\" failed',t);var n=new Error(\"probe error\");n.transport=u.name,f.emit(\"upgradeError\",n)}}))}function n(){h||(h=!0,p(),u.close(),u=null)}function o(e){var r=new Error(\"probe error: \"+e);r.transport=u.name,n(),a('probe transport \"%s\" failed because of error: %s',t,e),f.emit(\"upgradeError\",r)}function i(){o(\"transport closed\")}function s(){o(\"socket closed\")}function c(t){u&&t.name!==u.name&&(a('\"%s\" works - aborting \"%s\"',t.name,u.name),n())}function p(){u.removeListener(\"open\",e),u.removeListener(\"error\",o),u.removeListener(\"close\",i),f.removeListener(\"close\",s),f.removeListener(\"upgrading\",c)}a('probing transport \"%s\"',t);var u=this.createTransport(t,{probe:1}),h=!1,f=this;r.priorWebsocketSuccess=!1,u.once(\"open\",e),u.once(\"error\",o),u.once(\"close\",i),this.once(\"close\",s),this.once(\"upgrading\",c),u.open()},r.prototype.onOpen=function(){if(a(\"socket open\"),this.readyState=\"open\",r.priorWebsocketSuccess=\"websocket\"===this.transport.name,this.emit(\"open\"),this.flush(),\"open\"===this.readyState&&this.upgrade&&this.transport.pause){a(\"starting upgrade probes\");for(var t=0,e=this.upgrades.length;t<e;t++)this.probe(this.upgrades[t])}},r.prototype.onPacket=function(t){if(\"opening\"===this.readyState||\"open\"===this.readyState||\"closing\"===this.readyState)switch(a('socket receive: type \"%s\", data \"%s\"',t.type,t.data),this.emit(\"packet\",t),this.emit(\"heartbeat\"),t.type){case\"open\":this.onHandshake(JSON.parse(t.data));break;case\"pong\":this.setPing(),this.emit(\"pong\");break;case\"error\":var e=new Error(\"server error\");e.code=t.data,this.onError(e);break;case\"message\":this.emit(\"data\",t.data),this.emit(\"message\",t.data)}else a('packet received with socket readyState \"%s\"',this.readyState)},r.prototype.onHandshake=function(t){this.emit(\"handshake\",t),this.id=t.sid,this.transport.query.sid=t.sid,this.upgrades=this.filterUpgrades(t.upgrades),this.pingInterval=t.pingInterval,this.pingTimeout=t.pingTimeout,this.onOpen(),\"closed\"!==this.readyState&&(this.setPing(),this.removeListener(\"heartbeat\",this.onHeartbeat),this.on(\"heartbeat\",this.onHeartbeat))},r.prototype.onHeartbeat=function(t){clearTimeout(this.pingTimeoutTimer);var e=this;e.pingTimeoutTimer=setTimeout(function(){\"closed\"!==e.readyState&&e.onClose(\"ping timeout\")},t||e.pingInterval+e.pingTimeout)},r.prototype.setPing=function(){var t=this;clearTimeout(t.pingIntervalTimer),t.pingIntervalTimer=setTimeout(function(){a(\"writing ping packet - expecting pong within %sms\",t.pingTimeout),t.ping(),t.onHeartbeat(t.pingTimeout)},t.pingInterval)},r.prototype.ping=function(){var t=this;this.sendPacket(\"ping\",function(){t.emit(\"ping\")})},r.prototype.onDrain=function(){this.writeBuffer.splice(0,this.prevBufferLen),this.prevBufferLen=0,0===this.writeBuffer.length?this.emit(\"drain\"):this.flush()},r.prototype.flush=function(){\"closed\"!==this.readyState&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length&&(a(\"flushing %d packets in socket\",this.writeBuffer.length),this.transport.send(this.writeBuffer),this.prevBufferLen=this.writeBuffer.length,this.emit(\"flush\"))},r.prototype.write=r.prototype.send=function(t,e,n){return this.sendPacket(\"message\",t,e,n),this},r.prototype.sendPacket=function(t,e,n,r){if(\"function\"==typeof e&&(r=e,e=void 0),\"function\"==typeof n&&(r=n,n=null),\"closing\"!==this.readyState&&\"closed\"!==this.readyState){n=n||{},n.compress=!1!==n.compress;var o={type:t,data:e,options:n};this.emit(\"packetCreate\",o),this.writeBuffer.push(o),r&&this.once(\"flush\",r),this.flush()}},r.prototype.close=function(){function t(){r.onClose(\"forced close\"),a(\"socket closing - telling transport to close\"),r.transport.close()}function e(){r.removeListener(\"upgrade\",e),r.removeListener(\"upgradeError\",e),t()}function n(){r.once(\"upgrade\",e),r.once(\"upgradeError\",e)}if(\"opening\"===this.readyState||\"open\"===this.readyState){this.readyState=\"closing\";var r=this;this.writeBuffer.length?this.once(\"drain\",function(){this.upgrading?n():t()}):this.upgrading?n():t()}return this},r.prototype.onError=function(t){a(\"socket error %j\",t),r.priorWebsocketSuccess=!1,this.emit(\"error\",t),this.onClose(\"transport error\",t)},r.prototype.onClose=function(t,e){if(\"opening\"===this.readyState||\"open\"===this.readyState||\"closing\"===this.readyState){a('socket close with reason: \"%s\"',t);var n=this;clearTimeout(this.pingIntervalTimer),clearTimeout(this.pingTimeoutTimer),this.transport.removeAllListeners(\"close\"),this.transport.close(),this.transport.removeAllListeners(),this.readyState=\"closed\",this.id=null,this.emit(\"close\",t,e),n.writeBuffer=[],n.prevBufferLen=0}},r.prototype.filterUpgrades=function(t){for(var e=[],n=0,r=t.length;n<r;n++)~c(this.transports,t[n])&&e.push(t[n]);return e}},function(t,e,n){function r(t){var e,n=!1,r=!1,a=!1!==t.jsonp;\nif(\"undefined\"!=typeof location){var c=\"https:\"===location.protocol,p=location.port;p||(p=c?443:80),n=t.hostname!==location.hostname||p!==t.port,r=t.secure!==c}if(t.xdomain=n,t.xscheme=r,e=new o(t),\"open\"in e&&!t.forceJSONP)return new i(t);if(!a)throw new Error(\"JSONP disabled\");return new s(t)}var o=n(16),i=n(18),s=n(32),a=n(33);e.polling=r,e.websocket=a},function(t,e,n){var r=n(17);t.exports=function(t){var e=t.xdomain,n=t.xscheme,o=t.enablesXDR;try{if(\"undefined\"!=typeof XMLHttpRequest&&(!e||r))return new XMLHttpRequest}catch(i){}try{if(\"undefined\"!=typeof XDomainRequest&&!n&&o)return new XDomainRequest}catch(i){}if(!e)try{return new(self[[\"Active\"].concat(\"Object\").join(\"X\")])(\"Microsoft.XMLHTTP\")}catch(i){}}},function(t,e){try{t.exports=\"undefined\"!=typeof XMLHttpRequest&&\"withCredentials\"in new XMLHttpRequest}catch(n){t.exports=!1}},function(t,e,n){function r(){}function o(t){if(c.call(this,t),this.requestTimeout=t.requestTimeout,this.extraHeaders=t.extraHeaders,\"undefined\"!=typeof location){var e=\"https:\"===location.protocol,n=location.port;n||(n=e?443:80),this.xd=\"undefined\"!=typeof location&&t.hostname!==location.hostname||n!==t.port,this.xs=t.secure!==e}}function i(t){this.method=t.method||\"GET\",this.uri=t.uri,this.xd=!!t.xd,this.xs=!!t.xs,this.async=!1!==t.async,this.data=void 0!==t.data?t.data:null,this.agent=t.agent,this.isBinary=t.isBinary,this.supportsBinary=t.supportsBinary,this.enablesXDR=t.enablesXDR,this.requestTimeout=t.requestTimeout,this.pfx=t.pfx,this.key=t.key,this.passphrase=t.passphrase,this.cert=t.cert,this.ca=t.ca,this.ciphers=t.ciphers,this.rejectUnauthorized=t.rejectUnauthorized,this.extraHeaders=t.extraHeaders,this.create()}function s(){for(var t in i.requests)i.requests.hasOwnProperty(t)&&i.requests[t].abort()}var a=n(16),c=n(19),p=n(8),u=n(30),h=n(3)(\"engine.io-client:polling-xhr\");if(t.exports=o,t.exports.Request=i,u(o,c),o.prototype.supportsBinary=!0,o.prototype.request=function(t){return t=t||{},t.uri=this.uri(),t.xd=this.xd,t.xs=this.xs,t.agent=this.agent||!1,t.supportsBinary=this.supportsBinary,t.enablesXDR=this.enablesXDR,t.pfx=this.pfx,t.key=this.key,t.passphrase=this.passphrase,t.cert=this.cert,t.ca=this.ca,t.ciphers=this.ciphers,t.rejectUnauthorized=this.rejectUnauthorized,t.requestTimeout=this.requestTimeout,t.extraHeaders=this.extraHeaders,new i(t)},o.prototype.doWrite=function(t,e){var n=\"string\"!=typeof t&&void 0!==t,r=this.request({method:\"POST\",data:t,isBinary:n}),o=this;r.on(\"success\",e),r.on(\"error\",function(t){o.onError(\"xhr post error\",t)}),this.sendXhr=r},o.prototype.doPoll=function(){h(\"xhr poll\");var t=this.request(),e=this;t.on(\"data\",function(t){e.onData(t)}),t.on(\"error\",function(t){e.onError(\"xhr poll error\",t)}),this.pollXhr=t},p(i.prototype),i.prototype.create=function(){var t={agent:this.agent,xdomain:this.xd,xscheme:this.xs,enablesXDR:this.enablesXDR};t.pfx=this.pfx,t.key=this.key,t.passphrase=this.passphrase,t.cert=this.cert,t.ca=this.ca,t.ciphers=this.ciphers,t.rejectUnauthorized=this.rejectUnauthorized;var e=this.xhr=new a(t),n=this;try{h(\"xhr open %s: %s\",this.method,this.uri),e.open(this.method,this.uri,this.async);try{if(this.extraHeaders){e.setDisableHeaderCheck&&e.setDisableHeaderCheck(!0);for(var r in this.extraHeaders)this.extraHeaders.hasOwnProperty(r)&&e.setRequestHeader(r,this.extraHeaders[r])}}catch(o){}if(\"POST\"===this.method)try{this.isBinary?e.setRequestHeader(\"Content-type\",\"application/octet-stream\"):e.setRequestHeader(\"Content-type\",\"text/plain;charset=UTF-8\")}catch(o){}try{e.setRequestHeader(\"Accept\",\"*/*\")}catch(o){}\"withCredentials\"in e&&(e.withCredentials=!0),this.requestTimeout&&(e.timeout=this.requestTimeout),this.hasXDR()?(e.onload=function(){n.onLoad()},e.onerror=function(){n.onError(e.responseText)}):e.onreadystatechange=function(){if(2===e.readyState)try{var t=e.getResponseHeader(\"Content-Type\");n.supportsBinary&&\"application/octet-stream\"===t&&(e.responseType=\"arraybuffer\")}catch(r){}4===e.readyState&&(200===e.status||1223===e.status?n.onLoad():setTimeout(function(){n.onError(e.status)},0))},h(\"xhr data %s\",this.data),e.send(this.data)}catch(o){return void setTimeout(function(){n.onError(o)},0)}\"undefined\"!=typeof document&&(this.index=i.requestsCount++,i.requests[this.index]=this)},i.prototype.onSuccess=function(){this.emit(\"success\"),this.cleanup()},i.prototype.onData=function(t){this.emit(\"data\",t),this.onSuccess()},i.prototype.onError=function(t){this.emit(\"error\",t),this.cleanup(!0)},i.prototype.cleanup=function(t){if(\"undefined\"!=typeof this.xhr&&null!==this.xhr){if(this.hasXDR()?this.xhr.onload=this.xhr.onerror=r:this.xhr.onreadystatechange=r,t)try{this.xhr.abort()}catch(e){}\"undefined\"!=typeof document&&delete i.requests[this.index],this.xhr=null}},i.prototype.onLoad=function(){var t;try{var e;try{e=this.xhr.getResponseHeader(\"Content-Type\")}catch(n){}t=\"application/octet-stream\"===e?this.xhr.response||this.xhr.responseText:this.xhr.responseText}catch(n){this.onError(n)}null!=t&&this.onData(t)},i.prototype.hasXDR=function(){return\"undefined\"!=typeof XDomainRequest&&!this.xs&&this.enablesXDR},i.prototype.abort=function(){this.cleanup()},i.requestsCount=0,i.requests={},\"undefined\"!=typeof document)if(\"function\"==typeof attachEvent)attachEvent(\"onunload\",s);else if(\"function\"==typeof addEventListener){var f=\"onpagehide\"in self?\"pagehide\":\"unload\";addEventListener(f,s,!1)}},function(t,e,n){function r(t){var e=t&&t.forceBase64;u&&!e||(this.supportsBinary=!1),o.call(this,t)}var o=n(20),i=n(29),s=n(21),a=n(30),c=n(31),p=n(3)(\"engine.io-client:polling\");t.exports=r;var u=function(){var t=n(16),e=new t({xdomain:!1});return null!=e.responseType}();a(r,o),r.prototype.name=\"polling\",r.prototype.doOpen=function(){this.poll()},r.prototype.pause=function(t){function e(){p(\"paused\"),n.readyState=\"paused\",t()}var n=this;if(this.readyState=\"pausing\",this.polling||!this.writable){var r=0;this.polling&&(p(\"we are currently polling - waiting to pause\"),r++,this.once(\"pollComplete\",function(){p(\"pre-pause polling complete\"),--r||e()})),this.writable||(p(\"we are currently writing - waiting to pause\"),r++,this.once(\"drain\",function(){p(\"pre-pause writing complete\"),--r||e()}))}else e()},r.prototype.poll=function(){p(\"polling\"),this.polling=!0,this.doPoll(),this.emit(\"poll\")},r.prototype.onData=function(t){var e=this;p(\"polling got data %s\",t);var n=function(t,n,r){return\"opening\"===e.readyState&&e.onOpen(),\"close\"===t.type?(e.onClose(),!1):void e.onPacket(t)};s.decodePayload(t,this.socket.binaryType,n),\"closed\"!==this.readyState&&(this.polling=!1,this.emit(\"pollComplete\"),\"open\"===this.readyState?this.poll():p('ignoring poll - transport state \"%s\"',this.readyState))},r.prototype.doClose=function(){function t(){p(\"writing close packet\"),e.write([{type:\"close\"}])}var e=this;\"open\"===this.readyState?(p(\"transport open - closing\"),t()):(p(\"transport not open - deferring close\"),this.once(\"open\",t))},r.prototype.write=function(t){var e=this;this.writable=!1;var n=function(){e.writable=!0,e.emit(\"drain\")};s.encodePayload(t,this.supportsBinary,function(t){e.doWrite(t,n)})},r.prototype.uri=function(){var t=this.query||{},e=this.secure?\"https\":\"http\",n=\"\";!1!==this.timestampRequests&&(t[this.timestampParam]=c()),this.supportsBinary||t.sid||(t.b64=1),t=i.encode(t),this.port&&(\"https\"===e&&443!==Number(this.port)||\"http\"===e&&80!==Number(this.port))&&(n=\":\"+this.port),t.length&&(t=\"?\"+t);var r=this.hostname.indexOf(\":\")!==-1;return e+\"://\"+(r?\"[\"+this.hostname+\"]\":this.hostname)+n+this.path+t}},function(t,e,n){function r(t){this.path=t.path,this.hostname=t.hostname,this.port=t.port,this.secure=t.secure,this.query=t.query,this.timestampParam=t.timestampParam,this.timestampRequests=t.timestampRequests,this.readyState=\"\",this.agent=t.agent||!1,this.socket=t.socket,this.enablesXDR=t.enablesXDR,this.pfx=t.pfx,this.key=t.key,this.passphrase=t.passphrase,this.cert=t.cert,this.ca=t.ca,this.ciphers=t.ciphers,this.rejectUnauthorized=t.rejectUnauthorized,this.forceNode=t.forceNode,this.isReactNative=t.isReactNative,this.extraHeaders=t.extraHeaders,this.localAddress=t.localAddress}var o=n(21),i=n(8);t.exports=r,i(r.prototype),r.prototype.onError=function(t,e){var n=new Error(t);return n.type=\"TransportError\",n.description=e,this.emit(\"error\",n),this},r.prototype.open=function(){return\"closed\"!==this.readyState&&\"\"!==this.readyState||(this.readyState=\"opening\",this.doOpen()),this},r.prototype.close=function(){return\"opening\"!==this.readyState&&\"open\"!==this.readyState||(this.doClose(),this.onClose()),this},r.prototype.send=function(t){if(\"open\"!==this.readyState)throw new Error(\"Transport not open\");this.write(t)},r.prototype.onOpen=function(){this.readyState=\"open\",this.writable=!0,this.emit(\"open\")},r.prototype.onData=function(t){var e=o.decodePacket(t,this.socket.binaryType);this.onPacket(e)},r.prototype.onPacket=function(t){this.emit(\"packet\",t)},r.prototype.onClose=function(){this.readyState=\"closed\",this.emit(\"close\")}},function(t,e,n){function r(t,n){var r=\"b\"+e.packets[t.type]+t.data.data;return n(r)}function o(t,n,r){if(!n)return e.encodeBase64Packet(t,r);var o=t.data,i=new Uint8Array(o),s=new Uint8Array(1+o.byteLength);s[0]=v[t.type];for(var a=0;a<i.length;a++)s[a+1]=i[a];return r(s.buffer)}function i(t,n,r){if(!n)return e.encodeBase64Packet(t,r);var o=new FileReader;return o.onload=function(){e.encodePacket({type:t.type,data:o.result},n,!0,r)},o.readAsArrayBuffer(t.data)}function s(t,n,r){if(!n)return e.encodeBase64Packet(t,r);if(g)return i(t,n,r);var o=new Uint8Array(1);o[0]=v[t.type];var s=new k([o.buffer,t.data]);return r(s)}function a(t){try{t=d.decode(t,{strict:!1})}catch(e){return!1}return t}function c(t,e,n){for(var r=new Array(t.length),o=l(t.length,n),i=function(t,n,o){e(n,function(e,n){r[t]=n,o(e,r)})},s=0;s<t.length;s++)i(s,t[s],o)}var p,u=n(22),h=n(23),f=n(24),l=n(25),d=n(26);\"undefined\"!=typeof ArrayBuffer&&(p=n(27));var y=\"undefined\"!=typeof navigator&&/Android/i.test(navigator.userAgent),m=\"undefined\"!=typeof navigator&&/PhantomJS/i.test(navigator.userAgent),g=y||m;e.protocol=3;var v=e.packets={open:0,close:1,ping:2,pong:3,message:4,upgrade:5,noop:6},b=u(v),w={type:\"error\",data:\"parser error\"},k=n(28);e.encodePacket=function(t,e,n,i){\"function\"==typeof e&&(i=e,e=!1),\"function\"==typeof n&&(i=n,n=null);var a=void 0===t.data?void 0:t.data.buffer||t.data;if(\"undefined\"!=typeof ArrayBuffer&&a instanceof ArrayBuffer)return o(t,e,i);if(\"undefined\"!=typeof k&&a instanceof k)return s(t,e,i);if(a&&a.base64)return r(t,i);var c=v[t.type];return void 0!==t.data&&(c+=n?d.encode(String(t.data),{strict:!1}):String(t.data)),i(\"\"+c)},e.encodeBase64Packet=function(t,n){var r=\"b\"+e.packets[t.type];if(\"undefined\"!=typeof k&&t.data instanceof k){var o=new FileReader;return o.onload=function(){var t=o.result.split(\",\")[1];n(r+t)},o.readAsDataURL(t.data)}var i;try{i=String.fromCharCode.apply(null,new Uint8Array(t.data))}catch(s){for(var a=new Uint8Array(t.data),c=new Array(a.length),p=0;p<a.length;p++)c[p]=a[p];i=String.fromCharCode.apply(null,c)}return r+=btoa(i),n(r)},e.decodePacket=function(t,n,r){if(void 0===t)return w;if(\"string\"==typeof t){if(\"b\"===t.charAt(0))return e.decodeBase64Packet(t.substr(1),n);if(r&&(t=a(t),t===!1))return w;var o=t.charAt(0);return Number(o)==o&&b[o]?t.length>1?{type:b[o],data:t.substring(1)}:{type:b[o]}:w}var i=new Uint8Array(t),o=i[0],s=f(t,1);return k&&\"blob\"===n&&(s=new k([s])),{type:b[o],data:s}},e.decodeBase64Packet=function(t,e){var n=b[t.charAt(0)];if(!p)return{type:n,data:{base64:!0,data:t.substr(1)}};var r=p.decode(t.substr(1));return\"blob\"===e&&k&&(r=new k([r])),{type:n,data:r}},e.encodePayload=function(t,n,r){function o(t){return t.length+\":\"+t}function i(t,r){e.encodePacket(t,!!s&&n,!1,function(t){r(null,o(t))})}\"function\"==typeof n&&(r=n,n=null);var s=h(t);return n&&s?k&&!g?e.encodePayloadAsBlob(t,r):e.encodePayloadAsArrayBuffer(t,r):t.length?void c(t,i,function(t,e){return r(e.join(\"\"))}):r(\"0:\")},e.decodePayload=function(t,n,r){if(\"string\"!=typeof t)return e.decodePayloadAsBinary(t,n,r);\"function\"==typeof n&&(r=n,n=null);var o;if(\"\"===t)return r(w,0,1);for(var i,s,a=\"\",c=0,p=t.length;c<p;c++){var u=t.charAt(c);if(\":\"===u){if(\"\"===a||a!=(i=Number(a)))return r(w,0,1);if(s=t.substr(c+1,i),a!=s.length)return r(w,0,1);if(s.length){if(o=e.decodePacket(s,n,!1),w.type===o.type&&w.data===o.data)return r(w,0,1);var h=r(o,c+i,p);if(!1===h)return}c+=i,a=\"\"}else a+=u}return\"\"!==a?r(w,0,1):void 0},e.encodePayloadAsArrayBuffer=function(t,n){function r(t,n){e.encodePacket(t,!0,!0,function(t){return n(null,t)})}return t.length?void c(t,r,function(t,e){var r=e.reduce(function(t,e){var n;return n=\"string\"==typeof e?e.length:e.byteLength,t+n.toString().length+n+2},0),o=new Uint8Array(r),i=0;return e.forEach(function(t){var e=\"string\"==typeof t,n=t;if(e){for(var r=new Uint8Array(t.length),s=0;s<t.length;s++)r[s]=t.charCodeAt(s);n=r.buffer}e?o[i++]=0:o[i++]=1;for(var a=n.byteLength.toString(),s=0;s<a.length;s++)o[i++]=parseInt(a[s]);o[i++]=255;for(var r=new Uint8Array(n),s=0;s<r.length;s++)o[i++]=r[s]}),n(o.buffer)}):n(new ArrayBuffer(0))},e.encodePayloadAsBlob=function(t,n){function r(t,n){e.encodePacket(t,!0,!0,function(t){var e=new Uint8Array(1);if(e[0]=1,\"string\"==typeof t){for(var r=new Uint8Array(t.length),o=0;o<t.length;o++)r[o]=t.charCodeAt(o);t=r.buffer,e[0]=0}for(var i=t instanceof ArrayBuffer?t.byteLength:t.size,s=i.toString(),a=new Uint8Array(s.length+1),o=0;o<s.length;o++)a[o]=parseInt(s[o]);if(a[s.length]=255,k){var c=new k([e.buffer,a.buffer,t]);n(null,c)}})}c(t,r,function(t,e){return n(new k(e))})},e.decodePayloadAsBinary=function(t,n,r){\"function\"==typeof n&&(r=n,n=null);for(var o=t,i=[];o.byteLength>0;){for(var s=new Uint8Array(o),a=0===s[0],c=\"\",p=1;255!==s[p];p++){if(c.length>310)return r(w,0,1);c+=s[p]}o=f(o,2+c.length),c=parseInt(c);var u=f(o,0,c);if(a)try{u=String.fromCharCode.apply(null,new Uint8Array(u))}catch(h){var l=new Uint8Array(u);u=\"\";for(var p=0;p<l.length;p++)u+=String.fromCharCode(l[p])}i.push(u),o=f(o,c)}var d=i.length;i.forEach(function(t,o){r(e.decodePacket(t,n,!0),o,d)})}},function(t,e){t.exports=Object.keys||function(t){var e=[],n=Object.prototype.hasOwnProperty;for(var r in t)n.call(t,r)&&e.push(r);return e}},function(t,e,n){function r(t){if(!t||\"object\"!=typeof t)return!1;if(o(t)){for(var e=0,n=t.length;e<n;e++)if(r(t[e]))return!0;return!1}if(\"function\"==typeof Buffer&&Buffer.isBuffer&&Buffer.isBuffer(t)||\"function\"==typeof ArrayBuffer&&t instanceof ArrayBuffer||s&&t instanceof Blob||a&&t instanceof File)return!0;if(t.toJSON&&\"function\"==typeof t.toJSON&&1===arguments.length)return r(t.toJSON(),!0);for(var i in t)if(Object.prototype.hasOwnProperty.call(t,i)&&r(t[i]))return!0;return!1}var o=n(10),i=Object.prototype.toString,s=\"function\"==typeof Blob||\"undefined\"!=typeof Blob&&\"[object BlobConstructor]\"===i.call(Blob),a=\"function\"==typeof File||\"undefined\"!=typeof File&&\"[object FileConstructor]\"===i.call(File);t.exports=r},function(t,e){t.exports=function(t,e,n){var r=t.byteLength;if(e=e||0,n=n||r,t.slice)return t.slice(e,n);if(e<0&&(e+=r),n<0&&(n+=r),n>r&&(n=r),e>=r||e>=n||0===r)return new ArrayBuffer(0);for(var o=new Uint8Array(t),i=new Uint8Array(n-e),s=e,a=0;s<n;s++,a++)i[a]=o[s];return i.buffer}},function(t,e){function n(t,e,n){function o(t,r){if(o.count<=0)throw new Error(\"after called too many times\");--o.count,t?(i=!0,e(t),e=n):0!==o.count||i||e(null,r)}var i=!1;return n=n||r,o.count=t,0===t?e():o}function r(){}t.exports=n},function(t,e){function n(t){for(var e,n,r=[],o=0,i=t.length;o<i;)e=t.charCodeAt(o++),e>=55296&&e<=56319&&o<i?(n=t.charCodeAt(o++),56320==(64512&n)?r.push(((1023&e)<<10)+(1023&n)+65536):(r.push(e),o--)):r.push(e);return r}function r(t){for(var e,n=t.length,r=-1,o=\"\";++r<n;)e=t[r],e>65535&&(e-=65536,o+=d(e>>>10&1023|55296),e=56320|1023&e),o+=d(e);return o}function o(t,e){if(t>=55296&&t<=57343){if(e)throw Error(\"Lone surrogate U+\"+t.toString(16).toUpperCase()+\" is not a scalar value\");return!1}return!0}function i(t,e){return d(t>>e&63|128)}function s(t,e){if(0==(4294967168&t))return d(t);var n=\"\";return 0==(4294965248&t)?n=d(t>>6&31|192):0==(4294901760&t)?(o(t,e)||(t=65533),n=d(t>>12&15|224),n+=i(t,6)):0==(4292870144&t)&&(n=d(t>>18&7|240),n+=i(t,12),n+=i(t,6)),n+=d(63&t|128)}function a(t,e){e=e||{};for(var r,o=!1!==e.strict,i=n(t),a=i.length,c=-1,p=\"\";++c<a;)r=i[c],p+=s(r,o);return p}function c(){if(l>=f)throw Error(\"Invalid byte index\");var t=255&h[l];if(l++,128==(192&t))return 63&t;throw Error(\"Invalid continuation byte\")}function p(t){var e,n,r,i,s;if(l>f)throw Error(\"Invalid byte index\");if(l==f)return!1;if(e=255&h[l],l++,0==(128&e))return e;if(192==(224&e)){if(n=c(),s=(31&e)<<6|n,s>=128)return s;throw Error(\"Invalid continuation byte\")}if(224==(240&e)){if(n=c(),r=c(),s=(15&e)<<12|n<<6|r,s>=2048)return o(s,t)?s:65533;throw Error(\"Invalid continuation byte\")}if(240==(248&e)&&(n=c(),r=c(),i=c(),s=(7&e)<<18|n<<12|r<<6|i,s>=65536&&s<=1114111))return s;throw Error(\"Invalid UTF-8 detected\")}function u(t,e){e=e||{};var o=!1!==e.strict;h=n(t),f=h.length,l=0;for(var i,s=[];(i=p(o))!==!1;)s.push(i);return r(s)}/*! https://mths.be/utf8js v2.1.2 by @mathias */\nvar h,f,l,d=String.fromCharCode;t.exports={version:\"2.1.2\",encode:a,decode:u}},function(t,e){!function(){\"use strict\";for(var t=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",n=new Uint8Array(256),r=0;r<t.length;r++)n[t.charCodeAt(r)]=r;e.encode=function(e){var n,r=new Uint8Array(e),o=r.length,i=\"\";for(n=0;n<o;n+=3)i+=t[r[n]>>2],i+=t[(3&r[n])<<4|r[n+1]>>4],i+=t[(15&r[n+1])<<2|r[n+2]>>6],i+=t[63&r[n+2]];return o%3===2?i=i.substring(0,i.length-1)+\"=\":o%3===1&&(i=i.substring(0,i.length-2)+\"==\"),i},e.decode=function(t){var e,r,o,i,s,a=.75*t.length,c=t.length,p=0;\"=\"===t[t.length-1]&&(a--,\"=\"===t[t.length-2]&&a--);var u=new ArrayBuffer(a),h=new Uint8Array(u);for(e=0;e<c;e+=4)r=n[t.charCodeAt(e)],o=n[t.charCodeAt(e+1)],i=n[t.charCodeAt(e+2)],s=n[t.charCodeAt(e+3)],h[p++]=r<<2|o>>4,h[p++]=(15&o)<<4|i>>2,h[p++]=(3&i)<<6|63&s;return u}}()},function(t,e){function n(t){return t.map(function(t){if(t.buffer instanceof ArrayBuffer){var e=t.buffer;if(t.byteLength!==e.byteLength){var n=new Uint8Array(t.byteLength);n.set(new Uint8Array(e,t.byteOffset,t.byteLength)),e=n.buffer}return e}return t})}function r(t,e){e=e||{};var r=new i;return n(t).forEach(function(t){r.append(t)}),e.type?r.getBlob(e.type):r.getBlob()}function o(t,e){return new Blob(n(t),e||{})}var i=\"undefined\"!=typeof i?i:\"undefined\"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:\"undefined\"!=typeof MSBlobBuilder?MSBlobBuilder:\"undefined\"!=typeof MozBlobBuilder&&MozBlobBuilder,s=function(){try{var t=new Blob([\"hi\"]);return 2===t.size}catch(e){return!1}}(),a=s&&function(){try{var t=new Blob([new Uint8Array([1,2])]);return 2===t.size}catch(e){return!1}}(),c=i&&i.prototype.append&&i.prototype.getBlob;\"undefined\"!=typeof Blob&&(r.prototype=Blob.prototype,o.prototype=Blob.prototype),t.exports=function(){return s?a?Blob:o:c?r:void 0}()},function(t,e){e.encode=function(t){var e=\"\";for(var n in t)t.hasOwnProperty(n)&&(e.length&&(e+=\"&\"),e+=encodeURIComponent(n)+\"=\"+encodeURIComponent(t[n]));return e},e.decode=function(t){for(var e={},n=t.split(\"&\"),r=0,o=n.length;r<o;r++){var i=n[r].split(\"=\");e[decodeURIComponent(i[0])]=decodeURIComponent(i[1])}return e}},function(t,e){t.exports=function(t,e){var n=function(){};n.prototype=e.prototype,t.prototype=new n,t.prototype.constructor=t}},function(t,e){\"use strict\";function n(t){var e=\"\";do e=s[t%a]+e,t=Math.floor(t/a);while(t>0);return e}function r(t){var e=0;for(u=0;u<t.length;u++)e=e*a+c[t.charAt(u)];return e}function o(){var t=n(+new Date);return t!==i?(p=0,i=t):t+\".\"+n(p++)}for(var i,s=\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_\".split(\"\"),a=64,c={},p=0,u=0;u<a;u++)c[s[u]]=u;o.encode=n,o.decode=r,t.exports=o},function(t,e,n){(function(e){function r(){}function o(){return\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:\"undefined\"!=typeof e?e:{}}function i(t){if(s.call(this,t),this.query=this.query||{},!c){var e=o();c=e.___eio=e.___eio||[]}this.index=c.length;var n=this;c.push(function(t){n.onData(t)}),this.query.j=this.index,\"function\"==typeof addEventListener&&addEventListener(\"beforeunload\",function(){n.script&&(n.script.onerror=r)},!1)}var s=n(19),a=n(30);t.exports=i;var c,p=/\\n/g,u=/\\\\n/g;a(i,s),i.prototype.supportsBinary=!1,i.prototype.doClose=function(){this.script&&(this.script.parentNode.removeChild(this.script),this.script=null),this.form&&(this.form.parentNode.removeChild(this.form),this.form=null,this.iframe=null),s.prototype.doClose.call(this)},i.prototype.doPoll=function(){var t=this,e=document.createElement(\"script\");this.script&&(this.script.parentNode.removeChild(this.script),this.script=null),e.async=!0,e.src=this.uri(),e.onerror=function(e){t.onError(\"jsonp poll error\",e)};var n=document.getElementsByTagName(\"script\")[0];n?n.parentNode.insertBefore(e,n):(document.head||document.body).appendChild(e),this.script=e;var r=\"undefined\"!=typeof navigator&&/gecko/i.test(navigator.userAgent);r&&setTimeout(function(){var t=document.createElement(\"iframe\");document.body.appendChild(t),document.body.removeChild(t)},100)},i.prototype.doWrite=function(t,e){function n(){r(),e()}function r(){if(o.iframe)try{o.form.removeChild(o.iframe)}catch(t){o.onError(\"jsonp polling iframe removal error\",t)}try{var e='<iframe src=\"javascript:0\" name=\"'+o.iframeId+'\">';i=document.createElement(e)}catch(t){i=document.createElement(\"iframe\"),i.name=o.iframeId,i.src=\"javascript:0\"}i.id=o.iframeId,o.form.appendChild(i),o.iframe=i}var o=this;if(!this.form){var i,s=document.createElement(\"form\"),a=document.createElement(\"textarea\"),c=this.iframeId=\"eio_iframe_\"+this.index;s.className=\"socketio\",s.style.position=\"absolute\",s.style.top=\"-1000px\",s.style.left=\"-1000px\",s.target=c,s.method=\"POST\",s.setAttribute(\"accept-charset\",\"utf-8\"),a.name=\"d\",s.appendChild(a),document.body.appendChild(s),this.form=s,this.area=a}this.form.action=this.uri(),r(),t=t.replace(u,\"\\\\\\n\"),this.area.value=t.replace(p,\"\\\\n\");try{this.form.submit()}catch(h){}this.iframe.attachEvent?this.iframe.onreadystatechange=function(){\"complete\"===o.iframe.readyState&&n()}:this.iframe.onload=n}}).call(e,function(){return this}())},function(t,e,n){function r(t){var e=t&&t.forceBase64;e&&(this.supportsBinary=!1),this.perMessageDeflate=t.perMessageDeflate,this.usingBrowserWebSocket=o&&!t.forceNode,this.protocols=t.protocols,this.usingBrowserWebSocket||(l=i),s.call(this,t)}var o,i,s=n(20),a=n(21),c=n(29),p=n(30),u=n(31),h=n(3)(\"engine.io-client:websocket\");if(\"undefined\"==typeof self)try{i=n(34)}catch(f){}else o=self.WebSocket||self.MozWebSocket;var l=o||i;t.exports=r,p(r,s),r.prototype.name=\"websocket\",r.prototype.supportsBinary=!0,r.prototype.doOpen=function(){if(this.check()){var t=this.uri(),e=this.protocols,n={agent:this.agent,perMessageDeflate:this.perMessageDeflate};n.pfx=this.pfx,n.key=this.key,n.passphrase=this.passphrase,n.cert=this.cert,n.ca=this.ca,n.ciphers=this.ciphers,n.rejectUnauthorized=this.rejectUnauthorized,this.extraHeaders&&(n.headers=this.extraHeaders),this.localAddress&&(n.localAddress=this.localAddress);try{this.ws=this.usingBrowserWebSocket&&!this.isReactNative?e?new l(t,e):new l(t):new l(t,e,n)}catch(r){return this.emit(\"error\",r)}void 0===this.ws.binaryType&&(this.supportsBinary=!1),this.ws.supports&&this.ws.supports.binary?(this.supportsBinary=!0,this.ws.binaryType=\"nodebuffer\"):this.ws.binaryType=\"arraybuffer\",this.addEventListeners()}},r.prototype.addEventListeners=function(){var t=this;this.ws.onopen=function(){t.onOpen()},this.ws.onclose=function(){t.onClose()},this.ws.onmessage=function(e){t.onData(e.data)},this.ws.onerror=function(e){t.onError(\"websocket error\",e)}},r.prototype.write=function(t){function e(){n.emit(\"flush\"),setTimeout(function(){n.writable=!0,n.emit(\"drain\")},0)}var n=this;this.writable=!1;for(var r=t.length,o=0,i=r;o<i;o++)!function(t){a.encodePacket(t,n.supportsBinary,function(o){if(!n.usingBrowserWebSocket){var i={};if(t.options&&(i.compress=t.options.compress),n.perMessageDeflate){var s=\"string\"==typeof o?Buffer.byteLength(o):o.length;s<n.perMessageDeflate.threshold&&(i.compress=!1)}}try{n.usingBrowserWebSocket?n.ws.send(o):n.ws.send(o,i)}catch(a){h(\"websocket closed before onclose event\")}--r||e()})}(t[o])},r.prototype.onClose=function(){s.prototype.onClose.call(this)},r.prototype.doClose=function(){\"undefined\"!=typeof this.ws&&this.ws.close()},r.prototype.uri=function(){var t=this.query||{},e=this.secure?\"wss\":\"ws\",n=\"\";this.port&&(\"wss\"===e&&443!==Number(this.port)||\"ws\"===e&&80!==Number(this.port))&&(n=\":\"+this.port),this.timestampRequests&&(t[this.timestampParam]=u()),this.supportsBinary||(t.b64=1),t=c.encode(t),t.length&&(t=\"?\"+t);var r=this.hostname.indexOf(\":\")!==-1;return e+\"://\"+(r?\"[\"+this.hostname+\"]\":this.hostname)+n+this.path+t},r.prototype.check=function(){return!(!l||\"__initialize\"in l&&this.name===r.prototype.name)}},function(t,e){},function(t,e){var n=[].indexOf;t.exports=function(t,e){if(n)return t.indexOf(e);for(var r=0;r<t.length;++r)if(t[r]===e)return r;return-1}},function(t,e,n){\"use strict\";function r(t,e,n){this.io=t,this.nsp=e,this.json=this,this.ids=0,this.acks={},this.receiveBuffer=[],this.sendBuffer=[],this.connected=!1,this.disconnected=!0,this.flags={},n&&n.query&&(this.query=n.query),this.io.autoConnect&&this.open()}var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},i=n(7),s=n(8),a=n(37),c=n(38),p=n(39),u=n(3)(\"socket.io-client:socket\"),h=n(29),f=n(23);t.exports=e=r;var l={connect:1,connect_error:1,connect_timeout:1,connecting:1,disconnect:1,error:1,reconnect:1,reconnect_attempt:1,reconnect_failed:1,reconnect_error:1,reconnecting:1,ping:1,pong:1},d=s.prototype.emit;s(r.prototype),r.prototype.subEvents=function(){if(!this.subs){var t=this.io;this.subs=[c(t,\"open\",p(this,\"onopen\")),c(t,\"packet\",p(this,\"onpacket\")),c(t,\"close\",p(this,\"onclose\"))]}},r.prototype.open=r.prototype.connect=function(){return this.connected?this:(this.subEvents(),this.io.open(),\"open\"===this.io.readyState&&this.onopen(),this.emit(\"connecting\"),this)},r.prototype.send=function(){var t=a(arguments);return t.unshift(\"message\"),this.emit.apply(this,t),this},r.prototype.emit=function(t){if(l.hasOwnProperty(t))return d.apply(this,arguments),this;var e=a(arguments),n={type:(void 0!==this.flags.binary?this.flags.binary:f(e))?i.BINARY_EVENT:i.EVENT,data:e};return n.options={},n.options.compress=!this.flags||!1!==this.flags.compress,\"function\"==typeof e[e.length-1]&&(u(\"emitting packet with ack id %d\",this.ids),this.acks[this.ids]=e.pop(),n.id=this.ids++),this.connected?this.packet(n):this.sendBuffer.push(n),this.flags={},this},r.prototype.packet=function(t){t.nsp=this.nsp,this.io.packet(t)},r.prototype.onopen=function(){if(u(\"transport is open - connecting\"),\"/\"!==this.nsp)if(this.query){var t=\"object\"===o(this.query)?h.encode(this.query):this.query;u(\"sending connect packet with query %s\",t),this.packet({type:i.CONNECT,query:t})}else this.packet({type:i.CONNECT})},r.prototype.onclose=function(t){u(\"close (%s)\",t),this.connected=!1,this.disconnected=!0,delete this.id,this.emit(\"disconnect\",t)},r.prototype.onpacket=function(t){var e=t.nsp===this.nsp,n=t.type===i.ERROR&&\"/\"===t.nsp;if(e||n)switch(t.type){case i.CONNECT:this.onconnect();break;case i.EVENT:this.onevent(t);break;case i.BINARY_EVENT:this.onevent(t);break;case i.ACK:this.onack(t);break;case i.BINARY_ACK:this.onack(t);break;case i.DISCONNECT:this.ondisconnect();break;case i.ERROR:this.emit(\"error\",t.data)}},r.prototype.onevent=function(t){var e=t.data||[];u(\"emitting event %j\",e),null!=t.id&&(u(\"attaching ack callback to event\"),e.push(this.ack(t.id))),this.connected?d.apply(this,e):this.receiveBuffer.push(e)},r.prototype.ack=function(t){var e=this,n=!1;return function(){if(!n){n=!0;var r=a(arguments);u(\"sending ack %j\",r),e.packet({type:f(r)?i.BINARY_ACK:i.ACK,id:t,data:r})}}},r.prototype.onack=function(t){var e=this.acks[t.id];\"function\"==typeof e?(u(\"calling ack %s with %j\",t.id,t.data),e.apply(this,t.data),delete this.acks[t.id]):u(\"bad ack %s\",t.id)},r.prototype.onconnect=function(){this.connected=!0,this.disconnected=!1,this.emit(\"connect\"),this.emitBuffered()},r.prototype.emitBuffered=function(){var t;for(t=0;t<this.receiveBuffer.length;t++)d.apply(this,this.receiveBuffer[t]);for(this.receiveBuffer=[],t=0;t<this.sendBuffer.length;t++)this.packet(this.sendBuffer[t]);this.sendBuffer=[]},r.prototype.ondisconnect=function(){u(\"server disconnect (%s)\",this.nsp),this.destroy(),this.onclose(\"io server disconnect\")},r.prototype.destroy=function(){if(this.subs){for(var t=0;t<this.subs.length;t++)this.subs[t].destroy();this.subs=null}this.io.destroy(this)},r.prototype.close=r.prototype.disconnect=function(){return this.connected&&(u(\"performing disconnect (%s)\",this.nsp),this.packet({type:i.DISCONNECT})),this.destroy(),this.connected&&this.onclose(\"io client disconnect\"),this},r.prototype.compress=function(t){return this.flags.compress=t,this},r.prototype.binary=function(t){return this.flags.binary=t,this}},function(t,e){function n(t,e){var n=[];e=e||0;for(var r=e||0;r<t.length;r++)n[r-e]=t[r];return n}t.exports=n},function(t,e){\"use strict\";function n(t,e,n){return t.on(e,n),{destroy:function(){t.removeListener(e,n)}}}t.exports=n},function(t,e){var n=[].slice;t.exports=function(t,e){if(\"string\"==typeof e&&(e=t[e]),\"function\"!=typeof e)throw new Error(\"bind() requires a function\");var r=n.call(arguments,2);return function(){return e.apply(t,r.concat(n.call(arguments)))}}},function(t,e){function n(t){t=t||{},this.ms=t.min||100,this.max=t.max||1e4,this.factor=t.factor||2,this.jitter=t.jitter>0&&t.jitter<=1?t.jitter:0,this.attempts=0}t.exports=n,n.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),n=Math.floor(e*this.jitter*t);t=0==(1&Math.floor(10*e))?t-n:t+n}return 0|Math.min(t,this.max)},n.prototype.reset=function(){this.attempts=0},n.prototype.setMin=function(t){this.ms=t},n.prototype.setMax=function(t){this.max=t},n.prototype.setJitter=function(t){this.jitter=t}}])});\n//# sourceMappingURL=socket.io.js.map"
  },
  {
    "path": "game_resources/js/plugins/Nasty_Text_Pop_Events.js",
    "content": "//=============================================================================\n// Nasty Text Pop Over Event\n// Version: 1.2.1 - Added default offset x and y positioning in options\n// Version: 1.2.0\n//=============================================================================\nvar Imported = Imported || {};\nImported.Nasty_Event_Text_Pop = true;\n\nvar Nasty = Nasty || {};\n//=============================================================================\n /*:\n * @plugindesc Make text over events, players and followers!\n *<Nasty_Text_Pop_Over_Events>\n * @author Nelderson\n *\n * @param Font Size 1\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 1\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 1\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 1\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 1\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 1\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 1\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 1\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 1\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 2\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 2\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 2\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 2\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 2\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 2\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 2\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 2\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 2\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 3\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 3\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 3\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 3\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 3\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 3\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 3\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 3\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 3\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 4\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 4\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 4\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 4\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 4\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 4\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 4\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 4\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 4\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 5\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 5\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 5\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 5\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 5\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 5\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 5\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 5\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 5\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 6\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 6\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 6\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 6\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 6\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 6\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 6\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 6\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 6\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 7\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 7\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 7\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 7\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 7\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 7\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 7\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 7\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 7\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 8\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 8\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 8\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 8\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 8\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 8\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 8\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 8\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 8\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 9\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 9\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 9\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 9\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 9\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 9\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 9\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 9\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 9\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @param Font Size 10\n * @desc USize of the font to be displayed.\n * @default 28\n *\n * @param Font Color 10\n * @desc Color of the font\n * @default #ffffff\n *\n * @param Outline Size 10\n * @desc Size of the outline from the text\n * @default 4\n *\n * @param Outline Color 10\n * @desc Color of the outline on text.\n * @default rgba(0, 0, 0, 0.5)\n *\n * @param Font Name 10\n * @desc Name of the font you want to use.\n * @default GameFont\n *\n * @param Font italic? 10\n * @desc Do you want Italic font?\n * @default false\n *\n * @param Time 10\n * @desc Time before text disappers.  Set to 0 for eternal.\n * @default 120\n *\n * @param Offset_X 10\n * @desc Default offset x for text.\n * @default 0\n *\n * @param Offset_Y 10\n * @desc Default offset y for text.\n * @default 0\n *\n *@param =============\n *\n * @help\n * ============================================================================\n * Introduction and Instructions\n * ============================================================================\n *\n * Want to make events on the map say something, but the message box crimps\n * your style by pausing everything else going on?  Then NASTY Text Pop\n * might be the answer for you!\n *\n * You can call the text with the Plugin command:\n *\n * NastyTextPop ID# template# #ofFrames String of text here\n *\n *   -ID#\n *    0 = The event using the command\n *    1-9999 = Event number on the map.\n *   -1 = Your player\n *   -2 = Follower 1\n *   -3 = Follower 2\n *   -4 = Follower 3\n *\n *  -Template#\n *   This number coreponds to the plugin manager numbers for text size\n *   font name, outline width, etc.\n *\n *  -#ofFrames\n *   Number of frames before the text disappers. 60 frames in a second\n *   Putting a 0 will hold the text there until the map is refreshed.\n *\n *  -String of text here\n *   Place any text after the first 3 arguments, and it will all show\n *   on the specified EventID, Player or Follower.\n *\n * Ex.  NastyTextPop -1 1 120 Tesing This!\n *\n *  This would show \"Testing This!\" over the Player for 120\n *  frames and use the settings in the first plugin spot.\n *\n * As of Version 1.1.0 you can now use the Script Command:\n *\n *  this.NastyTextPop({\n *     argument1: value\n *     argument2: value\n *     argument3: value\n *     etc..\n *   })\n *\n *  Arguments you can use:\n *\n *  text: \"String Here\" - What you want to pop up.\n *\n *  id: Number -\n*     0 = The event using the command\n *    1-9999 = Event number on the map.\n *   -1 = Your player\n *   -2 = Follower 1\n *   -3 = Follower 2\n *   -4 = Follower 3\n *\n *  template: Number - Template setup in plugin manager.\n *\n *  windowOpacity: Number - Opacity of window.  0 is default.\n *\n *  time: Number - Frames before text erases.  0 until map refreshes.\n *\n *  font: 'FontName' - Change font\n *\n *  fontsize: Number - Size of the font.\n *\n *  fontcolor: 'String' - Color of text\n *\n *  outlineColor: 'String' - Color of Outline text\n *\n *  outlineWidth: Number - Outline width\n *\n *  italic: true/false - Italic font?\n *\n *  width: Number - Offset of Window width\n *\n *  height: Number - Offset of Window height\n *\n *  x: Number - Offset of x\n *\n *  y: Number - Offset of y\n *\n *  Ex: Place this in script call~\n *\n *     this.NastyTextPop({\n *       time: 0,\n *       italic: true,\n *       windowOpacity: 255,\n *       fontsize: 28,\n *       outlineColor: '#ff2456',\n *       outlineWidth: 6,\n *       width: -600,\n *       height: 100,\n *       text: 'Test This Right? \\n\\\\I[10] \\nThis is kinda cool bruh!\\nTry not to abuse it..',\n *      })\n *\n * HAVE FUN!\n */\n//=============================================================================\n\n//=============================================================================\n// Parameter Variables\n//=============================================================================\nNasty.Event_Text_Pop = Nasty.Event_Text_Pop || {};\n\n(function ($) {\nNasty.Parameters = $plugins.filter(function(p)\n   { return p.description.contains('<Nasty_Text_Pop_Over_Events>');\n   })[0].parameters;\n\nNasty.Param = Nasty.Param || {};\nNasty.Param.TextPop = [];\n\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 1']),\n  namepop_color: String(Nasty.Parameters['Font Color 1']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 1']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 1']),\n  namepop_font: String(Nasty.Parameters['Font Name 1']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 1']),\n  namepop_time: Number(Nasty.Parameters['Time 1']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 1']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 1'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 2']),\n  namepop_color: String(Nasty.Parameters['Font Color 2']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 2']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 2']),\n  namepop_font: String(Nasty.Parameters['Font Name 2']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 2']),\n  namepop_time: Number(Nasty.Parameters['Time 2']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 2']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 2'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 3']),\n  namepop_color: String(Nasty.Parameters['Font Color 3']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 3']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 3']),\n  namepop_font: String(Nasty.Parameters['Font Name 3']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 3']),\n  namepop_time: Number(Nasty.Parameters['Time 3']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 3']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 3'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 4']),\n  namepop_color: String(Nasty.Parameters['Font Color 4']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 4']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 4']),\n  namepop_font: String(Nasty.Parameters['Font Name 4']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 4']),\n  namepop_time: Number(Nasty.Parameters['Time 4']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 4']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 4'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 5']),\n  namepop_color: String(Nasty.Parameters['Font Color 5']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 5']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 5']),\n  namepop_font: String(Nasty.Parameters['Font Name 5']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 5']),\n  namepop_time: Number(Nasty.Parameters['Time 5']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 5']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 5'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 6']),\n  namepop_color: String(Nasty.Parameters['Font Color 6']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 6']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 6']),\n  namepop_font: String(Nasty.Parameters['Font Name 6']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 6']),\n  namepop_time: Number(Nasty.Parameters['Time 6']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 6']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 6'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 7']),\n  namepop_color: String(Nasty.Parameters['Font Color 7']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 7']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 7']),\n  namepop_font: String(Nasty.Parameters['Font Name 7']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 7']),\n  namepop_time: Number(Nasty.Parameters['Time 7']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 7']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 7'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 8']),\n  namepop_color: String(Nasty.Parameters['Font Color 8']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 8']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 8']),\n  namepop_font: String(Nasty.Parameters['Font Name 8']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 8']),\n  namepop_time: Number(Nasty.Parameters['Time 8']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 8']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 8'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 9']),\n  namepop_color: String(Nasty.Parameters['Font Color 9']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 9']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 9']),\n  namepop_font: String(Nasty.Parameters['Font Name 9']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 9']),\n  namepop_time: Number(Nasty.Parameters['Time 9']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 9']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 9'])\n});\nNasty.Param.TextPop.push({\n  namepop_size: Number(Nasty.Parameters['Font Size 10']),\n  namepop_color: String(Nasty.Parameters['Font Color 10']),\n  namepop_outlineWidth: Number(Nasty.Parameters['Outline Size 10']),\n  namepop_outlineColor: String(Nasty.Parameters['Outline Color 10']),\n  namepop_font: String(Nasty.Parameters['Font Name 10']),\n  namepop_ital: String(Nasty.Parameters['Font italic? 10']),\n  namepop_time: Number(Nasty.Parameters['Time 10']),\n  namepop_offsetx: Number(Nasty.Parameters['Offset_X 10']),\n  namepop_offsety: Number(Nasty.Parameters['Offset_Y 10'])\n});\n\n\nvar Nasty_EvText_gme_charcter_init_alias = Game_Character.prototype.initialize;\nGame_Character.prototype.initialize = function() {\n   Nasty_EvText_gme_charcter_init_alias.call(this);\n   this.namepop = \"\";\n   this.namepop_size = 28;\n   this.namepop_color = '#ffffff';\n   this.namepop_outlineColor = 'rgba(0, 0, 0, 0.5)';\n   this.namepop_outlineWidth = 4;\n   this.namepop_time = 0;\n   this.namepop_font = 'GameFont';\n   this.namepop_ital = false;\n   this.windowOpacity = 0;\n   this.namepop_ox = 0;\n   this.namepop_oy = 0;\n   this.namepop_width =  0;\n   this.namepop_height = 0;\n   this.textpop_flag = false; //Shut off switch\n};\n\nGame_Character.prototype.setTextOptions = function(textOption) {\n   var text = Nasty.Param.TextPop[textOption];\n   this.namepop_size = text.namepop_size;\n   this.namepop_color = text.namepop_color;\n   this.namepop_outlineColor = text.namepop_outlineColor;\n   this.namepop_outlineWidth = text.namepop_outlineWidth;\n   this.namepop_time = text.namepop_time;\n   this.namepop_font = text.namepop_font;\n   this.namepop_ital = text.namepop_ital;\n   this.namepop_ox = text.namepop_offsetx;\n   this.namepop_oy = text.namepop_offsety;\n   this.textpop_flag = true;\n};\n\nvar Nasty_evText_chrsprite_init_alias = Sprite_Character.prototype.initialize;\nSprite_Character.prototype.initialize = function(character) {\n  Nasty_evText_chrsprite_init_alias.call(this, character);\n  this.char = character;\n  this.text_timer = 0;\n};\n\nvar Nasty_sprCharacterTxtPop_update_alias = Sprite_Character.prototype.update;\nSprite_Character.prototype.update = function() {\n    Nasty_sprCharacterTxtPop_update_alias.call(this);\n    if (this.text_timer > 0 && this.char.textpop_flag === false){\n      this.text_timer -=1;\n      if (this.text_timer <= 0){\n        this.removeChild(this.namepop_sprite);\n        this.tmer_rat = undefined; //Reset ratio, just to avoid issues\n      }\n      else if (this.text_timer < 60){\n        this.namepop_sprite.contentsOpacity-= 4;\n        this.namepop_sprite.opacity -= 4;\n      }\n    }\n    if (this.char.textpop_flag === true){\n     if (this.namepop === this.char.namepop) return;\n      this.namepop = this.char.namepop;\n      this.removeChild(this.namepop_sprite);\n      this.start_namepop();\n      this.char.textpop_flag = false; //Release from update\n    }\n};\n\nSprite_Character.prototype.start_namepop = function(){\n    if (this.namepop === \"\") return;\n    var b_width = (this.namepop.length * (this.char.namepop_size/2) + 24)+this.char.namepop_width;\n    var b_height = (this.char.namepop_size + 28) + this.char.namepop_height;\n    var x = (0 - b_width/2) + this.char.namepop_ox;\n    var y = (0 - b_height - 48) - this.char.namepop_oy;\n    this.namepop_sprite = new Window_CharacterPop(x,y,b_width,b_height,this.char);\n    this.namepop_sprite.z = 100;\n    this.namepop_sprite.opacity = this.char.windowOpacity;\n    //###Change Font, Font Size, Color, and Time based off Character values##\n    this.namepop_sprite.contents.textColor = this.char.namepop_color;\n    this.namepop_sprite.contents.outlineColor = this.char.namepop_outlineColor;\n    this.namepop_sprite.contents.outlineWidth = this.char.namepop_outlineWidth;\n    this.namepop_sprite.contents.fontSize = this.char.namepop_size;\n    this.namepop_sprite.contents.fontFace  = this.char.namepop_font;\n    this.namepop_sprite.contents.fontItalic = this.char.namepop_ital;\n    this.namepop_sprite.drawTextEx(this.namepop, 0, 0);\n    this.text_timer = this.char.namepop_time;\n    this.namepop_time = this.char.namepop_time;\n    this.namepop_sprite.visible = true;\n    this.addChild(this.namepop_sprite);\n};\n\n  //-----------------------------------------------------------------------------\n  // Window_CharacterPop\n  //\n\n  function Window_CharacterPop() {\n      this.initialize.apply(this, arguments);\n  }\n\n  Window_CharacterPop.prototype = Object.create(Window_Base.prototype);\n  Window_CharacterPop.prototype.constructor = Window_CharacterPop;\n\n  Window_CharacterPop.prototype.initialize = function(x, y, width, height,character) {\n      Window_Base.prototype.initialize.call(this, x, y, width, height);\n      this.character = character;\n  };\n\n  var Nasty_TxtPop_drawTextEx_alias = Window_Base.prototype.drawTextEx;\n  Window_Base.prototype.drawTextEx = function(text, x, y) {\n    //Only run for Window_CharacterPop windows\n    if (this.constructor.name==='Window_CharacterPop'){\n      if (text) {\n          var textState = { index: 0, x: x, y: y, left: x };\n          textState.text = this.convertEscapeCharacters(text);\n          textState.height = this.calcTextHeight(textState, false);\n          while (textState.index < textState.text.length) {\n              this.processCharacter(textState);\n          }\n          return textState.x - x;\n      } else {\n          return 0;\n      }\n    }else {\n      //All other Windows\n      return Nasty_TxtPop_drawTextEx_alias.call(this,text, x, y);\n    }\n  };\n\nvar Nasty_txtpop_standardpadding_alias = Window_Base.prototype.standardPadding;\n  Window_Base.prototype.standardPadding = function() {\n     if (this.constructor.name==='Window_CharacterPop'){\n       return 8;\n     }else{\n      return Nasty_txtpop_standardpadding_alias.call(this);\n    }\n  };\n\n  //=============================================================================\n  // Game_Interpreter - New Plugin Commands\n  //=============================================================================\n\n  var Nasty_TextPopEvents_change_pluginCommand =\n      Game_Interpreter.prototype.pluginCommand;\n\n  Game_Interpreter.prototype.pluginCommand = function(command, args) {\n      Nasty_TextPopEvents_change_pluginCommand.call(this, command, args);\n      if (command.toUpperCase() === 'NASTYTEXTPOP') {\n        var ev_id = args.shift(),\n            template = args.shift()-1,\n            time = args.shift(),\n            textString = (args.join(\" \"));\n            char = this.getCharacter_for_Nasty_Text_Pop(ev_id);\n\n      char.namepop = textString;\n      char.namepop_size = Nasty.Param.TextPop[template].namepop_size;\n      char.namepop_color = Nasty.Param.TextPop[template].namepop_color;\n      char.namepop_outlineColor = Nasty.Param.TextPop[template].namepop_outlineColor;\n      char.namepop_outlineWidth = Nasty.Param.TextPop[template].namepop_outlineWidth;\n      char.namepop_time = time;\n      char.namepop_font = Nasty.Param.TextPop[template].namepop_font;\n      if (Nasty.Param.TextPop[template].namepop_ital==='true') char.namepop_ital = true;\n      char.textpop_flag = true; //Catch in update\n      }\n    };\n\n    var Nasty_txtpop_reset_text_options_alias = Game_Interpreter.prototype.pluginCommand;\n    Game_Interpreter.prototype.pluginCommand = function(command, args) {\n        Nasty_txtpop_reset_text_options_alias.call(this, command, args);\n        if (command.toUpperCase() === 'RESETTEXTOPTIONS') {\n          for (i=0; i<args.length; i++){\n          char = this.getCharacter_for_Nasty_Text_Pop(args[i]);\n          char.namepop = \"\";\n          char.windowOpacity = 0;\n          char.namepop_ox = 0;\n          char.namepop_oy = 0;\n          char.namepop_width = 0;\n          char.namepop_height = 0;\n          char.namepop_ital = false;\n          }\n        }\n      };\n\n  Game_Interpreter.prototype.NastyTextPop = function(data){\n    //Check for data arguments\n    data.text = data.text || \"\";\n    data.id = data.id || 0;\n    data.template = data.template-1 || 0;\n    data.windowOpacity = data.windowOpacity || 0;\n    data.font = data.font || Nasty.Param.TextPop[data.template].namepop_font;\n    data.fontsize = data.fontsize ||  Nasty.Param.TextPop[data.template].namepop_size;\n    data.fontcolor = data.fontcolor || Nasty.Param.TextPop[data.template].namepop_color;\n    data.outlineColor = data.outlineColor || Nasty.Param.TextPop[data.template].namepop_outlineColor;\n    data.outlineWidth = data.outlineWidth || Nasty.Param.TextPop[data.template].namepop_outlineWidth;\n    data.italic = data.italic || Nasty.Param.TextPop[data.template].namepop_ital;\n    data.time = data.time || Nasty.Param.TextPop[data.template].namepop_time;\n    data.width = data.width || 0;\n    data.height = data.height || 0;\n    data.x = data.x || 0;\n    data.y = data.y || 0;\n    //Convert data arguments to Characters\n    char = this.getCharacter_for_Nasty_Text_Pop(data.id);\n    char.namepop = data.text;\n    char.namepop_size = data.fontsize;\n    char.namepop_color = data.fontcolor;\n    char.namepop_outlineColor = data.outlineColor;\n    char.namepop_outlineWidth = data.outlineWidth;\n    char.windowOpacity = data.windowOpacity;\n    char.namepop_time = data.time;\n    char.namepop_ox = data.x;\n    char.namepop_oy = data.y;\n    char.namepop_width = data.width;\n    char.namepop_height = data.height;\n    if (data.italic===true) char.namepop_ital = true;\n    char.namepop_font = data.font;\n    char.textpop_flag = true;\n  };\n\n  Game_Interpreter.prototype.getCharacter_for_Nasty_Text_Pop = function(param){\n    //Similar to Game_Interpreter.character function just added follower logic.\n      if ($gameParty.inBattle()) {\n          return null;\n      } else if (param == -1) {\n          return $gamePlayer;\n      } else if (param < -1) {\n            return $gamePlayer._followers.follower((Math.abs(param)-2));\n      } else if (this.isOnCurrentMap()) {\n          return $gameMap.event(param > 0 ? param : this._eventId);\n      } else {\n          return null;\n      }\n  };\n})(Nasty.Event_Text_Pop);\n"
  },
  {
    "path": "game_resources/js/plugins/Online_Chat.js",
    "content": "var Imported = Imported || {};\nImported.Online_Chat = true;\n\n(function () {\nvar Nasty = Nasty || {};\n//=============================================================================\n// Online Chat\n// Version: 1.0.6 - Fix for crashing while in menu\n// Version: 1.0.5 - Allows for chat to be retained on map transfer/menu/battle\n// Version: 1.0.4 - Add function to enable/disable chat and chat by leader name\n//=============================================================================\n\n//=============================================================================\n /*:\n * @plugindesc Online Chat for Neldersons Online Core\n * <Online_Chat>\n * @author Nelderson\n *\n * @param Chat Key Code\n * @desc Key code to toggle the chat on/off (Default F1 - 112)\n * @default 112\n *\n * @param Chat with Username or Character Name\n * @desc 0=Username 1=Character Name (Leader of party)\n * @default 0\n *\n * @param Input Character limit\n * @desc Limit the amount of characters per message\n * @default 80\n *\n * @param Room Name by Map\n * @desc Change the room name by map that you are on?\n * @default false\n *\n * @param Recall Message Limit\n * @desc Recalls this many messages when switching maps/battles/etc\n * @default 20\n *\n * @param Chat Username Color\n * @desc Color of usernames in chat window\n * @default #c92cac\n *\n * @param Chat Text Color\n * @desc Color of chat text in chat window\n * @default #000000\n *\n * @param Chat Text Window Width\n * @desc Chat Window width\n * @default 800\n *\n * @param Chat Text Window Height\n * @desc Chat Window Height\n * @default 500\n *\n * @param Chat Text Window Offset X\n * @desc Offset X Poisition of Chat Text Window from CENTER\n * @default 0\n *\n * @param Chat Text Window Offset Y\n * @desc Offset Y Poisition of Chat Text Window from CENTER\n * @default 0\n *\n * @param Chat Text Font\n * @desc Font for Chat Text (Defaults to game default)\n * @default\n *\n * @param Chat Text Font Size\n * @desc Font size for Chat Text\n * @default 15\n *\n * @param Chat Text Background Color\n * @desc Background color and transparency for Chat Window\n * @default rgba(255,255,255,0.7)\n *\n * @param Chat Text Background Picture\n * @desc Background Pic from img/pictures folder instead of Background Color\n * @default\n *\n * @param Chat Input Window Width\n * @desc Chat Input Window width\n * @default 600\n *\n * @param Chat Input Window Height\n * @desc Chat Input Window Height\n * @default 40\n *\n * @param Chat Input Window Offset X\n * @desc Offset X Poisition of Chat Input Window from CENTER\n * @default 0\n *\n * @param Chat Input Window Offset Y\n * @desc Offset Y Poisition of Chat Input Window from CENTER\n * @default 564\n *\n * @param Input Text Font\n * @desc Font for Input Text (Defaults to game default)\n * @default\n *\n * @param Input Text Font Size\n * @desc Font size for Input Text\n * @default 15\n *\n * @param Input Text Background Color\n * @desc Background color and transparency for Input Window\n * @default rgba(255,255,255,0.7)\n *\n * @param Input Text Background Picture\n * @desc Background Pic from img/pictures folder instead of Background Color\n * @default\n *\n * @help\n * ============================================================================\n * Introduction and Instructions\n * ============================================================================\n * This plugin allows you to chat with other players.\n *\n * There are two ways to access the chat windows.  Either by plugin\n * command or the Key Code from the parameters(Default F1).\n *\n * The only thing that is overwritten are the defaults for the SPACEBAR\n * and Z key within the Input Keymapper so that they will not interfere\n * with typing in the chat input window\n *\n * =====================\n * ===Plugin Commands===\n * =====================\n *\n * ToggleChat - Turns Chat Windows On/Off\n * SendChatMessage - Sends the message in the chat input window.\n * EnableChat - Enables chat to be opened\n * DisableChat - Disables chat to be opened\n *\n */\n //=============================================================================\n var socket = null;\n var chatHistory = [];\n Nasty.Parameters = $plugins.filter(function(p)\n\t { return p.description.contains('<Online_Chat>');})[0].parameters;\n\n  //Chat text window\n  var textWinWidth = Nasty.Parameters['Chat Text Window Width'];\n  var textWinHeight = Nasty.Parameters['Chat Text Window Height'];\n  var textWinOffsetX = Nasty.Parameters['Chat Text Window Offset X'];\n  var textWinOffsetY = Nasty.Parameters['Chat Text Window Offset Y'];\n  var textWinFont = Nasty.Parameters['Chat Text Font'];\n  var textWinFontSize = Nasty.Parameters['Chat Text Font Size'];\n  var textWinBack = Nasty.Parameters['Chat Text Background Color'];\n  var textWinBackPic = Nasty.Parameters['Chat Text Background Picture'];\n\n  //Chat input window\n  var inputWinWidth = Nasty.Parameters['Chat Input Window Width'];\n  var inputWinHeight = Nasty.Parameters['Chat Input Window Height'];\n  var inputWinOffsetX = Nasty.Parameters['Chat Input Window Offset X'];\n  var inputWinOffsetY = Nasty.Parameters['Chat Input Window Offset Y'];\n  var inputWinFont = Nasty.Parameters['Input Text Font'];\n  var inputWinFontSize = Nasty.Parameters['Input Text Font Size'];\n  var inputWinBack = Nasty.Parameters['Input Text Background Color'];\n  var inputWinBackPic = Nasty.Parameters['Input Text Background Picture'];\n  var inputCharLimit = Nasty.Parameters['Input Character limit'];\n\n  var chatKeyCode = Nasty.Parameters['Chat Key Code'];\n  var chatUserColor = Nasty.Parameters['Chat Username Color'];\n  var chatTextColor = Nasty.Parameters['Chat Text Color'];\n  var roomMapNameFlag = Nasty.Parameters['Room Name by Map'];\n  var NetPlayerChatNameType = Number(Nasty.Parameters['Chat with Username or Character Name']);\n  var recallMessageLimit = Number(Nasty.Parameters['Recall Message Limit']);\n\n  var networkName = '';\n\nvar OnlineMV_ChatSystem_SocketConn_Alias = Game_Network.prototype.connectSocketsAfterLogin;\nGame_Network.prototype.connectSocketsAfterLogin = function(){\n  OnlineMV_ChatSystem_SocketConn_Alias.call(this);\n\n  $gameNetwork.connectSocket('chat','/chat',false);\n  socket = $gameNetwork._socket.chat;\n  Nasty.chatEnabled = true;\n\n  socket.on('MyID',function(data){\n    networkName = data.name;\n\t});\n\n  socket.on('messageServer', function(data){\n    var chat = document.getElementById('txtarea');\n    var message = document.createElement('div');\n    var user = document.createElement('span');\n    var chatText = document.createElement('span');\n    //Combine user/text spans to div container\n    user.style.color = chatUserColor;\n    chatText.style.color = chatTextColor;\n    user.textContent = data.id+ ': ';\n    chatText.textContent = data.message;\n    if (message){\n      message.appendChild(user);\n      message.appendChild(chatText);\n    }\n    chatHistory.push([user, chatText]);\n    //Append to chat text div\n    if (chat) {\n      chat.appendChild(message);\n      chat.scrollTop = chat.scrollHeight;\n    }\n  });\n};\n\n//=============================================================================\n//  GAME CHAT code\n//=============================================================================\n\n  var OnlineChat_createDisplayObj_Scene_Map = Scene_Map.prototype.createDisplayObjects;\n  Scene_Map.prototype.createDisplayObjects = function() {\n    OnlineChat_createDisplayObj_Scene_Map.call(this);\n    this.createChatDOMElements();\n    this.appendChatHistory();\n  };\n\n  Scene_Map.prototype.appendChatHistory = function(){\n  var diff = chatHistory.length - recallMessageLimit;\n  if (diff>0) chatHistory.splice(0,diff);\n  var chat = document.getElementById('txtarea');\n    for (var i=0;i<chatHistory.length;i++){\n      var message = document.createElement('div');\n      message.appendChild(chatHistory[i][0]);\n      message.appendChild(chatHistory[i][1]);\n      chat.appendChild(message);\n    }\n  };\n\n   Scene_Map.prototype.createChatDOMElements = function(){\n     //Chat Bar for Inputing messages\n     this.chatinput = document.createElement('INPUT');\n     this.chatinput.id = 'chatInput';\n     this.chatinput.maxLength = inputCharLimit;\n     this.chatinput.style.fontSize = inputWinFont + 'px';\n     this.chatinput.style.fontStyle = inputWinFont;\n     this.chatinput.style.color = '#ffffff';\n     this.chatinput.style.fontStyle = '';\n     this.chatinput.style.position = 'absolute';\n     this.chatinput.style.textIndent = '15px';\n     this.chatinput.style.zIndex = 100;\n     this.chatinput.placeholder = 'Insert Text Here';\n     this.chatinput.style.color = '#000000';\n     this.chatinput.style.border = 'none';\n     this.chatinput.style.visibility = 'hidden';\n     if (inputWinBackPic===''){\n       this.chatinput.style.background = inputWinBack;\n     }else{\n       this.chatinput.style.backgroundImage = \"url('img/pictures/\"+inputWinBackPic+\".png')\";\n     }\n     //Chat Message area\n     this.txtarea = document.createElement('div');\n     this.txtarea.id = 'txtarea';\n     this.txtarea.style.padding = '15px';\n     this.txtarea.style.fontSize = textWinFontSize + 'px';\n     this.txtarea.style.fontStyle = textWinFont;\n     this.txtarea.style.position = 'absolute';\n     this.txtarea.style.overflowY = 'auto';\n     this.txtarea.style.width = textWinWidth + 'px';\n     this.txtarea.style.height = textWinHeight + 'px';\n     this.txtarea.style.zIndex = 99;\n     this.txtarea.style.visibility = 'hidden';\n     if (textWinBackPic===''){\n       this.txtarea.style.background = textWinBack;\n     }else{\n       this.txtarea.style.backgroundImage = \"url('img/pictures/\"+textWinBackPic+\".png')\";\n     }\n     //Add and adjust both DOM elements\n     document.body.appendChild(this.txtarea);\n     document.body.appendChild(this.chatinput);\n     //--Mobile fix for input--\n     $(\"#chatInput\").tap(function(){$(\"#chatInput\").focus();});\n     //-------------------------\n     Graphics._centerElement(this.chatinput);\n     Graphics._centerElement(this.txtarea);\n     this.chatinput.style.width = inputWinWidth +'px';\n     this.chatinput.style.height = inputWinHeight + 'px';\n     this.chatinput.style.top = inputWinOffsetY +'px';\n     this.chatinput.style.left = inputWinOffsetX +'px';\n     this.txtarea.style.left = textWinOffsetX + 'px';\n     this.txtarea.style.top = textWinOffsetY + 'px';\n\n     var that = this;\n     $(\"#chatInput\").keypress(function(e){\n \t\t\tif (e.which == 13) { //enter\n \t\t\t\tthat.sendChatMessage();\n \t\t\t}\n \t\t});\n   };\n\n   var Online_Chat_SceneMap_isMenuCalled_alias = Scene_Map.prototype.isMenuCalled;\n   Scene_Map.prototype.isMenuCalled = function() {\n    if (document.activeElement===document.getElementById('chatInput')) return false;\n    return Online_Chat_SceneMap_isMenuCalled_alias.call(this);\n   };\n\n   var Online_Chat_SceneMap_ProcessTouch_alias = Scene_Map.prototype.processMapTouch;\n   Scene_Map.prototype.processMapTouch = function() {\n     if (document.activeElement!==document.getElementById('chatInput')){\n       Online_Chat_SceneMap_ProcessTouch_alias.call(this);\n     }\n   };\n\n   var Chat_Online_sceneMap_updtSceneAlias = Scene_Map.prototype.updateScene;\n   Scene_Map.prototype.updateScene = function() {\n     Chat_Online_sceneMap_updtSceneAlias.call(this);\n       if (!SceneManager.isSceneChanging()) {\n           this.updateChat();\n       }\n   };\n\n   Scene_Map.prototype.updateChat = function(){\n     if (document.activeElement===document.getElementById('chatInput')){\n       if (Input.isTriggered('ok')){\n         this.sendChatMessage();\n       }\n     }\n     //Toggle Chat Windows On/Off\n     if (Input.isTriggered('chat')){\n       this.toggleChat();\n     }\n   };\n\n   Scene_Map.prototype.sendChatMessage = function(){\n   if (NetPlayerChatNameType===1) networkName=$gameParty.leader()._name;\n     var value = document.getElementById('chatInput').value;\n     value = value.trim();\n     if (value==='') return;\n     //Emit message to server\n       socket.emit('clientMessage',{\n         id: networkName,\n         message: value\n       });\n     document.getElementById('chatInput').value = '';\n   };\n\n   Scene_Map.prototype.toggleChat = function(){\n     if (!Nasty.chatEnabled) {\n      document.getElementById('txtarea').style.visibility = 'hidden';\n      document.getElementById('chatInput').style.visibility = 'hidden';\n      return;\n     }\n     if (document.getElementById('txtarea').style.visibility ==='hidden'){\n       document.getElementById('txtarea').style.visibility = 'visible';\n       document.getElementById('chatInput').style.visibility = 'visible';\n       $(\"#chatInput\").focus();\n     }else{\n       document.getElementById('txtarea').style.visibility = 'hidden';\n       document.getElementById('chatInput').style.visibility = 'hidden';\n     }\n   };\n\n   var NastySceneMapChat_Terminate = Scene_Map.prototype.terminate;\n   Scene_Map.prototype.terminate = function() {\n       NastySceneMapChat_Terminate.call(this);\n       document.body.removeChild(this.txtarea);\n       document.body.removeChild(this.chatinput);\n   };\n\n   var OnlineChat_gamePlayer_canMoveAlias = Game_Player.prototype.canMove;\n   Game_Player.prototype.canMove = function() {\n     if (document.activeElement===document.getElementById('chatInput')){\n       return false;\n     }\n     return OnlineChat_gamePlayer_canMoveAlias.call(this);\n   };\n\n   var Nel_OnlineChat_pluginCommands_alias = Game_Interpreter.prototype.pluginCommand;\n   Game_Interpreter.prototype.pluginCommand = function(command, args) {\n       Nel_OnlineChat_pluginCommands_alias.call(this, command, args);\n       if (command.toUpperCase() === 'TOGGLECHAT'){\n         if (SceneManager._scene instanceof Scene_Map){\n           SceneManager._scene.toggleChat();\n         }\n       }\n       if (command.toUpperCase() === 'SENDCHATMESSAGE'){\n         if (SceneManager._scene instanceof Scene_Map){\n           SceneManager._scene.sendChatMessage();\n         }\n       }\n       if (command.toUpperCase() === 'ENABLECHAT'){\n          Nasty.chatEnabled = true;\n       }\n       if (command.toUpperCase() === 'DISABLECHAT'){\n          Nasty.chatEnabled = false;\n          if (SceneManager._scene instanceof Scene_Map){\n            SceneManager._scene.toggleChat();\n          }\n       }\n     };\n\n  //Re-Map Input Keys\n  Input.keyMapper[chatKeyCode] = 'chat';\n  Input.keyMapper['90'] = 'none'; // Z\n  Input.keyMapper['32'] = 'none'; // SpaceBar\n})();\n"
  },
  {
    "path": "game_resources/js/plugins/Online_CloudSave.js",
    "content": "/*\nOnline Cloud Save v.0.1.1\n\nTake data from one source and be able to load it on other devices\n\nSign in > Check the Database > Have data? > Load from database\n                                      No > New Game\n\n*/\n(function() {\n\n  var CloudSave_StorageManager_save_alias = StorageManager.save;\n  StorageManager.save = function(savefileId, json) {\n    if (savefileId>0){\n      var data = LZString.compressToBase64(json);\n      $.post($gameNetwork._serverURL+'/cloudsave/savetocloud', {savedata: data});\n    }\n  };\n\n  //Overwrite Save Command in Menu\n  Scene_Menu.prototype.commandSave = function() {\n      DataManager.saveGameWithoutRescue(2);\n      this._commandWindow.processCancel();\n  };\n\n  DataManager.loadGameWithoutRescue = function(savefileId) {\n    if (savefileId >0){\n      var globalInfo = this.loadGlobalInfo();\n      var json = StorageManager.load(savefileId);\n      return true;\n    }\n  };\n\n  StorageManager.load = function(savefileId) {\n    if (savefileId>0){\n    $.get($gameNetwork._serverURL+'/cloudsave/loadfromcloud', function(data){\n      if (data===\"No account\") return; //Loads new game if no data\n       var json = LZString.decompressFromBase64(data);\n       DataManager.createGameObjects();\n       DataManager.extractSaveContents(JsonEx.parse(json));\n    }).fail(function(){\n      window.alert(\"Cloudsave Failed!\");\n    });\n    }\n  };\n\n  var CloudSave_GameNetwork_ConnectafterLogin = Game_Network.prototype.connectSocketsAfterLogin;\n  Game_Network.prototype.connectSocketsAfterLogin = function(socket) {\n    CloudSave_GameNetwork_ConnectafterLogin.call(this,socket);\n    //Set header so that token is passed correctly to the server\n    $.ajaxSetup({\n      headers: {\n        'x-access-token': $gameNetwork._token\n      }\n    });\n    DataManager.loadGameWithoutRescue(2);\n  };\n})();\n"
  },
  {
    "path": "game_resources/js/plugins/Online_GlobalVars.js",
    "content": "//=============================================================================\n// Online Global Variables and Switches\n// Version: 0.2 - Add parameters for non global switches and variables\n// Version: 0.1 - Send switch and variable data to all clients connected\n//=============================================================================\n\n//=============================================================================\n /*:\n * @plugindesc Send switch and variable data to others.\n *<Online_GlobalVars>\n * @author Nelderson\n *\n * @param Global Switch Threshold\n * @desc Any switch below this number will be global.\n * @default 100\n *\n * @param Global Variable Threshold\n * @desc Any variable below this number will be global.\n * @default 100\n *\n * @help\n * ============================================================================\n * Introduction and Instructions\n * ============================================================================\n * This plugin allows you to send variable and switch data to others in\n * the same server/room.\n *\n * There are 2 basic configurations:\n *\n * Global Switch Threshold and Global Variable Threshold\n *\n * These allow you to define where global variables/switches\n * end and where normal variables/switches happen\n *\n * Ex. Global Switch Threshold of 100\n *\n * Anything below and including 100 is a global switch,\n * and anything above is a normal switch\n *\n */\n //=============================================================================\n\n(function () {\n\n  var GlobalVar_PParameters = $plugins.filter(function(p)\n     { return p.description.contains('<Online_GlobalVars>');})[0].parameters;\n\n  var switchThreshold = Number(GlobalVar_PParameters['Global Switch Threshold']);\n  var variableThreshold = Number(GlobalVar_PParameters['Global Variable Threshold']);\n  var socket=null;\n\n  var OnlineMV_GlobalVars_SocketConn_Alias = Game_Network.prototype.connectSocketsAfterLogin;\n  Game_Network.prototype.connectSocketsAfterLogin = function(){\n    OnlineMV_GlobalVars_SocketConn_Alias.call(this);\n    $gameNetwork.connectSocket('globalvar','/globalvar');\n    //Emitters and Listeners\n    //emit/broadcast and on\n    socket = $gameNetwork._socket.globalvar;\n\n    socket.on('receivedSwitch', function(data){\n      //Do something with received data\n      $gameSwitches.setNetworkValue(data.switch, data.value);\n    });\n\n    socket.on('receivedVariable', function(data){\n      //Do something with received data\n      $gameVariables.setNetworkValue(data.variable, data.value);\n    });\n\n  };\n\n  var Online_GlobalSwitch_setVal = Game_Switches.prototype.setValue;\n  Game_Switches.prototype.setValue = function(switchId, value) {\n    if (switchId>0 && switchId<$dataSystem.switches.length && switchId<=switchThreshold) {\n      //Send data to server!\n      socket.emit('switchDatatoServer',{\n        switch: switchId,\n        value: value\n      });\n    }\n    Online_GlobalSwitch_setVal.call(this,switchId, value);\n  };\n\n  Game_Switches.prototype.setNetworkValue = function(switchId, value) {\n      if (switchId > 0 && switchId < $dataSystem.switches.length) {\n          this._data[switchId] = value;\n          this.onChange();\n      }\n  };\n\n  var Online_GlobalVariable_setVal = Game_Variables.prototype.setValue;\n  Game_Variables.prototype.setValue = function(variableId, value) {\n    if (variableId>0 && variableId<$dataSystem.variables.length && variableId<=variableThreshold) {\n      socket.emit('variableDatatoServer',{\n        variable: variableId,\n        value: value\n      });\n    }\n    Online_GlobalVariable_setVal.call(this, variableId, value);\n  };\n\n  Game_Variables.prototype.setNetworkValue = function(variableId, value) {\n      if (variableId > 0 && variableId < $dataSystem.variables.length) {\n          if (typeof value === 'number') {\n              value = Math.floor(value);\n          }\n          this._data[variableId] = value;\n          this.onChange();\n      }\n  };\n\n})();\n"
  },
  {
    "path": "game_resources/js/plugins/Online_Login_Core.js",
    "content": "var Imported = Imported || {};\nImported.Online_Login_Core = true;\n\n(function () {\n\tvar Nasty = Nasty || {};\n//=============================================================================\n// Online Login Core\n// Version: 1.1.6 - Added logic to use localstorage to auto login\n// Version: 1.1.5 - Added Password Reset Logic\n// Version: 1.1.4 - Added event switches for when users login multiple times\n// Version: 1.1.3\n//=============================================================================\n\n//=============================================================================\n /*:\n * @plugindesc Login window for Neldersons Online Core\n *<Online_Login_Core>\n * @author Nelderson and SirMcPotato/Vinxce\n *\n * @param Force Login on Startup\n * @desc Make the title screen into a login screen\n * @default true\n *\n * @param socket.io connection\n * @desc Automatically connects to socket once signed in.\n * @default true\n *\n * @param Switch on First Shutdown\n * @desc Original user that is logged in will have this switch flipped\n * @default 1\n *\n * @param Switch on Second Shutdown\n * @desc Second user that is logged in will have this switch flipped\n * @default 2\n *\n * @help\n * ============================================================================\n * Introduction and Instructions\n * ============================================================================\n * You can use the login window in two ways.\n *\n *  1.  Set Force login on Startup parameter to true:\n *      This will force the login screen on startup.\n *\n *  2.  Set Force login on Startup parameter to false:\n *      You can use this plugin command to pop up the\n *      login window at any point in your game:\n *\n *         Online_Login\n *\n *   The socket.io connection parameter refers to if you\n *   want to automatically upgrade to sockets after login.\n *\n */\n //=============================================================================\n Nasty.Parameters = $plugins.filter(function(p)\n\t\t{ return p.description.contains('<Online_Login_Core>');})[0].parameters;\n\n\n\t\tvar Nel_online_login_core_plugincomm_alias = Game_Interpreter.prototype.pluginCommand;\n    Game_Interpreter.prototype.pluginCommand = function(command, args) {\n        Nel_online_login_core_plugincomm_alias.call(this, command, args);\n        if (command.toUpperCase() === 'ONLINE_LOGIN') {\n\t\t\t\t\tif ($gameNetwork._token===0){\n\t\t\t\t\t\tSceneManager.goto(MMO_Scene_Title);\n\t\t\t\t\t}\n        }\n\t\t\t};\n\t\t\t\n\t//----------------------------------------------------------------------------\n\t// MMO_Scene_Title\n\t//\n\t// Title scene including login form.\n  //----------------------------------------------------------------------------\n\n\tfunction MMO_Scene_Title() {\n\t    this.initialize.apply(this, arguments);\n\t}\n\n\tMMO_Scene_Title.prototype = Object.create(Scene_Base.prototype);\n\tMMO_Scene_Title.prototype.constructor = MMO_Scene_Title;\n\n\tMMO_Scene_Title.prototype.initialize = function() {\n\t\t\tScene_Base.prototype.initialize.call(this);\n\t};\n\n\tMMO_Scene_Title.prototype.reBindInput = function() {\n\t\tInput.initialize();\n\t};\n\n\tMMO_Scene_Title.prototype.create = function() {\n\t    Scene_Base.prototype.create.call(this);\n\t    this.createBackground();\n\t};\n\n\tMMO_Scene_Title.prototype.start = function() {\n\t\tScene_Base.prototype.start.call(this);\n\t\tvar token = localStorage.getItem('token');\n\t\tvar that = this\n\n\t\tSceneManager.clearStack();\n\t\tthis.playTitleMusic();\n\t\tthis.startFadeIn(this.fadeSpeed(), false);\n\n\t\tif (token) {\n\t\t\t//Need to veriy token\n\t\t\t$.get($gameNetwork._serverURL+'/verify-token', {token: token},\n\t\t\tfunction(data){\n\t\t\t\tthat.createLogoutContinueForm(data.token.name, token);\n\t\t\t})\n\t\t\t.fail(function(){\n\t\t\t\tthat.createLoginForm();\n\t\t\t});\n\t\t}\n\t\telse{\n\t\t\tthis.createLoginForm();\n\t\t}\n\t};\n\n\tMMO_Scene_Title.prototype.update = function() {\n\t    Scene_Base.prototype.update.call(this);\n\t};\n\n\tMMO_Scene_Title.prototype.isBusy = function() {\n\t    return Scene_Base.prototype.isBusy.call(this);\n\t};\n\n\tMMO_Scene_Title.prototype.terminate = function() {\n\t    Scene_Base.prototype.terminate.call(this);\n\t    SceneManager.snapForBackground();\n\t};\n\n\n\tMMO_Scene_Title.prototype.createRegistrationForm = function() {\n\t\t$(\"#ErrorPrinter\").html(\n\t\t\t'<div id=\"RegisterForm\" class=\"panel panel-primary\" style=\"width:'+(Graphics.boxWidth - (Graphics.boxWidth / 3))+'px\">'+\n\t\t\t\t'<div class=\"panel-heading\">Register</div>'+\n\t\t\t\t'<div class=\"panel-body\">'+\n\t\t\t\t\t'<div id=\"loginErrBox\"></div>'+\n  \t\t\t\t'<div class=\"form-group\">'+\n    \t\t\t\t'<input type=\"text\" id=\"regUsername\" name=\"username\" placeholder=\"Enter Username\" class=\"form-control\"/>'+\n  \t\t\t\t'</div>'+\n  \t\t\t\t\t'<div class=\"form-group\">'+\n    \t\t\t'<input type=\"text\" name=\"email\" id=\"regEmail\"  placeholder=\"Email Address\" class=\"form-control\"/>'+\n  \t\t\t\t'</div>'+\n  \t\t\t\t\t'<div class=\"form-group\">'+\n    \t\t\t'<input type=\"password\" name=\"password\" id=\"regPassword\" placeholder=\"Password\" class=\"form-control\"/>'+\n  \t\t\t\t\t'</div>'+\n  \t\t\t\t\t'<button id=\"btnSubmit\"type=\"submit\" class=\"btn btn-default\">Submit</button>'+\n\t\t\t\t\t\t'<button id =\"btnCancel\" type=\"button\" class=\"btn btn-primary\">Cancel</button>'+\n\t\t\t\t'</div>'+\n\t\t\t'</div>');\n\n\t\t\tvar that = this;\n\t\t\t$(\".form-control\").keypress(function(e){\n\t\t\t\tif (e.which == 13) { //enter\n\t\t\t\t\tthat.registerAttempt();\n\t\t\t\t}\n\t\t\t});\n      $(\"#regUsername\").tap(function(){$(\"#regUsername\").focus();});\n      $(\"#regEmail\").tap(function(){$(\"#regEmail\").focus();});\n      $(\"#regPassword\").tap(function(){$(\"#regPassword\").focus();});\n      $(\"#btnSubmit\").bind(\"click touchstart\",function(){that.registerAttempt();});\n      $(\"#btnCancel\").bind(\"click touchstart\",function(){that.createLoginForm();});\n\n\t\t};\n\t// Testing purpose, need to be rewritten into something more modulable,\n\t// maybe using template file?\n\t// Can be wise to work on a set of sprite-based form inputs for\n\t// a better visual integration.\n\tMMO_Scene_Title.prototype.createLoginForm = function() {\n\t\t$(\"#ErrorPrinter\").html(\n\t\t\t'<div id=\"LoginForm\" class=\"panel panel-primary\" style=\"width:'+(Graphics.boxWidth - (Graphics.boxWidth / 3))+'px\">'+\n\t\t\t\t'<div class=\"panel-heading\">Login</div>'+\n\t\t\t\t'<div class=\"panel-body\">'+\n\t\t\t\t\t'<div id=\"loginErrBox\"></div>'+\n\t\t\t\t\t'<div class=\"input-group\">'+\n\t\t\t\t\t\t'<span class=\"input-group-addon\" id=\"username-addon\"><i class=\"fa fa-user\"></i></span>'+\n\t\t\t\t\t\t'<input type=\"text\" class=\"form-control login-input\" id=\"inputUsername\" placeholder=\"Username\" aria-describedby=\"username-addon\">'+\n\t\t\t\t\t'</div><br>'+\n\t\t\t\t\t'<div class=\"input-group\">'+\n\t\t\t\t\t\t'<span class=\"input-group-addon\" id=\"password-addon\"><i class=\"fa fa-lock\"></i></span>'+\n\t\t\t\t\t\t'<input type=\"password\" class=\"form-control login-input\" id=\"inputPassword\" placeholder=\"Password\" aria-describedby=\"password-addon\">'+\n\t\t\t\t\t'</div><br>'+\n\t\t\t\t\t'<button id=\"btnConnect\" class=\"btn btn-primary\">Connect</button>'+\n\t\t\t\t\t'<button id=\"btnRegister\" class=\"btn btn-default\">Register</button>'+\n          '<button id=\"btnForgotPassword\" class=\"btn btn-link btn-sm\">Forgot Password?</button>'+\n\t\t\t\t'</div>'+\n\t\t\t'</div>');\n\n\t\t//Bind commands\n\t\tvar that = this;\n\t\t$(\".login-input\").keypress(function(e){\n\t\t\tif (e.which == 13) { //enter\n\t\t\t\tthat.connectAttempt();\n\t\t\t}\n\t\t});\n    $(\"#inputUsername\").tap(function(){$(\"#inputUsername\").focus();});\n    $(\"#inputPassword\").tap(function(){$(\"#inputPassword\").focus();});\n\t\t$(\"#btnConnect\").bind(\"click touchstart\",function(){that.connectAttempt();});\n\t\t$(\"#btnRegister\").bind(\"click touchstart\",function(){that.createRegistrationForm();});\n\t\t$(\"#btnForgotPassword\").bind(\"click touchstart\",function(){that.createLostPasswordForm();});\n    $(\"#inputUsername\").focus();\n\t};\n\n\tMMO_Scene_Title.prototype.createActivationForm = function() {\n\t\t$(\"#ErrorPrinter\").html(\n\t\t\t'<div id=\"ActivationForm\" class=\"panel panel-primary\" style=\"width:'+(Graphics.boxWidth - (Graphics.boxWidth / 3))+'px\">'+\n\t\t\t\t'<div class=\"panel-heading\">Activation</div>'+\n\t\t\t\t'<div class=\"panel-body\">'+\n\t\t\t\t\t'<div id=\"loginErrBox\"></div>'+\n\t\t\t\t\t'<div class=\"input-group\">'+\n\t\t\t\t\t'</div><br>'+\n\t\t\t\t\t'<button id=\"btnActLogin\" class=\"btn btn-primary\">Login</button>'+\n\t\t\t\t'</div>'+\n\t\t\t'</div>');\n\n\t\t//Bind commands\n\t\tvar that = this;\n\t\t$(\".login-input\").keypress(function(e){\n\t\t\tif (e.which == 13) { //enter\n\t\t\t\tthat.createLoginForm();\n\t\t\t}\n\t\t});\n    $(\"#btnActLogin\").bind(\"click touchstart\",function(){that.createLoginForm();});\n\t};\n\n\tMMO_Scene_Title.prototype.createLogoutContinueForm = function(name, token) {\n\t\t$(\"#ErrorPrinter\").html(\n\t\t\t`<div id=\"ActivationForm\" class=\"panel panel-primary\" style=\"width: ${(Graphics.boxWidth - (Graphics.boxWidth / 3))}px\">\n\t\t\t\t<div class=\"panel-heading\">Welcome ${name}</div>\n\t\t\t\t<div class=\"panel-body\">\n\t\t\t\t\t<div id=\"loginErrBox\"></div>\n\t\t\t\t\t<div class=\"input-group\">\n\t\t\t\t\t</div><br>\n\t\t\t\t\t<button id=\"btnContinue\" class=\"btn btn-primary\">Continue</button>\n\t\t\t\t\t<button id=\"btnLogout\" class=\"btn btn-default\">Log Out</button>\n\t\t\t\t</div>\n\t\t\t</div>`);\n\n\t\t//Bind commands\n\t\tvar that = this;\n\n    $(\"#btnLogout\").bind(\"click touchstart\",function(){\n\t\t\tlocalStorage.removeItem('token');\n\t\t\tthat.createLoginForm();\n\t\t});\n\n    $(\"#btnContinue\").bind(\"click touchstart\",function(){\n\t\t\t$gameNetwork._token = token;\n\t\t\tvar ioFlag = String(Nasty.Parameters['socket.io connection']);\n\t\t\t$(\"#ErrorPrinter\").fadeOut({duration: 1000}).html(\"\");\n\t\t\tif (ioFlag==='true'){\n\t\t\t\t$gameNetwork.connectSocket('main','/');\n\t\t\t\t$gameNetwork._socket.main.on('firstShutDown',function(data){\n\t\t\t\t\t$gameSwitches.setValue(Number(Nasty.Parameters['Switch on First Shutdown']),true);\n\t\t\t\t});\n\t\t\t\t$gameNetwork._socket.main.on('secondShutDown',function(data){\n\t\t\t\t\t$gameSwitches.setValue(Number(Nasty.Parameters['Switch on Second Shutdown']),true);\n\t\t\t\t});\n\t\t\t}\n\t\t\t$gameNetwork.connectSocketsAfterLogin();\n\t\t\tthat.fadeOutAll();\n\t\t\tSceneManager.goto(Scene_Map);\n\t\t\treturn that.displayInfo(\"Ok : \");\n\t\t});\n\t};\n\n\tMMO_Scene_Title.prototype.displayError = function(msg) {\n\t\t$(\"#loginErrBox\").html('<div class=\"alert alert-danger fade in\">'+msg+'</div>');\n\t};\n\n\tMMO_Scene_Title.prototype.displayInfo = function(msg) {\n\t\t$(\"#loginErrBox\").html('<div class=\"alert alert-info fade in\">'+msg+'</div>');\n\t};\n\n  MMO_Scene_Title.prototype.displaySuccess = function(msg) {\n\t\t$(\"#loginErrBox\").html('<div class=\"alert alert-success fade in\">'+msg+'</div>');\n\t};\n\n  MMO_Scene_Title.prototype.createLostPasswordForm = function() {\n\t\t$(\"#ErrorPrinter\").html(\n\t\t\t'<div id=\"LostPasswordFrom\" class=\"panel panel-primary\" style=\"width:'+(Graphics.boxWidth - (Graphics.boxWidth / 3))+'px\">'+\n\t\t\t\t'<div class=\"panel-heading\">Lost Password - Enter Email</div>'+\n\t\t\t\t'<div class=\"panel-body\">'+\n\t\t\t\t\t'<div id=\"loginErrBox\"></div>'+\n  \t\t\t\t\t'<div class=\"form-group\">'+\n    \t\t\t'<input type=\"text\" name=\"email\" id=\"inputEmailLP\"  placeholder=\"Email Address\" class=\"form-control\"/>'+\n  \t\t\t\t'</div>'+\n  \t\t\t\t\t'<button id=\"btnSubmitLP\"type=\"submit\" class=\"btn btn-primary\">Submit</button>'+\n\t\t\t\t\t\t'<button id =\"btnCancelLP\" type=\"button\" class=\"btn btn-default\">Cancel</button>'+\n\t\t\t\t'</div>'+\n\t\t\t'</div>');\n\n\t\t\tvar that = this;\n\t\t\t$(\".form-control\").keypress(function(e){\n\t\t\t\tif (e.which == 13) { //enter\n\t\t\t\t\tthat.lostPasswordRequest();\n\t\t\t\t}\n\t\t\t});\n      $(\"#inputEmailLP\").tap(function(){$(\"#inputEmailLP\").focus();});\n      $(\"#btnSubmitLP\").bind(\"click touchstart\",function(){that.lostPasswordRequest();});\n      $(\"#btnCancelLP\").bind(\"click touchstart\",function(){that.createLoginForm();});\n      $(\"#inputEmailLP\").focus();\n\t\t};\n\n    MMO_Scene_Title.prototype.createResetPasswordForm = function() {\n  \t\t$(\"#ErrorPrinter\").html(\n  \t\t\t'<div id=\"PasswordResetForm\" class=\"panel panel-primary\" style=\"width:'+(Graphics.boxWidth - (Graphics.boxWidth / 3))+'px\">'+\n  \t\t\t\t'<div class=\"panel-heading\">Password Reset</div>'+\n  \t\t\t\t'<div class=\"panel-body\">'+\n  \t\t\t\t\t'<div id=\"loginErrBox\"></div>'+\n    \t\t\t\t\t'<div class=\"form-group\">'+\n      \t\t\t'<input type=\"password\" name=\"password\" id=\"inputPasswordCP\"  placeholder=\"New Password\" class=\"form-control\"/>'+\n    \t\t\t\t'</div>'+\n            '<div class=\"form-group\">'+\n          '<input type=\"password\" name=\"password\" id=\"inputPasswordConfirmCP\"  placeholder=\"Confirm Password\" class=\"form-control\"/>'+\n          '</div>'+\n    \t\t\t\t\t'<button id=\"btnChangeCP\"type=\"submit\" class=\"btn btn-primary\">Change</button>'+\n  \t\t\t\t\t\t'<button id =\"btnCancelCP\" type=\"button\" class=\"btn btn-default\">Cancel</button>'+\n  \t\t\t\t'</div>'+\n  \t\t\t'</div>');\n\n  \t\t\tvar that = this;\n  \t\t\t$(\".form-control\").keypress(function(e){\n  \t\t\t\tif (e.which == 13) { //enter\n  \t\t\t\t\tthat.changePasswordRequest();\n  \t\t\t\t}\n  \t\t\t});\n        $(\"#inputPasswordCP\").tap(function(){$(\"#inputEmailLP\").focus();});\n        $(\"#inputPasswordConfirmCP\").tap(function(){$(\"#inputEmailLP\").focus();});\n        $(\"#btnChangeCP\").bind(\"click touchstart\",function(){that.changePasswordRequest();});\n        $(\"#btnCancelCP\").bind(\"click touchstart\",function(){that.createLoginForm();});\n        $(\"#inputPasswordCP\").focus();\n  \t\t};\n\n      MMO_Scene_Title.prototype.changePasswordRequest = function(){\n    \t\tvar that = this;\n        var pass1 = $(\"#inputPasswordCP\").val();\n        var pass2 = $(\"#inputPasswordConfirmCP\").val();\n        if (pass1.length === 0)\n    \t\t\treturn this.displayError(\"You must provide a new password!\");\n        if (pass2.length === 0)\n      \t\treturn this.displayError(\"You must confirm your password!\");\n        if (pass1!==pass2)\n          return this.displayError(\"Passwords do not match!\");\n        this.displayInfo('Connecting <i class=\"fa fa-spin fa-spinner\"></i>');\n\n        shapwd = CryptoJS.SHA1(pass1+$gameNetwork._firstHash).toString(CryptoJS.enc.Hex);\n\n        $.post($gameNetwork._serverURL+'/resetpassword', {\n            password: shapwd,\n            tempHash: $gameSystem._tempPasswordHash,\n            tempName: $gameSystem._tempPasswordName\n          }).done(function (data) {\n            if (data.err) return that.displayError(\"Error : \"+data.err);\n            that.createLoginForm();\n            that.displaySuccess(\"Password Changed Successfully\");\n          });\n      };\n\n    MMO_Scene_Title.prototype.lostPasswordRequest = function(){\n  \t\tvar that = this;\n  \t\tvar email = $(\"#inputEmailLP\").val();\n      if (email.length === 0)\n  \t\t\treturn this.displayError(\"You must provide a username!\");\n      this.displayInfo('Connecting <i class=\"fa fa-spin fa-spinner\"></i>');\n\n      $.post($gameNetwork._serverURL+'/lostpassword', {\n        email: email,\n      }).done(function (data) {\n        if (data.err) return that.displayError(\"Error : \"+data.err);\n        that.createLoginForm();\n        that.displayInfo(\"Check email for temporary password\");\n      });\n\t\t};\n\t\t\n\tMMO_Scene_Title.prototype.connectAttempt = function(){\n\t\tvar that = this;\n\t\tvar username = $(\"#inputUsername\").val();\n\t\tvar password = $(\"#inputPassword\").val();\n\n\t\tif (username.length === 0)\n\t\t\treturn this.displayError(\"You must provide a username!\");\n\t\tif (password.length === 0)\n\t\t\treturn this.displayError(\"You must provide a password!\");\n\n\t\tshapwd = CryptoJS.SHA1(password+$gameNetwork._firstHash).toString(CryptoJS.enc.Hex);\n\t\tthis.displayInfo('Connecting <i class=\"fa fa-spin fa-spinner\"></i>');\n        $.post($gameNetwork._serverURL+'/login', {\n\t\t\t\t\tusername: username,\n\t\t\t\t\tpassword: shapwd\n      }).done(function (data) {\n\t\t\t\tif (data.err)\n\t\t\t\t\t\treturn that.displayError(\"Error : \"+data.err);\n        if (data.temp){\n          //Make Password reset form\n          $gameSystem._tempPasswordName = data.name;\n          $gameSystem._tempPasswordHash = data.temp;\n          that.createResetPasswordForm();\n        }\n\t\t\t\t\tif (data.token) {\n\t\t\t\t\t\t$gameNetwork._token = data.token;\n\t\t\t\t\t\tlocalStorage.setItem('token', data.token);\n\t\t\t\t\t\tvar ioFlag = String(Nasty.Parameters['socket.io connection']);\n\t\t\t\t\t\t$(\"#ErrorPrinter\").fadeOut({duration: 1000}).html(\"\");\n            if (ioFlag==='true'){\n\t\t\t\t\t\t\t$gameNetwork.connectSocket('main','/');\n              $gameNetwork._socket.main.on('firstShutDown',function(data){\n                $gameSwitches.setValue(Number(Nasty.Parameters['Switch on First Shutdown']),true);\n              });\n              $gameNetwork._socket.main.on('secondShutDown',function(data){\n                $gameSwitches.setValue(Number(Nasty.Parameters['Switch on Second Shutdown']),true);\n              });\n\t\t\t\t\t\t}\n            $gameNetwork.connectSocketsAfterLogin();\n            that.fadeOutAll();\n\t\t\t\t\t  SceneManager.goto(Scene_Map);\n\t\t\t\t\t\treturn that.displayInfo(\"Ok : \"+data.msg);\n\t\t\t\t\t}\n      });\n\t};\n\n\tMMO_Scene_Title.prototype.registerAttempt = function(){\n\t\tvar that = this;\n\t\tvar username = $(\"#regUsername\").val();\n\t\tvar password = $(\"#regPassword\").val();\n\t\tvar email = $(\"#regEmail\").val();\n\t\tif (username.length === 0) return this.displayError(\"You must provide a username!\");\n\t\tif (password.length === 0) return this.displayError(\"You must provide a password!\");\n\t\tif (email.length === 0) return this.displayError(\"You must provide a valid Email!\");\n\n\t\tthis.displayInfo('Connecting <i class=\"fa fa-spin fa-spinner\"></i>');\n\n\t\t//POST FOR REGISTER\n\t\t$.post($gameNetwork._serverURL + '/register', {\n\t\t\tusername: username,\n\t\t\tpassword: password,\n\t\t\temail: email\n\t}).done(function (result) {\n\t\tvar data = result.pageData;\n\t\tif (data.err)\n\t\t\treturn that.displayError(\"Error : \"+data.err);\n\t\tif (data.msg) {\n\t\t\t\tthat.createActivationForm();\n\t\t\tthat.displayInfo(\"Check your email for the activation link!\");\n\t\t}\n\t});\n\t};\n\n\tMMO_Scene_Title.prototype.createBackground = function() {\n\t\tvar startupFlag = String(Nasty.Parameters['Force Login on Startup']);\n\t\tif (startupFlag==='true'){\n\t    this._backSprite1 = new Sprite(ImageManager.loadTitle1($dataSystem.title1Name));\n\t    this._backSprite2 = new Sprite(ImageManager.loadTitle2($dataSystem.title2Name));\n\t    this.addChild(this._backSprite1);\n\t    this.addChild(this._backSprite2);\n\t\t\tthis.centerSprite(this._backSprite1);\n\t    this.centerSprite(this._backSprite2);\n\t\t\tthis.createForeground();\n\t\t}else{\n\t\t\tthis._backgroundSprite = new Sprite();\n\t    this._backgroundSprite.bitmap = SceneManager.backgroundBitmap();\n\t    this.addChild(this._backgroundSprite);\n\t\t}\n\t};\n\n\tMMO_Scene_Title.prototype.createForeground = function() {\n\t    this._gameTitleSprite = new Sprite(new Bitmap(Graphics.width, Graphics.height));\n\t    this.addChild(this._gameTitleSprite);\n\t    if ($dataSystem.optDrawTitle) {\n\t        this.drawGameTitle();\n\t    }\n\t};\n\n\tMMO_Scene_Title.prototype.drawGameTitle = function() {\n\t    var x = 20;\n\t    var y = Graphics.height / 4;\n\t    var maxWidth = Graphics.width - x * 2;\n\t    var text = $dataSystem.gameTitle;\n\t    this._gameTitleSprite.bitmap.outlineColor = 'black';\n\t    this._gameTitleSprite.bitmap.outlineWidth = 8;\n\t    this._gameTitleSprite.bitmap.fontSize = 72;\n\t    this._gameTitleSprite.bitmap.drawText(text, x, y, maxWidth, 48, 'center');\n\t};\n\n\tMMO_Scene_Title.prototype.centerSprite = function(sprite) {\n\t    sprite.x = Graphics.width / 2;\n\t    sprite.y = Graphics.height / 2;\n\t    sprite.anchor.x = 0.5;\n\t    sprite.anchor.y = 0.5;\n\t};\n\n\tMMO_Scene_Title.prototype.playTitleMusic = function() {\n\t    AudioManager.playBgm($dataSystem.titleBgm);\n\t    AudioManager.stopBgs();\n\t    AudioManager.stopMe();\n\t};\n\n  //----------------------------------------------------------------------------\n\t//\n\t// Override of Scene_Boot.start, for calling our own Scene_Title!\n\t//\n\nvar Nel__SceneBase_Boot_alias_MMO_Login = Scene_Boot.prototype.start;\n\n\tScene_Boot.prototype.start = function() {\n\t\tvar startupFlag = String(Nasty.Parameters['Force Login on Startup']);\n\t\tif (startupFlag==='false'){\n\t\t\tNel__SceneBase_Boot_alias_MMO_Login.call(this);\n\t\t}\n\t\telse{\n\t    Scene_Base.prototype.start.call(this);\n\t    SoundManager.preloadImportantSounds();\n\t    if (DataManager.isBattleTest()) {\n\t        DataManager.setupBattleTest();\n\t        SceneManager.goto(Scene_Battle);\n\t    } else if (DataManager.isEventTest()) {\n\t        DataManager.setupEventTest();\n\t        SceneManager.goto(Scene_Map);\n\t    } else {\n\t        this.checkPlayerLocation();\n\t        DataManager.setupNewGame();\n\t        SceneManager.goto(MMO_Scene_Title);\n\t    }\n\t    this.updateDocumentTitle();\n\t\t}\n\t};\n\n    //-----------------------------------------------------------------------------\n\t//\n\t// Overriding 'Input._onKeyDown' to pass 'event' as parameter\n\t// to 'Input._shouldPreventDefault'\n\t//\n\n\tInput._onKeyDown = function(event) {\n\t    if (this._shouldPreventDefault(event)) {\n\t        event.preventDefault();\n\t    }\n\t    if (event.keyCode === 144) {    // Numlock\n\t        this.clear();\n\t    }\n\t    var buttonName = this.keyMapper[event.keyCode];\n\t    if (buttonName) {\n\t        this._currentState[buttonName] = true;\n\t    }\n\t};\n\n    //-----------------------------------------------------------------------------\n\t//\n\t// Overriding Input._shouldPreventDefault to allow the use of the 'backspace key'\n\t// in input forms.\n\t//\n\n\tInput._shouldPreventDefault = function(e) {\n\t    switch (e.keyCode) {\n\t\t    case 8:     // backspace\n\t\t    \tif ($(e.target).is(\"input, textarea\"))\n\t\t    \t\tbreak;\n\t\t    case 33:    // pageup\n\t\t    case 34:    // pagedown\n\t\t    case 37:    // left arrow\n\t\t    case 38:    // up arrow\n\t\t    case 39:    // right arrow\n\t\t    case 40:    // down arrow\n\t\t        return true;\n\t    }\n\t    return false;\n\t};\n\n\n})();\n"
  },
  {
    "path": "game_resources/js/plugins/Online_Main_Core.js",
    "content": "var Imported = Imported || {};\nImported.Online_Main_Core = true;\n//=============================================================================\n// Online Main Core\n// Version: 1.1.1\n//=============================================================================\n\n//=============================================================================\n /*:\n * @plugindesc Connect to a server with Socket.io!\n *<Online_Main_Core>\n * @author Nelderson\n *\n * @param Server URL\n * @desc API/Socket.io server location\n * @default http://localhost:8000\n *\n * @param First Hash\n * @desc Same as the server firstHash config\n * @default d28cb767c4272d8ab91000283c67747cb2ef7cd1\n *\n * @help\n * ============================================================================\n * Introduction and Instructions\n * ============================================================================\n * This entire core just points and connects to your api/sockets!\n *\n */\n //=============================================================================\n\n var $gameNetwork = null;\n\n var Nel_Online_Core_dataCreateGameObj =  DataManager.createGameObjects;\n DataManager.createGameObjects = function() {\n    Nel_Online_Core_dataCreateGameObj.call(this);\n    //Keep gameNetwork the same for New Game to keep login info\n    $gameNetwork = $gameNetwork || new Game_Network();\n };\n\n var Nel_MainCore_Online_PluginOpt = $plugins.filter(function(p)\n    { return p.description.contains('<Online_Main_Core>');})[0].parameters;\n\nfunction Game_Network() {\n    this.initialize.apply(this, arguments);\n}\n\nGame_Network.prototype.initialize = function() {\n    this._serverURL = String(Nel_MainCore_Online_PluginOpt['Server URL']);\n    this._firstHash = String(Nel_MainCore_Online_PluginOpt['First Hash']);\n    this._socket = {};\n    this._token =0;\n};\n\nGame_Network.prototype.decodedJWT = function(){\n  if ($gameNetwork._token===0) return false;\n  var b64 =  $gameNetwork._token;\n  var body = b64.match(/[.](\\S+)[.]/);\n  var buf = new Buffer(body[0], 'base64').toString(\"ascii\");\n  var obj = JSON.parse(buf);\n  return obj;\n};\n\nGame_Network.prototype.connectSocketsAfterLogin = function(socket) {\n  //This runs right after logging in.\n  //Alias your own socket events\n  //(Similar to how you would add plugin commands)\n};\n\n\nGame_Network.prototype.connectSocket = function(socket_name, namespace) {\n  var url = this._serverURL;\n  this._socket[socket_name] = io.connect(url+namespace, {\n    query: 'token=' + $gameNetwork._token\n  });\n  var socket = this._socket[socket_name];\n  socket.on('connect', function () {\n    //Pass token on all POST/GET requests in the header\n    $.ajaxSetup({\n      headers: {\n        'x-access-token': $gameNetwork._token\n      }\n    });\n    console.log('Socket Authenticated');\n  });\n  socket.on('disconnect', function () {\n    console.log('Socket Disconnected');\n  });\n};\n"
  },
  {
    "path": "game_resources/js/plugins/Online_Metrics.js",
    "content": "var Imported = Imported || {};\nImported.Online_Metrics = true;\nvar Nasty = Nasty || {};\n\n(function () {\n//=============================================================================\n// Online Metrics\n// Version: 1.0.1\n//=============================================================================\n\n//=============================================================================\n /*:\n * @plugindesc Very simple netwokred metrics for your game.\n *<Online_Metrics>\n *\n * Requires Oniline Main Core and Server side setup to use.\n * @author Nelderson\n *\n * @param Anonymous\n * @desc If false requires users to be logged in with Login_Core\n * @default true\n *\n *\n * @help\n * ============================================================================\n * Introduction and Instructions\n * ============================================================================\n *\n *  Metrics allow you to store game data that you can use to project\n *  and show trends within your game.\n *\n *  REQUIRES: Online_Main_Core\n *\n * There are two ways to send metrics to your database:\n *\n *\n * 1. Plugin Command: SendMetrics <location>\n *\n *  This plugin command will send the default metrics derfined under\n *  the default_metrics function in the plugin js file.  Feel free to\n *  change the default values to match your game.\n *\n *  <location> is the location where this is taking place for future reference.\n *\n *  Ex. SendMetrics AfterBossBattle\n *\n * 2. Script Call: $gameSystem.sendMetrics(data);\n *\n *  This script call passes a data object that is then uploaded to the database.\n *  The data object can hold any arbitrary data you want.\n *\n *  Ex. $gameSystem.sendMetrics({\n *        goblin_kill_count = $gameVariables.value(35);\n *        save_count: $gameSystem._saveCount,\n *        escape_count: $gameSystem._escapeCount,\n *        battle_count: $gameSystem._battleCount,\n *        location: \"AfterGoblinBattle\"\n *   });\n *\n */\n //=============================================================================\n\n var default_metrics =function() {\n   return{\n     save_count: $gameSystem._saveCount,\n     playtime: $gameSystem.playtime(),\n     battle_count: $gameSystem._battleCount,\n     win_count: $gameSystem._winCount,\n     escape_count: $gameSystem._escapeCount,\n     actors: $gameParty._actors,\n     gold: $gameParty._gold,\n     save_slot: DataManager.latestSavefileId()\n   };\n };\n\n Nasty.Parameters = $plugins.filter(function(p)\n    { return p.description.contains('<Online_Metrics>');})[0].parameters;\n\nvar anonymousBool = Nasty.Parameters['Anonymous'];\n\nvar Online_Metrics_plugin_command = Game_Interpreter.prototype.pluginCommand;\nGame_Interpreter.prototype.pluginCommand = function(command, args) {\n  Online_Metrics_plugin_command.call(this,command, args);\n  if (command.toUpperCase() === 'SENDMETRICS') {\n    $gameSystem.sendMetricsFromPlugin(args[0]);\n  }\n};\n\nvar Nel_Metrics_GS_init_Alias = Game_System.prototype.initialize;\n\n Game_System.prototype.initialize = function(){\n   Nel_Metrics_GS_init_Alias.call(this);\n   this._metricsID = 'false';\n };\n\nGame_System.prototype.sendMetrics = function(data){\n  data.id = $gameSystem._metricsID;\n  $.post($gameNetwork._serverURL+'/metrics/datadump', data).done(function(data){\n    if (anonymousBool==='true'){\n      $gameSystem._metricsID = data;\n    }\n  });\n};\n\nGame_System.prototype.sendMetricsFromPlugin = function(data){\n  var metrics = default_metrics();\n  metrics.location = data;\n  metrics.id = $gameSystem._metricsID;\n  $.post($gameNetwork._serverURL+'/metrics/datadump', metrics).done(function(data){\n    if (anonymousBool==='true'){\n      $gameSystem._metricsID = data;\n    }\n  });\n};\n})();\n"
  },
  {
    "path": "game_resources/js/plugins/Online_Network_Players.js",
    "content": "var Imported = Imported || {};\nImported.Online_Network_Players = true;\n\n(function () {\nvar Nasty = Nasty || {};\n//=============================================================================\n// Online Network Players\n// Version: 1.0.10 - Fixed bug when in battle sprites clearing on map.\n// Version: 1.0.9 - Added check to stop Game_Player refresh when null\n// Version: 1.0.8 - Fixed bug for remove player when not on map\n// Version: 1.0.7 - Fixed bug with NastyTextPop not being there\n// Version: 1.0.6 - Added names above characters with Nasty_Text_Pop_Events.js\n//=============================================================================\n\n//=============================================================================\n /*:\n * @plugindesc Network Players for Neldersons Online Core\n *<Online_Network_Players>\n * @author Nelderson and Galv\n *\n * @param Net Player Map ID\n * @desc Map ID for Net Player Spawn Event\n * @default 1\n *\n * @param Net Player Event ID\n * @desc Event ID for Net Player Spawn Event\n * @default 1\n *\n * @param Show Username or Character Name\n * @desc 0=Username, 1=Character Name\n * @default 0\n *\n * @param Show Name Above Players Head\n * @type boolean\n * @on Yes\n * @off No\n * @desc Shows Username/Character name over Players Head\n * @default true\n *\n * @param Player Text Options\n * @desc This refers to the number in Nasty_Text_Pop_Events for text options\n * @default 1\n *\n * @param Net Player Text Options\n * @desc This refers to the number in Nasty_Text_Pop_Events for text options\n * @default 1\n *\n * @help\n * ============================================================================\n * Introduction and Instructions\n * ============================================================================\n * This plugin allows you to see other players on the map.\n * Add Nasty_Text_Pop_Events.js to see players names above their character\n *\n *  Plugin Parameters:\n *\n *  1.  Net Player Map ID\n *      -The Map ID the Netplayer Spawn event is located\n *\n *  2.  Net Player Event ID\n *      -The Event ID the Netplayer Spawn event is located\n */\n //=============================================================================\n\n Nasty.Parameters = $plugins.filter(function(p)\n\t { return p.description.contains('<Online_Network_Players>');})[0].parameters;\n\nvar NetPlayerMap = Nasty.Parameters['Net Player Map ID'];\nvar NetPlayerEventID = Nasty.Parameters['Net Player Event ID'];\nvar NetPlayerNameType = Number(Nasty.Parameters['Show Username or Character Name']);\nvar showPlayersName = String(Nasty.Parameters['Show Name Above Players Head']);\nvar playerTextOptions = (Number(Nasty.Parameters['Player Text Options'])-1);\nvar netplayerTextOptions = (Number(Nasty.Parameters['Net Player Text Options'])-1);\n\nvar networkName = '';\nvar socket;\nvar networkPlayerid = 0;\nvar networkMapEvents = {};\nvar NetworkFlag = false;\n\nvar OnlineMV_NetPlayer_SocketConn_Alias = Game_Network.prototype.connectSocketsAfterLogin;\nGame_Network.prototype.connectSocketsAfterLogin = function(){\n\tOnlineMV_NetPlayer_SocketConn_Alias.call(this);\n\n\t$gameNetwork.connectSocket('netplayers','/netplayers',false);\n\tsocket = $gameNetwork._socket.netplayers;\n\n\tsocket.on('MyID',function(data){\n\t\tnetworkPlayerid = data.id; //Set Network ID\n\t\tcurrentRoom = data.room;\n\t\tNetworkFlag = true;\n    if (NetPlayerNameType===0){\n      networkName = data.name;\n    }\n\t});\n\n\tsocket.on('NetworkPlayersXY', function(data){\n    if(!SceneManager._scene._spriteset || SceneManager._scene instanceof Scene_Battle) return;\n\t\tvar player = data.playerid;\n    var name = data.name;\n\t\tvar cx = data.x;\n\t\tvar cy = data.y;\n\t\tvar moveSpeed = data.moveSpeed;\n\t\tvar moveFrequenzy = data.moveFrequenzy;\n\t\tvar characterName = data.characterName;\n\t\tvar characterIndex = data.characterIndex;\n\n\t\t//Make an event if net player isn't already there\n\t\tif (networkMapEvents[player]===undefined){\n\t\t\tvar NetEvent = $gameMap.addNetworkPlayer(1, 1,name);\n\t\t\tnetworkMapEvents[player] = NetEvent;\n\t\t}\n    networkMapEvents[player].namepop = name;\n    networkMapEvents[player].textpop_flag = true;\n\n\t\t// Update movement speed and frequenzy\n\t\tnetworkMapEvents[player].setMoveSpeed(moveSpeed);\n\t\tnetworkMapEvents[player].setMoveFrequency(moveFrequenzy);\n\n\t\t//Continue on with updating xy position\n\t\tvar dir = data.direction;\n\t\tnetworkMapEvents[player].moveStraight(dir);\n\t\t//Sanity Check XY position\n\t\tif (networkMapEvents[player].x!==data.x || networkMapEvents[player].y!==data.y){\n\t\t\tnetworkMapEvents[player].setPosition(data.x, data.y);\n\t\t}\n\t\t//Set Player Sprite\n\t\tnetworkMapEvents[player]._characterName = characterName;\n\t\tnetworkMapEvents[player]._characterIndex = characterIndex;\n\t });\n\n\t socket.on('changeRoomVar', function(data){\n\t\t currentRoom = data;\n\t\t networkMapEvents = {};\n\t });\n\n\t socket.on('removePlayer', function(data){\n     if(!SceneManager._scene._spriteset || SceneManager._scene instanceof Scene_Battle) return;\n\t\t var id = data.id;\n\t\t //Just in case player hasn't moved and disconnects\n\t\t if (!networkMapEvents[id]) return;\n\t\t var player = networkMapEvents[id]._eventId;\n\t\t var map = data.room;\n\t\t $gameMap.clearNetworkPlayer(player);\n\t\t delete networkMapEvents[id];\n\t });\n};\n\n//================//\n//Player Movement\n//================//\nGame_Player.prototype.moveByInput = function() {\n\t\tif (!this.isMoving() && this.canMove()) {\n\t\t\t\tvar direction = this.getInputDirection();\n\t\t\t\tif (direction > 0) {\n\t\t\t\t\t\t$gameTemp.clearDestination();\n\t\t\t\t} else if ($gameTemp.isDestinationValid()){\n\t\t\t\t\t\tvar x = $gameTemp.destinationX();\n\t\t\t\t\t\tvar y = $gameTemp.destinationY();\n\t\t\t\t\t\tdirection = this.findDirectionTo(x, y);\n\t\t\t\t}\n\t\t\t\tif (direction > 0) {\n          if (NetPlayerNameType===1) networkName=$gameParty.leader()._name;\n\t\t\t\t\t//Send x,y info to server\n\t\t\t\t\t\tthis.executeMove(direction);\n\t\t\t\t\t\tif (NetworkFlag){\n\t\t\t\t\t\tsocket.emit('DestinationXY', {\n\t\t\t\t\t\t\tplayerid: networkPlayerid,\n\t\t\t\t\t\t\tdirection: direction,\n              name: networkName,\n\t\t\t\t\t\t\tx: this.x,\n\t\t\t\t\t\t\ty: this.y,\n\t\t\t\t\t\t\tmoveSpeed: this.realMoveSpeed(),\n\t\t\t\t\t\t\tmoveFrequenzy: this.moveFrequency(),\n\t\t\t\t\t\t\tcharacterName: this._characterName,\n\t\t\t\t\t\t\tcharacterIndex: this._characterIndex\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n};\n\n//=================================//\n//Player Refresh for Text Over Self\n//=================================//\nvar NetPlayer_GmePlayer_refresh_alias = Game_Player.prototype.refresh;\nGame_Player.prototype.refresh = function() {\n  NetPlayer_GmePlayer_refresh_alias.call(this);\n  if(this.namepop===undefined) return;\n  if (showPlayersName==='false') return;\n    if (NetPlayerNameType===1) {\n      this.namepop = $gameParty.leader()._name;\n    }else{\n      this.namepop = networkName;\n    }\n    this.setTextOptions(playerTextOptions);\n};\n\nvar NetPlayer_SceneBase_popScene = Scene_Base.prototype.popScene;\nScene_Base.prototype.popScene = function() {\n    NetPlayer_SceneBase_popScene.call(this);\n    if ($gamePlayer) $gamePlayer.refresh();\n};\n\nvar NetPlayer_SceneBase_stop = Scene_Base.prototype.stop;\nScene_Base.prototype.stop = function() {\n    NetPlayer_SceneBase_stop.call(this);\n    if ($gamePlayer) $gamePlayer.refresh();\n};\n\n//==============================//\n//Room Change When Changing Maps\n//==============================//\nvar NetPlayer_SceneMap_Start_Alias = Scene_Map.prototype.start;\nScene_Map.prototype.start = function() {\n\tNetPlayer_SceneMap_Start_Alias.call(this);\n\tvar mapId = $gameMap.mapId();\n\tif (NetworkFlag){\n    //In case of menu or battle scene\n\t\tif (currentRoom !== mapId.toString()){\n\t\t\tsocket.emit('changeRoom', mapId.toString());\n\t\t}\n\t}\n};\n\nvar Online_NetPlayers_Map_CallMenu_Alias = Scene_Map.prototype.callMenu;\nScene_Map.prototype.callMenu = function() {\n  $gameMap.clearAllNetworkPlayerEvents();\n  networkMapEvents = {};\n  Online_NetPlayers_Map_CallMenu_Alias.call(this);\n};\n\n//========================//\n//Net Player Event Creator\n//========================//\nDataManager.loadNetworkPlayerMapData = function() {\n\tvar mapId = NetPlayerMap;\n  var filename = 'Map%1.json'.format(mapId.padZero(3));\n  this.loadDataFile('$networkPlayerMap', filename);\n};\n\nDataManager.loadNetworkPlayerMapData();\n\nGame_Map.prototype.addNetworkPlayer = function(x,y,playerid) {\n    var eId = this._events.length;\n    this._events[eId] = new Game_NetworkPlayer(this._mapId,eId,x,y, playerid);\n\t  SceneManager._scene._spriteset.createNetworkPlayer(eId);\n\t\treturn this._events[eId];\n};\n\nGame_Map.prototype.clearNetworkPlayer = function(eId) {\n\tthis._events[eId] = null;\n\tSceneManager._scene._spriteset.clearNetworkPlayer(eId);\n};\n\nGame_Map.prototype.clearAllNetworkPlayerEvents = function() {\n  for (var i = 1; i < this._events.length; i++) {\n    if (!this._events[i]) continue;\n    if (this._events[i]._isNetworkPlayer){\n      this._events[i] = null;\n    }\n    SceneManager._scene._spriteset.clearAllNetworkPlayerEvents();\n  }\n  this.removeNullEvents();\n};\n\nGame_Map.prototype.removeNullEvents = function() {\n\tfor (var i = this._events.length - 1; i > 0; i--) {\n\t\tif (this._events[i] === null) {\n\t\t\tthis._events.splice(i, 1);\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n};\n\nSpriteset_Map.prototype.createNetworkPlayer = function(id) {\n\tvar event = $gameMap._events[id];\n\tvar sId = this._characterSprites.length;\n\tthis._characterSprites[sId] = new Sprite_Character(event);\n\tthis._characterSprites[sId].update(); // To remove occsaional full-spriteset visible issue\n\tthis._tilemap.addChild(this._characterSprites[sId]);\n};\n\nSpriteset_Map.prototype.clearNetworkPlayer = function(eId) {\n\tfor (var i = 0; i < this._characterSprites.length; i++) {\n\t\tvar event = this._characterSprites[i]._character;\n\t\tif (event._isNetworkPlayer && eId == event._eventId) {\n\t\t\tthis._tilemap.removeChild(this._characterSprites[i]);\n\t\t}\n\t}\n};\n\nSpriteset_Map.prototype.clearAllNetworkPlayerEvents = function() {\n\tfor (var i = 0; i < this._characterSprites.length; i++) {\n\t\tvar event = this._characterSprites[i]._character;\n\t\tif (event._isNetworkPlayer) {\n\t\t\tthis._tilemap.removeChild(this._characterSprites[i]);\n\t\t}\n\t}\n};\n\n\nfunction Game_NetworkPlayer() {\n    this.initialize.apply(this, arguments);\n}\n\nGame_NetworkPlayer.prototype = Object.create(Game_Event.prototype);\nGame_NetworkPlayer.prototype.constructor = Game_NetworkPlayer;\n\nGame_NetworkPlayer.prototype.initialize = function(mapId,eventId,x,y, name) {\n\tGame_Event.prototype.initialize.call(this,mapId,eventId);\n  this._isNetworkPlayer = true;\n  this.setPosition(x,y);\n  if (this.namepop===undefined){\n    console.log(\"You need Nasty_Text_Pop_Events for names to show!\");\n  }else{\n    this.namepop = name;\n    this.setTextOptions(netplayerTextOptions);\n  }\n};\n\nGame_NetworkPlayer.prototype.event = function() {\n    return $networkPlayerMap.events[NetPlayerEventID];\n};\n\n})();\n"
  },
  {
    "path": "game_resources/sampleindex.html",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <meta charset=\"UTF-8\">\n        <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n        <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">\n        <meta name=\"viewport\" content=\"user-scalable=no\">\n        <link rel=\"icon\" href=\"icon/icon.png\" type=\"image/png\">\n        <link rel=\"apple-touch-icon\" href=\"icon/icon.png\">\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"fonts/gamefont.css\">\n\n        <!-- Nel Add -->\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"./css/bootstrap3.3.5.min.css\" >\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"./css/fontawesome4.7.0.min.css\" >\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"./css/MMO.css\">\n        <!-- Nel Add -->\n\n        <title>Online_Core_Test</title>\n    </head>\n    <body style=\"background-color: black\">\n      \n        <!-- Nel Add -->\n        <script type=\"text/javascript\" src=\"./js/libs/jquery-2.1.4.min.js\"></script>\n        <script type=\"text/javascript\" src=\"./js/libs/jquerymobile1.4.5.min.js\"></script>\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"./css/jquerymobile1.4.5.min.css\">\n        <script type=\"text/javascript\" src=\"./js/libs/crypto.sha1.js\"></script>\n        <script type=\"text/javascript\" src=\"./js/libs/socket.io-2.2.0.js\"></script>\n        <!-- Nel Add -->\n\n        <script type=\"text/javascript\" src=\"js/libs/pixi.js\"></script>\n        <script type=\"text/javascript\" src=\"js/libs/pixi-tilemap.js\"></script>\n        <script type=\"text/javascript\" src=\"js/libs/pixi-picture.js\"></script>\n        <script type=\"text/javascript\" src=\"js/libs/fpsmeter.js\"></script>\n        <script type=\"text/javascript\" src=\"js/libs/lz-string.js\"></script>\n        <script type=\"text/javascript\" src=\"js/rpg_core.js\"></script>\n        <script type=\"text/javascript\" src=\"js/rpg_managers.js\"></script>\n        <script type=\"text/javascript\" src=\"js/rpg_objects.js\"></script>\n        <script type=\"text/javascript\" src=\"js/rpg_scenes.js\"></script>\n        <script type=\"text/javascript\" src=\"js/rpg_sprites.js\"></script>\n        <script type=\"text/javascript\" src=\"js/rpg_windows.js\"></script>\n        <script type=\"text/javascript\" src=\"js/plugins.js\"></script>\n        <script type=\"text/javascript\" src=\"js/main.js\"></script>\n    </body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"mvonline\",\n  \"version\": \"0.2.2\",\n  \"description\": \"Rpgmaker MV Online Server\",\n  \"main\": \"server.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"engines\": {\n    \"node\": \"11.x\"\n  },\n  \"dependencies\": {\n    \"@sendgrid/mail\": \"^6.3.1\",\n    \"body-parser\": \"^1.18.3\",\n    \"connect-redis\": \"^3.4.0\",\n    \"express\": \"^4.16.4\",\n    \"jsonwebtoken\": \"^8.4.0\",\n    \"mailgun-js\": \"^0.22.0\",\n    \"mongoose\": \"^5.4.2\",\n    \"morgan\": \"^1.9.1\",\n    \"nodemailer\": \"^4.7.0\",\n    \"passport\": \"^0.4.0\",\n    \"passport-facebook\": \"^2.1.1\",\n    \"passport-google-oauth20\": \"^1.0.0\",\n    \"passport-local-mongoose\": \"^5.0.1\",\n    \"redis\": \"^2.8.0\",\n    \"sendgrid\": \"^5.2.3\",\n    \"socket.io\": \"2.2.0\",\n    \"socket.io-redis\": \"5.2.0\",\n    \"sticky-session\": \"1.1.2\",\n    \"swearjar\": \"^0.2.0\",\n    \"tracer\": \"^0.9.8\"\n  },\n  \"author\": \"Nelderson\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "server.js",
    "content": "//=============================================================================\n// Nelderson's Online Core Server\n// Version: 0.2.2 - Added abilty to limit users to one login.\n// Version: 0.2.1\n//=============================================================================\nvar express = require('express');\nvar app = express();\nvar server = require('http').createServer(app)\nvar io = require('socket.io')(server);\nvar sticky = require('sticky-session');\nvar config = require('./configurations/config');\nvar bodyParser = require('body-parser');\nvar logger = require('morgan'); //For development\nvar log = require('tracer').colorConsole(config.loggingConfig);\nvar loggedInUsers = {};\n\n//Database Connction\nrequire('./api_routes/loginDBConnection')();\n\nvar auth = require('./auth.js');\n\nconst redisAdapter = require('socket.io-redis');\nio.adapter(redisAdapter(config.redisConnection));\n\napp.use(logger('dev'));//For development\napp.use(bodyParser.json());\napp.use(bodyParser.urlencoded({extended: false}));\n\napp.use(function(req,res,next){\n  res.setHeader('Access-Control-Allow-Origin', '*');\n  next();\n});\n\n\nif (!sticky.listen(server, config.port, {workers: process.env.MV_WORKER_COUNT || null})) {\n  // Master code\n  server.once('listening', function() {\n    log.info('Master Server started on port: '+ config.port);\n  });\n} \nelse {\n  // Worker code\n  \n\n  log.info('Worker is on bruh and running on port: '+ config.port);\n\n  //----------------------------------\n  // SET ROUTES FOR EXPRESS API HERE:\n  //----------------------------------\n\n  // No Authentication required:\n  app.use('/',require('./api_routes/login_routes'));\n  app.use('/metrics',require('./api_routes/metrics'));\n\n  // Authentication required:\n  app.use('/cloudsave',require('./api_routes/cloudsave.js'));\n\n  //Static Server - Used to serve static files (HTNL,PNG,etc.)\n  app.use('/static', express.static('public'));\n  //----------------------------------\n  // ADD SOCKET IO MODULES HERE:\n  //----------------------------------\n  // var exampleSocket = require('./socket_modules/exampleSocket');\n  var netplayers = require('./socket_modules/netplayer');\n  var chat = require('./socket_modules/chat');\n  var globalvar = require('./socket_modules/globalvar');\n\n  //Authorize socket connection with token from login\n  io.use(auth.authSocket)\n\n  //When first connected to Socket.io\n  io.on('connection', function(socket){\n\n    if(config.enforceOneUser){\n      var username = socket.user.name;\n      if (loggedInUsers[username]){\n        socket.to(loggedInUsers[username]).emit('firstShutDown',{});\n        socket.emit('secondShutDown',{});\n        io.of('/').connected[loggedInUsers[username]].disconnect(true);\n        socket.disconnect(true);\n      }\n      else {\n        loggedInUsers[username] = socket.id;\n      }\n    }\n\n    io.clients(function(error, clients){\n      if (error) throw error;\n      log.info(\"There are \" + clients.length + \" players connected\");\n    });\n\n    socket.on('disconnect',function(data){\n      loggedInUsers[username] = null;\n    });\n  });\n\n  //----------------------------------\n  // BIND SOCKET IO MODULES HERE:\n  //----------------------------------\n  // exampleSocket(io);\n  netplayers(io);\n  chat(io);\n  globalvar(io);\n\n} // <---Don't delete\n"
  },
  {
    "path": "socket_modules/chat.js",
    "content": "//Version: 0.1.2 - Added MyID call to pass client username\n//Version: 0.1.1 - Cleanup of profanity filter.\n\nvar chatConfig = require('./../configurations/chat');\nvar config = require('./../configurations/config');\nvar log = require('tracer').colorConsole(config.loggingConfig);\nvar swearjar = require('swearjar');\nvar auth = require('../auth.js');\n\nmodule.exports = function (sio) {\n\tvar io = sio.of('/chat');\n\tio.use(auth.authSocket)\n\n\tio.on('connection', function(socket) {\n\t\t//Decoded Token\n\t\tvar token = socket.user;\n\t\tvar username = token.name;\n\n\t\tsocket.emit('MyID', {name: username});\n\n\t\tsocket.on('clientMessage',function(data) {\n\t\t\tif (chatConfig.profanityFilter){\n\t\t\t\tdata.message = swearjar.censor(data.message);\n\t\t\t}\n\n\t\t\tio.emit('messageServer',data);\n\n\t\t\tif (chatConfig.enableLogging){\n\t\t\t\tlog.info(username + ': ' + data.message);\n\t\t\t }\n\t\t});\n\t});\n};\n"
  },
  {
    "path": "socket_modules/exampleSocket.js",
    "content": "var config = require('./../configurations/config');\nvar log = require('tracer').colorConsole(config.loggingConfig);\n\nmodule.exports = function (sio) {\n  //Set IO Roomspace\n  var io = sio.of('/example');\n\n  //Initialize socket\n  io.on('connection', function(socket){\n    socket.on('test',function(data){\n\t    log.info('test');\n    });\n  });\n};\n"
  },
  {
    "path": "socket_modules/globalvar.js",
    "content": "var config = require('./../configurations/config');\nvar log = require('tracer').colorConsole(config.loggingConfig);\n\nmodule.exports = function (sio) {\n  //Set IO Namespace\n  var io = sio.of('/globalvar');\n\n  //Initialize socket\n  io.on('connection', function(socket){\n\n    socket.on('switchDatatoServer',function(data){\n      socket.broadcast.emit('receivedSwitch', data);\n    });\n\n    socket.on('variableDatatoServer',function(data){\n      socket.broadcast.emit('receivedVariable', data);\n    });\n\n  });\n};\n"
  },
  {
    "path": "socket_modules/netplayer.js",
    "content": "// Version: 0.1.0 - Cleanup of initial Version\nvar auth = require('../auth.js');\n\nmodule.exports = function (sio) {\n\n  var io = sio.of('/netplayers');\n\n  io.use(auth.authSocket)\n\n\n  io.on('connection', function(socket){\n    var token = socket.user\n    var username = token.name;\n    var id = socket.id;\n    var currentRoom = '0'; //Room names are based off Map ID\n\n    socket.emit('MyID', {id: id, room: currentRoom, name: username});\n\n    //Gather XY Position and broadcast to all other players\n    socket.on('DestinationXY', function(data){\n      socket.broadcast.to(currentRoom).emit('NetworkPlayersXY', data);\n    });\n\n    socket.on('changeRoom', function(data){\n      socket.broadcast.to(currentRoom).emit('removePlayer',{id: id, room: currentRoom});\n      socket.leave(currentRoom);\n      currentRoom = data;\n      socket.join(data);\n      socket.emit('changeRoomVar', data);\n    });\n\n    socket.on('disconnect', function(socket){\n      io.in(currentRoom).emit('removePlayer',{id: id, room: currentRoom});\n    });\n  });\n};\n"
  }
]