├── internal ├── settings.json ├── settings.js ├── terminal.js ├── mineflayer.js └── addonManager.js ├── .gitattributes ├── addons ├── configs │ ├── eat.json │ ├── cmd.json │ ├── chat.json │ ├── players.json │ ├── afk.json │ ├── nearby.json │ ├── lookat.json │ ├── follow.json │ └── goto.json └── commands │ ├── utils │ ├── setting.js │ ├── quit.js │ ├── players.js │ └── nearby.js │ ├── windows │ ├── setQuickBarSlot.js │ ├── window.js │ └── clickWindow.js │ ├── cmd.js │ ├── activateItem.js │ ├── management │ ├── addowner.js │ └── removeowner.js │ ├── chat.js │ ├── eat.js │ ├── movement │ ├── lookat.js │ ├── follow.js │ └── goto.js │ ├── eval.js │ ├── combat │ └── autoclicker.js │ └── afk.js ├── .gitignore ├── package.json ├── window ├── css │ ├── style.css │ └── reset.css ├── index.html └── js │ └── jquery-3.6.0.min.js ├── utils.js ├── index.js ├── README.md └── LICENSE /internal/settings.json: -------------------------------------------------------------------------------- 1 | { "debug": true, "devtools": true, "language_code": "en_US" } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /addons/configs/eat.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[Eat] There is no bot entity.." 5 | } 6 | } -------------------------------------------------------------------------------- /addons/configs/cmd.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[Cmd] There is no bot entity..", 5 | "command_sent": "[Cmd] Sent the command \"[[;goldenrod;]{cmd}]\"" 6 | } 7 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log* 3 | 4 | # Dependency directories 5 | node_modules/ 6 | 7 | # Optional npm cache directory 8 | .npm 9 | 10 | # Ignore ZIPs 11 | *.zip 12 | 13 | # ESLint 14 | .eslintrc* -------------------------------------------------------------------------------- /addons/configs/chat.json: -------------------------------------------------------------------------------- 1 | { 2 | "settings": { 3 | "print": true 4 | }, 5 | "lang": 6 | { 7 | "no_bot": "[Chat] There is no bot entity..", 8 | "command_sent": "[Chat] Sent the message \"[[;goldenrod;]{msg}]\"" 9 | } 10 | } -------------------------------------------------------------------------------- /addons/configs/players.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[Players] There is no bot entity..", 5 | "player_map": "[[;goldenrod;]{name}] [[;#AAAAAA;]({distance}m)]", 6 | "player_msg": "[Players] Online Players: {map}" 7 | } 8 | } -------------------------------------------------------------------------------- /addons/configs/afk.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[AFK] There is no bot entity..", 5 | "unknown_method": "[AFK] Unkown AFK method \"[[;indianred;]{method}]\"", 6 | "starting": "[AFK] Using method \"[[;goldenrod;]{method}]\" (Interval \"[[;goldenrod;]{interval}]\")" 7 | } 8 | } -------------------------------------------------------------------------------- /addons/configs/nearby.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[Nearby] There is no bot entity to search around..", 5 | "no_entities_nearby": "[Nearby] Nearby {type}: [[;#FF5555;]NaN]", 6 | "distance_map": "[[;goldenrod;]{name}] [[;#AAAAAA;]({distance}m)]", 7 | "distance_msg": "[Nearby] Nearby {type}: {map}" 8 | } 9 | } -------------------------------------------------------------------------------- /addons/commands/utils/setting.js: -------------------------------------------------------------------------------- 1 | function handler(sender, args) { 2 | 3 | } 4 | 5 | module.exports = { 6 | addon: { 7 | cmd: 'setting', 8 | aliases: ['settings', 'option', 'options'], 9 | usage: 'setting ', 10 | description: 'Set a setting value.', 11 | handler: handler 12 | } 13 | }; -------------------------------------------------------------------------------- /addons/configs/lookat.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[LookAt] There is no bot entity to search around..", 5 | "no_argument": "[LookAt] You must specify a target..", 6 | "no_target_found": "[LookAt] Unable to find the specified target \"{target}\"..", 7 | "started": "[LookAt] Looking at \"{target}\".." 8 | } 9 | } -------------------------------------------------------------------------------- /internal/settings.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | let settings_file = `${__dirname}/../internal/settings.json`; 3 | 4 | var settings = require(settings_file); 5 | 6 | function saveSettings() { 7 | try { 8 | fs.writeFileSync(settings_file, JSON.stringify(settings), 'utf8'); 9 | } catch (e) { 10 | console.log('Unable to save the settings file:', e) 11 | } 12 | } -------------------------------------------------------------------------------- /addons/configs/follow.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[Follow] There is no bot entity to search around..", 5 | "no_argument": "[Follow] You must specify a target..", 6 | "no_target_found": "[Follow] Unable to find the specified target \"{type}\"..", 7 | "started": "[Follow] Now following [[;goldenrod;]{target}]", 8 | "stopped": "[Follow] No longer following a target.." 9 | } 10 | } -------------------------------------------------------------------------------- /addons/commands/utils/quit.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'quit', 4 | aliases: ['exit'], 5 | usage: 'quit', 6 | description: 'Ends the session of the bot.', 7 | useConfig: false, 8 | handler: async function(sender, args) { 9 | if (!bot?.entity) return echo('There is no session to end..'); 10 | echo(`I will now gracefully exit the server..`) 11 | bot.quit('Quit Gracefully'); 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /addons/configs/goto.json: -------------------------------------------------------------------------------- 1 | { 2 | "lang": 3 | { 4 | "no_bot": "[Goto] There is no bot entity to search around..", 5 | "no_argument": "[Goto] You must specify a target..", 6 | "no_target_found": "[Goto] Unable to find the specified target \"{target}\"..", 7 | "started": "[Goto] Going to {target}", 8 | "stopped": "[Goto] No longer going to target..", 9 | "arrived": "[Goto] Arrived at {target}", 10 | "failed": "[Goto] Unable to get to {target}" 11 | } 12 | } -------------------------------------------------------------------------------- /addons/commands/windows/setQuickBarSlot.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'setquickbar', 4 | aliases: ['setquick', 'setslot', 'quickbar'], 5 | description: 'Sets your quick bar to a specific slot', 6 | handler: async function(sender, args) { 7 | if (!bot?.entity) return echo('There is no bot entity..'); 8 | bot.setQuickBarSlot(args[0]) 9 | let heldItem = bot.heldItem?.name || 'nothing'; 10 | echo(`Now holding ${heldItem}`) 11 | } 12 | } 13 | }; -------------------------------------------------------------------------------- /addons/commands/utils/players.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'players', 4 | usage: 'players', 5 | description: 'Show online players.', 6 | useConfig: true, 7 | handler: async function(sender, args) { 8 | let lang = this.config.lang; 9 | if (!bot?.entity) return echo(lang.no_bot); 10 | let map = Object.keys(bot.players).map(e => e.replace('{name}', e.username)); 11 | echo(lang.player_msg.replace('{map}', map.join(', '))); 12 | } 13 | } 14 | }; -------------------------------------------------------------------------------- /addons/commands/cmd.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'cmd', 4 | aliases: ['command'], 5 | autocomplete: ['players'], 6 | usage: 'cmd ', 7 | description: 'Run a command.', 8 | useConfig: true, 9 | handler: async function(sender, args) { 10 | let lang = this.config.lang; 11 | if (!bot?.entity) return echo(lang.no_bot); 12 | var command = args.join(' '); 13 | echo(lang.command_sent.replace('{cmd}', command)) 14 | bot.chat('/' + command); 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /addons/commands/activateItem.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'activateItem', 4 | usage: 'activateItem ', 5 | description: 'Activate an item in your inventory.', 6 | handler: async function(sender, args) { 7 | if (!bot?.entity) return echo('There is no bot entity..'); 8 | var offhand = (args[0] === 'true'); 9 | let withOrWithout = offhand ? 'with' : 'without' 10 | echo(`Activating item ${bot.heldItem.name} ${withOrWithout} offhand`) 11 | bot.activateItem(offhand) 12 | } 13 | } 14 | }; -------------------------------------------------------------------------------- /addons/commands/management/addowner.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'addowner', 4 | autocomplete: ['players'], 5 | usage: 'addowner ', 6 | description: 'Add a master to the bot', 7 | handler: async function(sender, args) { 8 | let masters = bot.mineprompt.masters; 9 | let username = args[0]; 10 | if(masters.includes(username)) return echo(`[[;indianred;]Error:] [[;goldenrod;]${username}] is already a master!`); 11 | bot.mineprompt.masters.push(username); 12 | return echo(`[[;goldenrod;]Masters:] ` + bot.mineprompt.masters.join(', ')); 13 | } 14 | } 15 | }; -------------------------------------------------------------------------------- /addons/commands/chat.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'chat', 4 | aliases: ['say'], 5 | autocomplete: ['players'], 6 | usage: 'chat ', 7 | description: 'Send a message.', 8 | useConfig: true, 9 | handler: async function(sender, args) { 10 | let lang = this.config.lang; 11 | let settings = this.config.settings; 12 | if (!bot?.entity) return echo(lang.no_bot); 13 | var message = args.join(' '); 14 | if(settings.print) { 15 | echo(lang.command_sent.replace('{msg}', message)) 16 | } 17 | bot.chat(message); 18 | } 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /addons/commands/windows/window.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'window', 4 | usage: 'window', 5 | description: 'Prints the current window', 6 | handler: async function(sender, args) { 7 | if (!bot?.entity) return echo('There is no bot entity..'); 8 | if(!bot.currentWindow) return echo('There is no window currently opened..'); 9 | for (const [slot, item] of Object.entries(bot.currentWindow.slots)) { 10 | if(item === null) continue; 11 | echo(`[${slot}] ${item.name} - ${item.displayName}`); // TODO : Add customName - but stripped of JSON and Colors 12 | } 13 | } 14 | } 15 | }; -------------------------------------------------------------------------------- /addons/commands/management/removeowner.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'removeowner', 4 | autocomplete: ['players'], 5 | usage: 'removeowner ', 6 | description: 'Remove a master from the bot', 7 | handler: async function(sender, args) { 8 | let masters = bot.mineprompt.masters; 9 | let username = args[0]; 10 | if(!masters.includes(username)) return echo(`[[;indianred;]Error:] [[;goldenrod;]${username}] is not a master!`); 11 | masters.splice(masters.indexOf(username), 1); 12 | return echo(`[[;indianred;]Removed] [[;goldenrod;]${username}] [[;indianred;]from the list of masters]`); 13 | return echo(`[[;goldenrod;]Masters:] ` + bot.mineprompt.masters.join(', ')); 14 | } 15 | } 16 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mineprompt", 3 | "version": "4.1.0", 4 | "description": "A Mineflayer Terminal created with ElectronJS", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "electron .", 8 | "nodemon": "nodemon --watch . --exec \"electron .\"" 9 | }, 10 | "author": "", 11 | "license": "MIT", 12 | "dependencies": { 13 | "glob": "^8.0.3", 14 | "jquery.terminal": "^2.35.3", 15 | "mineflayer": "^4.8.1", 16 | "mineflayer-pathfinder": "^2.4.2", 17 | "minimist-string": "^1.0.2", 18 | "moment": "^2.29.4", 19 | "moment-precise-range-plugin": "^1.3.0", 20 | "prismarine-auth": "^2.2.0", 21 | "request": "^2.88.2" 22 | }, 23 | "devDependencies": { 24 | "electron": "^21.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /addons/commands/eat.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'eat', 4 | usage: 'eat ', 5 | description: 'Follow a target player.', 6 | useConfig: true, 7 | handler: async function(sender, args) { 8 | let lang = this.config.lang; 9 | if (!bot?.entity) return echo(lang.no_bot); 10 | 11 | utils.eat(14, ['beetroot', 'cooked_beef', 'apple', 'pumpkin_pie']).then(function(item) { 12 | echo(`I ate a(n) ${item.name}`) 13 | }).catch(function(e) { 14 | if(e.message === 'threshold') return echo(`The bot was too full to eat, skipping.`); 15 | if(e.message === 'no_food') return echo(`We have no items to eat!`); 16 | console.log(e) 17 | }); 18 | 19 | 20 | } 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /window/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | height: 100%; 3 | margin: 0; 4 | } 5 | 6 | #terminal { 7 | height: 100%; 8 | min-width: 100%; 9 | overflow-y: hidden; 10 | } 11 | 12 | .box { 13 | display: flex; 14 | flex-flow: column; 15 | height: 100%; 16 | } 17 | 18 | .box .row.content { 19 | flex: 1 1 auto; 20 | } 21 | 22 | .box .row.footer { 23 | flex: 0 1 40px; 24 | } 25 | 26 | .cmd a[href]:not(.terminal-inverted), 27 | .terminal .terminal-output>:not(.raw) a[href]:not(.terminal-inverted), 28 | .terminal.external a[href]:not(.terminal-inverted) { 29 | --link-color: steelblue; 30 | --color: var(--link-color); 31 | text-shadow: 0 0 calc(var(--glow)*5px) var(--color, #ccc); 32 | text-decoration: none; 33 | } 34 | 35 | .footer { 36 | background-color: black; 37 | color: #757575; 38 | padding: 5px; 39 | border-top: 1px solid #353535; 40 | display: block; 41 | } 42 | 43 | #footer-left { 44 | float: left; 45 | } 46 | 47 | #footer-right { 48 | float: right; 49 | padding: 0; 50 | } 51 | 52 | .footer ul li { 53 | display: inline; 54 | } -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /* 3 | threshold - Once bot.food is lower than this, we can eat the item. 4 | filter - (Optional) An array of items to eat ['apple', 'cooked_beef'] 5 | */ 6 | eat: function(threshold, filter = []) { 7 | return new Promise(async function(resolve, reject) { 8 | if (bot.food > threshold) return reject(new Error("threshold")); // The bot had more hunger than the threshold 9 | let items = getItems(); // Get a list of food items sorted by food points (Optional : filter) 10 | if (!items.length) return reject(new Error("no_food")); // We have no edible items 11 | await bot.equip(items[0].id, 'hand'); 12 | await bot.consume() 13 | return resolve(items[0]); 14 | 15 | function getItems() { 16 | let foodByPoints = Object.values(bot.registry.foods).sort((a, b) => b.foodPoints - a.foodPoints); // Sort food items by foodPoints (Yes, I know about foodsByFoodPoints) 17 | let filtered = filter.length ? foodByPoints.filter(i => filter.includes(i.name)) : foodByPoints; // If there's a filter use it, use foodByPoints list 18 | let edible = filtered.filter(i => bot.inventory.items().map(e => e.name).includes(i.name)) 19 | return edible; 20 | } 21 | 22 | }) 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /addons/commands/movement/lookat.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'lookat', 4 | autocomplete: ['players', 'args'], 5 | args: ['north', 'east', 'south', 'west'], 6 | usage: 'lookat [force]', 7 | description: 'Look at a player or direction', 8 | useConfig: true, 9 | handler: async function(sender, args) { 10 | let lang = this.config.lang; 11 | if (!bot?.entity) return echo(lang.no_bot); 12 | if (args.length === 0) return echo(lang.no_argument); 13 | 14 | if(args[0] === 'nearest') { 15 | let target = bot.nearestEntity(e => e.type === 'player'); 16 | if (!target) return echo(lang.no_target_found.replace('{target}', args[0])); 17 | await bot.lookAt(target.position, args[1]); 18 | return echo(lang.started.replace('{target}', args[0])); 19 | } 20 | 21 | if (target = Object.values(bot.players).filter(e => e.username === args[0])[0]?.entity) { 22 | if (!target) return echo(lang.no_target_found.replace('{target}', args[0])); 23 | await bot.lookAt(target.position, args[1]); 24 | return echo(lang.started.replace('{target}', args[0])); 25 | } 26 | 27 | return echo(lang.no_target_found.replace('{target}', args)); 28 | 29 | } 30 | } 31 | }; -------------------------------------------------------------------------------- /window/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } -------------------------------------------------------------------------------- /window/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 19 |
20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /addons/commands/windows/clickWindow.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'clickwindow', 4 | aliases: ['cw'], 5 | usage: 'clickwindow ', // TODO : Integrate just "Slot #" 6 | description: 'Click a specific slot/item in a window.', 7 | handler: async function(sender, args) { 8 | if (!bot?.entity) return echo('There is no bot entity..'); 9 | if (!args[0]) return echo('You must specify a slot or item to click..'); 10 | 11 | if (!bot.currentWindow) return echo('There is no window currently opened..'); 12 | 13 | let slot = args[0]; 14 | if (!isNaN(slot)) { 15 | slot = +slot; // Convert String to Number 16 | echo(`Clicking on slot #${slot}`) 17 | } else { 18 | echo(`Trying to find item ${slot}`) 19 | let item = bot.currentWindow.slots.find(i => i?.name.includes(args[0])) 20 | if(!item) return echo(`Unable to find an item with the name ${args[0]}`) 21 | slot = item.slot; 22 | } 23 | 24 | let type = args[1] || 'left'; 25 | if (type !== 'left' && type !== 'right') return echo(`You must specify a click type. "${this.addon.usage}"`) 26 | 27 | if (type === 'left') bot.simpleClick.leftMouse(slot); 28 | if (type === 'right') bot.simpleClick.rightMouse(slot) 29 | 30 | function isNumeric(str) { 31 | if (typeof str != "string") return false 32 | return !isNaN(str) && !isNaN(parseFloat(str)); 33 | } 34 | } 35 | } 36 | }; -------------------------------------------------------------------------------- /addons/commands/eval.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'eval', 4 | usage: 'eval ', 5 | description: 'Run a segment of code', 6 | handler: async function(sender, args) { 7 | if(sender !== 'CONSOLE') return; 8 | if (!bot?.entity) return echo(lang.no_bot); 9 | 10 | let code = args.join(' '); 11 | 12 | // https://github.com/AnIdiotsGuide/discordjs-bot-guide/blob/master/examples/making-an-eval-command.md 13 | const clean = async (text) => { 14 | // If our input is a promise, await it before continuing 15 | if (text && text.constructor.name == "Promise") text = await text; 16 | 17 | // If the response isn't a string, `util.inspect()` 18 | // is used to 'stringify' the code in a safe way that 19 | // won't error out on objects with circular references 20 | // (like Collections, for example) 21 | if (typeof text !== "string") 22 | text = require("util").inspect(text, { depth: 1 }); 23 | 24 | // Replace symbols with character code alternatives 25 | text = text 26 | .replace(/`/g, "`" + String.fromCharCode(8203)) 27 | .replace(/@/g, "@" + String.fromCharCode(8203)); 28 | 29 | // Send off the cleaned up result 30 | return text; 31 | } 32 | 33 | const evaled = eval(code); 34 | 35 | // Put our eval result through the function 36 | // we defined above 37 | const cleaned = await clean(evaled); 38 | 39 | echo('[[;indianred;]Eval Results:]') 40 | echo(`\n[[;goldenrod;]${cleaned}]\n`) 41 | 42 | } 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /addons/commands/utils/nearby.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'nearby', 4 | aliases: ['near'], 5 | args: ['players', 'mobs'], 6 | autocomplete: ['args'], 7 | usage: 'nearby', 8 | description: 'Show nearby players or mobs.', 9 | useConfig: true, 10 | handler: function(sender, args) { 11 | let lang = this.config.lang; 12 | if (!bot?.entity) return echo(lang.no_bot); 13 | let type = args[0]?.toLowerCase() || 'players'; 14 | 15 | if(!this.args.includes(type)) return echo(lang.unknown_target.replace('{target}', type)); 16 | 17 | let distanceMap = getNearby(type); 18 | if (!distanceMap.length) return echo(lang.no_entities_nearby.replaceAll('{type}', type)); 19 | 20 | echo(lang.distance_msg.replace('{type}', type).replace('{map}', distanceMap.join(', '))); 21 | 22 | function getNearby(type) { 23 | let map = []; 24 | let mapMsg = null; 25 | switch(type) { 26 | case 'mobs': 27 | map = Object.values(bot.entities).filter(e => e.type === 'mob'); 28 | break; 29 | case 'players': 30 | default: 31 | map = Object.values(bot.entities).filter(e => e.type === 'player' && e.username !== bot.username); 32 | break; 33 | } 34 | map = map.sort((a, b) => bot.entity.position.distanceTo(a.position) - bot.entity.position.distanceTo(b.position)); 35 | return map.map(e => lang.distance_map.replaceAll('{name}', e.username || e.mobType).replaceAll('{distance}', Math.floor(bot.entity.position.distanceTo(e.position)))); 36 | } 37 | } 38 | } 39 | }; -------------------------------------------------------------------------------- /addons/commands/combat/autoclicker.js: -------------------------------------------------------------------------------- 1 | const autoClicker = { 2 | running: undefined, 3 | click_interval: 1000, 4 | blacklist: ['experience_orb'], 5 | start: () => { 6 | if (autoClicker.running) return 7 | autoClicker.running = setInterval(async function () { 8 | const entity = bot.entityAtCursor() 9 | if (!entity || autoClicker.blacklist.includes(entity.name)) return bot.swingArm() 10 | bot.attack(entity, true) 11 | }, autoClicker.click_interval) 12 | }, 13 | stop: () => { 14 | autoClicker.running = clearInterval(autoClicker.running) 15 | } 16 | } 17 | 18 | module.exports = { 19 | addon: { 20 | cmd: 'autoclicker', 21 | usage: 'autoclicker [interval {1000ms}]', 22 | description: 'autoclicker..', 23 | useConfig: false, 24 | handler: async function(sender, args) { 25 | 26 | if(!args.length) return term.echo(`[${this.cmd}] ${this.usage}`); 27 | 28 | let interval = args[1] || 1000; 29 | 30 | if(args[0] === 'start') { 31 | if(autoClicker.running) return term.echo('[Clicker] The autoclicker is already running.'); 32 | term.echo(`[Clicker] Now swinging at ${autoClicker.click_interval}ms speed.`); 33 | autoClicker.start(); 34 | } 35 | 36 | if(args[0] === 'stop') { 37 | if(!autoClicker.running) return term.echo('[Clicker] The autoclicker is already off.'); 38 | autoClicker.stop(); 39 | } 40 | if(args[0] === 'speed') { 41 | if(args.length === 1) return term.echo(`[Clicker] The clicker is running at: ${autoClicker.click_interval}`); 42 | let new_speed = args[1]; 43 | autoClicker.click_interval = args[1]; 44 | if(autoClicker.running) { 45 | autoClicker.stop(); 46 | term.echo(`[Clicker] Now swinging at ${autoClicker.click_interval}ms speed.`); 47 | autoClicker.start(); 48 | } 49 | } 50 | 51 | } 52 | } 53 | }; -------------------------------------------------------------------------------- /addons/commands/movement/follow.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'follow', 4 | args: ['nearest', 'stop'], 5 | autocomplete: ['players', 'args'], 6 | usage: 'follow ', 7 | description: 'Follow a target player.', 8 | useConfig: true, 9 | handler: async function(sender, args) { 10 | let lang = this.config.lang; 11 | if (!bot?.entity) return echo(lang.no_bot); 12 | 13 | if(sender !== 'CONSOLE' && args.length === 0) { 14 | // Follow player who ran the command 15 | 16 | let entity = bot.players[sender]?.entity; 17 | 18 | if(!entity) return bot.chat(`/msg ${sender} I cannot see you!`); 19 | 20 | bot.chat(`/msg ${sender} I will now start following you..`); 21 | echo(`[Follow] Now following ${entity.username}`) 22 | 23 | return bot.pathfinder.setGoal(new GoalFollow(entity, 2), true); 24 | } 25 | 26 | if(!args[0]) return echo(lang.no_argument); 27 | 28 | let target = args[0].toLowerCase(); 29 | let entity = null; 30 | 31 | if(target === 'stop') return bot.pathfinder.stop(), echo(lang.stopped); 32 | if(target === 'nearest') { 33 | entity = bot.nearestEntity(e => e.type === 'player'); 34 | if(!entity) return echo(lang.no_target_found.replace('{type}', entity)); 35 | bot.pathfinder.setGoal(new GoalFollow(entity, 2), true); 36 | return echo(lang.started.replace('{target}', entity.username)); 37 | } 38 | 39 | if (target = Object.values(bot.players).filter(e => e.username === args[0])[0]?.entity) { 40 | if (!target) return echo(lang.no_target_found.replace('{target}', args[0])); 41 | bot.pathfinder.setGoal(new GoalFollow(target, 2), true); 42 | return echo(lang.started.replace('{target}', args[0])); 43 | } 44 | 45 | if(!entity) return echo(lang.no_target_found.replace('{type}', target)); 46 | 47 | echo(lang.started.replace('{target}', entity.username)); 48 | 49 | } 50 | } 51 | }; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // main.js 2 | process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; 3 | 4 | var fs = require('fs'); 5 | var settings = JSON.parse(fs.readFileSync('./internal/settings.json')); 6 | 7 | console.log(settings) 8 | 9 | // Modules to control application life and create native browser window 10 | const { app, BrowserWindow, shell, globalShortcut } = require('electron'); 11 | const path = require('path'); 12 | 13 | let mainWindow; 14 | const createWindow = () => { 15 | // Create the browser window. 16 | mainWindow = new BrowserWindow({ 17 | title: `MinePrompt v${require('./package.json').version}`, 18 | width: 900, 19 | minWidth: 500, 20 | height: 500, 21 | webPreferences: { 22 | nodeIntegration: true, 23 | contextIsolation: false, 24 | backgroundThrottling: false // Keep 'false' (Performance drops when window is minimized) 25 | } 26 | }); 27 | 28 | mainWindow.removeMenu(); 29 | 30 | // Send clicked links (such as wiki) to the user's browser 31 | mainWindow.webContents.on('new-window', function(e, url) { 32 | e.preventDefault(); 33 | shell.openExternal(url); 34 | }); 35 | 36 | // and load the index.html of the app. 37 | mainWindow.loadFile('window/index.html'); 38 | 39 | mainWindow.webContents.on('before-input-event', (event, input) => { 40 | if (input.control && input.shift && input.key.toLowerCase() === 'i') { 41 | event.preventDefault(); 42 | mainWindow.webContents.openDevTools(); 43 | } 44 | }); 45 | 46 | if(settings.devtools) mainWindow.webContents.openDevTools(); 47 | 48 | } 49 | 50 | // This method will be called when Electron has finished 51 | // initialization and is ready to create browser windows. 52 | // Some APIs can only be used after this event occurs. 53 | app.whenReady().then(() => { 54 | createWindow(); 55 | 56 | app.on('activate', () => { 57 | // On macOS it's common to re-create a window in the app when the 58 | // dock icon is clicked and there are no other windows open. 59 | if (BrowserWindow.getAllWindows().length === 0) createWindow(); 60 | }); 61 | 62 | }); 63 | 64 | // Quit when all windows are closed, except on macOS. There, it's common 65 | // for applications and their menu bar to stay active until the user quits 66 | // explicitly with Cmd + Q. 67 | app.on('window-all-closed', () => { 68 | if (process.platform !== 'darwin') app.quit() 69 | }); 70 | 71 | // In this file you can include the rest of your app's specific main process 72 | // code. You can also put them in separate files and require them here. -------------------------------------------------------------------------------- /addons/commands/afk.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'afk', 4 | args: ['jump', 'leftclick', 'rightclick', 'sneak', 'rotate'], 5 | autocomplete: ['args'], 6 | aliases: ['away', 'awayfromkeyboard'], 7 | usage: 'afk ', 8 | description: 'Use a method of anti-afk to not be AFK kicked', 9 | useConfig: true, 10 | listeners: [], 11 | intervals: [], 12 | onReload: function() { 13 | this.listeners.forEach(listener => { 14 | if(listener.type === 'bot') bot.removeListener(listener.event, listener.function); 15 | if(listener.type === 'bot._client') bot._client.removeListener(listener.event, listener.function) 16 | }) 17 | this.intervals.forEach(interval => { 18 | clearInterval(interval) 19 | }) 20 | }, 21 | handler: async function(sender, args) { 22 | let lang = this.config.lang; 23 | let settings = this.config.settings; 24 | if (!bot?.entity) return echo(lang.no_bot); 25 | 26 | let method = args[0].toLowerCase(); 27 | let interval = Number(args[1]) || 2000; 28 | 29 | if(!this.args.includes(method)) return echo(lang.unknown_method.replace('{method}', method)); 30 | 31 | echo(lang.starting.replace('{method}', method).replace('{interval}', interval)); 32 | 33 | switch(method) { 34 | case "jump": 35 | this.intervals.push(setInterval(async function() { 36 | bot.setControlState('jump', true); 37 | bot.setControlState('jump', false); 38 | }, interval)) 39 | break; 40 | case "leftclick": 41 | this.intervals.push(setInterval(async function() { 42 | const entity = bot.entityAtCursor(); 43 | if (!entity) return bot.swingArm(); 44 | bot.attack(entity, true); 45 | }, interval)) 46 | break; 47 | case "rightclick": 48 | this.intervals.push(setInterval(async function() { 49 | 50 | let block = bot.blockAtCursor(3.5); 51 | if(block) return bot.activateBlock(block) 52 | if(!block) return bot.activateItem(), bot.deactivateItem(); 53 | 54 | }, interval)) 55 | 56 | // bot.activateBlock(block, direction?: Vec3, cursorPos?: Vec3) 57 | break; 58 | case "sneak": 59 | this.intervals.push(setInterval(async function() { 60 | bot.setControlState('sneak', true); 61 | bot.setControlState('sneak', false); 62 | }, interval)) 63 | break; 64 | case "rotate": 65 | let turns = [1.5708, 3.14159, 4.71239, 6.28319] 66 | let location = 0; 67 | this.intervals.push(setInterval(async function() { 68 | var item = turns[Math.floor(Math.random() * turns.length)]; 69 | await bot.look(item, 0, false) 70 | }, interval)) 71 | break; 72 | } 73 | 74 | } 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /internal/terminal.js: -------------------------------------------------------------------------------- 1 | var appVersion = require('../package.json').version; 2 | 3 | var term_commands = {}; 4 | 5 | function echo(msg) { 6 | term.echo(msg); 7 | } 8 | 9 | var term = $('#terminal').terminal(function(input) { 10 | if (input.length === 0) return; 11 | var command = $.terminal.parse_command(input); 12 | var cmd = command.name; 13 | var args = command.args; 14 | 15 | var cmd_object = Object.entries(term_commands).filter(([a, b]) => b.cmd === cmd || b.aliases?.includes(cmd))?.[0]?.[1]; 16 | 17 | if (!cmd_object) return echo('[[;#FF5555;]Unknown command. Type "help" for help.]'); 18 | cmd_object.handler('CONSOLE', args); 19 | }, { 20 | name: 'mineprompt', 21 | prompt: 'MinePrompt \u00bb ', 22 | autocompleteMenu: true, 23 | greetings: function() { 24 | return ` 25 | __ __ _ ____ v ${appVersion} _ 26 | | \\/ (_)_ __ ___| _ \\ _ __ ___ _ __ ___ _ __ | |_ 27 | | |\\/| | | '_ \\ / _ \\ |_) | '__/ _ \\| '_ ' _ \\| '_ \\| __| 28 | | | | | | | | | __/ __/| | | (_) | | | | | | |_) | |_ 29 | |_| |_|_|_| |_|\\___|_| |_| \\___/|_| |_| |_| .__/ \\__| 30 | |_| 31 | 32 | Consider supporting the developer by upgrading to the [[!;;;;https://discord.gg/5FV56jKwpk]premium version] ([[!;;;;https://discord.gg/5FV56jKwpk]discord]) 33 | `; 34 | }, 35 | onInit: function(term) { 36 | term.echo('Usage:\nconnect -u [username] -h -p [port] -v --auth [true\\false]'); 37 | $('#footer-left').html(`MinePrompt v${appVersion} by Pix3lPirat3#3858`); 38 | $('#footer-right').html(`Documentation`); 39 | }, 40 | keymap: { 41 | "CTRL+R": function() { 42 | // TODO : Optional 'startClient(bot.lastOptions)' when pressing CTRL + R (Ask for confirmation, 5s delay due to Bukkit's connection-delay) 43 | return false; 44 | } 45 | }, 46 | completion: function() { 47 | var term = this; 48 | return new Promise(function(resolve) { 49 | var command = term.get_command(); 50 | var name = command.match(/^([^\s]*)/)[0]; 51 | var list = []; 52 | if (!name) resolve(list); 53 | var word = term.before_cursor(true); 54 | var regex = new RegExp('^' + $.terminal.escape_regex(word)); 55 | if (name == word) { 56 | list = Object.keys(term_commands); 57 | 58 | var arrays = Object.entries(term_commands).map(([a, b]) => b.aliases); 59 | var merged = [].concat.apply([], arrays); 60 | 61 | list = list.concat(merged) 62 | } else if (command.match(/\s/)) { // There was a space, autocomplete args 63 | 64 | // Grab the matched command 65 | var cmd_object = Object.entries(term_commands).filter(([a, b]) => b.aliases?.includes(name) || b.cmd === name)[0]?.[1]; 66 | if (cmd_object) { 67 | // If there is a command object, grab it's tab-completeable arguments 68 | if (cmd_object.autocomplete?.includes('args')) list = list.concat(cmd_object.args); 69 | if (cmd_object.autocomplete?.includes('players') && bot?.players) list = list.concat(Object.keys(bot.players)); 70 | } 71 | } 72 | resolve(list); 73 | }); 74 | } 75 | }); 76 | -------------------------------------------------------------------------------- /addons/commands/movement/goto.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | addon: { 3 | cmd: 'goto', 4 | autocomplete: ['players', 'args'], 5 | args: ['nearest', 'stop'], 6 | usage: 'goto ', 7 | description: 'Go to a player or coordinates.', 8 | useConfig: true, 9 | handler: async function(sender, args) { 10 | let lang = this.config.lang; 11 | if (!bot?.entity) return echo(lang.no_bot); 12 | if(args.length === 0) return echo(lang.no_argument); 13 | 14 | if(args[0] === 'stop') return bot.pathfinder.stop(), echo(lang.stopped); 15 | 16 | if(args[0] === 'nearest') { 17 | let target = bot.nearestEntity(e => e.type === 'player'); 18 | if(!target) return echo(lang.no_target_found.replace('{target}', args[0])); 19 | let { x, y, z } = target.position; 20 | echo(lang.started.replace('{target}', Object.values(target.position).map(i => Math.floor(i)).join(', '))) 21 | try { 22 | await bot.pathfinder.goto(new GoalNear(x, y, z, args[1] || 2)); 23 | return echo(lang.arrived.replace('{target}', Object.values(target.position).map(i => Math.floor(i)).join(', '))) 24 | } catch(e) { 25 | return echo(lang.failed.replace('{target}', Object.values(target.position).map(i => Math.floor(i)).join(', '))) 26 | } 27 | } 28 | 29 | if(target = Object.values(bot.players).filter(e => e.username === args[0])[0]?.entity) { 30 | if(!target) return echo(lang.no_target_found.replace('{target}', args[0])); 31 | let { x, y, z } = target.position; 32 | echo(lang.started.replace('{target}', Object.values(target.position).map(i => Math.floor(i)).join(', '))) 33 | try { 34 | await bot.pathfinder.goto(new GoalNear(x, y, z, args[1] || 2)); 35 | return echo(lang.arrived.replace('{target}', Object.values(target.position).map(i => Math.floor(i)).join(', '))) 36 | } catch(e) { 37 | return echo(lang.failed.replace('{target}', Object.values(target.position).map(i => Math.floor(i)).join(', '))) 38 | } 39 | } 40 | 41 | if(args.length === 2) { 42 | let pos = { x: args[0], z: args[1] }; 43 | echo(lang.started.replace('{target}', Object.values(pos).map(i => Math.floor(i)).join(', '))) 44 | try { 45 | await bot.pathfinder.goto(new GoalNearXZ(pos.x, pos.z, args[2] || 2)); 46 | return echo(lang.arrived.replace('{target}', Object.values(pos).map(i => Math.floor(i)).join(', '))) 47 | } catch(e) { 48 | return echo(lang.failed.replace('{target}', Object.values(pos).map(i => Math.floor(i)).join(', '))) 49 | } 50 | } 51 | 52 | if(args.length === 3) { 53 | let pos = { x: args[0], y: args[1], z: args[2] }; 54 | echo(lang.started.replace('{target}', Object.values(pos).map(i => Math.floor(i)).join(', '))) 55 | try { 56 | await bot.pathfinder.goto(new GoalNear(pos.x, pos.y, pos.z, args[3] || 2)); 57 | return echo(lang.arrived.replace('{target}', Object.values(pos).map(i => Math.floor(i)).join(', '))) 58 | } catch(e) { 59 | return echo(lang.failed.replace('{target}', Object.values(pos).map(i => Math.floor(i)).join(', '))) 60 | } 61 | } 62 | 63 | return echo(lang.no_target_found.replace('{target}', args)); 64 | 65 | } 66 | } 67 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

