Skip to content

Commit

Permalink
Initial Minecraft 1.19.1/2 support, fix 1.16, jsbi
Browse files Browse the repository at this point in the history
  • Loading branch information
retrixe committed Aug 11, 2022
1 parent 32e77e3 commit 69f6e68
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 48 deletions.
1 change: 0 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { AppRegistry } from 'react-native'
import App from './src/App'
import { name as appName } from './app.json'

global.BigInt = require('jsbi').BigInt
global.Buffer = require('buffer').Buffer
// global.process = require('process');
global.process.env.NODE_ENV = __DEV__ ? 'development' : 'production'
Expand Down
11 changes: 0 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"browserify-zlib": "^0.2.0",
"buffer": "^6.0.3",
"events": "^3.3.0",
"jsbi": "^3.2.5",
"promise.allsettled": "^1.0.4",
"react": "18.0.0",
"react-native": "0.69.4",
Expand Down
36 changes: 28 additions & 8 deletions src/minecraft/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,7 @@ const getLoginPacket = (opts: ConnectionOptions) => {
data.push(!!opts.certificate)
if (opts.certificate) {
let buf = Buffer.alloc(8)
buf.writeBigInt64BE(
BigInt(new Date(opts.certificate.expiresAt).getTime())
)
buf.writeIntBE(new Date(opts.certificate.expiresAt).getTime(), 2, 6) // writeBigInt64BE
data.push(buf)
const publicKeyBase64Data = opts.certificate.keyPair.publicKey
.replace(/\n/g, '')
Expand All @@ -117,6 +115,13 @@ const getLoginPacket = (opts: ConnectionOptions) => {
data.push(writeVarInt(buf.byteLength))
data.push(buf)
}
if (opts.protocolVersion >= protocolMap['1.19.1']) {
if (opts.selectedProfile) {
const msb = Buffer.from(opts.selectedProfile.substring(0, 16), 'hex')
const lsb = Buffer.from(opts.selectedProfile.substring(16), 'hex')
data.push(concatPacketData([true, msb, lsb]))
} else data.push(concatPacketData([false]))
}
}
return concatPacketData(data)
}
Expand Down Expand Up @@ -181,7 +186,12 @@ const initiateConnection = async (opts: ConnectionOptions) => {
? Buffer.alloc(0) // Avoid errors shortening.
: conn.bufferedData.slice(packet.packetLength)
// Internally handle login packets.
const is1164 =
conn.options.protocolVersion >= protocolMap['1.16.4']
const is117 = conn.options.protocolVersion >= protocolMap[1.17]
const is119 = conn.options.protocolVersion >= protocolMap[1.19]
const is1191 =
conn.options.protocolVersion >= protocolMap['1.19.1']
if (packet.id === 0x03 && !conn.loggedIn /* Set Compression */) {
const [threshold] = readVarInt(packet.data)
conn.compressionThreshold = threshold
Expand All @@ -190,22 +200,32 @@ const initiateConnection = async (opts: ConnectionOptions) => {
conn.loggedIn = true // Login Success
} else if (
// Keep Alive (clientbound)
(packet.id === 0x21 && !is119) ||
(packet.id === 0x1e && is119)
(packet.id === 0x1f && is1164 && !is117) ||
(packet.id === 0x21 && is117 && !is119) ||
(packet.id === 0x1e && is119 && !is1191) ||
(packet.id === 0x20 && is1191)
) {
const id = is1191 ? 0x12 : is119 ? 0x11 : is117 ? 0x0f : 0x10
conn
.writePacket(is119 ? 0x11 : 0x0f, packet.data)
.writePacket(id, packet.data)
.catch(err => conn.emit('error', err))
} else if (
// Disconnect (login) or Disconnect (play)
(packet.id === 0x00 && !conn.loggedIn) ||
(packet.id === 0x1a && conn.loggedIn && !is119) ||
(packet.id === 0x17 && conn.loggedIn && is119)
(packet.id === 0x19 && conn.loggedIn && is1164 && !is117) ||
(packet.id === 0x1a && conn.loggedIn && is117 && !is119) ||
(packet.id === 0x17 && conn.loggedIn && is119 && !is1191) ||
(packet.id === 0x19 && conn.loggedIn && is1191)
) {
const [chatLength, chatVarIntLength] = readVarInt(packet.data)
conn.disconnectReason = packet.data
.slice(chatVarIntLength, chatVarIntLength + chatLength)
.toString('utf8')
} else if (packet.id === 0x04 && !conn.loggedIn) {
/* Login Plugin Request */
const [msgId] = readVarInt(packet.data)
const rs = concatPacketData([writeVarInt(msgId), false])
conn.writePacket(0x02, rs).catch(err => conn.emit('error', err))
} else if (packet.id === 0x01 && !conn.loggedIn) {
/* Encryption Request */
if (!accessToken || !selectedProfile) {
Expand Down
3 changes: 2 additions & 1 deletion src/screens/ServerScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const ServerScreen = (props: Props) => {
if (version === -1) {
const ping = pingResponses[servers[server].address]
// Try the latest.
if (!ping) version = protocolMap['1.19']
if (!ping) version = protocolMap['1.19.1']
else if (typeof ping.version === 'object') {
version = ping.version.protocol
} else version = (ping as LegacyPing).protocol
Expand Down Expand Up @@ -217,6 +217,7 @@ const ServerScreen = (props: Props) => {
dropdownIconColor={darkMode ? '#ffffff' : '#000000'}
>
<Picker.Item label='Auto' value='auto' />
<Picker.Item label='1.19.1/1.19.2' value='1.19.1' />
<Picker.Item label='1.19' value='1.19' />
<Picker.Item label='1.18.2' value='1.18.2' />
<Picker.Item label='1.18/1.18.1' value='1.18' />
Expand Down
27 changes: 19 additions & 8 deletions src/screens/chat/ChatScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
ColorMap
} from '../../minecraft/chatToJsx'
import { protocolMap, writeVarInt } from '../../minecraft/utils'
import { concatPacketData } from '../../minecraft/packet'
import { concatPacketData, PacketDataTypes } from '../../minecraft/packet'
import TextField from '../../components/TextField'
import Text from '../../components/Text'
import SettingScreen from '../settings/SettingScreen'
Expand Down Expand Up @@ -157,25 +157,36 @@ const ChatScreen = ({ navigation, route }: Props) => {
if (msg.startsWith('/') && saveHistory) {
setCommandHistory(ch => ch.concat([msg]))
}
if (connection.connection.options.protocolVersion < protocolMap['1.19']) {
const is119 =
connection.connection.options.protocolVersion >= protocolMap[1.19]
const is1191 =
connection.connection.options.protocolVersion >= protocolMap['1.19.1']
if (!is119) {
connection.connection
.writePacket(0x03, concatPacketData([msg]))
.catch(handleError(addMessage, sendMessageError))
} else {
const id = msg.startsWith('/') ? 0x03 : 0x04
const id = msg.startsWith('/')
? is1191
? 0x04
: 0x03
: is1191
? 0x05
: 0x04
const timestamp = Buffer.alloc(8)
timestamp.writeIntBE(Date.now(), 2, 6) // writeBigInt64BE(BigInt(Date.now()))
const salt = connection.connection.msgSalt ?? Buffer.alloc(8)
// TODO-1.19: Send signature(s) and preview chat if possible.
const data = concatPacketData([
id === 0x03 ? msg.substring(1) : msg,
// TODO-1.19: Send signature(s), preview chat, last seen messages and last received message if possible.
const data: PacketDataTypes[] = [
msg.startsWith('/') ? msg.substring(1) : msg,
timestamp,
salt,
writeVarInt(0),
false
])
]
if (is1191) data.push(writeVarInt(0), writeVarInt(0))
connection.connection
.writePacket(id, data)
.writePacket(id, concatPacketData(data))
.catch(handleError(addMessage, sendMessageError))
}
}
Expand Down
47 changes: 34 additions & 13 deletions src/screens/chat/packetHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,14 @@ export const packetHandler =
}
}

const is119 = connection.options.protocolVersion >= protocolMap['1.19']
if (packet.id === 0x0f /* Chat Message (clientbound) */ && !is119) {
const is117 = connection.options.protocolVersion >= protocolMap[1.17]
const is119 = connection.options.protocolVersion >= protocolMap[1.19]
const is1191 = connection.options.protocolVersion >= protocolMap['1.19.1']
if (
/* Chat Message (clientbound) */
(packet.id === 0x0e && !is117) ||
(packet.id === 0x0f && is117 && !is119)
) {
try {
const [chatLength, chatVarIntLength] = readVarInt(packet.data)
const chatJson = packet.data
Expand All @@ -66,8 +72,9 @@ export const packetHandler =
handleError(addMessage, parseMessageError)(e)
}
} else if (
packet.id === 0x30 /* Player Chat Message (clientbound) */ &&
is119
/* Player Chat Message (clientbound) */
(packet.id === 0x30 && is119 && !is1191) ||
(packet.id === 0x33 && is1191)
) {
try {
const [signedChatLen, signedChatViLen] = readVarInt(packet.data)
Expand Down Expand Up @@ -114,37 +121,46 @@ export const packetHandler =
handleError(addMessage, parseMessageError)(e)
}
} else if (
packet.id === 0x5f /* System Chat Message (clientbound) */ &&
is119
/* System Chat Message (clientbound) */
(packet.id === 0x5f && is119 && !is1191) ||
(packet.id === 0x62 && is1191)
) {
try {
const [chatLength, chatVarIntLength] = readVarInt(packet.data)
const chatJson = packet.data
.slice(chatVarIntLength, chatVarIntLength + chatLength)
.toString('utf8')
// As of 1.19.1, this is a boolean which says if this is an action bar or not.
const position = packet.data.readInt8(chatVarIntLength + chatLength)
// TODO-1.19 - 3: say command, 4: msg command, 5: team msg command, 6: emote command, 7: tellraw command
// Also in Player Chat Message.
if (position === 0 || position === 1) {
if (is119 && (position === 0 || position === 1)) {
addMessage(parseValidJson(chatJson))
} else if (is1191 && !position) {
addMessage(parseValidJson(chatJson))
}
} catch (e) {
handleError(addMessage, parseMessageError)(e)
}
} else if (
/* Open Window */
(packet.id === 0x2e && !is119) ||
(packet.id === 0x2b && is119) /* Open Window */
(packet.id === 0x2b && is119 && !is1191) ||
(packet.id === 0x2d && is119)
) {
// Just close the window.
const [windowId] = readVarInt(packet.data)
const buf = Buffer.alloc(1)
buf.writeUInt8(windowId)
connection // Close Window (serverbound)
.writePacket(0x09, buf)
.writePacket(is1191 ? 0x0c : is119 ? 0x0b : is117 ? 0x09 : 0x0a, buf)
.catch(handleError(addMessage, inventoryCloseError))
} else if (
(packet.id === 0x35 && !is119) ||
(packet.id === 0x33 && is119) /* Death Combat Event */
/* Death Combat Event */
(packet.id === 0x32 && !is117) ||
(packet.id === 0x35 && is117 && !is119) ||
(packet.id === 0x33 && is119 && !is1191) ||
(packet.id === 0x36 && is1191)
) {
const [, playerIdLen] = readVarInt(packet.data)
const offset = playerIdLen + 4 // Entity ID
Expand All @@ -158,9 +174,14 @@ export const packetHandler =
// Automatically respawn.
// LOW-TODO: Should this be manual, or a dialog, like MC?
connection // Client Status
.writePacket(is119 ? 0x06 : 0x04, writeVarInt(0))
.writePacket(is1191 ? 0x07 : is119 ? 0x06 : 0x04, writeVarInt(0))
.catch(handleError(addMessage, respawnError))
} else if (packet.id === 0x52 /* Update Health */) {
} else if (
/* Update Health */
(packet.id === 0x49 && !is117) ||
(packet.id === 0x52 && is117 && !is1191) ||
(packet.id === 0x55 && is1191)
) {
const newHealth = packet.data.readFloatBE(0)
if (healthRef.current != null && healthRef.current > newHealth) {
const info = healthMessage
Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5368,11 +5368,6 @@
"argparse" "^1.0.7"
"esprima" "^4.0.0"

"jsbi@^3.2.5":
"integrity" "sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ=="
"resolved" "https://registry.npmjs.org/jsbi/-/jsbi-3.2.5.tgz"
"version" "3.2.5"

"jsbn@~0.1.0":
"integrity" "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
"resolved" "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz"
Expand Down

0 comments on commit 69f6e68

Please sign in to comment.