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))
|
||||
}
|
||||
|
||||
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()
|
||||
|
|
|
@ -11,7 +11,14 @@ function inject (bot) {
|
|||
block: { x: null, y: null, z: null },
|
||||
|
||||
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 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