@mincraft/cli 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{Option as O,program as l}from"commander";function F(t){let o=[],e="",r=0;for(;r<t.length;)t[r]==="\\"&&r+1<t.length?(e+=t[r]+t[r+1],r+=2):t[r]===","?(o.push(e),e="",r++):(e+=t[r],r++);return o.push(e),o}function T(t){let o="",e=0;for(;e<t.length;)if(t[e]==="\\"&&e+1<t.length){let r=t[e+1];r===","||r==="{"||r==="}"?(o+=r,e+=2):(o+=t[e],e++)}else o+=t[e],e++;return o}function C(t){let o=[],e=F(t),r=/^\{\{(\d+(?:\.\d+)?)\}\}$/;for(let s of e){let n=s.trim();if(!n)continue;let a=n.match(r);if(a){let i=parseFloat(a[1]),c=Math.round(i*1e3);o.push({command:"",delay:c})}else{let i=T(n);o.push({command:i,delay:0})}}return o}import*as E from"readline";import p from"chalk";import{createBot as A}from"mineflayer";import{SocksClient as D}from"socks";var u=class{proxy;client;server;options;logger;isLoggedIn;bot;constructor({proxy:o,client:e,server:r,options:s},n){this.proxy=o,this.client=e,this.server=r,this.options=s,this.logger=n,this.isLoggedIn=!1}async registerAndLogIn(){let o={host:this.server.host,port:this.server.port,username:this.client.account.email,auth:this.client.account.auth,version:this.client.version,hideErrors:!0};this.proxy&&(o.connect=e=>{this.connectViaProxy(e)}),this.bot=A(o),this.options.verboseLogging&&this.registerClientEvents(),this.registerBotEvents()}connectViaProxy(o){this.logger.log("connecting via proxy");let{host:e,port:r,user:s,pass:n,type:a}=this.proxy,i=this.server;D.createConnection({proxy:{host:e,port:r,type:a,userId:s,password:n},command:"connect",destination:{host:i.host,port:i.port},timeout:3e4}).then(c=>{o.setSocket(c.socket),o.emit("connect")}).catch(c=>{this.logger.error(`proxy connection failed: ${c.message}`),o.emit("error",c)})}registerClientEvents(){this.bot._client.on("connect",()=>{this.logger.log("TCP connection established")}),this.bot._client.on("login",()=>{this.logger.log("login packet received")}),this.bot._client.on("error",o=>{this.logger.error(`client error: ${o.message}`)}),this.bot._client.on("end",o=>{this.logger.warn(`client ended: ${o}`)})}registerBotEvents(){this.bot.once("spawn",()=>{let{ign:o,uuid:e}=this.client.account;this.logger.log(`logged in as ${o} (${e})`),this.isLoggedIn=!0}),this.bot.once("kicked",o=>{this.logger.warn(`kicked: ${JSON.stringify(o)}`),this.disconnect()}),this.bot.once("error",o=>{this.logger.error(`bot error: ${o.message}`),this.isLoggedIn=!1}),this.bot.once("end",o=>{this.logger.warn(`disconnected by server: ${JSON.stringify(o)}`),this.disconnect()}),this.options.logMessages&&this.bot.on("messagestr",o=>{let e=o.split(`
3
- `);if(e.length===1)this.logger.log(o,"chat");else{this.logger.log(e[0],"chat");for(let r=1;r<e.length;r++)this.logger.raw(` ${e[r]}`)}})}disconnect(){this.bot&&(this.proxy?this.bot._client.socket?.destroy():this.bot.quit(),this.isLoggedIn=!1)}sendMessage(o){this.bot.chat(o)}};import*as y from"readline";import h from"chalk";function U(t){return t?`/${t.split("/").map((r,s)=>s===0?r==="err"?h.red(r):r==="warn"?h.yellow(r):h.gray(r):h.blue(r)).join("/")}`:""}function m(t,o){let e=(s,n="")=>{let a=o?n?`${o}/${n}`:o:n;return`[mc${U(a)}] ${s}`},r=s=>{t?(y.clearLine(process.stdout,0),y.cursorTo(process.stdout,0),console.log(s),t.prompt(!0)):console.log(s)};return{log:(s,n)=>r(e(s,n)),warn:(s,n="warn")=>r(e(s,n)),error:(s,n="err")=>r(e(s,n)),raw:r}}import*as f from"fs/promises";import*as d from"path";import*as $ from"esbuild";async function j(t){let e=(await $.build({entryPoints:[t],bundle:!0,write:!1,platform:"node",format:"esm",target:"es2022",loader:{". ts":"ts"},external:["mineflayer"],logLevel:"silent"})).outputFiles[0].text,r=t.replace(/\.ts$/,". macro.mjs");return await f.writeFile(r,e),r}async function B(t){try{await f.unlink(t)}catch{}}function N(t){return d.isAbsolute(t)?t:d.resolve(process.cwd(),t)}async function R(t){try{return await f.access(t),!0}catch{return!1}}function _(t){return d.basename(t).replace(/\.(ts|js|mjs)$/,"")}async function L(t,o,e){let r=N(t),s=r,n=null,a=m(e,`macro/${_(t)}`);try{if(!await R(r))return a.error(`file not found: ${r}`),!1;r.endsWith(".ts")&&(a.log("compiling macro to js"),n=await j(r),s=n);let g=await import(`file://${s}?t=${Date.now()}`);return typeof g.default!="function"?(a.error("macro file must export a default function"),!1):(a.log("running"),await g.default({bot:o,logger:a}),a.log("finished"),!0)}catch(i){return a.error(`failed: ${i.message}`),!1}finally{n&&await B(n)}}var x="v1.5.1";var P=(n=>(n.Exit=".exit",n.Logout=".lo",n.Login=".li",n.Macro=".macro",n.Help=".help",n))(P||{});function I(t){return Object.values(P).some(o=>t.startsWith(o))}function H(t,o){t(`type ${p.magenta(".li")} to log in to ${o}`),t(`type ${p.magenta(".lo")} to log out from ${o}`),t(`type ${p.magenta(".macro <filepath>")} to run a macro`),t(`type ${p.magenta(".help")} to show this REPL reference`),t(`type ${p.magenta(".exit")} to exit the REPL`),t(`type ${p.bold("any other value")} to send a message to the server`)}async function M(t,o){process.stdout.write("\x1B[2J\x1B[2;0H");let e=null,r=E.createInterface({input:process.stdin,output:process.stdout}),s=m(r),n=i=>s.raw(`>> ${i}`);r.setPrompt("> ");let a=async i=>{if(i=i.trim(),!i)return!1;if(!I(i)&&!e?.isLoggedIn)return s.error("log in using .li before sending messages"),!1;if(I(i)){let[c,...g]=i.split(" ");switch(c){case".exit":return e?.disconnect(),r.close(),!0;case".li":{e?.isLoggedIn?s.error("client is already logged in"):(e=new u(t,s),e.registerAndLogIn());break}case".lo":{e?.isLoggedIn?e?.disconnect():s.error("client isn't logged in");break}case".macro":{if(!e?.isLoggedIn){s.error("client must be logged in to run macros");break}let w=g.join(" ");if(!w){s.error("usage: .macro <filepath>");break}let v=e.bot;v&&await L(w,v,r);break}case".help":{H(n,t.server.host);break}}}else e?.sendMessage(i);return!1};if(r.on("line",async i=>{await a(i)&&process.exit(0),r.prompt()}),console.log(p.green(`mincraft REPL ${x}`)),n('type ".help" for more information.'),o&&o.length>0)for(let{command:i,delay:c}of o)c>0&&await new Promise(g=>setTimeout(g,c)),i&&(s.raw(`> ${i}`),await a(i)&&process.exit(0));r.prompt()}l.name("mincraft").description("Mineflayer CLI tool with supports for macros and proxies.").version(x.slice(1)).addHelpText("after",`
2
+ import{Option as R,program as c}from"commander";function T(t){let o=[],e="",r=0;for(;r<t.length;)t[r]==="\\"&&r+1<t.length?(e+=t[r]+t[r+1],r+=2):t[r]===","?(o.push(e),e="",r++):(e+=t[r],r++);return o.push(e),o}function U(t){let o="",e=0;for(;e<t.length;)if(t[e]==="\\"&&e+1<t.length){let r=t[e+1];r===","||r==="{"||r==="}"?(o+=r,e+=2):(o+=t[e],e++)}else o+=t[e],e++;return o}function v(t){let o=[],e=T(t),r=/^\{\{(\d+(?:\.\d+)?)\}\}$/;for(let n of e){let i=n.trim();if(!i)continue;let s=i.match(r);if(s){let a=parseFloat(s[1]),l=Math.round(a*1e3);o.push({command:"",delay:l})}else{let a=U(i);o.push({command:a,delay:0})}}return o}import*as P from"readline";import M from"chalk";import{createBot as j}from"mineflayer";import{SocksClient as A}from"socks";var u=class{proxy;client;server;options;logger;isLoggedIn;bot;constructor({proxy:o,client:e,server:r,options:n},i){this.proxy=o,this.client=e,this.server=r,this.options=n,this.logger=i,this.isLoggedIn=!1}async registerAndLogIn(){let o={host:this.server.host,port:this.server.port,username:this.client.account.email,auth:this.client.account.auth,version:this.client.version,hideErrors:!0};this.proxy&&(o.connect=e=>{this.connectViaProxy(e)}),this.bot=j(o),this.options.verboseLogging&&this.registerClientEvents(),this.registerBotEvents()}connectViaProxy(o){this.logger.log("connecting via proxy");let{host:e,port:r,user:n,pass:i,type:s}=this.proxy,a=this.server;A.createConnection({proxy:{host:e,port:r,type:s,userId:n,password:i},command:"connect",destination:{host:a.host,port:a.port},timeout:3e4}).then(l=>{o.setSocket(l.socket),o.emit("connect")}).catch(l=>{this.logger.error(`proxy connection failed: ${l.message}`),o.emit("error",l)})}registerClientEvents(){this.bot._client.on("connect",()=>{this.logger.log("TCP connection established")}),this.bot._client.on("login",()=>{this.logger.log("login packet received")}),this.bot._client.on("error",o=>{this.logger.error(`client error: ${o.message}`)}),this.bot._client.on("end",o=>{this.logger.warn(`client ended: ${o}`)})}registerBotEvents(){this.bot.once("spawn",()=>{let{ign:o,uuid:e}=this.client.account;this.logger.log(`logged in as ${o} (${e})`),this.isLoggedIn=!0}),this.bot.once("kicked",o=>{this.logger.warn(`kicked: ${JSON.stringify(o)}`),this.disconnect()}),this.bot.once("error",o=>{this.logger.error(`bot error: ${o.message}`),this.isLoggedIn=!1}),this.bot.once("end",o=>{this.logger.warn(`disconnected by server: ${JSON.stringify(o)}`),this.disconnect()}),this.options.logMessages&&this.bot.on("messagestr",o=>{let e=o.split(`
3
+ `);if(e.length===1)this.logger.log(o,"chat");else{this.logger.log(e[0],"chat");for(let r=1;r<e.length;r++)this.logger.raw(` ${e[r]}`)}})}disconnect(){this.bot&&(this.proxy?this.bot._client.socket?.destroy():this.bot.quit(),this.isLoggedIn=!1)}sendMessage(o){this.bot.chat(o)}};import*as y from"readline";import h from"chalk";function D(t){return t?`/${t.split("/").map((r,n)=>n===0?r==="err"?h.red(r):r==="warn"?h.yellow(r):h.gray(r):h.blue(r)).join("/")}`:""}function m(t,o){let e=(n,i="")=>{let s=o?i?`${o}/${i}`:o:i;return`[mc${D(s)}] ${n}`},r=n=>{t?(y.clearLine(process.stdout,0),y.cursorTo(process.stdout,0),console.log(n),t.prompt(!0)):console.log(n)};return{log:(n,i)=>r(e(n,i)),warn:(n,i="warn")=>r(e(n,i)),error:(n,i="err")=>r(e(n,i)),raw:r}}import*as d from"fs/promises";import*as f from"path";import*as L from"esbuild";async function B(t){let e=(await L.build({entryPoints:[t],bundle:!0,write:!1,platform:"node",format:"esm",target:"es2022",loader:{". ts":"ts"},external:["mineflayer"],logLevel:"silent"})).outputFiles[0].text,r=t.replace(/\.ts$/,". macro.mjs");return await d.writeFile(r,e),r}async function N(t){try{await d.unlink(t)}catch{}}function H(t){return f.isAbsolute(t)?t:f.resolve(process.cwd(),t)}async function _(t){try{return await d.access(t),!0}catch{return!1}}function G(t){return f.basename(t).replace(/\.(ts|js|mjs)$/,"")}async function $(t,o,e){let r=H(t),n=r,i=null,s=m(e,`macro/${G(t)}`);try{if(!await _(r))return s.error(`file not found: ${r}`),!1;r.endsWith(".ts")&&(s.log("compiling macro to js"),i=await B(r),n=i);let g=await import(`file://${n}?t=${Date.now()}`);return typeof g.default!="function"?(s.error("macro file must export a default function"),!1):(s.log("running"),await g.default({bot:o,logger:s}),s.log("finished"),!0)}catch(a){return s.error(`failed: ${a.message}`),!1}finally{i&&await N(i)}}var x="v1.6.0";var S=(s=>(s.Exit=".exit",s.Logout=".lo",s.Login=".li",s.Macro=".macro",s.Clear=".cls",s.Help=".help",s))(S||{});function E(t){return Object.values(S).some(o=>t.startsWith(o))}function I(){process.stdout.write("\x1B[2J\x1B[2;0H")}function p(t,o,e,r){let n=r?` ${r.map(i=>`<${i}>`).join(" ")}`:"";t(`type ${M.magenta(`${o}${n}`)} ${e}`)}function J(t,o){p(t,".li",`to log in to ${o}`),p(t,".lo",`to log out from ${o}`),p(t,".macro","to run a macro",["filepath"]),p(t,".cls","to clear the REPL history"),p(t,".exit","to exit the REPL"),p(t,".help","to show this documentation"),p(t,"any other value","to send a message to the server")}async function O(t,o){I();let e=null,r=P.createInterface({input:process.stdin,output:process.stdout}),n=m(r),i=a=>n.raw(`>> ${a}`);r.setPrompt("> ");let s=async a=>{if(a=a.trim(),!a)return!1;if(!E(a)&&!e?.isLoggedIn)return n.error("log in using .li before sending messages"),!1;if(E(a)){let[l,...g]=a.split(" ");switch(l){case".exit":return e?.disconnect(),r.close(),!0;case".li":{e?.isLoggedIn?n.error("client is already logged in"):(e=new u(t,n),e.registerAndLogIn());break}case".lo":{e?.isLoggedIn?e?.disconnect():n.error("client isn't logged in");break}case".macro":{if(!e?.isLoggedIn){n.error("client must be logged in to run macros");break}let w=g.join(" ");if(!w){n.error("usage: .macro <filepath>");break}let C=e.bot;C&&await $(w,C,r);break}case".help":{J(i,t.server.host);break}case".cls":{I();break}}}else e?.sendMessage(a);return!1};if(r.on("line",async a=>{await s(a)&&process.exit(0),r.prompt()}),console.log(M.green(`mincraft REPL ${x}`)),i('type ".help" for more information.'),o&&o.length>0)for(let{command:a,delay:l}of o)l>0&&await new Promise(g=>setTimeout(g,l)),a&&(n.raw(`> ${a}`),await s(a)&&process.exit(0));r.prompt()}c.name("mincraft").description("Mineflayer CLI tool with supports for macros and proxies.").version(x.slice(1)).addHelpText("after",`
4
4
  Examples:
5
5
  $ mincraft mc.hypixel.net 1.21.4 --ign FuriousDestroyer --email you@example.com
6
6
  $ mincraft mythic.gg 1.7.10 -p 58585 --ign MangoSyrup --email you@example.com --prox proxy.com:1234:mango:secret
7
7
  $ mincraft mc.hypixel.net 1.21.4 --ign Player --email you@example.com --exec "{{1}},.li,{{2.5}},hello,{{0.5}},.lo"
8
8
  $ mincraft mc.hypixel.net 1.21.4 --ign Player --email you@example.com --exec "{{1.5}},.li,{{5}},hello\\,world,{{0.5}},.lo"
9
- `);l.argument("<host>","Server hostname").option("-p, --port <PORT>","Server port",t=>parseInt(t,10),25565);l.argument("<version>","Client version, e.g. 1.21.4");var S=["host","port","user","pass"],k=":";l.option("--prox <HOST:PORT:USER:PASS>","Connect to the server with a proxy").option("--prox-field-order <FORMAT>",'The order of the proxy credential fields, e.g. "user,pass,host,port".').option("--prox-field-sep <SEP>","The separator of the proxy credential fields").option("--prox-type <4|5>","The SOCKS proxy type",t=>parseInt(t,10),5);var G="microsoft";l.addOption(new O("--ign <IN-GAME NAME>","Player username").conflicts("uuid")).addOption(new O("--uuid <UUID>","Player UUID").conflicts("ign")).requiredOption("--email <EMAIL>","Account email").option("--auth <AUTH>","Account authentication method",G);l.option("--no-log-messages","Do not log messages your client receives").option("--verbose","Enable additional logging messages").option("--exec <COMMANDS>",'Execute REPL commands on startup with optional delays, e.g. "{{1}},.li,{{2.5}},hello,{{0.5}},.lo", where {{N}} represents a delay. You can escape curly braces and commas to include them in commands/messages.',(t,o)=>o.concat(t),[]);l.action(async(t,o,e)=>{if(!e.ign&&!e.uuid&&l.error("error: must specify either --ign or --uuid"),e.proxFieldOrder){let n=e.proxyFieldSep??k;e.proxFieldOrder.split(n).every(i=>S.includes(i))||l.error("error: --prox-field-order includes invalid fields")}let r=await W(l),s=[];for(let n of e.exec){let a=C(n);s.push(...a)}await M(r,s.length>0?s:void 0)});async function J(t){let e=await(await fetch(`https://sessionserver.mojang.com/session/minecraft/profile/${t}`)).json();if(!e?.name)throw new Error("Could not fetch IGN from UUID");return e.name}async function q(t){let e=await(await fetch(`https://api.mojang.com/users/profiles/minecraft/${t}`)).json();if(!e?.id)throw new Error("Could not fetch UUID from IGN");return e.id}function V(t,o,e){let r=t.split(e),s=Object.fromEntries(o.map((n,a)=>[n,r[a]]));return s.port=+s.port,s}async function W(t){let o=t.args,e=t.opts();return{server:{host:o[0],port:e.port},client:{version:o[1],account:{auth:e.auth,uuid:e.uuid??await q(e.ign),ign:e.ign??await J(e.uuid),email:e.email}},...e.prox?{proxy:{...V(e.prox,e.proxFieldOrder??S,e.proxFieldSep??k),type:e.proxType}}:{},options:{logMessages:e.noLogMessages??!0,verboseLogging:e.verbose??!1}}}var b=m(),he=b.log,ye=b.warn,xe=b.error;l.parse();export{b as defaultLogger,xe as error,he as log,ye as warn};
9
+ `);c.argument("<host>","Server hostname").option("-p, --port <PORT>","Server port",t=>parseInt(t,10),25565);c.argument("<version>","Client version, e.g. 1.21.4");var k=["host","port","user","pass"],F=":";c.option("--prox <HOST:PORT:USER:PASS>","Connect to the server with a proxy").option("--prox-field-order <FORMAT>",'The order of the proxy credential fields, e.g. "user,pass,host,port".').option("--prox-field-sep <SEP>","The separator of the proxy credential fields").option("--prox-type <4|5>","The SOCKS proxy type",t=>parseInt(t,10),5);var q="microsoft";c.addOption(new R("--ign <IN-GAME NAME>","Player username").conflicts("uuid")).addOption(new R("--uuid <UUID>","Player UUID").conflicts("ign")).requiredOption("--email <EMAIL>","Account email").option("--auth <AUTH>","Account authentication method",q);c.option("--no-log-messages","Do not log messages your client receives").option("--verbose","Enable additional logging messages").option("--exec <COMMANDS>",'Execute REPL commands on startup with optional delays, e.g. "{{1}},.li,{{2.5}},hello,{{0.5}},.lo", where {{N}} represents a delay. You can escape curly braces and commas to include them in commands/messages.',(t,o)=>o.concat(t),[]);c.action(async(t,o,e)=>{if(!e.ign&&!e.uuid&&c.error("error: must specify either --ign or --uuid"),e.proxFieldOrder){let i=e.proxyFieldSep??F;e.proxFieldOrder.split(i).every(a=>k.includes(a))||c.error("error: --prox-field-order includes invalid fields")}let r=await Y(c),n=[];for(let i of e.exec){let s=v(i);n.push(...s)}await O(r,n.length>0?n:void 0)});async function V(t){let e=await(await fetch(`https://sessionserver.mojang.com/session/minecraft/profile/${t}`)).json();if(!e?.name)throw new Error("Could not fetch IGN from UUID");return e.name}async function W(t){let e=await(await fetch(`https://api.mojang.com/users/profiles/minecraft/${t}`)).json();if(!e?.id)throw new Error("Could not fetch UUID from IGN");return e.id}function K(t,o,e){let r=t.split(e),n=Object.fromEntries(o.map((i,s)=>[i,r[s]]));return n.port=+n.port,n}async function Y(t){let o=t.args,e=t.opts();return{server:{host:o[0],port:e.port},client:{version:o[1],account:{auth:e.auth,uuid:e.uuid??await W(e.ign),ign:e.ign??await V(e.uuid),email:e.email}},...e.prox?{proxy:{...K(e.prox,e.proxFieldOrder??k,e.proxFieldSep??F),type:e.proxType}}:{},options:{logMessages:e.noLogMessages??!0,verboseLogging:e.verbose??!1}}}var b=m(),xe=b.log,be=b.warn,we=b.error;c.parse();export{b as defaultLogger,we as error,xe as log,be as warn};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mincraft/cli",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "Mineflayer CLI tool with support for macros and proxies",
5
5
  "bin": {
6
6
  "mincraft": "./dist/index.mjs"
@@ -18,7 +18,7 @@
18
18
  "esbuild": "^0.27.2",
19
19
  "mineflayer": "^4.33.0",
20
20
  "socks": "^2.8.7",
21
- "@mincraft/types": "1.5.1"
21
+ "@mincraft/types": "1.6.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/debug": "^4.1.12",
package/src/index.ts CHANGED
@@ -6,4 +6,6 @@ export const log = defaultLogger.log;
6
6
  export const warn = defaultLogger.warn;
7
7
  export const error = defaultLogger.error;
8
8
 
9
+ export type LiteralStringUnion<T> = T | (string & { _?: never });
10
+
9
11
  program.parse();
package/src/repl.ts CHANGED
@@ -1,34 +1,55 @@
1
1
  import * as readline from "node:readline";
2
2
  import type { Config, DelayableCommands } from "@mincraft/types";
3
3
  import chalk from "chalk";
4
+ import type { LiteralStringUnion } from ".";
4
5
  import { BotClient } from "./bot";
5
6
  import { createLogger } from "./logger";
6
7
  import { loadAndRunMacro } from "./macro";
7
8
  import { version } from "./version";
8
9
 
9
- export enum BotCommand {
10
+ export enum ReplCommand {
10
11
  Exit = ".exit",
11
12
  Logout = ".lo",
12
13
  Login = ".li",
13
14
  Macro = ".macro",
15
+ Clear = ".cls",
14
16
  Help = ".help",
15
17
  }
16
18
 
17
- function isCommand(value: string) {
18
- return Object.values(BotCommand).some((cmd) => value.startsWith(cmd));
19
+ function isReplCommand(value: string) {
20
+ return Object.values(ReplCommand).some((cmd) => value.startsWith(cmd));
21
+ }
22
+
23
+ function clearRepl() {
24
+ process.stdout.write("\u001b[2J\u001b[2;0H");
25
+ }
26
+
27
+ function describeReplCommand(
28
+ log: (msg: string) => void,
29
+ command: LiteralStringUnion<ReplCommand>,
30
+ description: string,
31
+ args?: string[],
32
+ ) {
33
+ const argstr = args ? ` ${args.map((arg) => `<${arg}>`).join(" ")}` : "";
34
+ log(`type ${chalk.magenta(`${command}${argstr}`)} ${description}`);
19
35
  }
20
36
 
21
37
  function showReplHelp(log: (msg: string) => void, serverHost: string) {
22
- log(`type ${chalk.magenta(".li")} to log in to ${serverHost}`);
23
- log(`type ${chalk.magenta(".lo")} to log out from ${serverHost}`);
24
- log(`type ${chalk.magenta(".macro <filepath>")} to run a macro`);
25
- log(`type ${chalk.magenta(".help")} to show this REPL reference`);
26
- log(`type ${chalk.magenta(".exit")} to exit the REPL`);
27
- log(`type ${chalk.bold("any other value")} to send a message to the server`);
38
+ describeReplCommand(log, ReplCommand.Login, `to log in to ${serverHost}`);
39
+ describeReplCommand(log, ReplCommand.Logout, `to log out from ${serverHost}`);
40
+ describeReplCommand(log, ReplCommand.Macro, "to run a macro", ["filepath"]);
41
+ describeReplCommand(log, ReplCommand.Clear, "to clear the REPL history");
42
+ describeReplCommand(log, ReplCommand.Exit, "to exit the REPL");
43
+ describeReplCommand(log, ReplCommand.Help, "to show this documentation");
44
+ describeReplCommand(
45
+ log,
46
+ "any other value",
47
+ "to send a message to the server",
48
+ );
28
49
  }
29
50
 
30
51
  export async function run(config: Config, commands?: DelayableCommands) {
31
- process.stdout.write("\u001b[2J\u001b[2;0H");
52
+ clearRepl();
32
53
  let bot: BotClient = null;
33
54
 
34
55
  const rl = readline.createInterface({
@@ -37,7 +58,7 @@ export async function run(config: Config, commands?: DelayableCommands) {
37
58
  });
38
59
 
39
60
  const logger = createLogger(rl);
40
- const helpLogger = (msg: string) => logger.raw(`>> ${msg}`);
61
+ const logHelp = (msg: string) => logger.raw(`>> ${msg}`);
41
62
 
42
63
  rl.setPrompt("> ");
43
64
 
@@ -48,21 +69,21 @@ export async function run(config: Config, commands?: DelayableCommands) {
48
69
  return false;
49
70
  }
50
71
 
51
- if (!isCommand(input) && !bot?.isLoggedIn) {
72
+ if (!isReplCommand(input) && !bot?.isLoggedIn) {
52
73
  logger.error("log in using .li before sending messages");
53
74
  return false;
54
75
  }
55
76
 
56
- if (isCommand(input)) {
77
+ if (isReplCommand(input)) {
57
78
  const [cmd, ...args] = input.split(" ");
58
79
 
59
80
  switch (cmd) {
60
- case BotCommand.Exit: {
81
+ case ReplCommand.Exit: {
61
82
  bot?.disconnect();
62
83
  rl.close();
63
84
  return true;
64
85
  }
65
- case BotCommand.Login: {
86
+ case ReplCommand.Login: {
66
87
  if (bot?.isLoggedIn) {
67
88
  logger.error("client is already logged in");
68
89
  } else {
@@ -71,7 +92,7 @@ export async function run(config: Config, commands?: DelayableCommands) {
71
92
  }
72
93
  break;
73
94
  }
74
- case BotCommand.Logout: {
95
+ case ReplCommand.Logout: {
75
96
  if (!bot?.isLoggedIn) {
76
97
  logger.error("client isn't logged in");
77
98
  } else {
@@ -79,7 +100,7 @@ export async function run(config: Config, commands?: DelayableCommands) {
79
100
  }
80
101
  break;
81
102
  }
82
- case BotCommand.Macro: {
103
+ case ReplCommand.Macro: {
83
104
  if (!bot?.isLoggedIn) {
84
105
  logger.error("client must be logged in to run macros");
85
106
  break;
@@ -95,8 +116,12 @@ export async function run(config: Config, commands?: DelayableCommands) {
95
116
  }
96
117
  break;
97
118
  }
98
- case BotCommand.Help: {
99
- showReplHelp(helpLogger, config.server.host);
119
+ case ReplCommand.Help: {
120
+ showReplHelp(logHelp, config.server.host);
121
+ break;
122
+ }
123
+ case ReplCommand.Clear: {
124
+ clearRepl();
100
125
  break;
101
126
  }
102
127
  }
@@ -116,7 +141,7 @@ export async function run(config: Config, commands?: DelayableCommands) {
116
141
  });
117
142
 
118
143
  console.log(chalk.green(`mincraft REPL ${version}`));
119
- helpLogger('type ".help" for more information.');
144
+ logHelp('type ".help" for more information.');
120
145
 
121
146
  if (commands && commands.length > 0) {
122
147
  for (const { command, delay } of commands) {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "v1.5.1";
1
+ export const version = "v1.6.0";