work-in-progress proxy & catch protodef errors
This commit is contained in:
parent
74dc561d3d
commit
388d30ce51
4 changed files with 140 additions and 24 deletions
|
@ -1,23 +0,0 @@
|
||||||
const { literal } = require('brigadier-commands')
|
|
||||||
const { generateString } = require('/var/tmp/nbt-overflow.js')
|
|
||||||
const fs = require('fs')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
register (dispatcher) {
|
|
||||||
const node = dispatcher.register(
|
|
||||||
literal('test')
|
|
||||||
.executes(this.testCommand)
|
|
||||||
)
|
|
||||||
|
|
||||||
node.description = 'Tests something'
|
|
||||||
node.permissionLevel = 1
|
|
||||||
},
|
|
||||||
|
|
||||||
testCommand (context) {
|
|
||||||
const source = context.source
|
|
||||||
const bot = source.bot
|
|
||||||
|
|
||||||
const payload = fs.readFileSync('/var/tmp/test_payload.bin')
|
|
||||||
bot.core.run(`data modify storage test '${generateString(payload).replace(/\'/g, m => '\\' + m)}' set value a`)
|
|
||||||
}
|
|
||||||
}
|
|
9
index.js
9
index.js
|
@ -54,6 +54,15 @@ async function main () {
|
||||||
|
|
||||||
bot.on('error', error => bot.console.error(error))
|
bot.on('error', error => bot.console.error(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
process.on('uncaughtException', error => {
|
||||||
|
if (error.stack.includes('protodef')) {
|
||||||
|
console.error('Uncaught protodef exception!\n' + error.stack)
|
||||||
|
return // Ignore protodef-related errors (packet-related)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -11,7 +11,14 @@ function inject (bot) {
|
||||||
block: { x: null, y: null, z: null },
|
block: { x: null, y: null, z: null },
|
||||||
|
|
||||||
refill () {
|
refill () {
|
||||||
const refillCommand = `/fill ${this.start.x} ${this.start.y} ${this.start.z} ${this.end.x} ${this.end.y} ${this.end.z} repeating_command_block{CustomName:'""'}`
|
const refillCommand = `fill ${this.start.x} ${this.start.y} ${this.start.z} ${this.end.x} ${this.end.y} ${this.end.z} repeating_command_block{CustomName:'""'}`
|
||||||
|
|
||||||
|
if (bot.proxy?.client) {
|
||||||
|
// Use chat commands when a player is logged into the proxy
|
||||||
|
bot.chat.command(refillCommand)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const location = { x: Math.floor(bot.position.x), y: Math.floor(bot.position.y) - 1, z: Math.floor(bot.position.z) }
|
const location = { x: Math.floor(bot.position.x), y: Math.floor(bot.position.y) - 1, z: Math.floor(bot.position.z) }
|
||||||
const commandBlockId = bot.registry?.itemsByName.command_block.id
|
const commandBlockId = bot.registry?.itemsByName.command_block.id
|
||||||
|
|
||||||
|
|
123
plugins/proxy.js
Normal file
123
plugins/proxy.js
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
const mc = require('minecraft-protocol')
|
||||||
|
|
||||||
|
const LOGIN_PACKET_NAMES = [
|
||||||
|
'login',
|
||||||
|
'difficulty',
|
||||||
|
'abilities',
|
||||||
|
'held_item_slot',
|
||||||
|
'declare_recipes',
|
||||||
|
'entity_status',
|
||||||
|
'declare_commands',
|
||||||
|
'unlock_recipes',
|
||||||
|
'position',
|
||||||
|
// 'server_data',
|
||||||
|
// 'player_info',
|
||||||
|
'initialize_world_border',
|
||||||
|
'update_time',
|
||||||
|
'spawn_position',
|
||||||
|
'game_state_change',
|
||||||
|
'set_ticking_state',
|
||||||
|
'step_tick',
|
||||||
|
'update_view_position'
|
||||||
|
]
|
||||||
|
|
||||||
|
function createLoginPacketMap () {
|
||||||
|
return new Map(LOGIN_PACKET_NAMES.map(name => [name, null]))
|
||||||
|
}
|
||||||
|
|
||||||
|
function inject (bot, options) {
|
||||||
|
if (!options.proxy?.enabled) return
|
||||||
|
|
||||||
|
options.proxy.version ??= bot._client.version
|
||||||
|
options.proxy.enforceSecureProfile ??= false
|
||||||
|
|
||||||
|
bot.proxy = {
|
||||||
|
server: mc.createServer(options.proxy),
|
||||||
|
options: options.proxy,
|
||||||
|
client: null,
|
||||||
|
loginPackets: createLoginPacketMap(),
|
||||||
|
_players: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
bot.on('end', () => {
|
||||||
|
bot.proxy.loginPackets = createLoginPacketMap()
|
||||||
|
bot.proxy._players = {}
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.on('packet.registry_data', packet => {
|
||||||
|
bot.proxy.options.registryCodec = packet.codec // * nmp gets the registry codec from options
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.on('packet', (data, meta) => {
|
||||||
|
if (bot.proxy.client && bot.proxy.client.state === mc.states.PLAY && meta.state === mc.states.PLAY) {
|
||||||
|
// Forward packets
|
||||||
|
bot.proxy.client.write(meta.name, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store login-related packets
|
||||||
|
if (!bot.proxy.loginPackets.has(meta.name)) return
|
||||||
|
if (meta.name === 'entity_status' && (data.entityStatus < 24 || data.entityStatus > 28)) return // Only forward permission level entity statuses on login
|
||||||
|
if (meta.name === 'game_state_change' && data.reason !== 13) return // Only forward "Start waiting for level chunks"
|
||||||
|
|
||||||
|
bot.proxy.loginPackets.set(meta.name, data)
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.proxy.server.on('playerJoin', client => {
|
||||||
|
if (bot.proxy.client) bot.proxy.client.end('Logged in from another client!')
|
||||||
|
|
||||||
|
bot.proxy.client = client
|
||||||
|
|
||||||
|
client.on('packet', (data, meta) => {
|
||||||
|
if (bot._client.state !== mc.states.PLAY || meta.state !== mc.states.PLAY) return
|
||||||
|
bot._client.write(meta.name, data)
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('position', packet => {
|
||||||
|
bot.position.x = packet.x
|
||||||
|
bot.position.y = packet.y
|
||||||
|
bot.position.z = packet.z
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
client.on('look', packet => {
|
||||||
|
bot.position.yaw = packet.yaw
|
||||||
|
bot.position.pitch = packet.pitch
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('position_look', packet => {
|
||||||
|
bot.position.x = packet.x
|
||||||
|
bot.position.y = packet.y
|
||||||
|
bot.position.z = packet.z
|
||||||
|
bot.position.yaw = packet.yaw
|
||||||
|
bot.position.pitch = packet.pitch
|
||||||
|
})
|
||||||
|
|
||||||
|
client.on('vehicle_move', packet => {
|
||||||
|
bot.position.x = packet.x
|
||||||
|
bot.position.y = packet.y
|
||||||
|
bot.position.z = packet.z
|
||||||
|
bot.position.yaw = packet.yaw
|
||||||
|
bot.position.pitch = packet.pitch
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const [name, data] of bot.proxy.loginPackets) {
|
||||||
|
if (!data) continue
|
||||||
|
client.write(name, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// send player info
|
||||||
|
for (const player of Object.values(bot.proxy._players)) {console.log('writing data for player %s (%s)', player.player?.username, player.uuid)
|
||||||
|
client.write('player_info', { action: player.flags, data: [{ ...player, flags: undefined }] })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.on('packet.player_info', packet => {
|
||||||
|
for (const player of packet.data) {
|
||||||
|
const old = bot.proxy._players[player.uuid] ?? { flags: 0 }
|
||||||
|
const filteredPlayer = Object.fromEntries(Object.entries(player).filter(([k, v]) => v != null))
|
||||||
|
bot.proxy._players[player.uuid] = { ...old, ...filteredPlayer, flags: old.flags | packet.action }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = inject
|
Loading…
Reference in a new issue