Skip to content
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
643 changes: 643 additions & 0 deletions fix-plan.md

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions packages/bedrock-url/src/bedrock-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import { URLSearchParams } from './url-search-params'
const SCHEME = 'bedrock'
const SCHEME_PREFIX = 'bedrock://'

/**
* Minimal URL implementation for the bedrock:// scheme.
*
* QuickJS polyfill: Minecraft Bedrock Script API does not provide the
* standard URL class. This implementation supports the bedrock:// scheme
* used for addon-to-addon communication via script events.
*/
export class BedrockURL {
#host = ''
#hostname = ''
Expand Down
7 changes: 7 additions & 0 deletions packages/bedrock-url/src/url-search-params.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* Minimal URLSearchParams implementation.
*
* QuickJS polyfill: Minecraft Bedrock Script API does not provide the
* standard URLSearchParams class. This implements the subset needed for
* the bedrock:// URL scheme used in addon-to-addon communication.
*/
export class URLSearchParams {
readonly #entries: [string, string][] = []

Expand Down
18 changes: 18 additions & 0 deletions packages/crypto/src/cipher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import { sha256 } from '@noble/hashes/sha2.js'

const KEY_LENGTH = 32

/**
* Fallback random byte generator.
*
* QuickJS limitation: Minecraft Bedrock Script API does not expose
* crypto.getRandomValues or any other CSPRNG. Math.random() (Mersenne Twister)
* is used as fallback — NOT cryptographically secure. Users in environments
* with CSPRNG access should inject it via CipherOptions.randomBytes.
*/
function defaultRandomBytes(bytesLength: number): Uint8Array {
const out = new Uint8Array(bytesLength)
for (let i = 0; i < bytesLength; i++) {
Expand All @@ -31,6 +39,16 @@ export class Cipher {
return defaultRandomBytes(length)
}

/**
* Create a Cipher from a password using HKDF-SHA256 key derivation.
*
* QuickJS limitation: PBKDF2/scrypt are preferred for password-based KDFs
* but their iteration count causes script timeouts in Minecraft Bedrock
* Script API. HKDF is used as a lightweight alternative — suitable here
* because communication is confined to the local game instance (no remote
* brute-force exposure). The salt parameter is REQUIRED for security;
* when omitted, a fixed default salt is used (NOT recommended).
*/
static fromPassword(password: string, salt?: string | Uint8Array, options?: CipherOptions): Cipher {
const ikm = utf8Encode(password)
const saltBytes = salt !== undefined
Expand Down
5 changes: 5 additions & 0 deletions packages/ipc/src/chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ interface PendingPacket {
/**
* Splits large serialized payloads into smaller chunks and reassembles them on the receiving end.
* Used internally by {@link IPC} — you typically don't need to interact with this class directly.
*
* Note on sizing: String.slice() operates on UTF-16 code units, not bytes.
* TextEncoder is unavailable in Minecraft Bedrock Script API (QuickJS),
* so chunkSize is expressed in characters (UTF-16 code units). Consumers
* handling non-ASCII content should pre-encode to a byte-safe format.
*/
export class Chunker {
readonly #chunkSize: number
Expand Down
6 changes: 6 additions & 0 deletions packages/utils/src/base64.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { utf8Decode, utf8Encode } from './textCodec'

/**
* Base64 encoding/decoding.
*
* QuickJS polyfill: atob/btoa are unavailable in Minecraft Bedrock Script API,
* so we implement the RFC 4648 algorithm directly.
*/
export class Base64 {
static #CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

Expand Down
3 changes: 3 additions & 0 deletions packages/utils/src/getRandomProbability.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/**
* Random Probability
*
* Note: Uses Math.random() rather than crypto.getRandomValues because
* QuickJS in Minecraft Bedrock Script API does not expose a Web Crypto API.
* @param {number} probability Probability percentage 0.01-100
* @returns {boolean} The hit probability returns true, and vice versa false
*/
Expand Down
3 changes: 3 additions & 0 deletions packages/utils/src/getRandomRangeValue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/**
* Random Range Value
*
* Note: Uses Math.random() rather than crypto.getRandomValues because
* QuickJS in Minecraft Bedrock Script API does not expose a Web Crypto API.
* @param {number} min A random minimum
* @param {number} max A random maximum
* @returns {number} A random integer between min and max
Expand Down
9 changes: 9 additions & 0 deletions packages/utils/src/textCodec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* QuickJS polyfill: TextEncoder is unavailable in Minecraft Bedrock Script API,
* so we use encodeURIComponent to build UTF-8 byte arrays.
*/
export function utf8Encode(s: string): Uint8Array {
const encoded = encodeURIComponent(s)
const bytes: number[] = []
Expand All @@ -13,6 +17,11 @@ export function utf8Encode(s: string): Uint8Array {
return new Uint8Array(bytes)
}

/**
* QuickJS polyfill: TextDecoder is unavailable, so we use decodeURIComponent
* to decode UTF-8 byte arrays back to strings.
* @throws {URIError} If the byte sequence is not valid UTF-8
*/
export function utf8Decode(bytes: Uint8Array): string {
let s = ''
for (const b of bytes) {
Expand Down
4 changes: 4 additions & 0 deletions packages/utils/src/unique.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/**
* Forked from simple-unique (https://github.com/lete114/Simple-Unique)
* Completely random generation of unique strings
*
* Note: Uses Math.random() rather than crypto.getRandomValues because
* QuickJS in Minecraft Bedrock Script API does not provide a Web Crypto API.
* Not suitable for security-sensitive uniqueness (e.g. session tokens).
* @param size - Length of the random string (default 10)
*/
export function unique(size: number = 10): string {
Expand Down
Loading