Compare commits

...
Sign in to create a new pull request.

22 commits
corev2 ... main

Author SHA1 Message Date
7f66a2ceb9
Add security changes 2025-04-13 00:44:30 -04:00
6cce31f1db
wa 2025-04-11 23:41:53 -04:00
45c1cfe7c0
Remove 1.18 support 2025-04-10 23:39:20 -04:00
e4bcb28226
a 2025-04-10 23:36:36 -04:00
2fd92ba056
Add updates to about command 2025-04-10 23:36:15 -04:00
0b15a6ca6a
MOre chages 2025-04-06 03:14:09 -04:00
a3bf5502c6
MOre chages 2025-04-06 01:34:37 -04:00
16239ec110
Several chjanges 2025-03-29 13:32:56 -04:00
0c52e6cf23
Prevent bot from starting if keys aren't set 2025-03-02 08:07:30 -05:00
e611f84cfa
Bugfix 2025-02-21 19:39:10 -05:00
bfb97c91e4
e 2025-02-21 19:04:15 -05:00
dbcc5bc0cd
a 2025-02-21 19:02:31 -05:00
c48f7b9060
Updates to about command 2025-02-21 19:02:14 -05:00
8b4f729025
Add comment that some people will ignore to the top of the about commadn 2025-02-21 18:54:51 -05:00
b3374aeb13
License 2025-02-21 18:49:44 -05:00
539ca480ca Upload files to "/" 2025-02-21 16:29:11 -05:00
9a2333c95c
Update example settings 2025-02-17 17:14:48 -05:00
15b01bdfa1
affwafgeaegwgeaw 2025-02-15 20:48:52 -05:00
a36dece7d4
䙯牴湩瑥 2025-02-14 01:06:21 -05:00
d3f88873f0
Change version compatibility in readme 2025-02-14 00:59:45 -05:00
e8752d7eac
Simplify math 2025-02-13 15:16:57 -05:00
8aa3d1ae61
bugfix 2025-02-13 15:08:51 -05:00
39 changed files with 440 additions and 510 deletions

View file

