Skip to content

Support for hashed block network ID's #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
* `stateString` is the string representation of a block
* `biomeId` is the biome numerical id

#### Block(type,biomeId,metadata)
#### Block.fromProperties(typeId, properties, biomeId)

* `typeId` - The block type ID (numerical or string)
* `properties` - A dictionary of block state properties to build from
* `biomeId` - The biome numerical id

#### Block(type, biomeId, metadata, stateId = null)

Constructor of a block
* `type` is the block numerical id
* `biomeId` is the biome numerical id
* `metadata` is the metadata numerical value
* `stateId` (optional) represents the state of the block (same as metadata in newer versions)

#### block.canHarvest(heldItemType)

Expand All @@ -24,6 +31,13 @@ Tells you if `heldItemType` is one of the right tool to harvest the block.

Parse the block state and return its properties.

#### getHash(prefixedName, states)

**(Bedrock Edition)** Returns an integer hash to represent the block state.

* `prefixedName` - The name of the block, including the `minecraft:` prefix (string).
* `states` - A record of block state properties.

#### block.digTime(heldItemType, creative, inWater, notOnGround, enchantments = [], effects = {})

Tells you how long it will take to dig the block, in milliseconds.
Expand All @@ -45,15 +59,19 @@ Numerical id.

#### block.name

Minecraft ID (string) of the block.

#### block.displayName

Display name of the block.

#### block.shapes

Array of bounding boxes representing the block shape. Each bounding box is an array of the form `[xmin, ymin, zmin, xmax, ymax, zmax]`. Depends on the type and state of the block.

#### block.entity

If this block is a block entity, this contains the NBT data for the entity
If this block is a block entity, this contains the NBT data for the entity.

#### block.blockEntity

Expand All @@ -64,6 +82,10 @@ Simplified block entity data using prismarine-nbt's simplify() function. Only fo
Number which represents different things depending on the block.
See http://www.minecraftwiki.net/wiki/Data_values#Data

#### block.hash

**(Bedrock Edition)** A hash uniquely representing the block name and its properties (number).

#### block.light

#### block.skyLight
Expand Down Expand Up @@ -93,7 +115,7 @@ Boolean, whether the block is considered diggable.

#### block.boundingBox

The shape of the block according to the physics engine's collision decection. Currently one of:
The shape of the block according to the physics engine's collision detection. Currently one of:

* `block` - currently, partially solid blocks, such as half-slabs and ladders, are considered entirely solid.
* `empty` - such as flowers and lava.
Expand Down Expand Up @@ -131,11 +153,12 @@ Sets the text for the sign, can be plaintext, or array of JSON or prismarine-cha

#### getSignText (): [string, string?]

Gets the plain text content of the sign, the first item of the array returned and the second is the back and will be undefined for versions that don't support writing on the back of signs.
Gets the plain text content of the sign. The first item of the array returned and the second is the back, which will be undefined for versions that don't support writing on the back of signs.

#### get .signText

Deprecated, returns a plaintext string containing the sign's text
Deprecated, returns a plaintext string containing the sign's text.

#### set .signText
Deprecated, sets the text for a sign's text, can be plaintext, or array of JSON or prismarine-chat instances

Deprecated, sets the text for a sign's text. Can be plaintext, or array of JSON or prismarine-chat instances.
13 changes: 12 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface Effect {
duration: number;
}

type States = { [key: string]: string | number }

export type Shape = [number, number, number, number, number, number];

Expand Down Expand Up @@ -42,6 +43,9 @@ export declare class Block {
// Contains a full NBT, unserialized object
entity: NBT | null;

// (Bedrock Edition) A hash to uniquely represent block name and its properties
hash?: number

/**
* A biome instance.
* @see https://github.com/prismarinejs/prismarine-biome#api.
Expand Down Expand Up @@ -170,14 +174,21 @@ export declare class Block {
* @param properties - A dictionary of block states to build from.
* @param biomeId - The biome this block is in.
*/
static fromProperties(typeId: number | string, properties: { [key: string]: string | number }, biomeId: number): Block;
static fromProperties(typeId: number | string, properties: States, biomeId: number): Block;

/**
* Create a block from a given string.
* @param stateString - the string representation of a block
* @param biomeId - the biome numerical id
*/
static fromString(stateString: string, biomeId: number): Block;

/**
* (Bedrock Edition) Returns an integer hash to represent the block state
* @param prefixedName name of the block, with a minecraft: prefix
* @param states a record of block state properties
*/
static getHash(prefixedName: string, states: States): number | undefined
}

/** @deprecated */
Expand Down
29 changes: 29 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ function provider (registry, { Biome, version }) {
if (this.name.includes('sign')) {
mergeObject(this, blockMethods.sign)
}

if (blockEnum && registry.supportFeature('blockHashes')) {
this.hash = Block.getHash(this.name, this._properties)
}
}

static fromStateId (stateId, biomeId) {
Expand Down Expand Up @@ -271,6 +275,21 @@ function provider (registry, { Biome, version }) {
return Object.assign(this._properties, this.computedStates)
}

static getHash (name, states) {
if (registry.supportFeature('blockHashes')) {
const sortedStates = {}
for (const key of Object.keys(states).sort()) {
sortedStates[key] = states[key]
}
const tag = nbt.comp({
name: { type: 'string', value: name.includes(':') ? name : `minecraft:${name}` },
states: nbt.comp(sortedStates)
})
const buf = nbt.writeUncompressed(tag, 'little')
return computeFnv1a32Hash(buf)
}
}

canHarvest (heldItemType) {
if (!this.harvestTools) { return true }; // for blocks harvestable by hand
return heldItemType && this.harvestTools && this.harvestTools[heldItemType]
Expand Down Expand Up @@ -393,3 +412,13 @@ function provider (registry, { Biome, version }) {
function mergeObject (to, from) {
Object.defineProperties(to, Object.getOwnPropertyDescriptors(from))
}

function computeFnv1a32Hash (buf) {
const FNV1_OFFSET_32 = 0x811c9dc5
let h = FNV1_OFFSET_32
for (let i = 0; i < buf.length; i++) {
h ^= buf[i] & 0xff
h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24)
}
return h & 0xffffffff
}
26 changes: 24 additions & 2 deletions test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ describe('Dig time', () => {
it('using iron_shovel', () => {
const tool = registry.itemsByName[toolName]
const block = Block.fromStateId(registry.blocksByName[blockName].defaultState)
console.log('Block', block)
const time = block.digTime(tool.id, false, false, false, [], {})
expect(time).toBe(750)
})
Expand Down Expand Up @@ -171,8 +172,29 @@ describe('fromString', () => {
'1.20': 'minecraft:candle[lit=true]'
}
for (const [version, str] of Object.entries(versions)) {
it(version, () => {
const Block = require('prismarine-block')(version)
const block = Block.fromString(str, 0)
// console.log(block)
expect(block.getProperties().lit).toBeTruthy()
})
}
})

describe('Block hash computation', () => {
for (const version of ['bedrock_1.20.0']) {
const Block = require('prismarine-block')(version)
const block = Block.fromString(str, 0)
expect(block.getProperties().lit).toBeTruthy()
it('minecraft:soul_soil', function () {
const block = Block.fromString('minecraft:soul_soil', 0)
expect(block.hash).toBe(601701031)
})
it('minecraft:planks', function () {
const block = Block.fromString('minecraft:planks', 0)
expect(block.hash).toBe(1835335165)
})
it('minecraft:stone', function () {
const block = Block.fromString('minecraft:stone', 0)
expect(block.hash).toBe(-1177000405)
})
}
})
Loading