Skip to content

Commit

Permalink
Bedrock (#32)
Browse files Browse the repository at this point in the history
* add(): Allow registering item states for bedrcok.

* fix(): remove temporary jsdoc

* add(): Bool to let the code know if things have already been loaded.

* add(): Assign `itemsArray` proprety of data

* fix(): Follow the rules of the linter

* fix(): Prevent undefined error

* fix(): Use a different method to assign the indexer.

* fix(): Use correct property for id

* add(): A basic example  to readme, move `buildIndexFromArray`

* optimization(): Don't do a double loop

* fix(): Use the correct var

* Start adding bedrock tests

* writeItemStates() function

* Update test for write func, update types, minecraft-bedrock-server (minecraft-wrap doesn't support bedrock yet?)

* don't use regex, component_based

* fix name being undefined

* update versions in test for item changes in mcdata

* Update docs

* move loggedIn to start_game

* Move indexer to lib

* add version to server messages to see what server started/stopped

* Linter

* more delay because there wasn't time for the client to connect

* linter again?

* Lint the way GitHub wants it

---------

Co-authored-by: ATXLtheAxolotl <flashtube107@gmail.com>
Co-authored-by: CreeperG16 <pappt1216@gmail.com>
  • Loading branch information
3 people committed Jul 29, 2023
1 parent a39ab01 commit 1aa8724
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 11 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,29 @@ chat type should be formatted and what the relevant parameters are.
#### .dimensionsById, dimensionsByName (1.19+)

Mapping to dimension data object containing dimension `name`, `minY` and `height`.

### mcpe

#### loadItemStates / writeItemStates

* loads/writes data from an item states array inside the bedrock start game packet.

```js
// In a client
const { createClient } = require('bedrock-protocol');
const registry = require('prismarine-registry')('bedrock_1.19.50');

const client = createClient({
'host': '127.0.0.1'
})

client.on('start_game', ({ itemstates }) => {
registry.loadItemStates(itemstates);
})

// In a server
server.on('connect', (client) => {
const itemstates = registry.writeItemStates()
client.write('start_game', { ...startGamePacket, itemstates })
})
```
33 changes: 32 additions & 1 deletion lib/bedrock/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
module.exports = (data) => ({})
const buildIndexFromArray = require('../indexer')

module.exports = (data) => {
return {
loadItemStates (itemStates) {
const items = []
for (const item of itemStates) {
const name = item.name.replace('minecraft:', '')
items.push({ ...data.itemsByName[name], name, id: item.runtime_id })
}
data.itemsArray = items
data.items = buildIndexFromArray(data.itemsArray, 'id')
data.itemsByName = buildIndexFromArray(data.itemsArray, 'name')
},

writeItemStates () {
const itemstates = []
for (const item of data.itemsArray) {
// Custom items with different namespaces can also be in the palette
let [ns, name] = item.name.split(':')
if (!name) {
name = ns
ns = 'minecraft'
}

itemstates.push({ name: `${ns}:${name}`, runtime_id: item.id, component_based: ns !== 'minecraft' })
}

return itemstates
}
}
}
31 changes: 21 additions & 10 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import {IndexedData} from 'minecraft-data'
import {NBT} from 'prismarine-nbt'
import { IndexedData } from 'minecraft-data'
import { NBT } from 'prismarine-nbt'

interface PCRegistry extends IndexedData {
loadDimensionCodec(codec: NBT): void
writeDimensionCodec(): NBT
declare function loader(mcVersion: string): loader.Registry
declare namespace loader {
export interface RegistryPc extends IndexedData {
loadDimensionCodec(codec: NBT): void;
writeDimensionCodec(): NBT;
}

export interface RegistryBedrock extends IndexedData {
loadItemStates(itemStates: ItemState[]): void;
writeItemStates(): ItemState[];
}

export type Registry = RegistryBedrock | RegistryPc
export type ItemState = {
name: string
runtime_id: number
component_based: boolean
}
}

interface BedrockRegistry extends IndexedData {

}
export type Registry = PCRegistry & BedrockRegistry
export default function loader(mcVersion: string): Registry
export = loader
7 changes: 7 additions & 0 deletions lib/indexer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = function buildIndexFromArray (array, fieldToIndex) {
if (array === undefined) { return undefined }
return array.reduce(function (index, element) {
index[element[fieldToIndex]] = element
return index
}, {})
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
},
"homepage": "https://github.com/PrismarineJS/prismarine-registry#readme",
"devDependencies": {
"bedrock-protocol": "^3.22.0",
"debug": "^4.3.3",
"minecraft-bedrock-server": "^1.1.2",
"minecraft-protocol": "^1.30.0",
"minecraft-wrap": "^1.4.0",
"mocha": "^10.0.0",
Expand Down
31 changes: 31 additions & 0 deletions test/mcbedrock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const Registry = require('prismarine-registry')
const collectPackets = require('./util/collectBedrockPackets')
const assert = require('assert')

async function main (version = '1.19.63') {
const registry = Registry(`bedrock_${version}`)
let loggedIn = false
const handlers = {
start_game (version, params) {
registry.loadItemStates(params.itemstates)
console.log('Loaded item palette', registry.items)

const reEncoded = registry.writeItemStates()
assert.deepEqual(
reEncoded.sort((a, b) => a.runtime_id - b.runtime_id),
params.itemstates.sort((a, b) => a.runtime_id - b.runtime_id)
)
console.log('Re-encoded item palette')

loggedIn = true
}
}

await collectPackets(version, Object.keys(handlers), (name, params) => handlers[name](version, params))
await new Promise((resolve) => setTimeout(resolve, 6000))
if (!loggedIn) {
throw new Error('Did not login')
}
}

module.exports = main
12 changes: 12 additions & 0 deletions test/mcbedrock.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-env mocha */

const SUPPORTED_VERSIONS = ['1.17.10', '1.18.0', '1.18.11', '1.18.30', '1.19.1', '1.19.10']
const test = require('./mcbedrock')

describe('mcbedrock', function () {
this.timeout(9000 * 10)

for (const version of SUPPORTED_VERSIONS) {
it('works on ' + version, () => test(version))
}
})
52 changes: 52 additions & 0 deletions test/util/collectBedrockPackets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const bedrock = require('bedrock-protocol')
const { startServer } = require('minecraft-bedrock-server')
const debug = require('debug')('prismarine-registry')
const path = require('path')

async function collectPackets (version, names = ['start_game'], cb) {
const collected = []
const server = await new Promise((resolve) => {
const server = startServer(version, () => resolve(server), {
'online-mode': false,
'server-port': 19130,
path: path.join(__dirname, `server_bedrock_${version}`)
})
})

console.log('Started server', version)

const client = bedrock.createClient({
version,
host: '127.0.0.1',
port: 19130,
username: 'test',
offline: true
})

let clientConnected = false

client.on('join', () => {
console.log('[client] Client connected')
clientConnected = true
})

for (const name of names) {
client.on(name, (packet) => {
cb(name, packet)
collected.push(packet)
})
}

client.on('packet', ({ name }) => debug('[client] -> ', name))

setTimeout(() => {
console.log('Stopping server', version)
server.kill()
client.close()
if (!clientConnected) {
throw new Error('Client never connected')
}
}, 9000)
}

module.exports = collectPackets

0 comments on commit 1aa8724

Please sign in to comment.