@ -7,7 +7,7 @@ botv12 is a Minecraft bot originally designed for [Kaboom](https://kaboom.pw/) a
- a command core, to run commands quickly
- a hashing system, to enable trusted users to securely run certain commands in chat
It supports all Minecraft versions from 1.13 to 1.21.3 that are supported by node-minecraft-protocol. It may work on other versions, however, support will not be provided for them. It is recommended to use the bot on the version of the server, if at all possible.
It supports all Minecraft versions from 1.19 to 1.21.3 that are supported by node-minecraft-protocol - newer versions have bugs on Kaboom servers. It may work on other versions, however, support will not be provided for them.
## How to install?
@ -18,12 +18,6 @@ It supports all Minecraft versions from 1.13 to 1.21.3 that are supported by nod
5. Copy the reference configuration (`settings_example.js` in the root) to `settings.js`, and adjust the settings to fit your needs. The secrets are also contained in this file as well.
6. Run ./launch.sh (macOS, Linux, FreeBSD) or ./launch.cmd (Windows). This will start a bot launcher, which will restart the bot when the process closes. Alternatively, you can run `node index.js` to start the bot only once (it will still rejoin when kicked). If it displays an error saying `node` is not a command, please make sure Node.js is on your PATH.
## Command list
| Name | Usage | Description |
|-|-|-|
| about | [serverlist \| servers \| server] | About the bot. May also show system information or a list of connected servers. |
| test | | Debug command for the chat parser |
## License
This project is licensed under the MIT License. Using, modifying, and distributing this code is allowed, even for commercial purposes. If you make any copies of this bot, you MUST link back to this repository. See the License file for the full terms and conditions.

View file

@ -2,14 +2,9 @@ import parsePlain from '../util/chatparse_plain.js'
const priority = 0
const parse = (data, b) => {
if (data.type === 'system' || data.type === 'legacy') {
if (data.type === 'system') {
if (data.json.translate === '%s %s %s' || data.json.translate === '[%s] %s %s') {
let subtype = 'chipmunkmod_'
if (data.json.translate === '%s %s %s') {
subtype += 'name3'
} else if (data.json.translate === '[%s] %s %s') {
subtype += 'chomens'
}
let subtype = 'chipmunkmod'
if (data.json.with && data.json.with[1] && data.json.with[2]) {
const username = parsePlain(data.json.with[1])
const uuid = b.findUUID(username)

View file

@ -1,27 +0,0 @@
import parsePlain from '../util/chatparse_plain.js'
const priority = 0
const parse = (data, b) => {
if (data.type === 'system' || data.type === 'legacy') {
if (data.json.extra && data.json.extra[4] && data.json.extra[3] && data.json.extra[5] && data.json.extra[4].text === ' » ') { // ChipmunkMod format - m_c_player
const username = parsePlain(data.json.extra[3])
const uuid = b.findUUID(username)
const nickname = b.findDisplayName(uuid)
const message = parsePlain(data.json.extra[5])
return {
parsed: true,
json: data.json,
type: data.type,
subtype: 'chipmunkmod_mcp',
uuid,
message,
nickname,
username
}
}
}
return {
parsed: false
}
}
export { priority, parse }

View file

@ -2,9 +2,8 @@ import parsePlain from '../util/chatparse_plain.js'
const priority = 2
const parse = (data, b) => {
if (data.type === 'system' || data.type === 'legacy') {
if (data.type === 'system') {
let subtype = 'generic_system'
if (data.type === 'legacy' && data.uuid) subtype += '_withuuid'
const parsed = parsePlain(data.json)
const split = parsed.split(': ')
const chatName = split.splice(0, 1)[0]

View file

@ -1,33 +0,0 @@
import parsePlain from '../util/chatparse_plain.js'
const priority = 1
const parse = (data, b) => {
if (data.type === 'legacy') {
let subtype = 'vanilla_legacy'
if (data.type === 'legacy' && data.uuid) subtype += '_withuuid'
if (data.json.translate === 'chat.type.text') { // Servers without Extras chat
let message
let username
if (data.json.with && data.json.with.length >= 2) {
message = parsePlain(data.json.with[1])
username = parsePlain(data.json.with[0])
}
const uuid = b.findUUID(username)
const nickname = b.findDisplayName(uuid)
return {
parsed: true,
json: data.json,
type: data.type,
subtype,
uuid,
message,
nickname,
username
}
}
}
return {
parsed: false
}
}
export { priority, parse }

View file

@ -1,3 +1,12 @@
/*
If you are forking the bot, you must comply with the MIT License, which only requires
attribution. If you choose to remove or modify this command, you must find another way to comply
with the MIT License, such as adding a message on join or in another command.
You may also make your fork open source as well, and add a message in the readme.
Additionally, if you're forking a fork with a different license, such as GPL, make sure you
comply with any additional terms.
*/
import os from 'node:os'
import { execSync } from 'child_process'
import { getMessage, formatTime } from '../util/lang.js'
@ -6,8 +15,9 @@ import { readdirSync, readFileSync } from 'node:fs'
import botVersion from '../util/version.js'
import version from '../version.js'
import { bots } from '../index.js'
import settings from '../settings.js'
const aboutBot = function (c) {
const aboutBot = c => {
c.reply({
translate: getMessage(c.lang, 'command.about.author'),
color: c.colors.secondary,
@ -29,33 +39,63 @@ const aboutBot = function (c) {
})
}
c.reply({ text: '' })
c.reply({
text: getMessage(c.lang, 'command.about.license'),
color: c.colors.secondary
})
c.reply({
translate: getMessage(c.lang, 'command.about.sourceCode'),
color: c.colors.secondary,
with: [
{
text: version.sourceURL,
color: c.colors.primary,
clickEvent: {
action: 'open_url',
value: version.sourceURL
if (settings.officialUbotRealFullVersionFreeTwoThousandTwentyOneSafeNoVirusWorkingGenerator) {
c.reply({
text: getMessage(c.lang, 'command.about.license'),
color: c.colors.secondary
})
} else {
c.reply({
translate: getMessage(c.lang, 'command.about.fork'),
color: c.colors.secondary,
with: [
{
text: version.originalName,
color: c.colors.primary
},
hoverEvent: {
action: 'show_text',
contents: {
text: getMessage(c.lang, 'command.about.sourceCode.openInBrowser')
{
text: version.originalAuthor,
color: c.colors.primary
},
{
text: version.originalRepo,
color: c.colors.primary,
clickEvent: {
action: 'open_url',
value: version.originalRepo
},
value: { // Added twice for backwards compatibility
text: getMessage(c.lang, 'command.about.sourceCode.openInBrowser')
hoverEvent: {
action: 'show_text',
contents: {
text: getMessage(c.lang, 'command.about.sourceCode.openInBrowser')
}
}
}
}
]
})
]
})
}
if (version.sourceURL) {
c.reply({
translate: getMessage(c.lang, 'command.about.sourceCode'),
color: c.colors.secondary,
with: [
{
text: version.sourceURL,
color: c.colors.primary,
clickEvent: {
action: 'open_url',
value: version.sourceURL
},
hoverEvent: {
action: 'show_text',
contents: {
text: getMessage(c.lang, 'command.about.sourceCode.openInBrowser')
}
}
}
]
})
}
c.reply({ text: '' })
c.reply({
text: getMessage(c.lang, 'command.about.subcommands'),
@ -101,7 +141,7 @@ const os2 = function (o2, l) {
}
}
const aboutServer = function (c) {
const aboutServer = c => {
const displayInfo = function (name, infoFunc) {
let thisItem
try {
@ -130,10 +170,6 @@ const aboutServer = function (c) {
contents: {
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
},
value: { // Added twice for backwards compatibility
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
}
}
}
@ -165,19 +201,10 @@ const aboutServer = function (c) {
})
}
// System memory (total)
displayInfo('command.about.serverInfo.totalMem', () => {
return memoryconvert(os.totalmem())
})
// System memory (free)
displayInfo('command.about.serverInfo.freeMem', () => {
return memoryconvert(os.freemem())
})
// System memory (used)
displayInfo('command.about.serverInfo.usedMem', () => {
return memoryconvert(os.totalmem() - os.freemem())
return `${memoryconvert(os.totalmem() - os.freemem())} / ${memoryconvert(os.totalmem())} ` +
`(${getMessage(c.lang, 'command.about.serverInfo.freeMem', [memoryconvert(os.freemem())])})`
})
// Username and UID
@ -225,19 +252,17 @@ const aboutServer = function (c) {
})
}
const displayServerList = function (c) {
const displayServerList = c => {
bots.forEach((item, i) => {
if (c.bot.id === i && c.bot.host.options.hideLocally) return
if (item.host.options && item.host.options.hidden && c.verify !== 2 && c.bot.id !== i) return
let message = 'command.about.serverListItem'
if (c.bot.id === i) message = 'command.about.serverListItem.thisServer'
let host = item.host.host
const port = item.host.port
if (item.host.options && item.host.options.displayAsIPv6) {
host = `[${host}]`
}
c.reply({
translate: getMessage(c.lang, message),
translate: getMessage(c.lang, 'command.about.serverListItem'),
color: c.colors.secondary,
with: [
{
@ -256,10 +281,6 @@ const displayServerList = function (c) {
contents: {
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
},
value: { // Added twice for backwards compatibility
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
}
}
}
@ -268,7 +289,47 @@ const displayServerList = function (c) {
})
}
const execute = function (c) {
const displaySettings = c => {
const reply = function (name, item) {
return {
translate: '%s: %s',
color: c.colors.primary,
with: [
{
text: getMessage(c.lang, `command.about.settings.${name}`),
color: c.colors.secondary
},
{
text: item,
color: c.colors.primary,
clickEvent: {
action: 'copy_to_clipboard',
value: item
},
hoverEvent: {
action: 'show_text',
contents: {
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
}
}
}
]
}
}
for(const i in settings){
let output = settings[i] + ""
if(i == "colors" || i == "servers") continue;
if(i == "keyTrusted" || i == "keyOwner" || i == "onlineEmail" || i == "onlinePass") continue
c.reply(reply(i,output))
}
for(const i in settings.colors){
let output = settings.colors[i] + ""
c.reply(reply(i,output))
}
}
const execute = c => {
let subcmd
if (c.args.length >= 1) subcmd = c.args[0].toLowerCase()
if (subcmd === 'servers') subcmd = 'serverlist'
@ -278,6 +339,8 @@ const execute = function (c) {
aboutServer(c)
} else if (subcmd === 'serverlist') {
displayServerList(c)
} else if (subcmd === 'settings') {
displaySettings(c)
} else {
aboutBot(c)
}

View file

@ -1,4 +1,4 @@
const execute = (c) => {
const execute = c => {
c.bot.ccq.push(c.args.join(' '))
}
const consoleIndex = true

View file

@ -1,5 +1,5 @@
import { getMessage } from '../util/lang.js'
const execute = (c) => {
const execute = c => {
let subcmd
if (c.args.length >= 1) subcmd = c.args.splice(0, 1)[0].toLowerCase()
switch (subcmd) {
@ -74,7 +74,7 @@ const execute = (c) => {
break
default:
c.reply({
translate: getMessage(c.lang, 'command.cloop.error.subcommand'),
translate: getMessage(c.lang, 'command.error.subcommand'),
color: c.colors.secondary,
with: [
{

View file

@ -4,7 +4,7 @@ import { inspect } from 'node:util'
import settings from '../settings.js'
import chatlog from '../util/chatlog.js'
const execute = (c) => {
const execute = c => {
const payload = c.args.join(' ')
if (!settings.disableLogging && !settings.disableEvalLogging) chatlog('eval', `${c.host}:${c.port} ${c.username} (${c.uuid}) Payload: ${payload}`)
let result
@ -38,10 +38,6 @@ const execute = (c) => {
contents: {
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
},
value: { // Added twice for backwards compatibility
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
}
}
}
@ -50,4 +46,5 @@ const execute = (c) => {
}
}
const level = 2
export { execute, level }
const consoleOnly = true
export { execute, level, consoleOnly }

View file

@ -1,5 +1,5 @@
import { getMessage } from '../util/lang.js'
const execute = (c) => {
const execute = c => {
let subcmd
if (c.args.length >= 1) subcmd = c.args.splice(0, 1)[0].toLowerCase()
console.log(subcmd)
@ -13,7 +13,7 @@ const execute = (c) => {
if (!/[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}/.test(command)) {
playerName = command
uuid = c.bot.findUUID(playerName)
if (uuid == '00000000-0000-0000-0000-000000000000') {
if (uuid === '00000000-0000-0000-0000-000000000000') {
c.reply({
text: getMessage(c.lang, 'command.filter.error.notFound')
})
@ -88,7 +88,7 @@ const execute = (c) => {
break
default:
c.reply({
translate: getMessage(c.lang, 'command.cloop.error.subcommand'),
translate: getMessage(c.lang, 'command.error.subcommand'),
color: c.colors.secondary,
with: [
{
@ -100,7 +100,7 @@ const execute = (c) => {
}
}
const level = 0
const level = 1
const aliases = ['blacklist']
const consoleIndex = true
export { execute, level, consoleIndex }
export { execute, level, consoleIndex, aliases }

View file

@ -1,149 +1,81 @@
import cmds from '../util/commands.js'
import registry from '../util/commands.js'
import { getMessage } from '../util/lang.js'
const sortHelp = function sortHelp (c1, c2) {
const level1 = cmds[c1.with[0].text].level ? cmds[c1.with[0].text].level : 0
const level2 = cmds[c2.with[0].text].level ? cmds[c2.with[0].text].level : 0
const level1 = c1.level ? c1.level : 0
const level2 = c2.level ? c2.level : 0
return level1 - level2
}
const printHelp = (c) => {
const commandList = []
const permsN = getMessage(c.lang, 'command.help.permsNormal')
const permsT = getMessage(c.lang, 'command.help.permsTrusted')
const permsO = getMessage(c.lang, 'command.help.permsOwner')
const permList = [permsN, permsT, permsO]
const colorList = ['green', 'red', 'dark_red']
const printHelp = c => {
const cmds = registry.listCommands()
const commands = []
for (const i in cmds) {
if (cmds[i].hidden) continue
commands.push({
name: i,
level: cmds[i].level
})
}
const sortedCommands = commands.sort(sortHelp)
const commandList = []
const colorList = ['green', 'red', 'dark_red']
for (const cmd of sortedCommands) {
let cmdColor
if (colorList[cmds[i].level]) {
cmdColor = colorList[cmds[i].level]
if (colorList[cmd.level]) {
cmdColor = colorList[cmd.level]
} else {
cmdColor = colorList[0]
}
let usage = getMessage(c.lang, `command.${i}.usage`).split('||')
let desc = getMessage(c.lang, `command.${i}.desc`)
if (cmds[i].usage) {
usage = cmds[i].usage.split('||')
}
if (cmds[i].desc) {
desc = cmds[i].desc
}
const hoverText = []
for (const item of usage) {
hoverText.push({
translate: getMessage(c.lang, 'command.help.commandUsage.lf'),
color: c.colors.secondary,
with: [
{
text: i,
color: c.colors.primary
},
{
text: item,
color: c.colors.primary
}
]
})
}
hoverText.push({
translate: getMessage(c.lang, 'command.help.commandDesc.lf'),
color: c.colors.secondary,
with: [
{
text: desc,
color: c.colors.primary
}
]
})
const rPerms = cmds[i].level ? cmds[i].level : 0
hoverText.push({
translate: getMessage(c.lang, 'command.help.commandPerms.lf'),
color: c.colors.secondary,
with: [
{
text: permList[rPerms],
color: c.colors.primary
}
]
})
hoverText.push({
translate: getMessage(c.lang, 'command.help.runCommand'),
color: c.colors.secondary
})
commandList.push(
{
translate: '%s ',
color: cmdColor,
with: [
{
text: i,
hoverEvent: {
action: 'show_text',
value: hoverText,
contents: hoverText
},
text: cmd.name,
clickEvent: {
action: 'suggest_command',
value: `${c.prefix}${i}`
value: `${c.prefix}${cmd.name}`
}
}
]
}
)
}
const permListFormat = []
permList.forEach((item, i) => {
for (let i = 0; i <= 2; i++) {
permListFormat.push({
translate: i === permList.length - 1 ? '%s' : '%s ',
color: colorList[i],
with: [
item
]
text: getMessage(c.lang, `command.perms${i}`)
})
})
if (i !== 2) permListFormat.push(' ')
}
c.reply({
translate: '%s %s',
translate: '%s (%s) (%s): %s',
with: [
{
translate: '%s (%s):',
with: [
getMessage(c.lang, 'command.help.cmdList'),
permListFormat
]
},
commandList.sort(sortHelp)
getMessage(c.lang, 'command.help.cmdList'),
commandList.length + '',
permListFormat,
commandList
]
})
}
const printCmdHelp = (c) => {
const printCmdHelp = c => {
let cmd
if (c.args.length >= 1) cmd = c.args[0].toLowerCase()
if (!cmds[cmd] || (cmds[cmd].hidden && c.type !== 'console')) {
c.reply({ text: getMessage(c.lang, 'command.help.noCommand') })
return
}
let usage = getMessage(c.lang, `command.${cmd}.usage`).split('||')
let desc = getMessage(c.lang, `command.${cmd}.desc`)
if (cmds[cmd].usage) {
usage = cmds[cmd].usage.split('||')
const cmdItem = registry.getCommand(cmd)
if (!cmdItem) {
return
}
if (cmds[cmd].desc) {
desc = cmds[cmd].desc
}
if (cmds[cmd].alias) {
console.log(cmds[cmds[cmd].alias])
usage = getMessage(c.lang, `command.${cmds[cmd].alias}.usage`).split('||')
desc = getMessage(c.lang, 'command.help.alias', [cmds[cmd].alias])
if (cmds[cmds[cmd].alias].usage) {
usage = cmds[cmds[cmd].alias].usage.split('||')
}
if (cmds[cmds[cmd].alias].desc) {
desc = cmds[cmds[cmd].alias].desc
}
if (cmdItem.alias) {
usage = getMessage(c.lang, `command.${cmdItem.alias}.usage`).split('||')
desc = getMessage(c.lang, 'command.help.alias', [cmdItem.alias])
}
for (const item of usage) {
c.reply({
@ -171,9 +103,9 @@ const printCmdHelp = (c) => {
}
]
})
if (cmds[cmd].aliases) {
if (cmdItem.aliases) {
const aliasList = []
for (const item of cmds[cmd].aliases) {
for (const item of cmdItem.aliases) {
if (aliasList.length > 0) {
aliasList.push({
text: ', ',
@ -182,22 +114,7 @@ const printCmdHelp = (c) => {
}
aliasList.push({
text: item,
color: c.colors.primary,
clickEvent: {
action: 'copy_to_clipboard',
value: item
},
hoverEvent: {
action: 'show_text',
contents: {
text: getMessage(c.lang, 'command.help.copyAlias'),
color: c.colors.secondary
},
value: { // Added twice for backwards compatibility
text: getMessage(c.lang, 'command.help.copyAlias'),
color: c.colors.secondary
}
}
color: c.colors.primary
})
}
c.reply({
@ -208,23 +125,20 @@ const printCmdHelp = (c) => {
]
})
}
const permsN = getMessage(c.lang, 'command.help.permsNormal')
const permsT = getMessage(c.lang, 'command.help.permsTrusted')
const permsO = getMessage(c.lang, 'command.help.permsOwner')
const rPerms = cmds[cmd].level ? cmds[cmd].level : 0
const rPerms = cmdItem.level ? cmdItem.level : 0
c.reply({
translate: getMessage(c.lang, 'command.help.commandPerms'),
color: c.colors.secondary,
with: [
{
text: [permsN, permsT, permsO][rPerms],
text: getMessage(c.lang, `command.perms${rPerms}`),
color: c.colors.primary
}
]
})
}
const execute = (c) => {
const execute = c => {
if (c.args.length > 0) {
printCmdHelp(c)
} else {

View file

@ -1,4 +1,4 @@
const execute = (c) => {
const execute = c => {
c.bot._client.end()
}
const consoleIndex = true

View file

@ -1,7 +1,7 @@
import { bots } from '../index.js'
import { getMessage } from '../util/lang.js'
const execute = (c) => {
const execute = c => {
let host = c.host
let port = c.port
if (c.bot.host.options && c.bot.host.options.hidden) {
@ -10,11 +10,13 @@ const execute = (c) => {
} else if (c.bot.host.options && c.bot.host.options.displayAsIPv6) {
host = `[${host}]`
}
let msg = c.args.join(' ').slice(0, 512)
msg = msg.replace(/:3/g, '')
const json = {
translate: '[%s] %s: %s',
with: [
{
text: c.serverName,
text: c.bot.host.options?.name ?? 'console',
hoverEvent: {
action: 'show_text',
value: {
@ -43,13 +45,13 @@ const execute = (c) => {
color: c.colors.primary
},
{
text: c.args.join(' ').slice(0, 512)
text: msg
}
],
color: c.colors.tertiary
}
bots.forEach(item => {
if (item.host.options && item.host.options.netmsgIncomingDisabled && c.type !== 'console') return
if (item.host.options.netmsgIncomingDisabled && c.type !== 'console') return
item.tellraw('@a', json)
})
}

View file

@ -1,4 +1,4 @@
const execute = (c) => {
const execute = c => {
c.bot.sc_tasks.cc.failed = true
}
const consoleIndex = true

View file

@ -1,4 +1,4 @@
const execute = (c) => {
const execute = c => {
process.exit(0)
}
const aliases = ['reboot']

View file

@ -1,6 +1,15 @@
import settings from '../settings.js'
import { getMessage } from '../util/lang.js'
import version from '../version.js'
const execute = (c) => {
const execute = c => {
const msg = c.args.join(' ').slice(0, 512)
if(msg.includes(settings.keyTrusted) && c.verify < 1){
c.bot.info(getMessage(c.lang, 'command.say.warning.trustedKey'))
return
} else if(msg.includes(settings.keyOwner) && c.verify < 2){
c.bot.info(getMessage(c.lang, 'command.say.warning.ownerKey'))
return
}
if (c.verify < 1) {
c.bot.tellraw('@a', {
translate: '%s %s: %s',
@ -29,12 +38,12 @@ const execute = (c) => {
text: version.botName,
color: settings.colors.primary
},
c.args.join(' ').slice(0, 512)
msg
]
})
return
}
c.bot.chat(c.args.join(' ').slice(0, 512))
c.bot.chat(msg)
}
const consoleIndex = true
const aliases = ['echo']

View file

@ -1,10 +1,7 @@
import { getMessage } from '../util/lang.js'
/*
Please note: I had this idea before I found out it was in other bots.
Please do not get mad at me because your bot also has this (or a similar) command.
*/
const execute = (c) => {
if (c.args[0] == 'set') {
const execute = c => {
if (c.args[0] === 'set') {
const scale = Math.min(Math.max(+c.args[1], 0.0625), 16)
c.reply({
translate: getMessage(c.lang, 'command.scale.set'),
@ -21,7 +18,7 @@ const execute = (c) => {
c.bot.ccq.push(`attribute ${c.uuid} movement_speed base set ${0.1 * scale}`) // Very close to 0.1 normally, so we just round
c.bot.ccq.push(`attribute ${c.uuid} step_height base set ${0.6 * scale}`)
c.bot.ccq.push(`attribute ${c.uuid} jump_strength base set ${0.42 * scale}`) // Very close to 0.42 normally, so we just round
} else if (c.args[0] == 'reset') {
} else if (c.args[0] === 'reset') {
c.reply({
translate: getMessage(c.lang, 'command.scale.reset'),
color: c.colors.secondary
@ -33,7 +30,7 @@ const execute = (c) => {
c.bot.ccq.push(`attribute ${c.uuid} jump_strength base reset`)
} else {
c.reply({
translate: getMessage(c.lang, 'command.cloop.error.subcommand'),
translate: getMessage(c.lang, 'command.error.subcommand'),
color: c.colors.secondary,
with: [
{

View file

@ -1,4 +1,4 @@
const execute = (c) => {
const execute = c => {
process.exit(1)
}
const aliases = ['exit']

View file

@ -1,41 +0,0 @@
const execute = (c) => {
// Blank template
/*
c.send(text, user?): Send text to all ("/tellraw @a")
c.reply(text): Send text to command sender
c.uuid: Unique identifier (UUID for Minecraft, Discord ID for Discord)
c.username: Username of sender
c.nickname: Nickname of sender when applicable
c.command: Command string
c.args: Arguments of command (above without the first section, and split at every space)
c.prefix: Prefix being used to send the command (when applicable)
c.bot: Bot that received the command. Will be different type based on where it was received
c.type: Type of bot receiving the command ("minecraft", "console", "discord")
c.lang: The language the player has selected, or the default if none
c.colors: The color palette the player has selected, or the default if none
*/
}
/*
Command description and usage have been moved to the message files. The format for a basic command is:
"command.(name).usage": " <required> [optional]",
"command.(name).desc": "Insert description here...",
replacing (name) with the name of the new command.
Some more complex commands may have messages of their own, which should be placed there too.
First, insert the following line near the top of the command's file (not in the execute function):
const { getMessage } = require('../../util/lang.js')
Then, to get a specific message:
getMessage(c.lang,"(message key)",[(arguments, in an array (optional))])
For example, this will show the "about" command's redirection to "serverinfo":
getMessage(c.lang,"command.about.serverinfo")
The with array can be used to add information to a message. For example:
getMessage(lang,"command.help.commandInfo",["cmd","usage","desc"])
shows the "help" command's formatting for command information, with some strings as items.
That message would render as (in en-US):
cmdusage - desc
Extra information is inserted wherever there is a "%s" or a "%n$s", with n being the index of the item in the array.
*/
const hidden = true // To show the command on the help command list, remove this line (optional)
const consoleIndex = true // When run from console, the second argument will be a bot ID (optional)
const aliases = ['example'] // Other command names that will work the same (optional)
const level = 0 // Permission level required to run this command (optional)
export { execute, hidden, consoleIndex, aliases, level } // Only export the items that were included in your command

View file

@ -1,5 +1,5 @@
import { getMessage } from '../util/lang.js'
const execute = (c) => {
const execute = c => {
const reply = function (name, item) {
return {
translate: '%s: %s',
@ -21,10 +21,6 @@ const execute = (c) => {
contents: {
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
},
value: { // Added twice for backwards compatibility
text: getMessage(c.lang, 'copyText'),
color: c.colors.secondary
}
}
}

View file

@ -1,6 +1,6 @@
import { getMessage } from '../util/lang.js'
const execute = function (c) {
const execute = c => {
let uuid
if (c.type === 'console') {
uuid = c.bot._client.uuid

View file

@ -1,6 +1,6 @@
import { getMessage } from '../util/lang.js'
const execute = (c) => {
const execute = c => {
const permsN = getMessage(c.lang, 'command.help.permsNormal')
const permsT = getMessage(c.lang, 'command.help.permsTrusted')
const permsO = getMessage(c.lang, 'command.help.permsOwner')

View file

@ -4,24 +4,9 @@ import generateUser from './util/usergen.js'
import EventEmitter from 'node:events'
import { readdirSync } from 'node:fs'
if (settings.keyTrusted === undefined || settings.keyOwner === undefined) process.exit(1)
const bots = []
const plugins = []
const bpl = readdirSync('plugins')
for (const plugin of bpl) {
if (!plugin.endsWith('.js')) {
continue
}
try {
import(`./plugins/${plugin}`).then((pluginItem) => {
for (const bot of bots) {
pluginItem.default(bot)
}
plugins.push(pluginItem.default) // For rejoining
})
} catch (e) { console.log(e) }
}
const createBot = function createBot (host, oldId) {
const bot = new EventEmitter()
@ -56,6 +41,10 @@ const createBot = function createBot (host, oldId) {
}
}
for (const pluginItem of plugins) {
if (pluginItem) pluginItem(bot)
}
if (typeof oldId !== 'undefined') {
for (const i in bots[oldId].interval) {
clearInterval(bots[oldId].interval[i])
@ -63,9 +52,6 @@ const createBot = function createBot (host, oldId) {
delete bots[oldId]
bot.id = oldId
bots[oldId] = bot
for (const pluginItem of plugins) {
pluginItem(bot)
}
} else {
bot.id = bots.length
bots.push(bot)
@ -76,8 +62,26 @@ const createBot = function createBot (host, oldId) {
})
}
for (const i in settings.servers) {
createBot(settings.servers[i])
const init = function () {
for (const i in settings.servers) {
createBot(settings.servers[i])
}
}
const plugins = []
const bpl = readdirSync('plugins')
for (const plugin of bpl) {
if (!plugin.endsWith('.js')) {
continue
}
try {
import(`./plugins/${plugin}`).then((pluginItem) => {
plugins.push(pluginItem.default) // For rejoining
if (plugins.length === bpl.length) {
init()
}
})
} catch (e) { console.log(e) }
}
export {

View file

@ -1,4 +1,5 @@
export default {
// Time
'time.week': ' week ',
'time.weekPlural': ' weeks ',
'time.day': ' day ',
@ -9,52 +10,78 @@ export default {
'time.minutePlural': ' minutes ',
'time.second': ' second ',
'time.secondPlural': ' seconds ',
'chat.antiSpamTriggered': 'Anti-spam has been triggered for this server.',
'command.about.usage': '',
'command.about.desc': 'About the bot',
'command.cb.usage': ' <command>',
'command.cb.desc': 'Run a command in a command block',
'command.cloop.usage': ' add <rate> <command>|| remove <index>|| list|| clear',
'command.cloop.desc': 'Manage command loops',
'command.eval.usage': ' <code>',
'command.eval.desc': 'Run JavaScript code',
'command.filter.usage': ' (syntax not finalized)',
'command.filter.desc': 'Manage filtered players',
'command.help.usage': ' [cmd]',
'command.help.desc': 'Shows command help',
// 'command.kick.usage': ' (syntax not finalized)',
// 'command.kick.desc': 'Kick a player',
'command.logoff.usage': '',
'command.logoff.desc': 'Disconnect and reconnect the bot from a server',
'command.netmsg.usage': ' <message>',
'command.netmsg.desc': 'Send a message to all servers the bot is connected to',
'command.refill.usage': '',
'command.refill.desc': 'Refill core',
'command.say.usage': ' <message>',
'command.say.desc': 'Sends a message to chat',
'command.restart.usage': '',
'command.restart.desc': 'Restart bot',
'command.scale.usage': ' set <size>|| reset',
'command.scale.desc': 'Change player size',
'command.stop.usage': '',
'command.stop.desc': 'Stop bot',
'command.template.usage': ' <required> [optional]',
'command.template.desc': 'Does nothing',
'command.test.usage': ' [args...]',
'command.test.desc': 'Chat parsing debugger command',
'command.tpr.usage': '',
'command.tpr.desc': 'Teleport to a random location',
'command.validate.usage': ' [args...]',
'command.validate.desc': 'Check the hashing system',
// Command Info
'commands.about.usage': '',
'commands.about.desc': 'About the bot',
'commands.cb.usage': ' <command>',
'commands.cb.desc': 'Run a command in a command block',
'commands.cloop.usage': ' add <rate> <command>|| remove <index>|| list|| clear',
'commands.cloop.desc': 'Manage command loops',
'commands.eval.usage': ' <code>',
'commands.eval.desc': 'Run JavaScript code',
'commands.filter.usage': ' (syntax not finalized)',
'commands.filter.desc': 'Manage filtered players',
'commands.help.usage': ' [cmd]',
'commands.help.desc': 'Shows command help',
'commands.logoff.usage': '',
'commands.logoff.desc': 'Disconnect and reconnect the bot from a server',
'commands.netmsg.usage': ' <message>',
'commands.netmsg.desc': 'Send a message to all servers the bot is connected to',
'commands.refill.usage': '',
'commands.refill.desc': 'Refill core',
'commands.say.usage': ' <message>',
'commands.say.desc': 'Sends a message to chat',
'commands.restart.usage': '',
'commands.restart.desc': 'Restart bot',
'commands.scale.usage': ' set <size>|| reset',
'commands.scale.desc': 'Change player size',
'commands.stop.usage': '',
'commands.stop.desc': 'Stop bot',
'commands.template.usage': ' <required> [optional]',
'commands.template.desc': 'Does nothing',
'commands.test.usage': ' [args...]',
'commands.test.desc': 'Chat parsing debugger command',
'commands.tpr.usage': '',
'commands.tpr.desc': 'Teleport to a random location',
'commands.validate.usage': ' [args...]',
'commands.validate.desc': 'Check the hashing system',
// Command Strings
'command.about.author': '%s - a Minecraft bot made by %s for Kaboom and clones',
'command.about.version': 'Version %s',
'command.about.preRelease': "This is a development version - there may be errors, and features may be changed or removed at any time. Please report any errors to the bot's developer.",
'command.about.sourceCode': 'Source code: %s',
'command.about.license': 'This bot is free and open-source software and is available under the terms of the MIT license.',
'command.about.fork': 'This bot is based on %s by %s, which is available at %s under the MIT license.',
'command.about.subcommands': "This command has subcommands to find out more about this bot - try running the commands \"servers\" for a list of Minecraft servers the bot is connected to, or \"serverinfo\" for technical specifications of the bot's server.",
'command.about.sourceCode.openInBrowser': 'Click to open the source code link in your default browser',
'command.about.serverInfo.os.android': 'Android %s',
'command.about.serverInfo.os.android.noVersion': 'Android',
'command.about.serverInfo.os.freebsd': 'FreeBSD',
'command.about.serverInfo.os.linux': 'Linux',
'command.about.serverInfo.os.macos': 'macOS',
'command.about.serverInfo.os.macos_old': 'OS X',
'command.about.serverInfo.os': 'Operating system',
'command.about.serverInfo.kernelVer': 'Kernel version',
'command.about.serverInfo.processor': 'CPU',
'command.about.serverInfo.arch': 'Architecture',
'command.about.serverInfo.freeMem': '%s free',
'command.about.serverInfo.usedMem': 'Used memory',
'command.about.serverInfo.osUsername': 'Username',
'command.about.serverInfo.hostName': 'Hostname',
'command.about.serverInfo.workingDir': 'Working directory',
'command.about.serverInfo.runTime': 'Bot uptime',
'command.about.serverInfo.upTime': 'System uptime',
'command.about.serverInfo.nodeVersion': 'Node.js version',
'command.about.serverInfo.osRelease': 'Linux release',
'command.about.serverInfo.osRelease.missing': '/etc/os-release does not exist. Information may be limited.',
'command.about.serverInfo.os.android.version': 'Android version',
'command.about.serverInfo.os.android.model': 'Device model',
'command.about.serverInfo.botName': 'Bot name',
'command.about.serverInfo.botVer': 'Bot version',
'command.about.serverListItem': 'Server %s - %s',
'command.cloop.error.tooShort': 'Command loops must have a rate above 20ms.',
'command.cloop.error.subcommand': 'Unknown subcommand, please do %s',
'command.cloop.success.add': 'Added command loop with command %s and rate %s',
'command.cloop.success.remove': 'Removed command loop %s',
'command.cloop.success.clear': 'Cleared all command loops',
@ -77,13 +104,12 @@ export default {
'command.help.commandPerms.lf': 'Required permissions - %s\n',
'command.help.commandAliases': 'Aliases - %s',
'command.help.runCommand': 'Click to run command',
'command.help.permsNormal': 'Public',
'command.help.permsTrusted': 'Trusted',
'command.help.permsOwner': 'Owner',
'command.help.noCommand': 'Command does not exist',
'command.help.alias': 'Alias to %s',
'command.help.copyAlias': 'Click to copy this alias to your clipboard',
'command.netmsg.serverAddress': 'Server Address',
'command.say.warning.trustedKey': 'This message is blocked because it contains the trusted key.',
'command.say.warning.ownerKey': 'This message is blocked because it contains the owner key.',
'command.scale.set': 'Set player size to %s',
'command.scale.reset': 'Reset player size',
'command.test.uuid': 'UUID',
@ -104,43 +130,34 @@ export default {
'command.test.colorWarning': 'Warning color',
'command.test.colorError': 'Error color',
'command.test.colorFatalError': 'Fatal error color',
'command.about.serverInfo.os.android': 'Android %s',
'command.about.serverInfo.os.android.noVersion': 'Android',
'command.about.serverInfo.os.freebsd': 'FreeBSD',
'command.about.serverInfo.os.linux': 'Linux',
'command.about.serverInfo.os.macos': 'macOS',
'command.about.serverInfo.os.macos_old': 'OS X',
'command.about.serverInfo.os': 'Operating system',
'command.about.serverInfo.kernelVer': 'Kernel version',
'command.about.serverInfo.processor': 'CPU',
'command.about.serverInfo.arch': 'Architecture',
'command.about.serverInfo.totalMem': 'Total memory',
'command.about.serverInfo.freeMem': 'Free memory',
'command.about.serverInfo.usedMem': 'Used memory',
'command.about.serverInfo.osUsername': 'Username',
'command.about.serverInfo.hostName': 'Hostname',
'command.about.serverInfo.workingDir': 'Working directory',
'command.about.serverInfo.runTime': 'Bot uptime',
'command.about.serverInfo.upTime': 'System uptime',
'command.about.serverInfo.nodeVersion': 'Node.js version',
'command.about.serverInfo.osRelease': 'Linux release',
'command.about.serverInfo.osRelease.missing': '/etc/os-release does not exist. Information may be limited.',
'command.about.serverInfo.os.android.version': 'Android version',
'command.about.serverInfo.os.android.model': 'Device model',
'command.about.serverInfo.botName': 'Bot name',
'command.about.serverInfo.botVer': 'Bot version',
'command.about.serverListItem': 'Server %s - %s',
'command.about.serverListItem.thisServer': 'Server %s - %s (this server)',
'command.tpr.success': 'Teleporting %s to %s, %s, %s',
'command.verify.success': 'Successfully verified with permission level %s',
// Command Errors
'command.error': 'An error occured (check console for more info)',
'command.error.subcmd': 'Unknown subcommand, please do %s',
// Permission Error
'command.disallowed.perms.short': 'You do not have permission to run this command.',
'command.disallowed.perms': 'You do not have permission to run this command. If you do have permission, please make sure you put the command hash at the end, or ran the command through the hashing system of your client or proxy.',
'command.disallowed.perms.yourLevel': 'Your permission level: %s',
'command.disallowed.perms.cmdLevel': 'Command requires: %s',
'command.disallowed.perms.chipmunkmod': 'Commands requiring trusted permissions cannot be run through custom chat mods. Please bypass custom chat to run this command.',
// Disabled Commands
'command.disabled.generic': 'This command has been disabled.',
'command.disabled.local': 'This command has been disabled on this server.',
'command.disabled.console': 'This command cannot be run from the console.',
'command.disabled.nonConsole': 'This command must be run from the console.',
copyText: 'Click to copy this item to your clipboard'
'command.disabled.noConsole': 'This command cannot be run from the console.',
'command.disabled.consoleOnly': 'This command must be run from the console.',
'command.disabled.chipmunkmod': 'This command cannot be run through a custom chat format.',
// Permission Levels
'command.perms0': 'Public',
'command.perms1': 'Trusted',
'command.perms2': 'Owner',
// Miscellaneous
copyText: 'Click to copy this item to your clipboard',
'chat.antiSpamTriggered': 'Anti-spam has been triggered for this server.'
}

34
package-lock.json generated
View file

@ -39,12 +39,12 @@
}
},
"node_modules/@types/node": {
"version": "22.13.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz",
"integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==",
"version": "22.14.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz",
"integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.20.0"
"undici-types": "~6.21.0"
}
},
"node_modules/@types/node-rsa": {
@ -424,9 +424,9 @@
"license": "MIT"
},
"node_modules/minecraft-data": {
"version": "3.83.1",
"resolved": "https://registry.npmjs.org/minecraft-data/-/minecraft-data-3.83.1.tgz",
"integrity": "sha512-5K26za9k5WV1OnfkGexA77lBhfGZeFw3rT3NM7/rbFXRZC65prCx7Tk2BQvC9UfzgxxvmxHfxM5y8G1U+Oxgfg==",
"version": "3.85.0",
"resolved": "https://registry.npmjs.org/minecraft-data/-/minecraft-data-3.85.0.tgz",
"integrity": "sha512-7RhCjMuvO6ZwhTB7eNymCj4TAZY1Xqkg4XYv6ieLeWjmW1Lc1PGCG6BhR4/xN3zYRVqMNKiBOtAQoGqkVTKECg==",
"license": "MIT"
},
"node_modules/minecraft-folder-path": {
@ -436,9 +436,9 @@
"license": "MIT"
},
"node_modules/minecraft-protocol": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/minecraft-protocol/-/minecraft-protocol-1.54.0.tgz",
"integrity": "sha512-v8pWRVhD9kyd/X52j/XESxrNxkmz1OHzSXAJkPLOQUUTENEqisJhu1c3abS7ZI+MAXHAEA/vaCb/Eh6XFxw0lA==",
"version": "1.55.0",
"resolved": "https://registry.npmjs.org/minecraft-protocol/-/minecraft-protocol-1.55.0.tgz",
"integrity": "sha512-jlzmRxoNuj2bFk1fxR+dTg6Z4RpOR1/FLrk1zhft0jCwAIEhgV2OPi6Ceg2KFKADneEX0suhCty855A/qFLQWA==",
"license": "BSD-3-Clause",
"dependencies": {
"@types/node-rsa": "^1.1.4",
@ -463,7 +463,7 @@
"yggdrasil": "^1.4.0"
},
"engines": {
"node": ">=14"
"node": ">=22"
}
},
"node_modules/mojangson": {
@ -539,9 +539,9 @@
}
},
"node_modules/prismarine-auth": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/prismarine-auth/-/prismarine-auth-2.6.0.tgz",
"integrity": "sha512-9XXYtr6rnJ5EZ/pf63HJvvYPh3lSPe/AIZubwj2BXBQBEidoBR3P5MIm/1nukLwnF1xHiNpF5Y20gcHCdigMDg==",
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/prismarine-auth/-/prismarine-auth-2.7.0.tgz",
"integrity": "sha512-L8wTF6sdtnN6hViPNy+Nx39a8iQBwR5iO92AWCiym5cSXp/92pmnuwnTdcmNDWyqq6zY4hbibVGYhgLA1Ox8sQ==",
"license": "MIT",
"dependencies": {
"@azure/msal-node": "^2.0.2",
@ -804,9 +804,9 @@
"license": "MIT"
},
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"license": "MIT"
},
"node_modules/uri-js": {

View file

@ -10,7 +10,12 @@ export default function load (b) {
b.chunks[data.x] = []
}
const chunk = new Chunk()
chunk.load(data.chunkData)
try {
chunk.load(data.chunkData)
} catch (e) {
console.log(data.chunkData.toString('base64'))
if (b.chunks[data.x]) console.log(b.chunks[data.x][data.z])
}
b.chunks[data.x][data.z] = chunk
})
b._client.on('block_change', data => {

View file

@ -1,4 +1,4 @@
import cmds from '../util/commands.js'
import registry from '../util/commands.js'
import settings from '../settings.js'
import Command from '../util/Command.js'
import hashcheck from '../util/hashcheck.js'
@ -23,13 +23,38 @@ export default function load (b) {
b.emit('command', context)
if (context.cancel === true) return
const commandItem = cmds[context.cmdName.toLowerCase()]
const commandItem = registry.getCommand(context.cmdName)
const cmdsplit = command.split(' ')
const verify = hashcheck(cmdsplit, uuid)
const permsN = getMessage(context.lang, 'command.help.permsNormal')
const permsT = getMessage(context.lang, 'command.help.permsTrusted')
const permsO = getMessage(context.lang, 'command.help.permsOwner')
// Block running eval in minecraft
if(commandItem.consoleOnly){
b.tellraw(uuid, {
text: getMessage(context.lang, 'command.disabled.consoleOnly')
})
return
}
// "Block ChipmunkMod" functionality
if(commandItem.blockChipmunkMod && subtype == "chipmunkmod"){
b.tellraw(uuid, {
text: getMessage(context.lang, 'command.disabled.chipmunkmod')
})
return
}
// Block ChipmunkMod Format in the trusted commands
if(commandItem && commandItem.level !== undefined && subtype == "chipmunkmod"){
b.tellraw(uuid, {
text: getMessage(context.lang, 'command.disallowed.perms.chipmunkmod')
})
return
}
if (commandItem && commandItem.level !== undefined && commandItem.level > verify) {
b.tellraw(uuid, {
text: getMessage(context.lang, 'command.disallowed.perms')

View file

@ -9,7 +9,7 @@ export default function load (b) {
b.blocknoZ = 0
b.ccStarted = false
b.pos = { x: 0, y: 0, z: 0 }
const refillPayload = 'command_block{CustomName:\'{"translate":"%s %s","with":[{"translate":"entity.minecraft.ender_dragon"},{"translate":"language.name"}],"color":"#FFAAEE"}\'}'
const refillPayload = 'command_block'
b.advanceccq = function () {
if (b.host.options.useChat) return
@ -61,7 +61,7 @@ export default function load (b) {
b.add_sc_task('cc', () => {
const xstart = b.currentChunk.x << 4
const zstart = b.currentChunk.z << 4
b.chat(`/fill ${xstart} 55 ${zstart} ${xstart + cs.x - 1} 55 ${zstart + cs.z - 1} ${refillPayload}`)
b.chat(`/fill ${xstart} 55 ${zstart} ${xstart + 15} 55 ${zstart + 15} ${refillPayload}`)
})
b.add_sc_task('cc_size', () => {
b.chat('/gamerule commandModificationBlockLimit 32768')
@ -75,9 +75,6 @@ export default function load (b) {
b.on('chat_unparsed', (data) => {
if (data.json.translate === 'commands.fill.failed' || (data.json.extra && data.json.extra[0] && data.json.extra[0].translate === 'commands.fill.failed') ||
data.json.translate === 'commands.fill.success' || (data.json.extra && data.json.extra[0] && data.json.extra[0].translate === 'commands.fill.success')) {
if (!b.ccStarted) {
b.emit('ccstart')
}
b.sc_tasks.cc.failed = 0
b.sc_tasks.cc_size.failed = 0
} else if (data.json.translate === 'commands.fill.toobig' || (data.json.extra && data.json.extra[0] && data.json.extra[0].translate === 'commands.fill.toobig')) {
@ -126,5 +123,8 @@ export default function load (b) {
}
if (cf) break
}
if (!cf && !b.ccStarted) {
b.emit('ccstart')
}
}, 500)
}

View file

@ -1,14 +1,14 @@
import { createInterface, cursorTo, clearLine } from 'node:readline'
import settings from '../settings.js'
import cmds from '../util/commands.js'
import { bots } from '../index.js'
import registry from '../util/commands.js'
import Command from '../util/Command.js'
import parse2 from '../util/chatparse_console.js'
import parse2 from '../util/chatparse_plain.js'
import { userInfo } from 'node:os'
import { bots } from '../index.js'
import settings from '../settings.js'
const consoleBotStub = {
host: {
host: 'bot console ',
host: 'bot console',
port: 25565
},
tellraw: (_unused, data) => console.log(parse2(data))
@ -27,7 +27,7 @@ rl.on('line', (l) => {
const cmdName = args[0].toLowerCase()
try {
const cmd = cmds[cmdName]
const cmd = registry.getCommand(cmdName)
if (!cmd) {
rl.prompt(false)
return

View file

@ -1,3 +1,5 @@
// This file is written in English - please do not use the translation system for this plugin.
import settings from '../settings.js'
import version from '../version.js'
import { bots } from '../index.js'

View file

@ -21,26 +21,26 @@ export default function load (b) {
let index = -1
if (/[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}/.test(string)) { // Uuid code
b.filteredPlayers.forEach((item, index2) => {
if (item.uuid == string) {
if (item.uuid === string) {
console.log(index2)
index = index2
}
})
} else { // Uuid code
b.filteredPlayers.forEach((item, index2) => {
if (item.username == string) {
if (item.username === string) {
console.log(index2)
index = index2
}
})
}
if (index == -1) return
if (index === -1) return
b.filteredPlayers.splice(index, 1)
}
b.isFiltered = function (string) {
let playerIsFiltered = false
b.filteredPlayers.forEach((item) => {
if (item.uuid == string) {
if (item.uuid === string) {
playerIsFiltered = true
}
})

View file

@ -3,13 +3,14 @@ import parseNBT from '../util/parseNBT.js'
export default function load (b) {
b.players = {}
b._client.on('player_remove', (data) => {
b._client.on('player_remove', data => {
for (const item of data.players) {
if (!data.players[item]) continue
b.players[item].here = false
b.emit('playerquit', item)
}
})
b._client.on('player_info', (data) => {
b._client.on('player_info', data => {
const buffer2 = {}
for (const player of data.data) {
let uuid
@ -48,7 +49,8 @@ export default function load (b) {
b.emit('playerdata', uuid, displayName, realName)
}
})
b.findUUID = (name) => {
b.findUUID = name => {
for (const i in b.players) {
if (b.players[i].realName === name) {
return i
@ -56,7 +58,7 @@ export default function load (b) {
}
return '00000000-0000-0000-0000-000000000000'
}
b.findRealName = (name) => {
b.findRealName = name => {
for (const i in b.players) {
if (b.players[i].displayName === name) {
return b.players[i].realName
@ -64,14 +66,14 @@ export default function load (b) {
}
return '[[[[ no name ]]]]'
}
b.findRealNameFromUUID = (uuid) => {
b.findRealNameFromUUID = uuid => {
if (b.players[uuid]) {
return b.players[uuid].realName
} else {
return uuid
}
}
b.findDisplayName = (uuid) => {
b.findDisplayName = uuid => {
if (b.players[uuid]) {
const displayName = b.players[uuid].displayName.split(' ')
return displayName[displayName.length - 1]

View file

@ -148,24 +148,6 @@ export default function load (b) {
})
})
b._client.on('chat', (data) => { // Legacy chat for versions <1.19
const json = parse1204(data.message)
let nickname
let username
let message
let uuid
if (data.uuid) uuid = data.uuid
b.emit('chat_unparsed', {
json,
type: 'legacy',
uuid,
message,
nickname,
username,
playerChatType: {}
})
})
b.on('chat_unparsed', (data) => {
for (const lvl of parsers) {
for (const item of lvl) {

View file

@ -2,9 +2,7 @@ export default {
terminalMode: 'blackTerminal_24bit', // Terminal mode. Most modern terminals support 24-bit color
version_mc: '1.21.1', // Minecraft version to connect with
defaultLang: 'en-US', // Default language
keyTrusted: '3e9f13473eec8d64c3eabf6385e3f8585f0af39ed30a8db9a4c8d8bcfa35659d7d06a58b342bfd2db5e3cbb4003a81da8f9d25f7cce1ad26face8e2871c3b217', // Trusted key
keyOwner: '17d2c6c53b8919dc1ec22c42845018ac389824c4d73a68572b7fc57ff1442c6bbf9924d5ee5fa90cb23e384278d469c4e260208265b8ba2e2bc873045d5ed42e', // Owner key
playerManagement: false, // Whether to enable player management features. This breaks a promise that I made several months ago, but many bots have it nowadays.
// Insert the trusted key (keyTrusted) and owner key (keyOwner) here. Both of these values should be strings, and they should not be identical. Do not tell anyone the keys unless you trust them, as they can be used to get admin access to the bot, and (in the case of the owner key) access to your computer.
colors: { // All colors the bot uses
primary: '#EECCFF', // Used for primary subjects (e.g. items in lists)
secondary: '#DD99FF', // Used for secondary subjects (e.g. list labels)

View file

@ -12,6 +12,6 @@ export default function chatlog (fileName, item) {
const UTCSeconds = dateToday.getUTCSeconds().toString().padStart(2, '0')
const UTCMilliSeconds = dateToday.getUTCMilliseconds().toString().padStart(3, '0')
const filenameToday = `${UTCMonths}-${UTCDays}-${UTCYears}`
const logDate = `${UTCMonths}/${UTCDays}/${UTCYears} ${UTCHours}:${UTCMinutes}:${UTCSeconds}.${UTCMilliSeconds}`
const logDate = `${UTCYears}-${UTCMonths}-${UTCDays} ${UTCHours}:${UTCMinutes}:${UTCSeconds}.${UTCMilliSeconds}`
appendFileSync(`logs/${filenameToday}/${fileName}.txt`, `[${logDate}] ${item}\n`)
}

View file

@ -1,6 +1,7 @@
import { readdirSync } from 'node:fs'
import CommandR from './cr.js'
const cmds = Object.create(null)
const registry = new CommandR()
const bpl = readdirSync('commands')
for (const plugin of bpl) {
@ -10,21 +11,9 @@ for (const plugin of bpl) {
try {
const commandName = plugin.split('.js')[0]
import(`../commands/${plugin}`).then((pluginItem) => {
cmds[commandName] = pluginItem // For rejoining
if (cmds[commandName].aliases) {
for (const j in cmds[commandName].aliases) {
cmds[cmds[commandName].aliases[j]] = {
execute: cmds[commandName].execute,
alias: commandName,
usage: cmds[commandName].usage,
level: cmds[commandName].level,
hidden: true,
consoleIndex: cmds[commandName].consoleIndex
}
}
}
registry.register(commandName, pluginItem.execute, pluginItem.level, pluginItem.consoleIndex, pluginItem.hidden, pluginItem.aliases, pluginItem.consoleOnly, pluginItem.blockChipmunkMod)
})
} catch (e) { console.log(e) }
}
export default cmds
export default registry

38
util/cr.js Normal file
View file

@ -0,0 +1,38 @@
export default class CommandR {
constructor () {
this._commands = Object.create(null)
this._aliases = Object.create(null)
this.register = function (name, payload, level, consoleIndex, hidden, aliases, consoleOnly, blockChipmunkMod) {
const command = {}
command.execute = payload
command.level = level
command.hidden = hidden
if (aliases) for (const alias of aliases) this._aliases[alias] = name
command.aliases = aliases
command.consoleIndex = consoleIndex
command.consoleOnly = consoleOnly
command.blockChipmunkMod = blockChipmunkMod
this._commands[name] = command
}
this.getCommand = function (name) {
if (this._commands[name]) {
return this._commands[name]
}
if (this._aliases[name]) {
return this._commands[this._aliases[name]]
}
return false
}
this.listCommands = function (includeHidden) {
if (includeHidden) return this._commands
const list = {}
for (const item in this._commands) {
if (!this._commands[item].hidden) list[item] = this._commands[item]
}
return list
}
}
}

View file

@ -1,5 +1,5 @@
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
const THRESHOLD = 1000 // KiB = 1024; KB = 1000
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB']
const THRESHOLD = 1000
export default function memoryconvert (bytes) {
for (let i = 0; i < UNITS.length; i++) {

View file

@ -3,5 +3,8 @@ export default {
botVersion: '12.0.0-alpha.2', // Version of the bot. This is different from the one in package.json, which has to be updated seperately.
botAuthor: 'owo439895035', // The creator of the bot
isPreRelease: true, // If this version is a pre-release version. Used by the about command to show a warning if set to true.
sourceURL: 'https://code.chipmunk.land/7cc5c4f330d47060/botv12' // Source code repository URL. This is different from the one in package.json.
sourceURL: 'https://code.chipmunk.land/7cc5c4f330d47060/botv12', // Source code repository URL. This is different from the one in package.json.
originalRepo: 'https://code.chipmunk.land/7cc5c4f330d47060/botv12',
originalName: 'botv12',
originalAuthor: 'owo439895035' // These three fields should only be changed in forks of forks, if the original fork is compliant with MIT
}