MinePrompt (DEPRECATED)

2 |

This project is now deprecated, use mineprompt rewritten

3 |

A Mineflayer Terminal created with ElectronJS.

4 | 5 |

6 | 7 | 8 | 9 | 10 |

11 | 12 |

13 | 14 |

15 | 16 |

17 | 18 |

19 | 20 | --- 21 | 22 | Shield: [![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa] 23 | 24 | This work is licensed under a 25 | [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License][cc-by-nc-sa]. 26 | 27 | [![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa] 28 | 29 | [cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/ 30 | [cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png 31 | [cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg 32 | 33 | --- 34 | 35 | ### Notice 36 | You can check out the updated version of MinePrompt at https://discord.gg/5FV56jKwpk 37 | 38 | If you'd like support for using [Mineflayer](https://github.com/PrismarineJS/mineflayer/) check out their [Discord](https://discord.gg/sMvsKNvPc5) 39 | 40 | ### Usage 41 | 42 | Usage Video: [Pix3lPirat3's Usage YouTube](https://www.youtube.com/watch?v=CK3QPQXZloQ&ab_channel=Pix3lPirat3) 43 | 44 | Create your copy of the repository on your system, go to the directory, then install the modules. This includes [ElectronJS](https://www.npmjs.com/package/electron) 45 | ```bash 46 | npm i 47 | npm i electron -g 48 | ``` 49 | 50 | Start the terminal by running 51 | ```bash 52 | electron . 53 | ``` 54 | or 55 | ```bash 56 | npm run start 57 | ``` 58 | 59 | ### Reload Warning 60 | 61 | Using the `reload` command reloads the **commands system and language files (only)** by reading and loading the command files into memory. This may cause issues with any events registered in command listeners, as they're set on variables that are not reloaded, such as `bot`. 62 | 63 | ### Planned Features 64 | 65 | - [ ] Settings Command `settings developer.openConsole true` 66 | - [ ] Discord Addon (+ implement handling multiple programs open) 67 | - [x] Translations System *(A way for addons to register messages)* 68 | 69 | ### Commands 70 | *This list is not in any specific order* 71 | 72 | - [x] Nearby `nearby ` (Get the nearby players / mobs) 73 | - [x] Follow `follow ` (Follow a player) 74 | - [x] Goto `goto ` (Go to a player, or coordinates) 75 | - [x] Lookat `lookat ` (Look at a specific player, direction, or block) 76 | - [x] Eat `eat [item]` (Eat an item (sorted by food points), optionally specify an item) 77 | - [x] Players `players` (Get a list of online players) 78 | - [x] Quit `quit` (Gracefully quits the server) 79 | - [x] AFK `afk ` (Use a specific method of anti-afk, such as left/right clicking, jumping, moving, and so on) 80 | - [x] Chat `chat ` (Sends your message to the in-game chat) 81 | - [x] Cmd `cmd ` (Sends your command to the in-game chat) 82 | - [x] Eval `eval ` (Evaluates the specified code, returns the result) 83 | - [x] Addowner `addowner ` (Adds player as a master - to use in-game commands) 84 | - [x] Removeowner `removeowner ` (Removes player as a master) 85 | - [ ] Settings `settings ` (Set a value in the settings) 86 | - [ ] Inventory `inventory` (Show the player's inventory) 87 | - [ ] Drop `drop [amount]` (Drop items from inventory) 88 | - [ ] Collect `collect [item] [amount]` (Collect nearby items) 89 | - [ ] Harvest `harvest [amount]` (Harvest nearby blocks) 90 | - [ ] Autoclicker `autoclicker [jitter]` (Autoclicker - Jitter click (randomize position)) 91 | - [ ] Equip `equip [slot]` (Equip an item to hand, or armor to armor slots) 92 | - [ ] Mend `mend ` (Equip items with mending in the offhand, once repaired switch and repeat) 93 | - [ ] Fish `fish [amount] [saveDurability]` (Fish, a specific amount, and whether to save durability or not) 94 | - [ ] Build `build ` (Advanced command, will be a way-later-project, and definitely will have tons of flaws) 95 | - [ ] Move `move [amount]` (Move a specific amount of blocks in a direction) 96 | - [ ] Farm `farm [time] [region]` (Farm a crop for an optional time, and in an optional region. Storage chests can be defined) 97 | - [ ] Quarry `quarry [depth]` (Quarry a chunk to a specific depth / Y coordinate) 98 | - [ ] Mineshaft `mineshaft ` (Create a mineshaft at current coordinates, branch mining) 99 | - [ ] Generator `generator [saveDurability] [switchTools] [mendingOnly]` (Stationary mining, e.g. cobblestone generators) 100 | 101 | ### License 102 | 103 | This project uses the [MIT](https://github.com/Pix3lPirat3/mineprompt/blob/main/LICENSE) license. 104 | 105 | ### Contributions 106 | 107 | You're welcome create a PR, and report issues. You can do that via GitHub Issues or via Discord. 108 | -------------------------------------------------------------------------------- /internal/mineflayer.js: -------------------------------------------------------------------------------- 1 | var mineflayer = require('mineflayer'); 2 | const { Vec3 } = require('vec3'); 3 | var utils = require('./../utils.js'); 4 | 5 | const Movements = require('mineflayer-pathfinder').Movements; 6 | const { GoalNear, GoalNearXZ, GoalBlock, GoalXZ, GoalY, GoalInvert, GoalFollow, GoalBreakBlock } = require('mineflayer-pathfinder').goals; 7 | const pathfinder = require('mineflayer-pathfinder').pathfinder; 8 | 9 | var moment = require('moment'); 10 | require('moment-precise-range-plugin'); 11 | 12 | var bot = null; 13 | 14 | var formatterRegistered = false; 15 | 16 | // Set everything in "commander" then load via bot.commander. 17 | var commander = require('../internal/addonManager'); 18 | commander.getCommands(); 19 | 20 | async function startClient(options) { 21 | 22 | echo(`\n[[;#FFA500;]Connect] [[;#777777;]\u00bb] Connecting [[;#FFA500;]${options.username}] to [[;#FFA500;]${options.host}]..\n`) 23 | 24 | bot = mineflayer.createBot(options); 25 | 26 | bot.lastOptions = options; // Used in the 'reconnect' module 27 | 28 | bot.loadPlugin(pathfinder); 29 | 30 | // TODO: Disable building/breaking by default 31 | var defaultMove = new Movements(bot); 32 | defaultMove.allow1by1towers = false // Do not build 1x1 towers when going up 33 | defaultMove.canDig = false // Disable breaking of blocks when pathing 34 | bot.pathfinder.setMovements(defaultMove); 35 | 36 | bot.on('error', function(reason) { 37 | echo(`[Error] There was a client error:\n[[;#FF5555;]${reason}]`); 38 | }) 39 | bot.on('kicked', function(reason) { 40 | echo(`[Kicked] The client was kicked:\n[[;#FF5555;]${reason}]`); 41 | }) 42 | 43 | bot.mineprompt = { 44 | masters: [] // Pix3lPirat3, Pix3lSlime 45 | } 46 | 47 | let prefix = '!'; 48 | bot.on('chat', function(username, message) { 49 | if(!message.startsWith('!')) return; 50 | if(!bot.mineprompt.masters.includes(username)) return; 51 | 52 | const args = message.slice(prefix.length).trim().split(/ +/g); 53 | const command = args.shift().toLowerCase(); 54 | 55 | var cmd_object = Object.entries(term_commands).filter(([a, b]) => b.cmd === command || b.aliases?.includes(command))?.[0]?.[1]; 56 | if(!cmd_object) return; 57 | 58 | cmd_object.handler(username, args); 59 | }) 60 | 61 | bot.on('spawn', function() { 62 | let pos = bot.entity.position.floored(); 63 | echo(`[Events] [Spawn] ${bot.username} has spawned. (Position: X: ${pos.x}, Y: ${pos.y}, Z: ${pos.z})`) 64 | }) 65 | 66 | var sessionStart, sessionEnd, sessionTimer, sessionRuntime; 67 | 68 | bot.once('spawn', function() { 69 | sessionStart = moment(Date.now()); 70 | term.set_prompt(`${bot.username} \u00bb `) 71 | 72 | // Highlight the player's name when mentioned in chat (Optional: sound) 73 | 74 | if (!formatterRegistered) { 75 | $.terminal.new_formatter(function(string, options) { 76 | if (options.echo) return string.replace(new RegExp(bot?.username || 'NULL', 'gi'), `[[;goldenrod;]${bot?.username}]`); 77 | }); 78 | } 79 | 80 | sessionTimer = setInterval(function() { 81 | sessionRuntime = moment.preciseDiff(sessionStart, Date.now()); 82 | if(!bot?.entity) return; 83 | let pos = bot.entity.position.floored(); 84 | $('#footer-left').text(`Runtime: ${sessionRuntime}`); 85 | $('#footer-right').text(`Health: ${bot.health} | Hunger: ${bot.food} | Position: ${pos}`); 86 | }, 1000) 87 | }) 88 | 89 | bot.once('end', function(reason) { 90 | if (chatLogger) chatLogger.end(); 91 | echo(`\n[End]\n\n[[;#FF5555;]Session Ended]\n${bot.username}'s connection ended: [[;#FF5555;]${reason}]\nSession Runtime: [[;goldenrod;]${sessionRuntime}]\n`) 92 | sessionTimer = clearInterval(sessionTimer); 93 | $('#footer-left').text(`OFFLINE`); 94 | $('#footer-right').text(`Runtime: ENDED`); 95 | bot = null; 96 | }) 97 | 98 | bot.on('death', function() { 99 | echo(`[Death] You died..`) 100 | }) 101 | 102 | bot.on('entitySpawn', function(e) { 103 | if (e.type !== 'player' || e.username === bot.username) return; 104 | var distance = Math.floor(bot.entity.position.distanceTo(e.position)); 105 | echo(`[PlayerSpawn] I see ${e.username}, they are ${distance} blocks away`) 106 | }) 107 | 108 | bot.on('entityGone', function(e) { 109 | if (e.type !== 'player' || e.username === bot.username) return; 110 | var distance = Math.floor(bot.entity.position.distanceTo(e.position)); 111 | echo(`[PlayerSpawn] I no longer see ${e.username}, they were ${distance} blocks away`) 112 | }); 113 | 114 | // Chat Listener 115 | var chatPattern = /^(?:\[?(.*?)?\])?\s?(?:\[?(.*?)?\])?\s?([A-Za-z0-9_][^\s]*)\s?(?:\[?(.*?)?\])?\s?(?::|»|>>) (.*)/ 116 | bot.on('messagestr', function(message) { 117 | if (!chatPattern.test(message)) { 118 | echo(`» ${message}`) 119 | return; 120 | } 121 | var parts = chatPattern.exec(message); 122 | 123 | var group = parts[1]; 124 | var tag = parts[2]; 125 | var displayname = parts[3]; 126 | var suffix = parts[4]; 127 | var message = parts[5]; 128 | 129 | bot.emit('chat:formatted', group, tag, displayname, suffix, message); 130 | 131 | }) 132 | 133 | var dateMonthDayYear = new Date().toLocaleString().split(',')[0].replaceAll('/', '-'); // M-DD-YYYY 134 | let chatLogger; // Opened once chat is spoken, saves on files and memory. 135 | 136 | bot.on('chat:formatted', function(group, tag, username, suffix, message) { 137 | if (!chatLogger) chatLogger = fs.createWriteStream(`chat-${dateMonthDayYear}.logs`, { flags: 'a', encoding: 'UTF-8' }); // Only open if needed 138 | 139 | message = message.replaceAll('§', ''); // Remove the Minecraft (Minecraft uses § in the backend) color codes from the message 140 | echo(`[Chat] [${group}] ${username} » ${message}`); 141 | chatLogger.write(`[${group}] ${username} » ${message}\n`); 142 | }) 143 | 144 | } 145 | 146 | function loadAddons() { 147 | 148 | } -------------------------------------------------------------------------------- /internal/addonManager.js: -------------------------------------------------------------------------------- 1 | let fs = require('fs'); 2 | let glob = require("glob"); 3 | let path = require('path'); 4 | const parseSentence = require('minimist-string'); 5 | 6 | module.exports = { 7 | 8 | getCommands: function() { 9 | 10 | if(bot) { 11 | bot.pathfinder?.stop(); 12 | bot.stopDigging(); 13 | bot.clearControlStates(); 14 | } 15 | 16 | Object.values(term_commands).forEach(function(e) { 17 | if(e.onReload) e.onReload(); 18 | }); 19 | 20 | // Default Commands 21 | term_commands = { 22 | connect: { 23 | cmd: 'connect', 24 | aliases: ['conn'], 25 | usage: 'connect -u [username] -h -p [port] -v -auth [true\\false]', 26 | description: 'Connect to a server', 27 | handler: function(sender, args) { 28 | 29 | let opts = parseSentence(args.join(' ')); 30 | 31 | // NOTE : When using shorthand (-host) only one `-` is needed, when using longhand (--host) two are needed. 32 | let username = opts.u || opts.username; 33 | if(!username) username = 'Anonymous' + generateNumber(7), opts.v, opts.auth = false; // If no username is specified - use Anyonymous and disable authentication 34 | let host = opts.h || opts.host; 35 | if(!host) return echo('You must specify a host with -h or --host') 36 | let port = opts.p || opts.port; 37 | if(!port) echo('You can specify a port with -p or --port') 38 | let version = opts.v || opts.version; 39 | if(!version) return echo('You must specify a version with -v or --version') 40 | let authentication = opts.a || opts.auth; // (Default: true) 41 | if(!authentication) echo('You can specify authentication with -a or --auth (-a=true/false)') 42 | // Converting the "String" passed from the input to a Boolean (There must be a better way..) 43 | if(authentication === 'false' || authentication === '0') authentication = false; // Convert to Boolean 44 | if(authentication === 'true' || authentication === '1' || authentication == undefined) authentication = true; // Convert to Boolean 45 | 46 | let options = { 47 | username: username, 48 | host: host, 49 | port: port, 50 | version: version, 51 | auth: authentication ? 'microsoft' : undefined, 52 | skipValidation: !authentication, 53 | onMsaCode: function(data) { 54 | echo(`Use the code "${data.user_code}" on ${data.verification_uri} to authenticate your account.`) 55 | echo(`If you don't want to authenticate then add '-a false' (or --auth false)`) 56 | } 57 | } 58 | 59 | startClient(options); 60 | 61 | // Generates a number (l being length of digits) 62 | function generateNumber(length) { 63 | var add = 1, max = 12 - add; // 12 is the min safe number Math.random() can generate without it starting to pad the end with zeros. 64 | if (length > max) return generate(max) + generate(length - max); 65 | max = Math.pow(10, length + add); 66 | var min = max / 10; // Math.pow(10, length) basically 67 | var number = Math.floor(Math.random() * (max - min + 1)) + min; 68 | return ("" + number).substring(add); 69 | } 70 | } 71 | }, 72 | reload: { 73 | cmd: 'reload', 74 | description: 'Reload the command system', 75 | handler: function(sender, args) { 76 | echo(`\n[[;#FFA500;]Reload] [[;#777777;]\u00bb] Reloading the command manager..`); 77 | echo(`[[;#FFA500;]Warning] [[;#777777;]\u00bb] This causes issues with events, timers, and more.. ([[!;;;;https://github.com/Pix3lPirat3/mineprompt#reload-warning]Wiki])\n`); 78 | return commander.getCommands(); 79 | } 80 | }, 81 | help: { 82 | cmd: 'help', 83 | description: 'Display the help menu', 84 | handler: function() { 85 | if (!bot?.entity) return echo(term_commands.connect.usage); 86 | return echo('\n[[;#FFA500;]MinePrompt Commands:]\n' + Object.entries(term_commands).map(([a, b]) => `"${b.cmd}" \u00bb "${b.description}"`).join('\n') + '\n'); 87 | } 88 | } 89 | }; // Reset the term_commands object, prevent duplicates, and incase command files are removed 90 | 91 | let command_files = this.getFiles('commands'); 92 | command_files.forEach(function(addon) { 93 | try { 94 | delete require.cache[require.resolve(addon)]; 95 | 96 | let mineprompt_addon = require(addon); 97 | 98 | if(mineprompt_addon.addon.useConfig) { 99 | let fileName = path.basename(addon); 100 | let filePath = `${__dirname}/../addons/configs/${fileName.replace('js', 'json')}`; 101 | if(!fs.existsSync(filePath)) fs.writeFileSync(filePath, '{}'); 102 | mineprompt_addon.addon.config = JSON.parse(fs.readFileSync(filePath)); 103 | } 104 | 105 | var cmd = mineprompt_addon.addon.cmd; 106 | if (term_commands[cmd]) return echo(`[[;#FF5555;]Error] [[;#777777;]\u00bb] There was a repeated command "[[;#FF5555;]${cmd}]" in file "[[;#FF5555;]${addon}]"`); 107 | term_commands[cmd] = mineprompt_addon.addon; 108 | } catch (e) { 109 | echo(`[[;#FF5555;]Error] [[;#777777;]\u00bb] Unable to load the command file "[[;#FF5555;]${addon}]", skipping it.. [[;#FFA500;](Check Console)]`); 110 | console.log(`\nUnable to load the command file "${addon}", skipping it:\n`, e, '\n'); 111 | } 112 | }); 113 | 114 | console.log(`MinePrompt » Registered [${Object.keys(term_commands).length}] commands..`) 115 | 116 | }, 117 | 118 | getListeners: function() { 119 | // TODO : Implement when needed 120 | }, 121 | 122 | // Get all command files inside /addons/commands/*, recursively to allow sorting commands 123 | getFiles: function(type) { 124 | return glob.sync(`./addons/commands/**/*.js`, { realpath: true, absolute: true }); 125 | } 126 | 127 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-NonCommercial-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International 58 | Public License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-NonCommercial-ShareAlike 4.0 International Public License 63 | ("Public License"). To the extent this Public License may be 64 | interpreted as a contract, You are granted the Licensed Rights in 65 | consideration of Your acceptance of these terms and conditions, and the 66 | Licensor grants You such rights in consideration of benefits the 67 | Licensor receives from making the Licensed Material available under 68 | these terms and conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-NC-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution, NonCommercial, and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. NonCommercial means not primarily intended for or directed towards 126 | commercial advantage or monetary compensation. For purposes of 127 | this Public License, the exchange of the Licensed Material for 128 | other material subject to Copyright and Similar Rights by digital 129 | file-sharing or similar means is NonCommercial provided there is 130 | no payment of monetary compensation in connection with the 131 | exchange. 132 | 133 | l. Share means to provide material to the public by any means or 134 | process that requires permission under the Licensed Rights, such 135 | as reproduction, public display, public performance, distribution, 136 | dissemination, communication, or importation, and to make material 137 | available to the public including in ways that members of the 138 | public may access the material from a place and at a time 139 | individually chosen by them. 140 | 141 | m. Sui Generis Database Rights means rights other than copyright 142 | resulting from Directive 96/9/EC of the European Parliament and of 143 | the Council of 11 March 1996 on the legal protection of databases, 144 | as amended and/or succeeded, as well as other essentially 145 | equivalent rights anywhere in the world. 146 | 147 | n. You means the individual or entity exercising the Licensed Rights 148 | under this Public License. Your has a corresponding meaning. 149 | 150 | 151 | Section 2 -- Scope. 152 | 153 | a. License grant. 154 | 155 | 1. Subject to the terms and conditions of this Public License, 156 | the Licensor hereby grants You a worldwide, royalty-free, 157 | non-sublicensable, non-exclusive, irrevocable license to 158 | exercise the Licensed Rights in the Licensed Material to: 159 | 160 | a. reproduce and Share the Licensed Material, in whole or 161 | in part, for NonCommercial purposes only; and 162 | 163 | b. produce, reproduce, and Share Adapted Material for 164 | NonCommercial purposes only. 165 | 166 | 2. Exceptions and Limitations. For the avoidance of doubt, where 167 | Exceptions and Limitations apply to Your use, this Public 168 | License does not apply, and You do not need to comply with 169 | its terms and conditions. 170 | 171 | 3. Term. The term of this Public License is specified in Section 172 | 6(a). 173 | 174 | 4. Media and formats; technical modifications allowed. The 175 | Licensor authorizes You to exercise the Licensed Rights in 176 | all media and formats whether now known or hereafter created, 177 | and to make technical modifications necessary to do so. The 178 | Licensor waives and/or agrees not to assert any right or 179 | authority to forbid You from making technical modifications 180 | necessary to exercise the Licensed Rights, including 181 | technical modifications necessary to circumvent Effective 182 | Technological Measures. For purposes of this Public License, 183 | simply making modifications authorized by this Section 2(a) 184 | (4) never produces Adapted Material. 185 | 186 | 5. Downstream recipients. 187 | 188 | a. Offer from the Licensor -- Licensed Material. Every 189 | recipient of the Licensed Material automatically 190 | receives an offer from the Licensor to exercise the 191 | Licensed Rights under the terms and conditions of this 192 | Public License. 193 | 194 | b. Additional offer from the Licensor -- Adapted Material. 195 | Every recipient of Adapted Material from You 196 | automatically receives an offer from the Licensor to 197 | exercise the Licensed Rights in the Adapted Material 198 | under the conditions of the Adapter's License You apply. 199 | 200 | c. No downstream restrictions. You may not offer or impose 201 | any additional or different terms or conditions on, or 202 | apply any Effective Technological Measures to, the 203 | Licensed Material if doing so restricts exercise of the 204 | Licensed Rights by any recipient of the Licensed 205 | Material. 206 | 207 | 6. No endorsement. Nothing in this Public License constitutes or 208 | may be construed as permission to assert or imply that You 209 | are, or that Your use of the Licensed Material is, connected 210 | with, or sponsored, endorsed, or granted official status by, 211 | the Licensor or others designated to receive attribution as 212 | provided in Section 3(a)(1)(A)(i). 213 | 214 | b. Other rights. 215 | 216 | 1. Moral rights, such as the right of integrity, are not 217 | licensed under this Public License, nor are publicity, 218 | privacy, and/or other similar personality rights; however, to 219 | the extent possible, the Licensor waives and/or agrees not to 220 | assert any such rights held by the Licensor to the limited 221 | extent necessary to allow You to exercise the Licensed 222 | Rights, but not otherwise. 223 | 224 | 2. Patent and trademark rights are not licensed under this 225 | Public License. 226 | 227 | 3. To the extent possible, the Licensor waives any right to 228 | collect royalties from You for the exercise of the Licensed 229 | Rights, whether directly or through a collecting society 230 | under any voluntary or waivable statutory or compulsory 231 | licensing scheme. In all other cases the Licensor expressly 232 | reserves any right to collect such royalties, including when 233 | the Licensed Material is used other than for NonCommercial 234 | purposes. 235 | 236 | 237 | Section 3 -- License Conditions. 238 | 239 | Your exercise of the Licensed Rights is expressly made subject to the 240 | following conditions. 241 | 242 | a. Attribution. 243 | 244 | 1. If You Share the Licensed Material (including in modified 245 | form), You must: 246 | 247 | a. retain the following if it is supplied by the Licensor 248 | with the Licensed Material: 249 | 250 | i. identification of the creator(s) of the Licensed 251 | Material and any others designated to receive 252 | attribution, in any reasonable manner requested by 253 | the Licensor (including by pseudonym if 254 | designated); 255 | 256 | ii. a copyright notice; 257 | 258 | iii. a notice that refers to this Public License; 259 | 260 | iv. a notice that refers to the disclaimer of 261 | warranties; 262 | 263 | v. a URI or hyperlink to the Licensed Material to the 264 | extent reasonably practicable; 265 | 266 | b. indicate if You modified the Licensed Material and 267 | retain an indication of any previous modifications; and 268 | 269 | c. indicate the Licensed Material is licensed under this 270 | Public License, and include the text of, or the URI or 271 | hyperlink to, this Public License. 272 | 273 | 2. You may satisfy the conditions in Section 3(a)(1) in any 274 | reasonable manner based on the medium, means, and context in 275 | which You Share the Licensed Material. For example, it may be 276 | reasonable to satisfy the conditions by providing a URI or 277 | hyperlink to a resource that includes the required 278 | information. 279 | 3. If requested by the Licensor, You must remove any of the 280 | information required by Section 3(a)(1)(A) to the extent 281 | reasonably practicable. 282 | 283 | b. ShareAlike. 284 | 285 | In addition to the conditions in Section 3(a), if You Share 286 | Adapted Material You produce, the following conditions also apply. 287 | 288 | 1. The Adapter's License You apply must be a Creative Commons 289 | license with the same License Elements, this version or 290 | later, or a BY-NC-SA Compatible License. 291 | 292 | 2. You must include the text of, or the URI or hyperlink to, the 293 | Adapter's License You apply. You may satisfy this condition 294 | in any reasonable manner based on the medium, means, and 295 | context in which You Share Adapted Material. 296 | 297 | 3. You may not offer or impose any additional or different terms 298 | or conditions on, or apply any Effective Technological 299 | Measures to, Adapted Material that restrict exercise of the 300 | rights granted under the Adapter's License You apply. 301 | 302 | 303 | Section 4 -- Sui Generis Database Rights. 304 | 305 | Where the Licensed Rights include Sui Generis Database Rights that 306 | apply to Your use of the Licensed Material: 307 | 308 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 309 | to extract, reuse, reproduce, and Share all or a substantial 310 | portion of the contents of the database for NonCommercial purposes 311 | only; 312 | 313 | b. if You include all or a substantial portion of the database 314 | contents in a database in which You have Sui Generis Database 315 | Rights, then the database in which You have Sui Generis Database 316 | Rights (but not its individual contents) is Adapted Material, 317 | including for purposes of Section 3(b); and 318 | 319 | c. You must comply with the conditions in Section 3(a) if You Share 320 | all or a substantial portion of the contents of the database. 321 | 322 | For the avoidance of doubt, this Section 4 supplements and does not 323 | replace Your obligations under this Public License where the Licensed 324 | Rights include other Copyright and Similar Rights. 325 | 326 | 327 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 328 | 329 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 330 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 331 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 332 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 333 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 334 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 335 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 336 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 337 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 338 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 339 | 340 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 341 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 342 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 343 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 344 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 345 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 346 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 347 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 348 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 349 | 350 | c. The disclaimer of warranties and limitation of liability provided 351 | above shall be interpreted in a manner that, to the extent 352 | possible, most closely approximates an absolute disclaimer and 353 | waiver of all liability. 354 | 355 | 356 | Section 6 -- Term and Termination. 357 | 358 | a. This Public License applies for the term of the Copyright and 359 | Similar Rights licensed here. However, if You fail to comply with 360 | this Public License, then Your rights under this Public License 361 | terminate automatically. 362 | 363 | b. Where Your right to use the Licensed Material has terminated under 364 | Section 6(a), it reinstates: 365 | 366 | 1. automatically as of the date the violation is cured, provided 367 | it is cured within 30 days of Your discovery of the 368 | violation; or 369 | 370 | 2. upon express reinstatement by the Licensor. 371 | 372 | For the avoidance of doubt, this Section 6(b) does not affect any 373 | right the Licensor may have to seek remedies for Your violations 374 | of this Public License. 375 | 376 | c. For the avoidance of doubt, the Licensor may also offer the 377 | Licensed Material under separate terms or conditions or stop 378 | distributing the Licensed Material at any time; however, doing so 379 | will not terminate this Public License. 380 | 381 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 382 | License. 383 | 384 | 385 | Section 7 -- Other Terms and Conditions. 386 | 387 | a. The Licensor shall not be bound by any additional or different 388 | terms or conditions communicated by You unless expressly agreed. 389 | 390 | b. Any arrangements, understandings, or agreements regarding the 391 | Licensed Material not stated herein are separate from and 392 | independent of the terms and conditions of this Public License. 393 | 394 | 395 | Section 8 -- Interpretation. 396 | 397 | a. For the avoidance of doubt, this Public License does not, and 398 | shall not be interpreted to, reduce, limit, restrict, or impose 399 | conditions on any use of the Licensed Material that could lawfully 400 | be made without permission under this Public License. 401 | 402 | b. To the extent possible, if any provision of this Public License is 403 | deemed unenforceable, it shall be automatically reformed to the 404 | minimum extent necessary to make it enforceable. If the provision 405 | cannot be reformed, it shall be severed from this Public License 406 | without affecting the enforceability of the remaining terms and 407 | conditions. 408 | 409 | c. No term or condition of this Public License will be waived and no 410 | failure to comply consented to unless expressly agreed to by the 411 | Licensor. 412 | 413 | d. Nothing in this Public License constitutes or may be interpreted 414 | as a limitation upon, or waiver of, any privileges and immunities 415 | that apply to the Licensor or You, including from the legal 416 | processes of any jurisdiction or authority. 417 | 418 | ======================================================================= 419 | 420 | Creative Commons is not a party to its public 421 | licenses. Notwithstanding, Creative Commons may elect to apply one of 422 | its public licenses to material it publishes and in those instances 423 | will be considered the “Licensor.” The text of the Creative Commons 424 | public licenses is dedicated to the public domain under the CC0 Public 425 | Domain Dedication. Except for the limited purpose of indicating that 426 | material is shared under a Creative Commons public license or as 427 | otherwise permitted by the Creative Commons policies published at 428 | creativecommons.org/policies, Creative Commons does not authorize the 429 | use of the trademark "Creative Commons" or any other trademark or logo 430 | of Creative Commons without its prior written consent including, 431 | without limitation, in connection with any unauthorized modifications 432 | to any of its public licenses or any other arrangements, 433 | understandings, or agreements concerning use of licensed material. For 434 | the avoidance of doubt, this paragraph does not form part of the 435 | public licenses. 436 | 437 | Creative Commons may be contacted at creativecommons.org. 438 | -------------------------------------------------------------------------------- /window/js/jquery-3.6.0.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0