+ return
{scenes.map(scene =>
{
const qs = new URLSearchParams(window.location.search)
@@ -61,6 +72,41 @@ function SceneSelector () {
}
+const ActionsSelector = () => {
+ const { actions, selectorOpened } = useSnapshot(playgroundGlobalUiState)
+
+ if (!selectorOpened) return null
+ return
{Object.entries({
+ ...actions,
+ 'Close' () {
+ playgroundGlobalUiState.selectorOpened = false
+ }
+ }).map(([name, action]) =>
{
+ action()
+ playgroundGlobalUiState.selectorOpened = false
+ }}
+ >{name}
)}
+}
+
const Controls = () => {
// todo setting
const usingTouch = navigator.maxTouchPoints > 0
diff --git a/prismarine-viewer/viewer/lib/entities.ts b/prismarine-viewer/viewer/lib/entities.ts
index ef73faf7f..47a0303ef 100644
--- a/prismarine-viewer/viewer/lib/entities.ts
+++ b/prismarine-viewer/viewer/lib/entities.ts
@@ -1,5 +1,6 @@
//@ts-check
import EventEmitter from 'events'
+import { UnionToIntersection } from 'type-fest'
import nbt from 'prismarine-nbt'
import * as TWEEN from '@tweenjs/tween.js'
import * as THREE from 'three'
@@ -11,6 +12,7 @@ import { NameTagObject } from 'skinview3d/libs/nametag'
import { flat, fromFormattedString } from '@xmcl/text-component'
import mojangson from 'mojangson'
import { snakeCase } from 'change-case'
+import { EntityMetadataVersions } from '../../../src/mcDataTypes'
import * as Entity from './entity/EntityMesh'
import { WalkingGeneralSwing } from './entity/animations'
import externalTexturesJson from './entity/externalTextures.json'
@@ -20,12 +22,51 @@ export const TWEEN_DURATION = 120
type PlayerObjectType = PlayerObject & { animation?: PlayerAnimation }
-function getUsernameTexture (username: string, { fontFamily = 'sans-serif' }: any) {
+function convert2sComplementToHex (complement: number) {
+ if (complement < 0) {
+ complement = (0xFF_FF_FF_FF + complement + 1) >>> 0
+ }
+ return complement.toString(16)
+}
+
+function toRgba (color: string | undefined) {
+ if (color === undefined) {
+ return undefined
+ }
+ if (parseInt(color, 10) === 0) {
+ return 'rgba(0, 0, 0, 0)'
+ }
+ const hex = convert2sComplementToHex(parseInt(color, 10))
+ if (hex.length === 8) {
+ return `#${hex.slice(2, 8)}${hex.slice(0, 2)}`
+ } else {
+ return `#${hex}`
+ }
+}
+
+function toQuaternion (quaternion: any, defaultValue?: THREE.Quaternion) {
+ if (quaternion === undefined) {
+ return defaultValue
+ }
+ if (quaternion instanceof THREE.Quaternion) {
+ return quaternion
+ }
+ if (Array.isArray(quaternion)) {
+ return new THREE.Quaternion(quaternion[0], quaternion[1], quaternion[2], quaternion[3])
+ }
+ return new THREE.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w)
+}
+
+function getUsernameTexture ({
+ username,
+ nameTagBackgroundColor = 'rgba(0, 0, 0, 0.3)',
+ nameTagTextOpacity = 255
+}: any, { fontFamily = 'sans-serif' }: any) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if (!ctx) throw new Error('Could not get 2d context')
- const fontSize = 50
+ const fontSize = 48
const padding = 5
ctx.font = `${fontSize}px ${fontFamily}`
@@ -38,17 +79,17 @@ function getUsernameTexture (username: string, { fontFamily = 'sans-serif' }: an
}
canvas.width = textWidth
- canvas.height = (fontSize + padding * 2) * lines.length
+ canvas.height = (fontSize + padding) * lines.length
- ctx.fillStyle = 'rgba(0, 0, 0, 0.3)'
+ ctx.fillStyle = nameTagBackgroundColor
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.font = `${fontSize}px ${fontFamily}`
- ctx.fillStyle = 'white'
+ ctx.fillStyle = `rgba(255, 255, 255, ${nameTagTextOpacity / 255})`
let i = 0
for (const line of lines) {
i++
- ctx.fillText(line, padding + (textWidth - ctx.measureText(line).width) / 2, fontSize * i)
+ ctx.fillText(line, (textWidth - ctx.measureText(line).width) / 2, -padding + fontSize * i)
}
return canvas
@@ -57,17 +98,39 @@ function getUsernameTexture (username: string, { fontFamily = 'sans-serif' }: an
const addNametag = (entity, options, mesh) => {
if (entity.username !== undefined) {
if (mesh.children.some(c => c.name === 'nametag')) return // todo update
- const canvas = getUsernameTexture(entity.username, options)
+ const canvas = getUsernameTexture(entity, options)
const tex = new THREE.Texture(canvas)
tex.needsUpdate = true
- const spriteMat = new THREE.SpriteMaterial({ map: tex })
- const sprite = new THREE.Sprite(spriteMat)
- sprite.renderOrder = 1000
- sprite.scale.set(canvas.width * 0.005, canvas.height * 0.005, 1)
- sprite.position.y += entity.height + 0.6
- sprite.name = 'nametag'
-
- mesh.add(sprite)
+ let nameTag
+ if (entity.nameTagFixed) {
+ const geometry = new THREE.PlaneGeometry()
+ const material = new THREE.MeshBasicMaterial({ map: tex })
+ material.transparent = true
+ nameTag = new THREE.Mesh(geometry, material)
+ nameTag.rotation.set(entity.pitch, THREE.MathUtils.degToRad(entity.yaw + 180), 0)
+ nameTag.position.y += entity.height + 0.3
+ } else {
+ const spriteMat = new THREE.SpriteMaterial({ map: tex })
+ nameTag = new THREE.Sprite(spriteMat)
+ nameTag.position.y += entity.height + 0.6
+ }
+ nameTag.renderOrder = 1000
+ nameTag.scale.set(canvas.width * 0.005, canvas.height * 0.005, 1)
+ if (entity.nameTagRotationRight) {
+ nameTag.applyQuaternion(entity.nameTagRotationRight)
+ }
+ if (entity.nameTagScale) {
+ nameTag.scale.multiply(entity.nameTagScale)
+ }
+ if (entity.nameTagRotationLeft) {
+ nameTag.applyQuaternion(entity.nameTagRotationLeft)
+ }
+ if (entity.nameTagTranslation) {
+ nameTag.position.add(entity.nameTagTranslation)
+ }
+ nameTag.name = 'nametag'
+
+ mesh.add(nameTag)
}
}
@@ -302,6 +365,9 @@ export class Entities extends EventEmitter {
parseEntityLabel (jsonLike) {
if (!jsonLike) return
try {
+ if (jsonLike.type === 'string') {
+ return jsonLike.value
+ }
const parsed = typeof jsonLike === 'string' ? mojangson.simplify(mojangson.parse(jsonLike)) : nbt.simplify(jsonLike)
const text = flat(parsed).map(x => x.text)
return text.join('')
@@ -352,7 +418,7 @@ export class Entities extends EventEmitter {
}
}
- update (entity: import('prismarine-entity').Entity & { delete?; pos }, overrides) {
+ update (entity: import('prismarine-entity').Entity & { delete?; pos, name }, overrides) {
const isPlayerModel = entity.name === 'player'
if (entity.name === 'zombie' || entity.name === 'zombie_villager' || entity.name === 'husk') {
overrides.texture = `textures/1.16.4/entity/${entity.name === 'zombie_villager' ? 'zombie_villager/zombie_villager.png' : `zombie/${entity.name}.png`}`
@@ -453,6 +519,8 @@ export class Entities extends EventEmitter {
this.setRendering(this.rendering, group)
}
+ const meta = getGeneralEntitiesMetadata(entity)
+
//@ts-expect-error
// set visibility
const isInvisible = entity.metadata?.[0] & 0x20
@@ -463,10 +531,24 @@ export class Entities extends EventEmitter {
}
// ---
// not player
- const displayText = entity.metadata?.[3] && this.parseEntityLabel(entity.metadata[2])
- || entity.metadata?.[23] && this.parseEntityLabel(entity.metadata[23]) // text displays
+ const textDisplayMeta = getSpecificEntityMetadata('text_display', entity)
+ const displayTextRaw = textDisplayMeta?.text || meta.custom_name_visible && meta.custom_name
+ const displayText = this.parseEntityLabel(displayTextRaw)
if (entity.name !== 'player' && displayText) {
- addNametag({ ...entity, username: displayText }, this.entitiesOptions, this.entities[entity.id].children.find(c => c.name === 'mesh'))
+ const nameTagFixed = textDisplayMeta && (textDisplayMeta.billboard_render_constraints === 'fixed' || !textDisplayMeta.billboard_render_constraints)
+ const nameTagBackgroundColor = textDisplayMeta && toRgba(textDisplayMeta.background_color)
+ let nameTagTextOpacity: any
+ if (textDisplayMeta?.text_opacity) {
+ const rawOpacity = parseInt(textDisplayMeta?.text_opacity, 10)
+ nameTagTextOpacity = rawOpacity > 0 ? rawOpacity : 256 - rawOpacity
+ }
+ addNametag(
+ { ...entity, username: displayText, nameTagBackgroundColor, nameTagTextOpacity, nameTagFixed,
+ nameTagScale: textDisplayMeta?.scale, nameTagTranslation: textDisplayMeta && (textDisplayMeta.translation || new THREE.Vector3(0, 0, 0)),
+ nameTagRotationLeft: toQuaternion(textDisplayMeta?.left_rotation), nameTagRotationRight: toQuaternion(textDisplayMeta?.right_rotation) },
+ this.entitiesOptions,
+ this.entities[entity.id].children.find(c => c.name === 'mesh')
+ )
}
// todo handle map, map_chunks events
@@ -547,3 +629,19 @@ export class Entities extends EventEmitter {
}
}
}
+
+function getGeneralEntitiesMetadata (entity: { name; metadata }): Partial
> {
+ const entityData = loadedData.entitiesByName[entity.name]
+ return new Proxy({}, {
+ get (target, p, receiver) {
+ if (typeof p !== 'string' || !entityData) return
+ const index = entityData.metadataKeys?.indexOf(p)
+ return entity.metadata[index ?? -1]
+ },
+ })
+}
+
+function getSpecificEntityMetadata (name: T, entity): EntityMetadataVersions[T] | undefined {
+ if (entity.name !== name) return
+ return getGeneralEntitiesMetadata(entity) as any
+}
diff --git a/prismarine-viewer/viewer/lib/hand.ts b/prismarine-viewer/viewer/lib/hand.ts
new file mode 100644
index 000000000..6c9aacc53
--- /dev/null
+++ b/prismarine-viewer/viewer/lib/hand.ts
@@ -0,0 +1,96 @@
+import * as THREE from 'three'
+import { loadSkinToCanvas } from 'skinview-utils'
+import stevePng from 'mc-assets/dist/other-textures/latest/entity/player/wide/steve.png'
+
+let steveTexture: THREE.Texture
+export const getMyHand = async (image?: string) => {
+ let newMap: THREE.Texture
+ if (!image && steveTexture) {
+ newMap = steveTexture
+ } else {
+ image ??= stevePng
+ const skinCanvas = document.createElement('canvas')
+ const img = new Image()
+ img.src = image
+ await new Promise(resolve => {
+ img.onload = () => {
+ resolve()
+ }
+ })
+ loadSkinToCanvas(skinCanvas, img)
+ newMap = new THREE.CanvasTexture(skinCanvas)
+ // newMap.flipY = false
+ newMap.magFilter = THREE.NearestFilter
+ newMap.minFilter = THREE.NearestFilter
+ if (!image) {
+ steveTexture = newMap
+ }
+ }
+
+ // right arm
+ const box = new THREE.BoxGeometry()
+ const material = new THREE.MeshStandardMaterial()
+ const slim = false
+ const mesh = new THREE.Mesh(box, material)
+ mesh.scale.x = slim ? 3 : 4
+ mesh.scale.y = 12
+ mesh.scale.z = 4
+ setSkinUVs(box, 40, 16, slim ? 3 : 4, 12, 4)
+ material.map = newMap
+ material.needsUpdate = true
+ const group = new THREE.Group()
+ group.add(mesh)
+ group.scale.set(0.1, 0.1, 0.1)
+ mesh.rotation.z = Math.PI
+ return group
+}
+
+function setUVs (
+ box: THREE.BoxGeometry,
+ u: number,
+ v: number,
+ width: number,
+ height: number,
+ depth: number,
+ textureWidth: number,
+ textureHeight: number
+): void {
+ const toFaceVertices = (x1: number, y1: number, x2: number, y2: number) => [
+ new THREE.Vector2(x1 / textureWidth, 1 - y2 / textureHeight),
+ new THREE.Vector2(x2 / textureWidth, 1 - y2 / textureHeight),
+ new THREE.Vector2(x2 / textureWidth, 1 - y1 / textureHeight),
+ new THREE.Vector2(x1 / textureWidth, 1 - y1 / textureHeight),
+ ]
+
+ const top = toFaceVertices(u + depth, v, u + width + depth, v + depth)
+ const bottom = toFaceVertices(u + width + depth, v, u + width * 2 + depth, v + depth)
+ const left = toFaceVertices(u, v + depth, u + depth, v + depth + height)
+ const front = toFaceVertices(u + depth, v + depth, u + width + depth, v + depth + height)
+ const right = toFaceVertices(u + width + depth, v + depth, u + width + depth * 2, v + height + depth)
+ const back = toFaceVertices(u + width + depth * 2, v + depth, u + width * 2 + depth * 2, v + height + depth)
+
+ const uvAttr = box.attributes.uv as THREE.BufferAttribute
+ const uvRight = [right[3], right[2], right[0], right[1]]
+ const uvLeft = [left[3], left[2], left[0], left[1]]
+ const uvTop = [top[3], top[2], top[0], top[1]]
+ const uvBottom = [bottom[0], bottom[1], bottom[3], bottom[2]]
+ const uvFront = [front[3], front[2], front[0], front[1]]
+ const uvBack = [back[3], back[2], back[0], back[1]]
+
+ // Create a new array to hold the modified UV data
+ const newUVData = [] as number[]
+
+ // Iterate over the arrays and copy the data to uvData
+ for (const uvArray of [uvRight, uvLeft, uvTop, uvBottom, uvFront, uvBack]) {
+ for (const uv of uvArray) {
+ newUVData.push(uv.x, uv.y)
+ }
+ }
+
+ uvAttr.set(new Float32Array(newUVData))
+ uvAttr.needsUpdate = true
+}
+
+function setSkinUVs (box: THREE.BoxGeometry, u: number, v: number, width: number, height: number, depth: number): void {
+ setUVs(box, u, v, width, height, depth, 64, 64)
+}
diff --git a/prismarine-viewer/viewer/lib/holdingBlock.ts b/prismarine-viewer/viewer/lib/holdingBlock.ts
index f5a0ca799..5fc3e03c0 100644
--- a/prismarine-viewer/viewer/lib/holdingBlock.ts
+++ b/prismarine-viewer/viewer/lib/holdingBlock.ts
@@ -1,14 +1,19 @@
import * as THREE from 'three'
import * as tweenJs from '@tweenjs/tween.js'
import worldBlockProvider from 'mc-assets/dist/worldBlockProvider'
+import { GUI } from 'lil-gui'
import { getThreeBlockModelGroup, renderBlockThree, setBlockPosition } from './mesher/standaloneRenderer'
+import { getMyHand } from './hand'
export type HandItemBlock = {
- name
- properties
+ name?
+ properties?
+ type: 'block' | 'item' | 'hand'
+ id?: number
}
export default class HoldingBlock {
+ // TODO refactor with the tree builder for better visual understanding
holdingBlock: THREE.Object3D | undefined = undefined
swingAnimation: tweenJs.Group | undefined = undefined
blockSwapAnimation: {
@@ -16,22 +21,25 @@ export default class HoldingBlock {
hidden: boolean
} | undefined = undefined
cameraGroup = new THREE.Mesh()
- objectOuterGroup = new THREE.Group()
- objectInnerGroup = new THREE.Group()
- camera: THREE.Group | THREE.PerspectiveCamera
+ objectOuterGroup = new THREE.Group() // 3
+ objectInnerGroup = new THREE.Group() // 4
+ holdingBlockInnerGroup = new THREE.Group() // 5
+ camera = new THREE.PerspectiveCamera(75, 1, 0.1, 100)
stopUpdate = false
lastHeldItem: HandItemBlock | undefined
toBeRenderedItem: HandItemBlock | undefined
isSwinging = false
nextIterStopCallbacks: Array<() => void> | undefined
+ rightSide = true
- constructor (public scene: THREE.Scene) {
+ debug = {} as Record
+
+ constructor () {
this.initCameraGroup()
}
initCameraGroup () {
this.cameraGroup = new THREE.Mesh()
- this.scene.add(this.cameraGroup)
}
startSwing () {
@@ -44,17 +52,18 @@ export default class HoldingBlock {
// const DURATION = 1000 * 0.35 / 2
const DURATION = 1000 * 0.35 / 3
// const DURATION = 1000
+ const { position, rotation, object } = this.getFinalSwingPositionRotation()
const initialPos = {
- x: this.objectInnerGroup.position.x,
- y: this.objectInnerGroup.position.y,
- z: this.objectInnerGroup.position.z
+ x: object.position.x,
+ y: object.position.y,
+ z: object.position.z
}
const initialRot = {
- x: this.objectInnerGroup.rotation.x,
- y: this.objectInnerGroup.rotation.y,
- z: this.objectInnerGroup.rotation.z
+ x: object.rotation.x,
+ y: object.rotation.y,
+ z: object.rotation.z
}
- const mainAnim = new tweenJs.Tween(this.objectInnerGroup.position, this.swingAnimation).to({ y: this.objectInnerGroup.position.y - this.objectInnerGroup.scale.y / 2 }, DURATION).yoyo(true).repeat(Infinity).start()
+ const mainAnim = new tweenJs.Tween(object.position, this.swingAnimation).to(position, DURATION).yoyo(true).repeat(Infinity).start()
let i = 0
mainAnim.onRepeat(() => {
i++
@@ -67,14 +76,66 @@ export default class HoldingBlock {
this.swingAnimation!.removeAll()
this.swingAnimation = undefined
// todo refactor to be more generic for animations
- this.objectInnerGroup.position.set(initialPos.x, initialPos.y, initialPos.z)
- // this.objectInnerGroup.rotation.set(initialRot.x, initialRot.y, initialRot.z)
- Object.assign(this.objectInnerGroup.rotation, initialRot)
+ object.position.set(initialPos.x, initialPos.y, initialPos.z)
+ // object.rotation.set(initialRot.x, initialRot.y, initialRot.z)
+ Object.assign(object.rotation, initialRot)
}
})
- new tweenJs.Tween(this.objectInnerGroup.rotation, this.swingAnimation).to({ z: THREE.MathUtils.degToRad(90) }, DURATION).yoyo(true).repeat(Infinity).start()
- new tweenJs.Tween(this.objectInnerGroup.rotation, this.swingAnimation).to({ x: -THREE.MathUtils.degToRad(90) }, DURATION).yoyo(true).repeat(Infinity).start()
+ new tweenJs.Tween(object.rotation, this.swingAnimation).to(rotation, DURATION).yoyo(true).repeat(Infinity).start()
+ }
+ }
+
+ getFinalSwingPositionRotation (origPosition?: THREE.Vector3) {
+ const object = this.objectInnerGroup
+ if (this.lastHeldItem?.type === 'block') {
+ origPosition ??= object.position
+ return {
+ position: { y: origPosition.y - this.objectInnerGroup.scale.y / 2 },
+ rotation: { z: THREE.MathUtils.degToRad(90), x: -THREE.MathUtils.degToRad(90) },
+ object
+ }
+ }
+ if (this.lastHeldItem?.type === 'item') {
+ const object = this.holdingBlockInnerGroup
+ origPosition ??= object.position
+ return {
+ position: {
+ y: origPosition.y - object.scale.y * 2,
+ // z: origPosition.z - window.zFinal,
+ // x: origPosition.x - window.xFinal,
+ },
+ // rotation: { z: THREE.MathUtils.degToRad(90), x: -THREE.MathUtils.degToRad(90) }
+ rotation: {
+ // z: THREE.MathUtils.degToRad(window.zRotationFinal ?? 0),
+ // x: THREE.MathUtils.degToRad(window.xRotationFinal ?? 0),
+ // y: THREE.MathUtils.degToRad(window.yRotationFinal ?? 0),
+ x: THREE.MathUtils.degToRad(-120)
+ },
+ object
+ }
+ }
+ if (this.lastHeldItem?.type === 'hand') {
+ const object = this.holdingBlockInnerGroup
+ origPosition ??= object.position
+ return {
+ position: {
+ y: origPosition.y - (window.yFinal ?? 0.15),
+ z: origPosition.z - window.zFinal,
+ x: origPosition.x - window.xFinal,
+ },
+ rotation: {
+ x: THREE.MathUtils.degToRad(window.xRotationFinal || -14.7),
+ y: THREE.MathUtils.degToRad(window.yRotationFinal || 33.95),
+ z: THREE.MathUtils.degToRad(window.zRotationFinal || -28),
+ },
+ object
+ }
+ }
+ return {
+ position: {},
+ rotation: {},
+ object
}
}
@@ -89,11 +150,35 @@ export default class HoldingBlock {
})
}
- update (camera: typeof this.camera) {
- this.camera = camera
+ render (originalCamera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, ambientLight: THREE.AmbientLight, directionalLight: THREE.DirectionalLight) {
+ if (!this.lastHeldItem) return
this.swingAnimation?.update()
this.blockSwapAnimation?.tween.update()
+
+ const scene = new THREE.Scene()
+ scene.add(this.cameraGroup)
+ // if (this.camera.aspect !== originalCamera.aspect) {
+ // this.camera.aspect = originalCamera.aspect
+ // this.camera.updateProjectionMatrix()
+ // }
this.updateCameraGroup()
+ scene.add(ambientLight.clone())
+ scene.add(directionalLight.clone())
+
+ const viewerSize = renderer.getSize(new THREE.Vector2())
+ const minSize = Math.min(viewerSize.width, viewerSize.height)
+
+ renderer.autoClear = false
+ renderer.clearDepth()
+ if (this.rightSide) {
+ const x = viewerSize.width - minSize
+ // if (x) x -= x / 4
+ renderer.setViewport(x, 0, minSize, minSize)
+ } else {
+ renderer.setViewport(0, 0, minSize, minSize)
+ }
+ renderer.render(scene, this.camera)
+ renderer.setViewport(0, 0, viewerSize.width, viewerSize.height)
}
// worldTest () {
@@ -142,23 +227,36 @@ export default class HoldingBlock {
this.cameraGroup.position.copy(camera.position)
this.cameraGroup.rotation.copy(camera.rotation)
- const viewerSize = viewer.renderer.getSize(new THREE.Vector2())
- // const x = window.x ?? 0.25 * viewerSize.width / viewerSize.height
- // const x = 0 * viewerSize.width / viewerSize.height
- const x = 0.2 * viewerSize.width / viewerSize.height
- this.objectOuterGroup.position.set(x, -0.3, -0.45)
+ // const viewerSize = viewer.renderer.getSize(new THREE.Vector2())
+ // const aspect = viewerSize.width / viewerSize.height
+ const aspect = 1
+
+
+ // Adjust the position based on the aspect ratio
+ const { position, scale: scaleData } = this.getHandHeld3d()
+ const distance = -position.z
+ const side = this.rightSide ? 1 : -1
+ this.objectOuterGroup.position.set(
+ distance * position.x * aspect * side,
+ distance * position.y,
+ -distance
+ )
+
+ // const scale = Math.min(0.8, Math.max(1, 1 * aspect))
+ const scale = scaleData * 2.22 * 0.2
+ this.objectOuterGroup.scale.set(scale, scale, scale)
}
- async initHandObject (material: THREE.Material, blockstatesModels: any, blocksAtlases: any, block?: HandItemBlock) {
+ async initHandObject (material: THREE.Material, blockstatesModels: any, blocksAtlases: any, handItem?: HandItemBlock) {
let animatingCurrent = false
- if (!this.swingAnimation && !this.blockSwapAnimation && this.isDifferentItem(block)) {
+ if (!this.swingAnimation && !this.blockSwapAnimation && this.isDifferentItem(handItem)) {
animatingCurrent = true
await this.playBlockSwapAnimation()
this.holdingBlock?.removeFromParent()
this.holdingBlock = undefined
}
- this.lastHeldItem = block
- if (!block) {
+ this.lastHeldItem = handItem
+ if (!handItem) {
this.holdingBlock?.removeFromParent()
this.holdingBlock = undefined
this.swingAnimation = undefined
@@ -166,16 +264,28 @@ export default class HoldingBlock {
return
}
const blockProvider = worldBlockProvider(blockstatesModels, blocksAtlases, 'latest')
- const models = blockProvider.getAllResolvedModels0_1(block, true)
- const blockInner = getThreeBlockModelGroup(material, models, undefined, 'plains', loadedData)
- // const { mesh: itemMesh } = viewer.entities.getItemMesh({
- // itemId: 541,
- // })!
- // itemMesh.position.set(0.5, 0.5, 0.5)
- // const blockInner = itemMesh
+ let blockInner
+ if (handItem.type === 'block') {
+ const models = blockProvider.getAllResolvedModels0_1({
+ name: handItem.name,
+ properties: handItem.properties ?? {}
+ }, true)
+ blockInner = getThreeBlockModelGroup(material, models, undefined, 'plains', loadedData)
+ } else if (handItem.type === 'item') {
+ const { mesh: itemMesh } = viewer.entities.getItemMesh({
+ itemId: handItem.id,
+ })!
+ itemMesh.position.set(0.5, 0.5, 0.5)
+ blockInner = itemMesh
+ } else {
+ blockInner = await getMyHand()
+ }
blockInner.name = 'holdingBlock'
const blockOuterGroup = new THREE.Group()
- blockOuterGroup.add(blockInner)
+ this.holdingBlockInnerGroup.removeFromParent()
+ this.holdingBlockInnerGroup = new THREE.Group()
+ this.holdingBlockInnerGroup.add(blockInner)
+ blockOuterGroup.add(this.holdingBlockInnerGroup)
this.holdingBlock = blockInner
this.objectInnerGroup = new THREE.Group()
this.objectInnerGroup.add(blockOuterGroup)
@@ -190,18 +300,113 @@ export default class HoldingBlock {
this.objectOuterGroup.add(this.objectInnerGroup)
this.cameraGroup.add(this.objectOuterGroup)
- const rotation = -45 + -90
- // const rotation = -45 // should be for item
- this.holdingBlock.rotation.set(0, THREE.MathUtils.degToRad(rotation), 0, 'ZYX')
+ const rotationDeg = this.getHandHeld3d().rotation
+ let origPosition
+ const setRotation = () => {
+ const final = this.getFinalSwingPositionRotation(origPosition)
+ origPosition ??= final.object.position.clone()
+ if (this.debug.displayFinal) {
+ Object.assign(final.object.position, final.position)
+ Object.assign(final.object.rotation, final.rotation)
+ } else if (this.debug.displayFinal === false) {
+ final.object.rotation.set(0, 0, 0)
+ }
- // const scale = window.scale ?? 0.2
- const scale = 0.2
- this.objectOuterGroup.scale.set(scale, scale, scale)
- // this.objectOuterGroup.position.set(x, window.y ?? -0.41, window.z ?? -0.45)
- // this.objectOuterGroup.position.set(x, 0, -0.45)
+ this.holdingBlock!.rotation.x = THREE.MathUtils.degToRad(rotationDeg.x)
+ this.holdingBlock!.rotation.y = THREE.MathUtils.degToRad(rotationDeg.y)
+ this.holdingBlock!.rotation.z = THREE.MathUtils.degToRad(rotationDeg.z)
+ this.objectOuterGroup.rotation.y = THREE.MathUtils.degToRad(rotationDeg.yOuter)
+ }
+ // const gui = new GUI()
+ // gui.add(rotationDeg, 'x', -180, 180, 0.1)
+ // gui.add(rotationDeg, 'y', -180, 180, 0.1)
+ // gui.add(rotationDeg, 'z', -180, 180, 0.1)
+ // gui.add(rotationDeg, 'yOuter', -180, 180, 0.1)
+ // Object.assign(window, { xFinal: 0, yFinal: 0, zFinal: 0, xRotationFinal: 0, yRotationFinal: 0, zRotationFinal: 0, displayFinal: true })
+ // gui.add(window, 'xFinal', -10, 10, 0.05)
+ // gui.add(window, 'yFinal', -10, 10, 0.05)
+ // gui.add(window, 'zFinal', -10, 10, 0.05)
+ // gui.add(window, 'xRotationFinal', -180, 180, 0.05)
+ // gui.add(window, 'yRotationFinal', -180, 180, 0.05)
+ // gui.add(window, 'zRotationFinal', -180, 180, 0.05)
+ // gui.add(window, 'displayFinal')
+ // gui.onChange(setRotation)
+ setRotation()
if (animatingCurrent) {
await this.playBlockSwapAnimation()
}
}
+
+ getHandHeld3d () {
+ const type = this.lastHeldItem?.type ?? 'hand'
+ const { debug } = this
+
+ let scale = type === 'item' ? 0.68 : 0.45
+
+ const position = {
+ x: debug.x ?? 0.4,
+ y: debug.y ?? -0.7,
+ z: -0.45
+ }
+
+ if (type === 'item') {
+ position.x = -0.05
+ // position.y -= 3.2 / 10
+ // position.z += 1.13 / 10
+ }
+
+ if (type === 'hand') {
+ // position.x = viewer.camera.aspect > 1 ? 0.7 : 1.1
+ position.y = -0.8
+ scale = 0.8
+ }
+
+ const rotations = {
+ block: {
+ x: 0,
+ y: -45 + 90,
+ z: 0,
+ yOuter: 0
+ },
+ // hand: {
+ // x: 166.7,
+ // // y: -180,
+ // y: -165.2,
+ // // z: -156.3,
+ // z: -134.2,
+ // yOuter: -81.1
+ // },
+ hand: {
+ x: -32.4,
+ // y: 25.1
+ y: 42.8,
+ z: -41.3,
+ yOuter: 0
+ },
+ // item: {
+ // x: -174,
+ // y: 47.3,
+ // z: -134.2,
+ // yOuter: -41.2
+ // }
+ item: {
+ // x: -174,
+ // y: 47.3,
+ // z: -134.2,
+ // yOuter: -41.2
+ x: 0,
+ // y: -90, // todo thats the correct one but we don't make it look too cheap because of no depth
+ y: -70,
+ z: window.z ?? 25,
+ yOuter: 0
+ }
+ }
+
+ return {
+ rotation: rotations[type],
+ position,
+ scale
+ }
+ }
}
diff --git a/prismarine-viewer/viewer/lib/mesher/mesher.ts b/prismarine-viewer/viewer/lib/mesher/mesher.ts
index b38f04274..7c120abc1 100644
--- a/prismarine-viewer/viewer/lib/mesher/mesher.ts
+++ b/prismarine-viewer/viewer/lib/mesher/mesher.ts
@@ -159,7 +159,7 @@ setInterval(() => {
const geometry = getSectionGeometry(x, y, z, world)
const transferable = [geometry.positions?.buffer, geometry.normals?.buffer, geometry.colors?.buffer, geometry.uvs?.buffer].filter(Boolean)
//@ts-expect-error
- postMessage({ type: 'geometry', key, geometry }, transferable)
+ postMessage({ type: 'geometry', key, geometry, workerIndex }, transferable)
processTime = performance.now() - start
} else {
// console.info('[mesher] Missing section', x, y, z)
diff --git a/prismarine-viewer/viewer/lib/mesher/models.ts b/prismarine-viewer/viewer/lib/mesher/models.ts
index 91c0cf40f..51a00a448 100644
--- a/prismarine-viewer/viewer/lib/mesher/models.ts
+++ b/prismarine-viewer/viewer/lib/mesher/models.ts
@@ -4,7 +4,9 @@ import legacyJson from '../../../../src/preflatMap.json'
import { BlockType } from '../../../examples/shared'
import { World, BlockModelPartsResolved, WorldBlock as Block } from './world'
import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon'
-import { MesherGeometryOutput } from './shared'
+import { INVISIBLE_BLOCKS } from './worldConstants'
+import { MesherGeometryOutput, HighestBlockInfo } from './shared'
+
let blockProvider: WorldBlockProvider
@@ -226,14 +228,12 @@ const identicalCull = (currentElement: BlockElement, neighbor: Block, direction:
const models = neighbor.models?.map(m => m[useVar] ?? m[0]) ?? []
// TODO we should support it! rewrite with optimizing general pipeline
if (models.some(m => m.x || m.y || m.z)) return
- for (const model of models) {
- for (const element of model.elements ?? []) {
+ return models.every(model => {
+ return (model.elements ?? []).every(element => {
// todo check alfa on texture
- if (element.faces[lookForOppositeSide]?.cullface && elemCompareForm(currentElement) === elemCompareForm(element) && elementEdgeValidator(element)) {
- return true
- }
- }
- }
+ return !!(element.faces[lookForOppositeSide]?.cullface && elemCompareForm(currentElement) === elemCompareForm(element) && elementEdgeValidator(element))
+ })
+ })
}
let needSectionRecomputeOnChange = false
@@ -439,8 +439,6 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO:
}
}
-const invisibleBlocks = new Set(['air', 'cave_air', 'void_air', 'barrier'])
-
const isBlockWaterlogged = (block: Block) => block.getProperties().waterlogged === true || block.getProperties().waterlogged === 'true'
let unknownBlockModel: BlockModelPartsResolved
@@ -464,7 +462,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
// todo this can be removed here
signs: {},
// isFull: true,
- highestBlocks: {}, // todo migrate to map for 2% boost perf
+ highestBlocks: new Map([]),
hadErrors: false,
blocksCount: 0
}
@@ -474,16 +472,13 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
for (cursor.z = sz; cursor.z < sz + 16; cursor.z++) {
for (cursor.x = sx; cursor.x < sx + 16; cursor.x++) {
let block = world.getBlock(cursor, blockProvider, attr)!
- if (!invisibleBlocks.has(block.name)) {
- const highest = attr.highestBlocks[`${cursor.x},${cursor.z}`]
+ if (!INVISIBLE_BLOCKS.has(block.name)) {
+ const highest = attr.highestBlocks.get(`${cursor.x},${cursor.z}`)
if (!highest || highest.y < cursor.y) {
- attr.highestBlocks[`${cursor.x},${cursor.z}`] = {
- y: cursor.y,
- name: block.name
- }
+ attr.highestBlocks.set(`${cursor.x},${cursor.z}`, { y: cursor.y, stateId: block.stateId, biomeId: block.biome.id })
}
}
- if (invisibleBlocks.has(block.name)) continue
+ if (INVISIBLE_BLOCKS.has(block.name)) continue
if ((block.name.includes('_sign') || block.name === 'sign') && !world.config.disableSignsMapsSupport) {
const key = `${cursor.x},${cursor.y},${cursor.z}`
const props: any = block.getProperties()
@@ -531,7 +526,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
renderLiquid(world, cursor, blockProvider.getTextureInfo('lava_still'), block.type, biome, false, attr)
attr.blocksCount++
}
- if (block.name !== 'water' && block.name !== 'lava' && !invisibleBlocks.has(block.name)) {
+ if (block.name !== 'water' && block.name !== 'lava' && !INVISIBLE_BLOCKS.has(block.name)) {
// cache
let { models } = block
@@ -624,8 +619,8 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
return attr
}
-export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true) => {
- blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, 'latest')
+export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true, version = 'latest') => {
+ blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, version)
globalThis.blockProvider = blockProvider
if (useUnknownBlockModel) {
unknownBlockModel = blockProvider.getAllResolvedModels0_1({ name: 'unknown', properties: {} })
diff --git a/prismarine-viewer/viewer/lib/mesher/shared.ts b/prismarine-viewer/viewer/lib/mesher/shared.ts
index b08a2bd76..57d7d6a44 100644
--- a/prismarine-viewer/viewer/lib/mesher/shared.ts
+++ b/prismarine-viewer/viewer/lib/mesher/shared.ts
@@ -32,7 +32,9 @@ export type MesherGeometryOutput = {
tiles: Record,
signs: Record,
// isFull: boolean
- highestBlocks: Record
+ highestBlocks: Map
hadErrors: boolean
blocksCount: number
}
+
+export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined }
diff --git a/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts b/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts
index ef91b1919..e75d803de 100644
--- a/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts
+++ b/prismarine-viewer/viewer/lib/mesher/test/mesherTester.ts
@@ -33,7 +33,7 @@ export const setup = (version, initialBlocks: Array<[number[], string]>) => {
}
}
- setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false)
+ setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false, version)
const reload = () => {
mesherWorld.removeColumn(0, 0)
mesherWorld.addColumn(0, 0, chunk1.toJson())
diff --git a/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts b/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts
index e1d51f223..78374b6bd 100644
--- a/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts
+++ b/prismarine-viewer/viewer/lib/mesher/test/tests.test.ts
@@ -1,5 +1,6 @@
import { test, expect } from 'vitest'
import supportedVersions from '../../../../../src/supportedVersions.mjs'
+import { INVISIBLE_BLOCKS } from '../worldConstants'
import { setup } from './mesherTester'
const lastVersion = supportedVersions.at(-1)
@@ -16,7 +17,7 @@ const addPositions = [
test('Known blocks are not rendered', () => {
const { mesherWorld, getGeometry, pos, mcData } = setup(lastVersion, addPositions as any)
- const ignoreAsExpected = new Set(['air', 'cave_air', 'void_air', 'barrier', 'water', 'lava', 'moving_piston', 'light'])
+ const ignoreAsExpected = new Set([...INVISIBLE_BLOCKS, 'water', 'lava', 'moving_piston', 'light'])
let time = 0
let times = 0
@@ -42,11 +43,14 @@ test('Known blocks are not rendered', () => {
}
}
}
+ console.log('Checking blocks of version', lastVersion)
console.log('Average time', time / times)
// should be fixed, but to avoid regressions & for visibility
+ // TODO resolve creaking_heart issue (1.21.3)
expect(missingBlocks).toMatchInlineSnapshot(`
{
"bubble_column": true,
+ "creaking_heart": true,
"end_gateway": true,
"end_portal": true,
"structure_void": true,
diff --git a/prismarine-viewer/viewer/lib/mesher/worldConstants.ts b/prismarine-viewer/viewer/lib/mesher/worldConstants.ts
new file mode 100644
index 000000000..75f08e89e
--- /dev/null
+++ b/prismarine-viewer/viewer/lib/mesher/worldConstants.ts
@@ -0,0 +1 @@
+export const INVISIBLE_BLOCKS = new Set(['air', 'void_air', 'cave_air', 'barrier'])
diff --git a/prismarine-viewer/viewer/lib/viewer.ts b/prismarine-viewer/viewer/lib/viewer.ts
index d16dbe811..20f10284e 100644
--- a/prismarine-viewer/viewer/lib/viewer.ts
+++ b/prismarine-viewer/viewer/lib/viewer.ts
@@ -3,12 +3,14 @@ import * as THREE from 'three'
import { Vec3 } from 'vec3'
import { generateSpiralMatrix } from 'flying-squid/dist/utils'
import worldBlockProvider from 'mc-assets/dist/worldBlockProvider'
+import stevePng from 'mc-assets/dist/other-textures/latest/entity/player/wide/steve.png'
import { Entities } from './entities'
import { Primitives } from './primitives'
import { WorldRendererThree } from './worldrendererThree'
import { WorldRendererCommon, WorldRendererConfig, defaultWorldRendererConfig } from './worldrendererCommon'
import { getThreeBlockModelGroup, renderBlockThree, setBlockPosition } from './mesher/standaloneRenderer'
import { addNewStat } from './ui/newStats'
+import { getMyHand } from './hand'
export class Viewer {
scene: THREE.Scene
@@ -26,6 +28,8 @@ export class Viewer {
renderingUntilNoUpdates = false
processEntityOverrides = (e, overrides) => overrides
+ getMineflayerBot (): void | Record {} // to be overridden
+
get camera () {
return this.world.camera
}
@@ -78,15 +82,16 @@ export class Viewer {
// this.primitives.clear()
}
- setVersion (userVersion: string, texturesVersion = userVersion) {
+ setVersion (userVersion: string, texturesVersion = userVersion): void | Promise {
console.log('[viewer] Using version:', userVersion, 'textures:', texturesVersion)
- void this.world.setVersion(userVersion, texturesVersion).then(async () => {
+ this.entities.clear()
+ // this.primitives.clear()
+ return this.world.setVersion(userVersion, texturesVersion).then(async () => {
return new THREE.TextureLoader().loadAsync(this.world.itemsAtlasParser!.latestImage)
}).then((texture) => {
this.entities.itemsTexture = texture
+ this.world.renderUpdateEmitter.emit('itemsTextureDownloaded')
})
- this.entities.clear()
- // this.primitives.clear()
}
addColumn (x, z, chunk, isLightUpdate = false) {
@@ -98,24 +103,26 @@ export class Viewer {
}
setBlockStateId (pos: Vec3, stateId: number) {
- if (!this.world.loadedChunks[`${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}`]) {
- console.debug('[should be unreachable] setBlockStateId called for unloaded chunk', pos)
+ const set = async () => {
+ const sectionX = Math.floor(pos.x / 16) * 16
+ const sectionZ = Math.floor(pos.z / 16) * 16
+ if (this.world.queuedChunks.has(`${sectionX},${sectionZ}`)) {
+ await this.world.waitForChunkToLoad(pos)
+ }
+ if (!this.world.loadedChunks[`${sectionX},${sectionZ}`]) {
+ console.debug('[should be unreachable] setBlockStateId called for unloaded chunk', pos)
+ }
+ this.world.setBlockStateId(pos, stateId)
}
- this.world.setBlockStateId(pos, stateId)
+ void set()
}
- demoModel () {
+ async demoModel () {
//@ts-expect-error
const pos = cursorBlockRel(0, 1, 0).position
const blockProvider = worldBlockProvider(this.world.blockstatesModels, this.world.blocksAtlases, 'latest')
- const models = blockProvider.getAllResolvedModels0_1({
- name: 'item_frame',
- properties: {
- // map: false
- }
- }, true)
- const { material } = this.world
- const mesh = getThreeBlockModelGroup(material, models, undefined, 'plains', loadedData)
+
+ const mesh = await getMyHand()
// mesh.rotation.y = THREE.MathUtils.degToRad(90)
setBlockPosition(mesh, pos)
const helper = new THREE.BoxHelper(mesh, 0xff_ff_00)
@@ -150,12 +157,11 @@ export class Viewer {
setFirstPersonCamera (pos: Vec3 | null, yaw: number, pitch: number, roll = 0) {
const cam = this.cameraObjectOverride || this.camera
- let yOffset = this.playerHeight
+ let yOffset = this.getMineflayerBot()?.entity?.eyeHeight ?? this.playerHeight
if (this.isSneaking) yOffset -= 0.3
- if (this.world instanceof WorldRendererThree) {
- this.world.camera = cam as THREE.PerspectiveCamera
- }
+ this.world.camera = cam as THREE.PerspectiveCamera
+
this.world.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch)
}
@@ -205,6 +211,7 @@ export class Viewer {
} | null
worldEmitter.on('loadChunk', ({ x, z, chunk, worldConfig, isLightUpdate }) => {
this.world.worldConfig = worldConfig
+ this.world.queuedChunks.add(`${x},${z}`)
const args = [x, z, chunk, isLightUpdate]
if (!currentLoadChunkBatch) {
// add a setting to use debounce instead
@@ -212,6 +219,7 @@ export class Viewer {
data: [],
timeout: setTimeout(() => {
for (const args of currentLoadChunkBatch!.data) {
+ this.world.queuedChunks.delete(`${args[0]},${args[1]}`)
this.addColumn(...args as Parameters)
}
currentLoadChunkBatch = null
@@ -222,7 +230,7 @@ export class Viewer {
})
// todo remove and use other architecture instead so data flow is clear
worldEmitter.on('blockEntities', (blockEntities) => {
- if (this.world instanceof WorldRendererThree) this.world.blockEntities = blockEntities
+ if (this.world instanceof WorldRendererThree) (this.world).blockEntities = blockEntities
})
worldEmitter.on('unloadChunk', ({ x, z }) => {
@@ -237,14 +245,24 @@ export class Viewer {
this.world.updateViewerPosition(pos)
})
+
+ worldEmitter.on('renderDistance', (d) => {
+ this.world.viewDistance = d
+ this.world.chunksLength = d === 0 ? 1 : generateSpiralMatrix(d).length
+ })
+
worldEmitter.on('renderDistance', (d) => {
this.world.viewDistance = d
this.world.chunksLength = d === 0 ? 1 : generateSpiralMatrix(d).length
this.world.allChunksFinished = Object.keys(this.world.finishedChunks).length === this.world.chunksLength
})
+ worldEmitter.on('markAsLoaded', ({ x, z }) => {
+ this.world.markAsLoaded(x, z)
+ })
+
worldEmitter.on('updateLight', ({ pos }) => {
- if (this.world instanceof WorldRendererThree) this.world.updateLight(pos.x, pos.z)
+ if (this.world instanceof WorldRendererThree) (this.world).updateLight(pos.x, pos.z)
})
worldEmitter.on('time', (timeOfDay) => {
@@ -264,16 +282,20 @@ export class Viewer {
skyLight = Math.floor(skyLight) // todo: remove this after optimization
if (this.world.mesherConfig.skyLight === skyLight) return
- this.world.mesherConfig.skyLight = skyLight;
- (this.world as WorldRendererThree).rerenderAllChunks?.()
+ this.world.mesherConfig.skyLight = skyLight
+ if (this.world instanceof WorldRendererThree) {
+ (this.world).rerenderAllChunks?.()
+ }
})
worldEmitter.emit('listening')
}
render () {
- this.world.render()
- this.entities.render()
+ if (this.world instanceof WorldRendererThree) {
+ (this.world).render()
+ this.entities.render()
+ }
}
async waitForChunksToRender () {
diff --git a/prismarine-viewer/viewer/lib/worldDataEmitter.ts b/prismarine-viewer/viewer/lib/worldDataEmitter.ts
index 51c0a08b8..61d5a503a 100644
--- a/prismarine-viewer/viewer/lib/worldDataEmitter.ts
+++ b/prismarine-viewer/viewer/lib/worldDataEmitter.ts
@@ -6,6 +6,7 @@ import { generateSpiralMatrix, ViewRect } from 'flying-squid/dist/utils'
import { Vec3 } from 'vec3'
import { BotEvents } from 'mineflayer'
import { getItemFromBlock } from '../../../src/chatUtils'
+import { delayedIterator } from '../../examples/shared'
import { chunkPos } from './simpleUtils'
export type ChunkPosKey = string
@@ -22,14 +23,7 @@ export class WorldDataEmitter extends EventEmitter {
private readonly emitter: WorldDataEmitter
keepChunksDistance = 0
addWaitTime = 1
- _handDisplay = false
- get handDisplay () {
- return this._handDisplay
- }
- set handDisplay (newVal) {
- this._handDisplay = newVal
- this.eventListeners.heldItemChanged?.()
- }
+ isPlayground = false
constructor (public world: typeof __type_bot['world'], public viewDistance: number, position: Vec3 = new Vec3(0, 0, 0)) {
super()
@@ -105,23 +99,29 @@ export class WorldDataEmitter extends EventEmitter {
time: () => {
this.emitter.emit('time', bot.time.timeOfDay)
},
- heldItemChanged: () => {
- if (!this.handDisplay) {
- viewer.world.onHandItemSwitch(undefined)
- return
- }
- const newItem = bot.heldItem
- if (!newItem) {
- viewer.world.onHandItemSwitch(undefined)
- return
- }
- const block = loadedData.blocksByName[newItem.name]
- // todo clean types
- const blockProperties = block ? new window.PrismarineBlock(block.id, 'void', newItem.metadata).getProperties() : {}
- viewer.world.onHandItemSwitch({ name: newItem.name, properties: blockProperties })
+ heldItemChanged () {
+ handChanged(false)
},
} satisfies Partial
- this.eventListeners.heldItemChanged()
+ const handChanged = (isLeftHand: boolean) => {
+ const newItem = isLeftHand ? bot.inventory.slots[45] : bot.heldItem
+ if (!newItem) {
+ viewer.world.onHandItemSwitch(undefined, isLeftHand)
+ return
+ }
+ const block = loadedData.blocksByName[newItem.name]
+ // todo clean types
+ const blockProperties = block ? new window.PrismarineBlock(block.id, 'void', newItem.metadata).getProperties() : {}
+ // todo item props
+ viewer.world.onHandItemSwitch({ name: newItem.name, properties: blockProperties, id: newItem.type, type: block ? 'block' : 'item', }, isLeftHand)
+ }
+ bot.inventory.on('updateSlot', (index) => {
+ if (index === 45) {
+ handChanged(true)
+ }
+ })
+ handChanged(false)
+ handChanged(true)
bot._client.on('update_light', ({ chunkX, chunkZ }) => {
@@ -173,19 +173,11 @@ export class WorldDataEmitter extends EventEmitter {
}
async _loadChunks (positions: Vec3[], sliceSize = 5) {
- let i = 0
const promises = [] as Array>
- return new Promise(resolve => {
- const interval = setInterval(() => {
- if (i >= positions.length) {
- clearInterval(interval)
- void Promise.all(promises).then(() => resolve())
- return
- }
- promises.push(this.loadChunk(positions[i]))
- i++
- }, this.addWaitTime)
+ await delayedIterator(positions, this.addWaitTime, (pos) => {
+ promises.push(this.loadChunk(pos))
})
+ await Promise.all(promises)
}
readdDebug () {
@@ -221,6 +213,8 @@ export class WorldDataEmitter extends EventEmitter {
//@ts-expect-error
this.emitter.emit('loadChunk', { x: pos.x, z: pos.z, chunk, blockEntities: column.blockEntities, worldConfig, isLightUpdate })
this.loadedChunks[`${pos.x},${pos.z}`] = true
+ } else if (this.isPlayground) { // don't allow in real worlds pre-flag chunks as loaded to avoid race condition when the chunk might still be loading. In playground it's assumed we always pre-load all chunks first
+ this.emitter.emit('markAsLoaded', { x: pos.x, z: pos.z })
}
} else {
// console.debug('skipped loading chunk', dx, dz, '>', this.viewDistance)
diff --git a/prismarine-viewer/viewer/lib/worldrendererCommon.ts b/prismarine-viewer/viewer/lib/worldrendererCommon.ts
index 65546de4f..ec649a14f 100644
--- a/prismarine-viewer/viewer/lib/worldrendererCommon.ts
+++ b/prismarine-viewer/viewer/lib/worldrendererCommon.ts
@@ -11,13 +11,15 @@ import itemsAtlasLatest from 'mc-assets/dist/itemsAtlasLatest.png'
import itemsAtlasLegacy from 'mc-assets/dist/itemsAtlasLegacy.png'
import { AtlasParser } from 'mc-assets'
import TypedEmitter from 'typed-emitter'
+import { LineMaterial } from 'three-stdlib'
import { dynamicMcDataFiles } from '../../buildMesherConfig.mjs'
import { toMajorVersion } from '../../../src/utils'
import { buildCleanupDecorator } from './cleanupDecorator'
-import { MesherGeometryOutput, defaultMesherConfig } from './mesher/shared'
+import { defaultMesherConfig, HighestBlockInfo, MesherGeometryOutput } from './mesher/shared'
import { chunkPos } from './simpleUtils'
import { HandItemBlock } from './holdingBlock'
import { updateStatText } from './ui/newStats'
+import { WorldRendererThree } from './worldrendererThree'
function mod (x, n) {
return ((x % n) + n) % n
@@ -27,7 +29,9 @@ export const worldCleanup = buildCleanupDecorator('resetWorld')
export const defaultWorldRendererConfig = {
showChunkBorders: false,
- numWorkers: 4
+ numWorkers: 4,
+ // game renderer setting actually
+ displayHand: false
}
export type WorldRendererConfig = typeof defaultWorldRendererConfig
@@ -38,8 +42,14 @@ type CustomTexturesData = {
}
export abstract class WorldRendererCommon {
+ // todo
+ @worldCleanup()
+ threejsCursorLineMaterial: LineMaterial
+ @worldCleanup()
+ cursorBlock = null as Vec3 | null
isPlayground = false
displayStats = true
+ @worldCleanup()
worldConfig = { minY: 0, worldHeight: 256 }
// todo need to cleanup
material = new THREE.MeshLambertMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1 })
@@ -49,27 +59,37 @@ export abstract class WorldRendererCommon
version = undefined as string | undefined
@worldCleanup()
- loadedChunks = {} as Record
+ loadedChunks = {} as Record // data is added for these chunks and they might be still processing
@worldCleanup()
- finishedChunks = {} as Record
+ finishedChunks = {} as Record // these chunks are fully loaded into the world (scene)
@worldCleanup()
- sectionsOutstanding = new Map()
+ // loading sections (chunks)
+ sectionsWaiting = new Map()
+
+ @worldCleanup()
+ queuedChunks = new Set()
@worldCleanup()
renderUpdateEmitter = new EventEmitter() as unknown as TypedEmitter<{
dirty (pos: Vec3, value: boolean): void
update (/* pos: Vec3, value: boolean */): void
textureDownloaded (): void
+ itemsTextureDownloaded (): void
+ chunkFinished (key: string): void
}>
customTexturesDataUrl = undefined as string | undefined
@worldCleanup()
currentTextureImage = undefined as any
workers: any[] = []
+ @worldCleanup()
viewerPosition?: Vec3
lastCamUpdate = 0
droppedFpsPercentage = 0
+ @worldCleanup()
+ initialChunkLoadWasStartedIn: number | undefined
+ @worldCleanup()
initialChunksLoad = true
enableChunksLoadDelay = false
texturesVersion?: string
@@ -81,7 +101,7 @@ export abstract class WorldRendererCommon
handleResize = () => { }
mesherConfig = defaultMesherConfig
camera: THREE.PerspectiveCamera
- highestBlocks: Record = {}
+ highestBlocks = new Map()
blockstatesModels: any
customBlockStates: Record | undefined
customModels: Record | undefined
@@ -97,6 +117,10 @@ export abstract class WorldRendererCommon
workersProcessAverageTime = 0
workersProcessAverageTimeCount = 0
maxWorkersProcessTime = 0
+ geometryReceiveCount = {}
+ allLoadedIn: undefined | number
+ rendererDevice = '...'
+
edgeChunks = {} as Record
lastAddChunk = null as null | {
timeout: any
@@ -108,13 +132,15 @@ export abstract class WorldRendererCommon
abstract outputFormat: 'threeJs' | 'webgpu'
+ abstract changeBackgroundColor (color: [number, number, number]): void
+
constructor (public config: WorldRendererConfig) {
// this.initWorkers(1) // preload script on page load
this.snapshotInitialValues()
this.renderUpdateEmitter.on('update', () => {
const loadedChunks = Object.keys(this.finishedChunks).length
- updateStatText('loaded-chunks', `${loadedChunks}/${this.chunksLength} chunks (${this.lastChunkDistance})`)
+ updateStatText('loaded-chunks', `${loadedChunks}/${this.chunksLength} chunks (${this.lastChunkDistance}/${this.viewDistance})`)
})
}
@@ -122,7 +148,7 @@ export abstract class WorldRendererCommon
initWorkers (numWorkers = this.config.numWorkers) {
// init workers
- for (let i = 0; i < numWorkers; i++) {
+ for (let i = 0; i < numWorkers + 1; i++) {
// Node environment needs an absolute path, but browser needs the url of the file
const workerName = 'mesher.js'
// eslint-disable-next-line node/no-path-concat
@@ -133,6 +159,8 @@ export abstract class WorldRendererCommon
if (!this.active) return
this.handleWorkerMessage(data)
if (data.type === 'geometry') {
+ this.geometryReceiveCount[data.workerIndex] ??= 0
+ this.geometryReceiveCount[data.workerIndex]++
const geometry = data.geometry as MesherGeometryOutput
for (const key in geometry.highestBlocks) {
const highest = geometry.highestBlocks[key]
@@ -144,13 +172,13 @@ export abstract class WorldRendererCommon
this.lastChunkDistance = Math.max(...this.getDistance(new Vec3(chunkCoords[0], 0, chunkCoords[2])))
}
if (data.type === 'sectionFinished') { // on after load & unload section
- if (!this.sectionsOutstanding.get(data.key)) throw new Error(`sectionFinished event for non-outstanding section ${data.key}`)
- this.sectionsOutstanding.set(data.key, this.sectionsOutstanding.get(data.key)! - 1)
- if (this.sectionsOutstanding.get(data.key) === 0) this.sectionsOutstanding.delete(data.key)
+ if (!this.sectionsWaiting.get(data.key)) throw new Error(`sectionFinished event for non-outstanding section ${data.key}`)
+ this.sectionsWaiting.set(data.key, this.sectionsWaiting.get(data.key)! - 1)
+ if (this.sectionsWaiting.get(data.key) === 0) this.sectionsWaiting.delete(data.key)
const chunkCoords = data.key.split(',').map(Number)
if (this.loadedChunks[`${chunkCoords[0]},${chunkCoords[2]}`]) { // ensure chunk data was added, not a neighbor chunk update
- const loadingKeys = [...this.sectionsOutstanding.keys()]
+ const loadingKeys = [...this.sectionsWaiting.keys()]
if (!loadingKeys.some(key => {
const [x, y, z] = key.split(',').map(Number)
return x === chunkCoords[0] && z === chunkCoords[2]
@@ -158,13 +186,7 @@ export abstract class WorldRendererCommon
this.finishedChunks[`${chunkCoords[0]},${chunkCoords[2]}`] = true
}
}
- if (this.sectionsOutstanding.size === 0) {
- const allFinished = Object.keys(this.finishedChunks).length === this.chunksLength
- if (allFinished) {
- this.allChunksLoaded?.()
- this.allChunksFinished = true
- }
- }
+ this.checkAllFinished()
this.renderUpdateEmitter.emit('update')
if (data.processTime) {
@@ -187,8 +209,18 @@ export abstract class WorldRendererCommon
}
}
- onHandItemSwitch (item: HandItemBlock | undefined): void { }
- changeHandSwingingState (isAnimationPlaying: boolean): void { }
+ checkAllFinished () {
+ if (this.sectionsWaiting.size === 0) {
+ const allFinished = Object.keys(this.finishedChunks).length === this.chunksLength
+ if (allFinished) {
+ this.allChunksLoaded?.()
+ this.allChunksFinished = true
+ }
+ }
+ }
+
+ onHandItemSwitch (item: HandItemBlock | undefined, isLeftHand: boolean): void { }
+ changeHandSwingingState (isAnimationPlaying: boolean, isLeftHand: boolean): void { }
abstract handleWorkerMessage (data: WorkerReceive): void
@@ -268,7 +300,7 @@ export abstract class WorldRendererCommon
}
}
- async updateTexturesData () {
+ async updateTexturesData (resourcePackUpdate = false) {
const blocksAssetsParser = new AtlasParser(this.blocksAtlases, blocksAtlasLatest, blocksAtlasLegacy)
const itemsAssetsParser = new AtlasParser(this.itemsAtlases, itemsAtlasLatest, itemsAtlasLegacy)
const { atlas: blocksAtlas, canvas: blocksCanvas } = await blocksAssetsParser.makeNewAtlas(this.texturesVersion ?? this.version ?? 'latest', (textureName) => {
@@ -325,11 +357,17 @@ export abstract class WorldRendererCommon
return Math.floor(Math.max(this.worldConfig.minY, this.mesherConfig.clipWorldBelowY ?? -Infinity) / 16) * 16
}
+ updateChunksStatsText () {
+ updateStatText('downloaded-chunks', `${Object.keys(this.loadedChunks).length}/${this.chunksLength} chunks D (${this.workers.length}:${this.workersProcessAverageTime.toFixed(0)}ms/${this.allLoadedIn?.toFixed(1) ?? '-'}s)`)
+ }
+
addColumn (x: number, z: number, chunk: any, isLightUpdate: boolean) {
if (!this.active) return
if (this.workers.length === 0) throw new Error('workers not initialized yet')
this.initialChunksLoad = false
+ this.initialChunkLoadWasStartedIn ??= Date.now()
this.loadedChunks[`${x},${z}`] = true
+ this.updateChunksStatsText()
for (const worker of this.workers) {
// todo optimize
worker.postMessage({ type: 'chunk', x, z, chunk })
@@ -346,13 +384,19 @@ export abstract class WorldRendererCommon
}
}
+ markAsLoaded (x, z) {
+ this.loadedChunks[`${x},${z}`] = true
+ this.finishedChunks[`${x},${z}`] = true
+ this.checkAllFinished()
+ }
+
removeColumn (x, z) {
delete this.loadedChunks[`${x},${z}`]
for (const worker of this.workers) {
worker.postMessage({ type: 'unloadChunk', x, z })
}
- this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength
delete this.finishedChunks[`${x},${z}`]
+ this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength
for (let y = this.worldConfig.minY; y < this.worldConfig.worldHeight; y += 16) {
this.setSectionDirty(new Vec3(x, y, z), false)
}
@@ -369,24 +413,31 @@ export abstract class WorldRendererCommon
}
setBlockStateId (pos: Vec3, stateId: number) {
+ const key = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.y / 16) * 16},${Math.floor(pos.z / 16) * 16}`
+ const useChangeWorker = !this.sectionsWaiting[key]
for (const worker of this.workers) {
worker.postMessage({ type: 'blockUpdate', pos, stateId })
}
- this.setSectionDirty(pos)
+ this.setSectionDirty(pos, true, useChangeWorker)
if (this.neighborChunkUpdates) {
- if ((pos.x & 15) === 0) this.setSectionDirty(pos.offset(-16, 0, 0))
- if ((pos.x & 15) === 15) this.setSectionDirty(pos.offset(16, 0, 0))
- if ((pos.y & 15) === 0) this.setSectionDirty(pos.offset(0, -16, 0))
- if ((pos.y & 15) === 15) this.setSectionDirty(pos.offset(0, 16, 0))
- if ((pos.z & 15) === 0) this.setSectionDirty(pos.offset(0, 0, -16))
- if ((pos.z & 15) === 15) this.setSectionDirty(pos.offset(0, 0, 16))
+ if ((pos.x & 15) === 0) this.setSectionDirty(pos.offset(-16, 0, 0), true, useChangeWorker)
+ if ((pos.x & 15) === 15) this.setSectionDirty(pos.offset(16, 0, 0), true, useChangeWorker)
+ if ((pos.y & 15) === 0) this.setSectionDirty(pos.offset(0, -16, 0), true, useChangeWorker)
+ if ((pos.y & 15) === 15) this.setSectionDirty(pos.offset(0, 16, 0), true, useChangeWorker)
+ if ((pos.z & 15) === 0) this.setSectionDirty(pos.offset(0, 0, -16), true, useChangeWorker)
+ if ((pos.z & 15) === 15) this.setSectionDirty(pos.offset(0, 0, 16), true, useChangeWorker)
}
}
queueAwaited = false
messagesQueue = {} as { [workerIndex: string]: any[] }
- setSectionDirty (pos: Vec3, value = true) { // value false is used for unloading chunks
+ getWorkerNumber (pos: Vec3) {
+ const hash = mod(Math.floor(pos.x / 16) + Math.floor(pos.y / 16) + Math.floor(pos.z / 16), this.workers.length - 1)
+ return hash + 1
+ }
+
+ setSectionDirty (pos: Vec3, value = true, useChangeWorker = false) { // value false is used for unloading chunks
if (this.viewDistance === -1) throw new Error('viewDistance not set')
this.allChunksFinished = false
const distance = this.getDistance(pos)
@@ -397,8 +448,8 @@ export abstract class WorldRendererCommon
// Dispatch sections to workers based on position
// This guarantees uniformity accross workers and that a given section
// is always dispatched to the same worker
- const hash = mod(Math.floor(pos.x / 16) + Math.floor(pos.y / 16) + Math.floor(pos.z / 16), this.workers.length)
- this.sectionsOutstanding.set(key, (this.sectionsOutstanding.get(key) ?? 0) + 1)
+ const hash = useChangeWorker ? 0 : this.getWorkerNumber(pos)
+ this.sectionsWaiting.set(key, (this.sectionsWaiting.get(key) ?? 0) + 1)
this.messagesQueue[hash] ??= []
this.messagesQueue[hash].push({
// this.workers[hash].postMessage({
@@ -430,13 +481,13 @@ export abstract class WorldRendererCommon
// of sections not rendered are 0
async waitForChunksToRender () {
return new Promise((resolve, reject) => {
- if ([...this.sectionsOutstanding].length === 0) {
+ if ([...this.sectionsWaiting].length === 0) {
resolve()
return
}
const updateHandler = () => {
- if (this.sectionsOutstanding.size === 0) {
+ if (this.sectionsWaiting.size === 0) {
this.renderUpdateEmitter.removeListener('update', updateHandler)
resolve()
}
@@ -444,4 +495,27 @@ export abstract class WorldRendererCommon
this.renderUpdateEmitter.on('update', updateHandler)
})
}
+
+ async waitForChunkToLoad (pos: Vec3) {
+ return new Promise((resolve, reject) => {
+ const key = `${Math.floor(pos.x / 16) * 16},${Math.floor(pos.z / 16) * 16}`
+ if (this.loadedChunks[key]) {
+ resolve()
+ return
+ }
+ const updateHandler = () => {
+ if (this.loadedChunks[key]) {
+ this.renderUpdateEmitter.removeListener('update', updateHandler)
+ resolve()
+ }
+ }
+ this.renderUpdateEmitter.on('update', updateHandler)
+ })
+ }
+
+ destroy () {
+ console.warn('world destroy is not implemented')
+ }
+
+ abstract setHighlightCursorBlock (block: typeof this.cursorBlock, shapePositions?: Array<{ position; width; height; depth }>): void
}
diff --git a/prismarine-viewer/viewer/lib/worldrendererThree.ts b/prismarine-viewer/viewer/lib/worldrendererThree.ts
index e8769c888..4d317354e 100644
--- a/prismarine-viewer/viewer/lib/worldrendererThree.ts
+++ b/prismarine-viewer/viewer/lib/worldrendererThree.ts
@@ -3,7 +3,7 @@ import { Vec3 } from 'vec3'
import nbt from 'prismarine-nbt'
import PrismarineChatLoader from 'prismarine-chat'
import * as tweenJs from '@tweenjs/tween.js'
-import { BloomPass, RenderPass, UnrealBloomPass, EffectComposer, WaterPass, GlitchPass } from 'three-stdlib'
+import { BloomPass, RenderPass, UnrealBloomPass, EffectComposer, WaterPass, GlitchPass, LineSegmentsGeometry, Wireframe, LineMaterial } from 'three-stdlib'
import worldBlockProvider from 'mc-assets/dist/worldBlockProvider'
import { renderSign } from '../sign-renderer'
import { chunkPos, sectionPos } from './simpleUtils'
@@ -14,6 +14,7 @@ import { addNewStat } from './ui/newStats'
import { MesherGeometryOutput } from './mesher/shared'
export class WorldRendererThree extends WorldRendererCommon {
+ interactionLines: null | { blockPos; mesh } = null
outputFormat = 'threeJs' as const
blockEntities = {}
sectionObjects: Record = {}
@@ -22,6 +23,8 @@ export class WorldRendererThree extends WorldRendererCommon {
starField: StarField
cameraSectionPos: Vec3 = new Vec3(0, 0, 0)
holdingBlock: HoldingBlock
+ holdingBlockLeft: HoldingBlock
+ rendererDevice = '...'
get tilesRendered () {
return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj as any).tilesCount, 0)
@@ -33,35 +36,53 @@ export class WorldRendererThree extends WorldRendererCommon {
constructor (public scene: THREE.Scene, public renderer: THREE.WebGLRenderer, public config: WorldRendererConfig) {
super(config)
+ this.rendererDevice = String(WorldRendererThree.getRendererInfo(this.renderer))
this.starField = new StarField(scene)
- this.holdingBlock = new HoldingBlock(this.scene)
+ this.holdingBlock = new HoldingBlock()
+ this.holdingBlockLeft = new HoldingBlock()
+ this.holdingBlockLeft.rightSide = false
- this.renderUpdateEmitter.on('textureDownloaded', () => {
+ this.renderUpdateEmitter.on('itemsTextureDownloaded', () => {
if (this.holdingBlock.toBeRenderedItem) {
this.onHandItemSwitch(this.holdingBlock.toBeRenderedItem)
this.holdingBlock.toBeRenderedItem = undefined
}
+ if (this.holdingBlockLeft.toBeRenderedItem) {
+ this.onHandItemSwitch(this.holdingBlock.toBeRenderedItem, true)
+ this.holdingBlockLeft.toBeRenderedItem = undefined
+ }
})
this.addDebugOverlay()
}
- onHandItemSwitch (item: HandItemBlock | undefined) {
+ onHandItemSwitch (item: HandItemBlock | undefined, isLeft = false) {
+ if (!isLeft) {
+ item ??= {
+ type: 'hand',
+ }
+ }
+ const holdingBlock = isLeft ? this.holdingBlockLeft : this.holdingBlock
if (!this.currentTextureImage) {
- this.holdingBlock.toBeRenderedItem = item
+ holdingBlock.toBeRenderedItem = item
return
}
- void this.holdingBlock.initHandObject(this.material, this.blockstatesModels, this.blocksAtlases, item)
+ void holdingBlock.initHandObject(this.material, this.blockstatesModels, this.blocksAtlases, item)
}
- changeHandSwingingState (isAnimationPlaying: boolean) {
+ changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) {
+ const holdingBlock = isLeft ? this.holdingBlockLeft : this.holdingBlock
if (isAnimationPlaying) {
- this.holdingBlock.startSwing()
+ holdingBlock.startSwing()
} else {
- void this.holdingBlock.stopSwing()
+ void holdingBlock.stopSwing()
}
}
+ changeBackgroundColor (color: [number, number, number]): void {
+ this.scene.background = new THREE.Color(color[0], color[1], color[2])
+ }
+
timeUpdated (newTime: number): void {
const nightTime = 13_500
const morningStart = 23_000
@@ -216,10 +237,13 @@ export class WorldRendererThree extends WorldRendererCommon {
render () {
tweenJs.update()
- this.holdingBlock.update(this.camera)
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
const cam = this.camera instanceof THREE.Group ? this.camera.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera
this.renderer.render(this.scene, cam)
+ if (this.config.displayHand) {
+ this.holdingBlock.render(this.camera, this.renderer, viewer.ambientLight, viewer.directionalLight)
+ this.holdingBlockLeft.render(this.camera, this.renderer, viewer.ambientLight, viewer.directionalLight)
+ }
}
renderSign (position: Vec3, rotation: number, isWall: boolean, isHanging: boolean, blockEntity) {
@@ -361,9 +385,47 @@ export class WorldRendererThree extends WorldRendererCommon {
}
}
- setSectionDirty (pos, value = true) {
+ setSectionDirty (...args: Parameters) {
+ const [pos] = args
this.cleanChunkTextures(pos.x, pos.z) // todo don't do this!
- super.setSectionDirty(pos, value)
+ super.setSectionDirty(...args)
+ }
+
+ setHighlightCursorBlock (blockPos: typeof this.cursorBlock, shapePositions?: Array<{ position: any; width: any; height: any; depth: any; }>): void {
+ this.cursorBlock = blockPos
+ if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) {
+ return
+ }
+ if (this.interactionLines !== null) {
+ this.scene.remove(this.interactionLines.mesh)
+ this.interactionLines = null
+ }
+ if (blockPos === null) {
+ return
+ }
+
+ const group = new THREE.Group()
+ for (const { position, width, height, depth } of shapePositions ?? []) {
+ const scale = [1.0001 * width, 1.0001 * height, 1.0001 * depth] as const
+ const geometry = new THREE.BoxGeometry(...scale)
+ const lines = new LineSegmentsGeometry().fromEdgesGeometry(new THREE.EdgesGeometry(geometry))
+ const wireframe = new Wireframe(lines, this.threejsCursorLineMaterial)
+ const pos = blockPos.plus(position)
+ wireframe.position.set(pos.x, pos.y, pos.z)
+ wireframe.computeLineDistances()
+ group.add(wireframe)
+ }
+ this.scene.add(group)
+ this.interactionLines = { blockPos, mesh: group }
+ }
+
+ static getRendererInfo (renderer: THREE.WebGLRenderer) {
+ try {
+ const gl = renderer.getContext()
+ return `${gl.getParameter(gl.getExtension('WEBGL_debug_renderer_info')!.UNMASKED_RENDERER_WEBGL)} powered by three.js r{THREE.REVISION}`
+ } catch (err) {
+ console.warn('Failed to get renderer info', err)
+ }
}
}
diff --git a/rsbuild.config.ts b/rsbuild.config.ts
index b95942429..1085e3fcf 100644
--- a/rsbuild.config.ts
+++ b/rsbuild.config.ts
@@ -105,6 +105,7 @@ const appConfig = defineConfig({
if (fs.existsSync('./prismarine-viewer/dist/mesher.js') && dev) {
// copy mesher
fs.copyFileSync('./prismarine-viewer/dist/mesher.js', './dist/mesher.js')
+ fs.copyFileSync('./prismarine-viewer/dist/mesher.js.map', './dist/mesher.js.map')
} else if (!dev) {
await execAsync('pnpm run build-mesher')
}
diff --git a/scripts/genMcDataTypes.ts b/scripts/genMcDataTypes.ts
index f5b150696..82b5b8785 100644
--- a/scripts/genMcDataTypes.ts
+++ b/scripts/genMcDataTypes.ts
@@ -1,5 +1,6 @@
import minecraftData from 'minecraft-data'
import fs from 'fs'
+import supportedVersions from '../src/supportedVersions.mjs'
const data = minecraftData('1.20.1')
@@ -10,4 +11,41 @@ types += `\nexport type EntityNames = ${Object.keys(data.entitiesByName).map(blo
types += `\nexport type BiomesNames = ${Object.keys(data.biomesByName).map(blockName => `'${blockName}'`).join(' | ')};`
types += `\nexport type EnchantmentNames = ${Object.keys(data.enchantmentsByName).map(blockName => `'${blockName}'`).join(' | ')};`
+type Version = string
+const allVersionsEntitiesMetadata = {} as Record>
+for (const version of supportedVersions) {
+ const data = minecraftData(version)
+ for (const { name, metadataKeys } of data.entitiesArray) {
+ allVersionsEntitiesMetadata[name] ??= {}
+ if (!metadataKeys) {
+ // console.warn('Entity has no metadata', name, version)
+ }
+ for (const [i, key] of (metadataKeys ?? []).entries()) {
+ allVersionsEntitiesMetadata[name][key] ??= {
+ version: version,
+ firstKey: i,
+ }
+ }
+ }
+}
+
+types += '\n\nexport type EntityMetadataVersions = {\n'
+for (const [name, versions] of Object.entries(allVersionsEntitiesMetadata)) {
+ types += `'${name}': {`
+ for (const [key, v] of Object.entries(versions)) {
+ types += `\n/** ${v.version}+ (${v.firstKey}) */\n`
+ types += `'${key}': string;`
+ }
+ types += '},'
+}
+types += '\n}'
+
+const minify = false
+if (minify) {
+ types = types.replaceAll(/[\t]/g, '')
+}
+
fs.writeFileSync('./src/mcDataTypes.ts', types, 'utf8')
diff --git a/src/browserfs.ts b/src/browserfs.ts
index e3675b4c3..7e66dfe04 100644
--- a/src/browserfs.ts
+++ b/src/browserfs.ts
@@ -389,7 +389,7 @@ export const copyFilesAsyncWithProgress = async (pathSrc: string, pathDest: stri
return
}
if (!stat.isDirectory()) {
- await fs.promises.writeFile(pathDest, await fs.promises.readFile(pathSrc))
+ await fs.promises.writeFile(pathDest, await fs.promises.readFile(pathSrc) as any)
console.debug('copied single file', pathSrc, pathDest)
return
}
@@ -464,7 +464,7 @@ export const copyFilesAsync = async (pathSrc: string, pathDest: string, fileCopi
} else {
// Copy file
try {
- await fs.promises.writeFile(curPathDest, await fs.promises.readFile(curPathSrc))
+ await fs.promises.writeFile(curPathDest, await fs.promises.readFile(curPathSrc) as any)
console.debug('copied file', curPathSrc, curPathDest)
} catch (err) {
console.error('Error copying file', curPathSrc, curPathDest, err)
@@ -475,17 +475,36 @@ export const copyFilesAsync = async (pathSrc: string, pathDest: string, fileCopi
}))
}
-export const openWorldFromHttpDir = async (fileDescriptorUrl: string/* | undefined */, baseUrl = fileDescriptorUrl.split('/').slice(0, -1).join('/')) => {
+export const openWorldFromHttpDir = async (fileDescriptorUrls: string[]/* | undefined */, baseUrlParam) => {
// todo try go guess mode
let index
- const file = await fetch(fileDescriptorUrl).then(async a => a.json())
- if (file.baseUrl) {
- baseUrl = new URL(file.baseUrl, baseUrl).toString()
- index = file.index
- } else {
- index = file
+ let baseUrl
+ for (const url of fileDescriptorUrls) {
+ let file
+ try {
+ setLoadingScreenStatus(`Trying to get world descriptor from ${new URL(url).host}`)
+ const controller = new AbortController()
+ setTimeout(() => {
+ controller.abort()
+ }, 3000)
+ // eslint-disable-next-line no-await-in-loop
+ const response = await fetch(url, { signal: controller.signal })
+ // eslint-disable-next-line no-await-in-loop
+ file = await response.json()
+ } catch (err) {
+ console.error('Error fetching file descriptor', url, err)
+ }
+ if (!file) continue
+ if (file.baseUrl) {
+ baseUrl = new URL(file.baseUrl, baseUrl).toString()
+ index = file.index
+ } else {
+ index = file
+ baseUrl = baseUrlParam ?? url.split('/').slice(0, -1).join('/')
+ }
+ break
}
- if (!index) throw new Error(`The provided mapDir file is not valid descriptor file! ${fileDescriptorUrl}`)
+ if (!index) throw new Error(`The provided mapDir file is not valid descriptor file! ${fileDescriptorUrls.join(', ')}`)
await new Promise(async resolve => {
browserfs.configure({
fs: 'MountableFileSystem',
diff --git a/src/controls.ts b/src/controls.ts
index 602ea81d2..cb1c132bc 100644
--- a/src/controls.ts
+++ b/src/controls.ts
@@ -7,7 +7,7 @@ import { ControMax } from 'contro-max/build/controMax'
import { CommandEventArgument, SchemaCommandInput } from 'contro-max/build/types'
import { stringStartsWith } from 'contro-max/build/stringUtils'
import { UserOverrideCommand, UserOverridesConfig } from 'contro-max/build/types/store'
-import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, loadedGameState } from './globalState'
+import { isGameActive, showModal, gameAdditionalState, activeModalStack, hideCurrentModal, miscUiState, loadedGameState, hideModal } from './globalState'
import { goFullscreen, pointerLock, reloadChunks } from './utils'
import { options } from './optionsStorage'
import { openPlayerInventory } from './inventoryWindows'
@@ -54,6 +54,7 @@ export const contro = new ControMax({
ui: {
toggleFullscreen: ['F11'],
back: [null/* 'Escape' */, 'B'],
+ toggleMap: ['KeyM'],
leftClick: [null, 'A'],
rightClick: [null, 'Y'],
speedupCursor: [null, 'Left Stick'],
@@ -299,7 +300,7 @@ const alwaysPressedHandledCommand = (command: Command) => {
}
}
-function lockUrl () {
+export function lockUrl () {
let newQs = ''
if (fsState.saveLoaded) {
const save = localServer!.options.worldFolder.split('/').at(-1)
@@ -424,6 +425,14 @@ contro.on('trigger', ({ command }) => {
if (command === 'ui.toggleFullscreen') {
void goFullscreen(true)
}
+
+ if (command === 'ui.toggleMap') {
+ if (activeModalStack.at(-1)?.reactType === 'full-map') {
+ hideModal({ reactType: 'full-map' })
+ } else {
+ showModal({ reactType: 'full-map' })
+ }
+ }
})
contro.on('release', ({ command }) => {
@@ -514,6 +523,15 @@ export const f3Keybinds = [
}
},
mobileTitle: 'Cycle Game Mode'
+ },
+ {
+ key: 'KeyP',
+ async action () {
+ const { uuid, ping: playerPing, username } = bot.player
+ const proxyPing = await bot['pingProxy']()
+ void showOptionsModal(`${username}: last known total latency (ping): ${playerPing}. Connected to ${lastConnectOptions.value?.proxy} with current ping ${proxyPing}. Player UUID: ${uuid}`, [])
+ },
+ mobileTitle: 'Show Proxy & Ping Details'
}
]
diff --git a/src/defaultLocalServerOptions.js b/src/defaultLocalServerOptions.js
index 130726e0f..cd9495673 100644
--- a/src/defaultLocalServerOptions.js
+++ b/src/defaultLocalServerOptions.js
@@ -33,6 +33,6 @@ module.exports = {
keepAlive: false,
'everybody-op': true,
'max-entities': 100,
- 'version': '1.14.4',
- versionMajor: '1.14'
+ 'version': '1.18.2',
+ versionMajor: '1.18'
}
diff --git a/src/devtools.ts b/src/devtools.ts
index 16337c1d7..e87b6d333 100644
--- a/src/devtools.ts
+++ b/src/devtools.ts
@@ -46,7 +46,7 @@ customEvents.on('gameLoaded', () => {
window.inspectPacket = (packetName, full = false) => {
const listener = (...args) => console.log('packet', packetName, full ? args : args[0])
const attach = () => {
- bot?._client.on(packetName, listener)
+ bot?._client.prependListener(packetName, listener)
}
attach()
customEvents.on('mineflayerBotCreated', attach)
diff --git a/src/downloadAndOpenFile.ts b/src/downloadAndOpenFile.ts
index 49fc5c35a..6e59ea025 100644
--- a/src/downloadAndOpenFile.ts
+++ b/src/downloadAndOpenFile.ts
@@ -9,10 +9,10 @@ export const getFixedFilesize = (bytes: number) => {
const inner = async () => {
const qs = new URLSearchParams(window.location.search)
- const mapUrlDir = qs.get('mapDir')
+ const mapUrlDir = qs.getAll('mapDir')
const mapUrlDirGuess = qs.get('mapDirGuess')
const mapUrlDirBaseUrl = qs.get('mapDirBaseUrl')
- if (mapUrlDir) {
+ if (mapUrlDir.length) {
await openWorldFromHttpDir(mapUrlDir, mapUrlDirBaseUrl ?? undefined)
return true
}
diff --git a/src/flyingSquidUtils.ts b/src/flyingSquidUtils.ts
index 78254cf23..012830d9f 100644
--- a/src/flyingSquidUtils.ts
+++ b/src/flyingSquidUtils.ts
@@ -27,8 +27,10 @@ export async function savePlayers (autoSave: boolean) {
export const saveServer = async (autoSave = true) => {
if (!localServer || fsState.isReadonly) return
// todo
+ console.time('save server')
const worlds = [(localServer as any).overworld] as Array
await Promise.all([localServer.writeLevelDat(), savePlayers(autoSave), ...worlds.map(async world => world.saveNow())])
+ console.timeEnd('save server')
}
export const disconnect = async () => {
if (localServer) {
diff --git a/src/globalState.ts b/src/globalState.ts
index cefa78103..90e3e359c 100644
--- a/src/globalState.ts
+++ b/src/globalState.ts
@@ -1,6 +1,7 @@
//@ts-check
import { proxy, ref, subscribe } from 'valtio'
+import { WorldWarp } from 'flying-squid/dist/lib/modules/warps'
import { pointerLock } from './utils'
import type { OptionsGroupType } from './optionsGuiScheme'
@@ -153,6 +154,7 @@ export const gameAdditionalState = proxy({
isFlying: false,
isSprinting: false,
isSneaking: false,
+ warps: [] as WorldWarp[]
})
window.gameAdditionalState = gameAdditionalState
diff --git a/src/index.ts b/src/index.ts
index 1b65bb007..93bbe6b90 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -22,7 +22,7 @@ import PrismarineItem from 'prismarine-item'
import { options, watchValue } from './optionsStorage'
import './reactUi'
-import { contro, onBotCreate } from './controls'
+import { contro, lockUrl, onBotCreate } from './controls'
import './dragndrop'
import { possiblyCleanHandle, resetStateAfterDisconnect } from './browserfs'
import { watchOptionsAfterViewerInit, watchOptionsAfterWorldViewInit } from './watchOptions'
@@ -157,6 +157,7 @@ if (isIphone) {
// Create viewer
const viewer: import('prismarine-viewer/viewer/lib/viewer').Viewer = new Viewer(renderer)
window.viewer = viewer
+viewer.getMineflayerBot = () => bot
// todo unify
viewer.entities.getItemUv = (idOrName: number | string) => {
try {
@@ -420,7 +421,7 @@ async function connect (connectOptions: ConnectOptions) {
}
}
viewer.world.blockstatesModels = await import('mc-assets/dist/blockStatesModels.json')
- viewer.setVersion(version, options.useVersionsTextures === 'latest' ? version : options.useVersionsTextures)
+ void viewer.setVersion(version, options.useVersionsTextures === 'latest' ? version : options.useVersionsTextures)
}
const downloadVersion = connectOptions.botVersion || (singleplayer ? serverOptions.version : undefined)
@@ -692,6 +693,9 @@ async function connect (connectOptions: ConnectOptions) {
setLoadingScreenStatus('Placing blocks (starting viewer)')
localStorage.lastConnectOptions = JSON.stringify(connectOptions)
connectOptions.onSuccessfulPlay?.()
+ if (process.env.NODE_ENV === 'development' && !localStorage.lockUrl && new URLSearchParams(location.search).size === 0) {
+ lockUrl()
+ }
updateDataAfterJoin()
if (connectOptions.autoLoginPassword) {
bot.chat(`/login ${connectOptions.autoLoginPassword}`)
@@ -1046,6 +1050,10 @@ downloadAndOpenFile().then((downloadAction) => {
})
}
})
+
+ if (qs.get('serversList')) {
+ showModal({ reactType: 'serversList' })
+ }
}, (err) => {
console.error(err)
alert(`Failed to download file: ${err}`)
diff --git a/src/mcDataTypes.ts b/src/mcDataTypes.ts
index 7c70e0f04..3375cf28e 100644
--- a/src/mcDataTypes.ts
+++ b/src/mcDataTypes.ts
@@ -1,6 +1,4318 @@
-export type BlockNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'water' | 'lava' | 'sand' | 'suspicious_sand' | 'red_sand' | 'gravel' | 'suspicious_gravel' | 'gold_ore' | 'deepslate_gold_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'coal_ore' | 'deepslate_coal_ore' | 'nether_gold_ore' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'bamboo_block' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_oak_log' | 'stripped_mangrove_log' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'lapis_ore' | 'deepslate_lapis_ore' | 'lapis_block' | 'dispenser' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'note_block' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'powered_rail' | 'detector_rail' | 'sticky_piston' | 'cobweb' | 'grass' | 'fern' | 'dead_bush' | 'seagrass' | 'tall_seagrass' | 'piston' | 'piston_head' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'moving_piston' | 'dandelion' | 'torchflower' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'wither_rose' | 'lily_of_the_valley' | 'brown_mushroom' | 'red_mushroom' | 'gold_block' | 'iron_block' | 'bricks' | 'tnt' | 'bookshelf' | 'chiseled_bookshelf' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'wall_torch' | 'fire' | 'soul_fire' | 'spawner' | 'oak_stairs' | 'chest' | 'redstone_wire' | 'diamond_ore' | 'deepslate_diamond_ore' | 'diamond_block' | 'crafting_table' | 'wheat' | 'farmland' | 'furnace' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'acacia_sign' | 'cherry_sign' | 'jungle_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'oak_door' | 'ladder' | 'rail' | 'cobblestone_stairs' | 'oak_wall_sign' | 'spruce_wall_sign' | 'birch_wall_sign' | 'acacia_wall_sign' | 'cherry_wall_sign' | 'jungle_wall_sign' | 'dark_oak_wall_sign' | 'mangrove_wall_sign' | 'bamboo_wall_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'jungle_hanging_sign' | 'dark_oak_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'oak_wall_hanging_sign' | 'spruce_wall_hanging_sign' | 'birch_wall_hanging_sign' | 'acacia_wall_hanging_sign' | 'cherry_wall_hanging_sign' | 'jungle_wall_hanging_sign' | 'dark_oak_wall_hanging_sign' | 'mangrove_wall_hanging_sign' | 'crimson_wall_hanging_sign' | 'warped_wall_hanging_sign' | 'bamboo_wall_hanging_sign' | 'lever' | 'stone_pressure_plate' | 'iron_door' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'redstone_ore' | 'deepslate_redstone_ore' | 'redstone_torch' | 'redstone_wall_torch' | 'stone_button' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'sugar_cane' | 'jukebox' | 'oak_fence' | 'pumpkin' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'soul_torch' | 'soul_wall_torch' | 'glowstone' | 'nether_portal' | 'carved_pumpkin' | 'jack_o_lantern' | 'cake' | 'repeater' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'attached_pumpkin_stem' | 'attached_melon_stem' | 'pumpkin_stem' | 'melon_stem' | 'vine' | 'glow_lichen' | 'oak_fence_gate' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'nether_wart' | 'enchanting_table' | 'brewing_stand' | 'cauldron' | 'water_cauldron' | 'lava_cauldron' | 'powder_snow_cauldron' | 'end_portal' | 'end_portal_frame' | 'end_stone' | 'dragon_egg' | 'redstone_lamp' | 'cocoa' | 'sandstone_stairs' | 'emerald_ore' | 'deepslate_emerald_ore' | 'ender_chest' | 'tripwire_hook' | 'tripwire' | 'emerald_block' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'flower_pot' | 'potted_torchflower' | 'potted_oak_sapling' | 'potted_spruce_sapling' | 'potted_birch_sapling' | 'potted_jungle_sapling' | 'potted_acacia_sapling' | 'potted_cherry_sapling' | 'potted_dark_oak_sapling' | 'potted_mangrove_propagule' | 'potted_fern' | 'potted_dandelion' | 'potted_poppy' | 'potted_blue_orchid' | 'potted_allium' | 'potted_azure_bluet' | 'potted_red_tulip' | 'potted_orange_tulip' | 'potted_white_tulip' | 'potted_pink_tulip' | 'potted_oxeye_daisy' | 'potted_cornflower' | 'potted_lily_of_the_valley' | 'potted_wither_rose' | 'potted_red_mushroom' | 'potted_brown_mushroom' | 'potted_dead_bush' | 'potted_cactus' | 'carrots' | 'potatoes' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'skeleton_skull' | 'skeleton_wall_skull' | 'wither_skeleton_skull' | 'wither_skeleton_wall_skull' | 'zombie_head' | 'zombie_wall_head' | 'player_head' | 'player_wall_head' | 'creeper_head' | 'creeper_wall_head' | 'dragon_head' | 'dragon_wall_head' | 'piglin_head' | 'piglin_wall_head' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'trapped_chest' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'comparator' | 'daylight_detector' | 'redstone_block' | 'nether_quartz_ore' | 'hopper' | 'quartz_block' | 'chiseled_quartz_block' | 'quartz_pillar' | 'quartz_stairs' | 'activator_rail' | 'dropper' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'slime_block' | 'barrier' | 'light' | 'iron_trapdoor' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'sea_lantern' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'coal_block' | 'packed_ice' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'white_wall_banner' | 'orange_wall_banner' | 'magenta_wall_banner' | 'light_blue_wall_banner' | 'yellow_wall_banner' | 'lime_wall_banner' | 'pink_wall_banner' | 'gray_wall_banner' | 'light_gray_wall_banner' | 'cyan_wall_banner' | 'purple_wall_banner' | 'blue_wall_banner' | 'brown_wall_banner' | 'green_wall_banner' | 'red_wall_banner' | 'black_wall_banner' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'smooth_stone' | 'smooth_sandstone' | 'smooth_quartz' | 'smooth_red_sandstone' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'end_stone_bricks' | 'torchflower_crop' | 'pitcher_crop' | 'pitcher_plant' | 'beetroots' | 'dirt_path' | 'end_gateway' | 'repeating_command_block' | 'chain_command_block' | 'frosted_ice' | 'magma_block' | 'nether_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'observer' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'kelp' | 'kelp_plant' | 'dried_kelp_block' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'dead_tube_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_wall_fan' | 'dead_brain_coral_wall_fan' | 'dead_bubble_coral_wall_fan' | 'dead_fire_coral_wall_fan' | 'dead_horn_coral_wall_fan' | 'tube_coral_wall_fan' | 'brain_coral_wall_fan' | 'bubble_coral_wall_fan' | 'fire_coral_wall_fan' | 'horn_coral_wall_fan' | 'sea_pickle' | 'blue_ice' | 'conduit' | 'bamboo_sapling' | 'bamboo' | 'potted_bamboo' | 'void_air' | 'cave_air' | 'bubble_column' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'scaffolding' | 'loom' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'lectern' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'campfire' | 'soul_campfire' | 'sweet_berry_bush' | 'warped_stem' | 'stripped_warped_stem' | 'warped_hyphae' | 'stripped_warped_hyphae' | 'warped_nylium' | 'warped_fungus' | 'warped_wart_block' | 'warped_roots' | 'nether_sprouts' | 'crimson_stem' | 'stripped_crimson_stem' | 'crimson_hyphae' | 'stripped_crimson_hyphae' | 'crimson_nylium' | 'crimson_fungus' | 'shroomlight' | 'weeping_vines' | 'weeping_vines_plant' | 'twisting_vines' | 'twisting_vines_plant' | 'crimson_roots' | 'crimson_planks' | 'warped_planks' | 'crimson_slab' | 'warped_slab' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'crimson_fence' | 'warped_fence' | 'crimson_trapdoor' | 'warped_trapdoor' | 'crimson_fence_gate' | 'warped_fence_gate' | 'crimson_stairs' | 'warped_stairs' | 'crimson_button' | 'warped_button' | 'crimson_door' | 'warped_door' | 'crimson_sign' | 'warped_sign' | 'crimson_wall_sign' | 'warped_wall_sign' | 'structure_block' | 'jigsaw' | 'composter' | 'target' | 'bee_nest' | 'beehive' | 'honey_block' | 'honeycomb_block' | 'netherite_block' | 'ancient_debris' | 'crying_obsidian' | 'respawn_anchor' | 'potted_crimson_fungus' | 'potted_warped_fungus' | 'potted_crimson_roots' | 'potted_warped_roots' | 'lodestone' | 'blackstone' | 'blackstone_stairs' | 'blackstone_wall' | 'blackstone_slab' | 'polished_blackstone' | 'polished_blackstone_bricks' | 'cracked_polished_blackstone_bricks' | 'chiseled_polished_blackstone' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'polished_blackstone_brick_wall' | 'gilded_blackstone' | 'polished_blackstone_stairs' | 'polished_blackstone_slab' | 'polished_blackstone_pressure_plate' | 'polished_blackstone_button' | 'polished_blackstone_wall' | 'chiseled_nether_bricks' | 'cracked_nether_bricks' | 'quartz_bricks' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'candle_cake' | 'white_candle_cake' | 'orange_candle_cake' | 'magenta_candle_cake' | 'light_blue_candle_cake' | 'yellow_candle_cake' | 'lime_candle_cake' | 'pink_candle_cake' | 'gray_candle_cake' | 'light_gray_candle_cake' | 'cyan_candle_cake' | 'purple_candle_cake' | 'blue_candle_cake' | 'brown_candle_cake' | 'green_candle_cake' | 'red_candle_cake' | 'black_candle_cake' | 'amethyst_block' | 'budding_amethyst' | 'amethyst_cluster' | 'large_amethyst_bud' | 'medium_amethyst_bud' | 'small_amethyst_bud' | 'tuff' | 'calcite' | 'tinted_glass' | 'powder_snow' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'oxidized_copper' | 'weathered_copper' | 'exposed_copper' | 'copper_block' | 'copper_ore' | 'deepslate_copper_ore' | 'oxidized_cut_copper' | 'weathered_cut_copper' | 'exposed_cut_copper' | 'cut_copper' | 'oxidized_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'cut_copper_stairs' | 'oxidized_cut_copper_slab' | 'weathered_cut_copper_slab' | 'exposed_cut_copper_slab' | 'cut_copper_slab' | 'waxed_copper_block' | 'waxed_weathered_copper' | 'waxed_exposed_copper' | 'waxed_oxidized_copper' | 'waxed_oxidized_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_cut_copper' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_cut_copper_stairs' | 'waxed_oxidized_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_cut_copper_slab' | 'lightning_rod' | 'pointed_dripstone' | 'dripstone_block' | 'cave_vines' | 'cave_vines_plant' | 'spore_blossom' | 'azalea' | 'flowering_azalea' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'big_dripleaf' | 'big_dripleaf_stem' | 'small_dripleaf' | 'hanging_roots' | 'rooted_dirt' | 'mud' | 'deepslate' | 'cobbled_deepslate' | 'cobbled_deepslate_stairs' | 'cobbled_deepslate_slab' | 'cobbled_deepslate_wall' | 'polished_deepslate' | 'polished_deepslate_stairs' | 'polished_deepslate_slab' | 'polished_deepslate_wall' | 'deepslate_tiles' | 'deepslate_tile_stairs' | 'deepslate_tile_slab' | 'deepslate_tile_wall' | 'deepslate_bricks' | 'deepslate_brick_stairs' | 'deepslate_brick_slab' | 'deepslate_brick_wall' | 'chiseled_deepslate' | 'cracked_deepslate_bricks' | 'cracked_deepslate_tiles' | 'infested_deepslate' | 'smooth_basalt' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'potted_azalea_bush' | 'potted_flowering_azalea_bush' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'reinforced_deepslate' | 'decorated_pot'
-export type ItemNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'deepslate' | 'cobbled_deepslate' | 'polished_deepslate' | 'calcite' | 'tuff' | 'dripstone_block' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'rooted_dirt' | 'mud' | 'crimson_nylium' | 'warped_nylium' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'crimson_planks' | 'warped_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'sand' | 'suspicious_sand' | 'suspicious_gravel' | 'red_sand' | 'gravel' | 'coal_ore' | 'deepslate_coal_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'copper_ore' | 'deepslate_copper_ore' | 'gold_ore' | 'deepslate_gold_ore' | 'redstone_ore' | 'deepslate_redstone_ore' | 'emerald_ore' | 'deepslate_emerald_ore' | 'lapis_ore' | 'deepslate_lapis_ore' | 'diamond_ore' | 'deepslate_diamond_ore' | 'nether_gold_ore' | 'nether_quartz_ore' | 'ancient_debris' | 'coal_block' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'amethyst_block' | 'budding_amethyst' | 'iron_block' | 'copper_block' | 'gold_block' | 'diamond_block' | 'netherite_block' | 'exposed_copper' | 'weathered_copper' | 'oxidized_copper' | 'cut_copper' | 'exposed_cut_copper' | 'weathered_cut_copper' | 'oxidized_cut_copper' | 'cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'oxidized_cut_copper_stairs' | 'cut_copper_slab' | 'exposed_cut_copper_slab' | 'weathered_cut_copper_slab' | 'oxidized_cut_copper_slab' | 'waxed_copper_block' | 'waxed_exposed_copper' | 'waxed_weathered_copper' | 'waxed_oxidized_copper' | 'waxed_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_oxidized_cut_copper' | 'waxed_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_oxidized_cut_copper_slab' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'crimson_stem' | 'warped_stem' | 'bamboo_block' | 'stripped_oak_log' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_mangrove_log' | 'stripped_crimson_stem' | 'stripped_warped_stem' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'stripped_crimson_hyphae' | 'stripped_warped_hyphae' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'crimson_hyphae' | 'warped_hyphae' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'tinted_glass' | 'lapis_block' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'cobweb' | 'grass' | 'fern' | 'azalea' | 'flowering_azalea' | 'dead_bush' | 'seagrass' | 'sea_pickle' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'dandelion' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'lily_of_the_valley' | 'wither_rose' | 'torchflower' | 'pitcher_plant' | 'spore_blossom' | 'brown_mushroom' | 'red_mushroom' | 'crimson_fungus' | 'warped_fungus' | 'crimson_roots' | 'warped_roots' | 'nether_sprouts' | 'weeping_vines' | 'twisting_vines' | 'sugar_cane' | 'kelp' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'hanging_roots' | 'big_dripleaf' | 'small_dripleaf' | 'bamboo' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'crimson_slab' | 'warped_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'smooth_quartz' | 'smooth_red_sandstone' | 'smooth_sandstone' | 'smooth_stone' | 'bricks' | 'bookshelf' | 'chiseled_bookshelf' | 'decorated_pot' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'spawner' | 'chest' | 'crafting_table' | 'farmland' | 'furnace' | 'ladder' | 'cobblestone_stairs' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'jukebox' | 'oak_fence' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'crimson_fence' | 'warped_fence' | 'pumpkin' | 'carved_pumpkin' | 'jack_o_lantern' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'smooth_basalt' | 'soul_torch' | 'glowstone' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'infested_deepslate' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'deepslate_bricks' | 'cracked_deepslate_bricks' | 'deepslate_tiles' | 'cracked_deepslate_tiles' | 'chiseled_deepslate' | 'reinforced_deepslate' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'vine' | 'glow_lichen' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'cracked_nether_bricks' | 'chiseled_nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'enchanting_table' | 'end_portal_frame' | 'end_stone' | 'end_stone_bricks' | 'dragon_egg' | 'sandstone_stairs' | 'ender_chest' | 'emerald_block' | 'oak_stairs' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'crimson_stairs' | 'warped_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'blackstone_wall' | 'polished_blackstone_wall' | 'polished_blackstone_brick_wall' | 'cobbled_deepslate_wall' | 'polished_deepslate_wall' | 'deepslate_brick_wall' | 'deepslate_tile_wall' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'chiseled_quartz_block' | 'quartz_block' | 'quartz_bricks' | 'quartz_pillar' | 'quartz_stairs' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'barrier' | 'light' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'packed_ice' | 'dirt_path' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'sea_lantern' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'repeating_command_block' | 'chain_command_block' | 'magma_block' | 'nether_wart_block' | 'warped_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'dead_tube_coral' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'blue_ice' | 'conduit' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'cobbled_deepslate_stairs' | 'polished_deepslate_stairs' | 'deepslate_brick_stairs' | 'deepslate_tile_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'cobbled_deepslate_slab' | 'polished_deepslate_slab' | 'deepslate_brick_slab' | 'deepslate_tile_slab' | 'scaffolding' | 'redstone' | 'redstone_torch' | 'redstone_block' | 'repeater' | 'comparator' | 'piston' | 'sticky_piston' | 'slime_block' | 'honey_block' | 'observer' | 'hopper' | 'dispenser' | 'dropper' | 'lectern' | 'target' | 'lever' | 'lightning_rod' | 'daylight_detector' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'tripwire_hook' | 'trapped_chest' | 'tnt' | 'redstone_lamp' | 'note_block' | 'stone_button' | 'polished_blackstone_button' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'crimson_button' | 'warped_button' | 'stone_pressure_plate' | 'polished_blackstone_pressure_plate' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'iron_door' | 'oak_door' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'crimson_door' | 'warped_door' | 'iron_trapdoor' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'crimson_trapdoor' | 'warped_trapdoor' | 'oak_fence_gate' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'crimson_fence_gate' | 'warped_fence_gate' | 'powered_rail' | 'detector_rail' | 'rail' | 'activator_rail' | 'saddle' | 'minecart' | 'chest_minecart' | 'furnace_minecart' | 'tnt_minecart' | 'hopper_minecart' | 'carrot_on_a_stick' | 'warped_fungus_on_a_stick' | 'elytra' | 'oak_boat' | 'oak_chest_boat' | 'spruce_boat' | 'spruce_chest_boat' | 'birch_boat' | 'birch_chest_boat' | 'jungle_boat' | 'jungle_chest_boat' | 'acacia_boat' | 'acacia_chest_boat' | 'cherry_boat' | 'cherry_chest_boat' | 'dark_oak_boat' | 'dark_oak_chest_boat' | 'mangrove_boat' | 'mangrove_chest_boat' | 'bamboo_raft' | 'bamboo_chest_raft' | 'structure_block' | 'jigsaw' | 'turtle_helmet' | 'scute' | 'flint_and_steel' | 'apple' | 'bow' | 'arrow' | 'coal' | 'charcoal' | 'diamond' | 'emerald' | 'lapis_lazuli' | 'quartz' | 'amethyst_shard' | 'raw_iron' | 'iron_ingot' | 'raw_copper' | 'copper_ingot' | 'raw_gold' | 'gold_ingot' | 'netherite_ingot' | 'netherite_scrap' | 'wooden_sword' | 'wooden_shovel' | 'wooden_pickaxe' | 'wooden_axe' | 'wooden_hoe' | 'stone_sword' | 'stone_shovel' | 'stone_pickaxe' | 'stone_axe' | 'stone_hoe' | 'golden_sword' | 'golden_shovel' | 'golden_pickaxe' | 'golden_axe' | 'golden_hoe' | 'iron_sword' | 'iron_shovel' | 'iron_pickaxe' | 'iron_axe' | 'iron_hoe' | 'diamond_sword' | 'diamond_shovel' | 'diamond_pickaxe' | 'diamond_axe' | 'diamond_hoe' | 'netherite_sword' | 'netherite_shovel' | 'netherite_pickaxe' | 'netherite_axe' | 'netherite_hoe' | 'stick' | 'bowl' | 'mushroom_stew' | 'string' | 'feather' | 'gunpowder' | 'wheat_seeds' | 'wheat' | 'bread' | 'leather_helmet' | 'leather_chestplate' | 'leather_leggings' | 'leather_boots' | 'chainmail_helmet' | 'chainmail_chestplate' | 'chainmail_leggings' | 'chainmail_boots' | 'iron_helmet' | 'iron_chestplate' | 'iron_leggings' | 'iron_boots' | 'diamond_helmet' | 'diamond_chestplate' | 'diamond_leggings' | 'diamond_boots' | 'golden_helmet' | 'golden_chestplate' | 'golden_leggings' | 'golden_boots' | 'netherite_helmet' | 'netherite_chestplate' | 'netherite_leggings' | 'netherite_boots' | 'flint' | 'porkchop' | 'cooked_porkchop' | 'painting' | 'golden_apple' | 'enchanted_golden_apple' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'jungle_sign' | 'acacia_sign' | 'cherry_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'crimson_sign' | 'warped_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'jungle_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'dark_oak_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'bucket' | 'water_bucket' | 'lava_bucket' | 'powder_snow_bucket' | 'snowball' | 'leather' | 'milk_bucket' | 'pufferfish_bucket' | 'salmon_bucket' | 'cod_bucket' | 'tropical_fish_bucket' | 'axolotl_bucket' | 'tadpole_bucket' | 'brick' | 'clay_ball' | 'dried_kelp_block' | 'paper' | 'book' | 'slime_ball' | 'egg' | 'compass' | 'recovery_compass' | 'bundle' | 'fishing_rod' | 'clock' | 'spyglass' | 'glowstone_dust' | 'cod' | 'salmon' | 'tropical_fish' | 'pufferfish' | 'cooked_cod' | 'cooked_salmon' | 'ink_sac' | 'glow_ink_sac' | 'cocoa_beans' | 'white_dye' | 'orange_dye' | 'magenta_dye' | 'light_blue_dye' | 'yellow_dye' | 'lime_dye' | 'pink_dye' | 'gray_dye' | 'light_gray_dye' | 'cyan_dye' | 'purple_dye' | 'blue_dye' | 'brown_dye' | 'green_dye' | 'red_dye' | 'black_dye' | 'bone_meal' | 'bone' | 'sugar' | 'cake' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'cookie' | 'filled_map' | 'shears' | 'melon_slice' | 'dried_kelp' | 'pumpkin_seeds' | 'melon_seeds' | 'beef' | 'cooked_beef' | 'chicken' | 'cooked_chicken' | 'rotten_flesh' | 'ender_pearl' | 'blaze_rod' | 'ghast_tear' | 'gold_nugget' | 'nether_wart' | 'potion' | 'glass_bottle' | 'spider_eye' | 'fermented_spider_eye' | 'blaze_powder' | 'magma_cream' | 'brewing_stand' | 'cauldron' | 'ender_eye' | 'glistering_melon_slice' | 'allay_spawn_egg' | 'axolotl_spawn_egg' | 'bat_spawn_egg' | 'bee_spawn_egg' | 'blaze_spawn_egg' | 'cat_spawn_egg' | 'camel_spawn_egg' | 'cave_spider_spawn_egg' | 'chicken_spawn_egg' | 'cod_spawn_egg' | 'cow_spawn_egg' | 'creeper_spawn_egg' | 'dolphin_spawn_egg' | 'donkey_spawn_egg' | 'drowned_spawn_egg' | 'elder_guardian_spawn_egg' | 'ender_dragon_spawn_egg' | 'enderman_spawn_egg' | 'endermite_spawn_egg' | 'evoker_spawn_egg' | 'fox_spawn_egg' | 'frog_spawn_egg' | 'ghast_spawn_egg' | 'glow_squid_spawn_egg' | 'goat_spawn_egg' | 'guardian_spawn_egg' | 'hoglin_spawn_egg' | 'horse_spawn_egg' | 'husk_spawn_egg' | 'iron_golem_spawn_egg' | 'llama_spawn_egg' | 'magma_cube_spawn_egg' | 'mooshroom_spawn_egg' | 'mule_spawn_egg' | 'ocelot_spawn_egg' | 'panda_spawn_egg' | 'parrot_spawn_egg' | 'phantom_spawn_egg' | 'pig_spawn_egg' | 'piglin_spawn_egg' | 'piglin_brute_spawn_egg' | 'pillager_spawn_egg' | 'polar_bear_spawn_egg' | 'pufferfish_spawn_egg' | 'rabbit_spawn_egg' | 'ravager_spawn_egg' | 'salmon_spawn_egg' | 'sheep_spawn_egg' | 'shulker_spawn_egg' | 'silverfish_spawn_egg' | 'skeleton_spawn_egg' | 'skeleton_horse_spawn_egg' | 'slime_spawn_egg' | 'sniffer_spawn_egg' | 'snow_golem_spawn_egg' | 'spider_spawn_egg' | 'squid_spawn_egg' | 'stray_spawn_egg' | 'strider_spawn_egg' | 'tadpole_spawn_egg' | 'trader_llama_spawn_egg' | 'tropical_fish_spawn_egg' | 'turtle_spawn_egg' | 'vex_spawn_egg' | 'villager_spawn_egg' | 'vindicator_spawn_egg' | 'wandering_trader_spawn_egg' | 'warden_spawn_egg' | 'witch_spawn_egg' | 'wither_spawn_egg' | 'wither_skeleton_spawn_egg' | 'wolf_spawn_egg' | 'zoglin_spawn_egg' | 'zombie_spawn_egg' | 'zombie_horse_spawn_egg' | 'zombie_villager_spawn_egg' | 'zombified_piglin_spawn_egg' | 'experience_bottle' | 'fire_charge' | 'writable_book' | 'written_book' | 'item_frame' | 'glow_item_frame' | 'flower_pot' | 'carrot' | 'potato' | 'baked_potato' | 'poisonous_potato' | 'map' | 'golden_carrot' | 'skeleton_skull' | 'wither_skeleton_skull' | 'player_head' | 'zombie_head' | 'creeper_head' | 'dragon_head' | 'piglin_head' | 'nether_star' | 'pumpkin_pie' | 'firework_rocket' | 'firework_star' | 'enchanted_book' | 'nether_brick' | 'prismarine_shard' | 'prismarine_crystals' | 'rabbit' | 'cooked_rabbit' | 'rabbit_stew' | 'rabbit_foot' | 'rabbit_hide' | 'armor_stand' | 'iron_horse_armor' | 'golden_horse_armor' | 'diamond_horse_armor' | 'leather_horse_armor' | 'lead' | 'name_tag' | 'command_block_minecart' | 'mutton' | 'cooked_mutton' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'end_crystal' | 'chorus_fruit' | 'popped_chorus_fruit' | 'torchflower_seeds' | 'pitcher_pod' | 'beetroot' | 'beetroot_seeds' | 'beetroot_soup' | 'dragon_breath' | 'splash_potion' | 'spectral_arrow' | 'tipped_arrow' | 'lingering_potion' | 'shield' | 'totem_of_undying' | 'shulker_shell' | 'iron_nugget' | 'knowledge_book' | 'debug_stick' | 'music_disc_13' | 'music_disc_cat' | 'music_disc_blocks' | 'music_disc_chirp' | 'music_disc_far' | 'music_disc_mall' | 'music_disc_mellohi' | 'music_disc_stal' | 'music_disc_strad' | 'music_disc_ward' | 'music_disc_11' | 'music_disc_wait' | 'music_disc_otherside' | 'music_disc_relic' | 'music_disc_5' | 'music_disc_pigstep' | 'disc_fragment_5' | 'trident' | 'phantom_membrane' | 'nautilus_shell' | 'heart_of_the_sea' | 'crossbow' | 'suspicious_stew' | 'loom' | 'flower_banner_pattern' | 'creeper_banner_pattern' | 'skull_banner_pattern' | 'mojang_banner_pattern' | 'globe_banner_pattern' | 'piglin_banner_pattern' | 'goat_horn' | 'composter' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'sweet_berries' | 'glow_berries' | 'campfire' | 'soul_campfire' | 'shroomlight' | 'honeycomb' | 'bee_nest' | 'beehive' | 'honey_bottle' | 'honeycomb_block' | 'lodestone' | 'crying_obsidian' | 'blackstone' | 'blackstone_slab' | 'blackstone_stairs' | 'gilded_blackstone' | 'polished_blackstone' | 'polished_blackstone_slab' | 'polished_blackstone_stairs' | 'chiseled_polished_blackstone' | 'polished_blackstone_bricks' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'cracked_polished_blackstone_bricks' | 'respawn_anchor' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'small_amethyst_bud' | 'medium_amethyst_bud' | 'large_amethyst_bud' | 'amethyst_cluster' | 'pointed_dripstone' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'echo_shard' | 'brush' | 'netherite_upgrade_smithing_template' | 'sentry_armor_trim_smithing_template' | 'dune_armor_trim_smithing_template' | 'coast_armor_trim_smithing_template' | 'wild_armor_trim_smithing_template' | 'ward_armor_trim_smithing_template' | 'eye_armor_trim_smithing_template' | 'vex_armor_trim_smithing_template' | 'tide_armor_trim_smithing_template' | 'snout_armor_trim_smithing_template' | 'rib_armor_trim_smithing_template' | 'spire_armor_trim_smithing_template' | 'wayfinder_armor_trim_smithing_template' | 'shaper_armor_trim_smithing_template' | 'silence_armor_trim_smithing_template' | 'raiser_armor_trim_smithing_template' | 'host_armor_trim_smithing_template' | 'angler_pottery_sherd' | 'archer_pottery_sherd' | 'arms_up_pottery_sherd' | 'blade_pottery_sherd' | 'brewer_pottery_sherd' | 'burn_pottery_sherd' | 'danger_pottery_sherd' | 'explorer_pottery_sherd' | 'friend_pottery_sherd' | 'heart_pottery_sherd' | 'heartbreak_pottery_sherd' | 'howl_pottery_sherd' | 'miner_pottery_sherd' | 'mourner_pottery_sherd' | 'plenty_pottery_sherd' | 'prize_pottery_sherd' | 'sheaf_pottery_sherd' | 'shelter_pottery_sherd' | 'skull_pottery_sherd' | 'snort_pottery_sherd'
-export type EntityNames = 'allay' | 'area_effect_cloud' | 'armor_stand' | 'arrow' | 'axolotl' | 'bat' | 'bee' | 'blaze' | 'block_display' | 'boat' | 'camel' | 'cat' | 'cave_spider' | 'chest_boat' | 'chest_minecart' | 'chicken' | 'cod' | 'command_block_minecart' | 'cow' | 'creeper' | 'dolphin' | 'donkey' | 'dragon_fireball' | 'drowned' | 'egg' | 'elder_guardian' | 'end_crystal' | 'ender_dragon' | 'ender_pearl' | 'enderman' | 'endermite' | 'evoker' | 'evoker_fangs' | 'experience_bottle' | 'experience_orb' | 'eye_of_ender' | 'falling_block' | 'firework_rocket' | 'fox' | 'frog' | 'furnace_minecart' | 'ghast' | 'giant' | 'glow_item_frame' | 'glow_squid' | 'goat' | 'guardian' | 'hoglin' | 'hopper_minecart' | 'horse' | 'husk' | 'illusioner' | 'interaction' | 'iron_golem' | 'item' | 'item_display' | 'item_frame' | 'fireball' | 'leash_knot' | 'lightning_bolt' | 'llama' | 'llama_spit' | 'magma_cube' | 'marker' | 'minecart' | 'mooshroom' | 'mule' | 'ocelot' | 'painting' | 'panda' | 'parrot' | 'phantom' | 'pig' | 'piglin' | 'piglin_brute' | 'pillager' | 'polar_bear' | 'potion' | 'pufferfish' | 'rabbit' | 'ravager' | 'salmon' | 'sheep' | 'shulker' | 'shulker_bullet' | 'silverfish' | 'skeleton' | 'skeleton_horse' | 'slime' | 'small_fireball' | 'sniffer' | 'snow_golem' | 'snowball' | 'spawner_minecart' | 'spectral_arrow' | 'spider' | 'squid' | 'stray' | 'strider' | 'tadpole' | 'text_display' | 'tnt' | 'tnt_minecart' | 'trader_llama' | 'trident' | 'tropical_fish' | 'turtle' | 'vex' | 'villager' | 'vindicator' | 'wandering_trader' | 'warden' | 'witch' | 'wither' | 'wither_skeleton' | 'wither_skull' | 'wolf' | 'zoglin' | 'zombie' | 'zombie_horse' | 'zombie_villager' | 'zombified_piglin' | 'player' | 'fishing_bobber'
-export type BiomesNames = 'badlands' | 'bamboo_jungle' | 'basalt_deltas' | 'beach' | 'birch_forest' | 'cherry_grove' | 'cold_ocean' | 'crimson_forest' | 'dark_forest' | 'deep_cold_ocean' | 'deep_dark' | 'deep_frozen_ocean' | 'deep_lukewarm_ocean' | 'deep_ocean' | 'desert' | 'dripstone_caves' | 'end_barrens' | 'end_highlands' | 'end_midlands' | 'eroded_badlands' | 'flower_forest' | 'forest' | 'frozen_ocean' | 'frozen_peaks' | 'frozen_river' | 'grove' | 'ice_spikes' | 'jagged_peaks' | 'jungle' | 'lukewarm_ocean' | 'lush_caves' | 'mangrove_swamp' | 'meadow' | 'mushroom_fields' | 'nether_wastes' | 'ocean' | 'old_growth_birch_forest' | 'old_growth_pine_taiga' | 'old_growth_spruce_taiga' | 'plains' | 'river' | 'savanna' | 'savanna_plateau' | 'small_end_islands' | 'snowy_beach' | 'snowy_plains' | 'snowy_slopes' | 'snowy_taiga' | 'soul_sand_valley' | 'sparse_jungle' | 'stony_peaks' | 'stony_shore' | 'sunflower_plains' | 'swamp' | 'taiga' | 'the_end' | 'the_void' | 'warm_ocean' | 'warped_forest' | 'windswept_forest' | 'windswept_gravelly_hills' | 'windswept_hills' | 'windswept_savanna' | 'wooded_badlands'
-export type EnchantmentNames = 'protection' | 'fire_protection' | 'feather_falling' | 'blast_protection' | 'projectile_protection' | 'respiration' | 'aqua_affinity' | 'thorns' | 'depth_strider' | 'frost_walker' | 'binding_curse' | 'soul_speed' | 'swift_sneak' | 'sharpness' | 'smite' | 'bane_of_arthropods' | 'knockback' | 'fire_aspect' | 'looting' | 'sweeping' | 'efficiency' | 'silk_touch' | 'unbreaking' | 'fortune' | 'power' | 'punch' | 'flame' | 'infinity' | 'luck_of_the_sea' | 'lure' | 'loyalty' | 'impaling' | 'riptide' | 'channeling' | 'multishot' | 'quick_charge' | 'piercing' | 'mending' | 'vanishing_curse'
+export type BlockNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'water' | 'lava' | 'sand' | 'suspicious_sand' | 'red_sand' | 'gravel' | 'suspicious_gravel' | 'gold_ore' | 'deepslate_gold_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'coal_ore' | 'deepslate_coal_ore' | 'nether_gold_ore' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'bamboo_block' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_oak_log' | 'stripped_mangrove_log' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'lapis_ore' | 'deepslate_lapis_ore' | 'lapis_block' | 'dispenser' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'note_block' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'powered_rail' | 'detector_rail' | 'sticky_piston' | 'cobweb' | 'grass' | 'fern' | 'dead_bush' | 'seagrass' | 'tall_seagrass' | 'piston' | 'piston_head' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'moving_piston' | 'dandelion' | 'torchflower' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'wither_rose' | 'lily_of_the_valley' | 'brown_mushroom' | 'red_mushroom' | 'gold_block' | 'iron_block' | 'bricks' | 'tnt' | 'bookshelf' | 'chiseled_bookshelf' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'wall_torch' | 'fire' | 'soul_fire' | 'spawner' | 'oak_stairs' | 'chest' | 'redstone_wire' | 'diamond_ore' | 'deepslate_diamond_ore' | 'diamond_block' | 'crafting_table' | 'wheat' | 'farmland' | 'furnace' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'acacia_sign' | 'cherry_sign' | 'jungle_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'oak_door' | 'ladder' | 'rail' | 'cobblestone_stairs' | 'oak_wall_sign' | 'spruce_wall_sign' | 'birch_wall_sign' | 'acacia_wall_sign' | 'cherry_wall_sign' | 'jungle_wall_sign' | 'dark_oak_wall_sign' | 'mangrove_wall_sign' | 'bamboo_wall_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'jungle_hanging_sign' | 'dark_oak_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'oak_wall_hanging_sign' | 'spruce_wall_hanging_sign' | 'birch_wall_hanging_sign' | 'acacia_wall_hanging_sign' | 'cherry_wall_hanging_sign' | 'jungle_wall_hanging_sign' | 'dark_oak_wall_hanging_sign' | 'mangrove_wall_hanging_sign' | 'crimson_wall_hanging_sign' | 'warped_wall_hanging_sign' | 'bamboo_wall_hanging_sign' | 'lever' | 'stone_pressure_plate' | 'iron_door' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'redstone_ore' | 'deepslate_redstone_ore' | 'redstone_torch' | 'redstone_wall_torch' | 'stone_button' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'sugar_cane' | 'jukebox' | 'oak_fence' | 'pumpkin' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'soul_torch' | 'soul_wall_torch' | 'glowstone' | 'nether_portal' | 'carved_pumpkin' | 'jack_o_lantern' | 'cake' | 'repeater' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'attached_pumpkin_stem' | 'attached_melon_stem' | 'pumpkin_stem' | 'melon_stem' | 'vine' | 'glow_lichen' | 'oak_fence_gate' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'nether_wart' | 'enchanting_table' | 'brewing_stand' | 'cauldron' | 'water_cauldron' | 'lava_cauldron' | 'powder_snow_cauldron' | 'end_portal' | 'end_portal_frame' | 'end_stone' | 'dragon_egg' | 'redstone_lamp' | 'cocoa' | 'sandstone_stairs' | 'emerald_ore' | 'deepslate_emerald_ore' | 'ender_chest' | 'tripwire_hook' | 'tripwire' | 'emerald_block' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'flower_pot' | 'potted_torchflower' | 'potted_oak_sapling' | 'potted_spruce_sapling' | 'potted_birch_sapling' | 'potted_jungle_sapling' | 'potted_acacia_sapling' | 'potted_cherry_sapling' | 'potted_dark_oak_sapling' | 'potted_mangrove_propagule' | 'potted_fern' | 'potted_dandelion' | 'potted_poppy' | 'potted_blue_orchid' | 'potted_allium' | 'potted_azure_bluet' | 'potted_red_tulip' | 'potted_orange_tulip' | 'potted_white_tulip' | 'potted_pink_tulip' | 'potted_oxeye_daisy' | 'potted_cornflower' | 'potted_lily_of_the_valley' | 'potted_wither_rose' | 'potted_red_mushroom' | 'potted_brown_mushroom' | 'potted_dead_bush' | 'potted_cactus' | 'carrots' | 'potatoes' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'skeleton_skull' | 'skeleton_wall_skull' | 'wither_skeleton_skull' | 'wither_skeleton_wall_skull' | 'zombie_head' | 'zombie_wall_head' | 'player_head' | 'player_wall_head' | 'creeper_head' | 'creeper_wall_head' | 'dragon_head' | 'dragon_wall_head' | 'piglin_head' | 'piglin_wall_head' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'trapped_chest' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'comparator' | 'daylight_detector' | 'redstone_block' | 'nether_quartz_ore' | 'hopper' | 'quartz_block' | 'chiseled_quartz_block' | 'quartz_pillar' | 'quartz_stairs' | 'activator_rail' | 'dropper' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'slime_block' | 'barrier' | 'light' | 'iron_trapdoor' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'sea_lantern' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'coal_block' | 'packed_ice' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'white_wall_banner' | 'orange_wall_banner' | 'magenta_wall_banner' | 'light_blue_wall_banner' | 'yellow_wall_banner' | 'lime_wall_banner' | 'pink_wall_banner' | 'gray_wall_banner' | 'light_gray_wall_banner' | 'cyan_wall_banner' | 'purple_wall_banner' | 'blue_wall_banner' | 'brown_wall_banner' | 'green_wall_banner' | 'red_wall_banner' | 'black_wall_banner' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'smooth_stone' | 'smooth_sandstone' | 'smooth_quartz' | 'smooth_red_sandstone' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'end_stone_bricks' | 'torchflower_crop' | 'pitcher_crop' | 'pitcher_plant' | 'beetroots' | 'dirt_path' | 'end_gateway' | 'repeating_command_block' | 'chain_command_block' | 'frosted_ice' | 'magma_block' | 'nether_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'observer' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'kelp' | 'kelp_plant' | 'dried_kelp_block' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'dead_tube_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_wall_fan' | 'dead_brain_coral_wall_fan' | 'dead_bubble_coral_wall_fan' | 'dead_fire_coral_wall_fan' | 'dead_horn_coral_wall_fan' | 'tube_coral_wall_fan' | 'brain_coral_wall_fan' | 'bubble_coral_wall_fan' | 'fire_coral_wall_fan' | 'horn_coral_wall_fan' | 'sea_pickle' | 'blue_ice' | 'conduit' | 'bamboo_sapling' | 'bamboo' | 'potted_bamboo' | 'void_air' | 'cave_air' | 'bubble_column' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'scaffolding' | 'loom' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'lectern' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'campfire' | 'soul_campfire' | 'sweet_berry_bush' | 'warped_stem' | 'stripped_warped_stem' | 'warped_hyphae' | 'stripped_warped_hyphae' | 'warped_nylium' | 'warped_fungus' | 'warped_wart_block' | 'warped_roots' | 'nether_sprouts' | 'crimson_stem' | 'stripped_crimson_stem' | 'crimson_hyphae' | 'stripped_crimson_hyphae' | 'crimson_nylium' | 'crimson_fungus' | 'shroomlight' | 'weeping_vines' | 'weeping_vines_plant' | 'twisting_vines' | 'twisting_vines_plant' | 'crimson_roots' | 'crimson_planks' | 'warped_planks' | 'crimson_slab' | 'warped_slab' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'crimson_fence' | 'warped_fence' | 'crimson_trapdoor' | 'warped_trapdoor' | 'crimson_fence_gate' | 'warped_fence_gate' | 'crimson_stairs' | 'warped_stairs' | 'crimson_button' | 'warped_button' | 'crimson_door' | 'warped_door' | 'crimson_sign' | 'warped_sign' | 'crimson_wall_sign' | 'warped_wall_sign' | 'structure_block' | 'jigsaw' | 'composter' | 'target' | 'bee_nest' | 'beehive' | 'honey_block' | 'honeycomb_block' | 'netherite_block' | 'ancient_debris' | 'crying_obsidian' | 'respawn_anchor' | 'potted_crimson_fungus' | 'potted_warped_fungus' | 'potted_crimson_roots' | 'potted_warped_roots' | 'lodestone' | 'blackstone' | 'blackstone_stairs' | 'blackstone_wall' | 'blackstone_slab' | 'polished_blackstone' | 'polished_blackstone_bricks' | 'cracked_polished_blackstone_bricks' | 'chiseled_polished_blackstone' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'polished_blackstone_brick_wall' | 'gilded_blackstone' | 'polished_blackstone_stairs' | 'polished_blackstone_slab' | 'polished_blackstone_pressure_plate' | 'polished_blackstone_button' | 'polished_blackstone_wall' | 'chiseled_nether_bricks' | 'cracked_nether_bricks' | 'quartz_bricks' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'candle_cake' | 'white_candle_cake' | 'orange_candle_cake' | 'magenta_candle_cake' | 'light_blue_candle_cake' | 'yellow_candle_cake' | 'lime_candle_cake' | 'pink_candle_cake' | 'gray_candle_cake' | 'light_gray_candle_cake' | 'cyan_candle_cake' | 'purple_candle_cake' | 'blue_candle_cake' | 'brown_candle_cake' | 'green_candle_cake' | 'red_candle_cake' | 'black_candle_cake' | 'amethyst_block' | 'budding_amethyst' | 'amethyst_cluster' | 'large_amethyst_bud' | 'medium_amethyst_bud' | 'small_amethyst_bud' | 'tuff' | 'calcite' | 'tinted_glass' | 'powder_snow' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'oxidized_copper' | 'weathered_copper' | 'exposed_copper' | 'copper_block' | 'copper_ore' | 'deepslate_copper_ore' | 'oxidized_cut_copper' | 'weathered_cut_copper' | 'exposed_cut_copper' | 'cut_copper' | 'oxidized_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'cut_copper_stairs' | 'oxidized_cut_copper_slab' | 'weathered_cut_copper_slab' | 'exposed_cut_copper_slab' | 'cut_copper_slab' | 'waxed_copper_block' | 'waxed_weathered_copper' | 'waxed_exposed_copper' | 'waxed_oxidized_copper' | 'waxed_oxidized_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_cut_copper' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_cut_copper_stairs' | 'waxed_oxidized_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_cut_copper_slab' | 'lightning_rod' | 'pointed_dripstone' | 'dripstone_block' | 'cave_vines' | 'cave_vines_plant' | 'spore_blossom' | 'azalea' | 'flowering_azalea' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'big_dripleaf' | 'big_dripleaf_stem' | 'small_dripleaf' | 'hanging_roots' | 'rooted_dirt' | 'mud' | 'deepslate' | 'cobbled_deepslate' | 'cobbled_deepslate_stairs' | 'cobbled_deepslate_slab' | 'cobbled_deepslate_wall' | 'polished_deepslate' | 'polished_deepslate_stairs' | 'polished_deepslate_slab' | 'polished_deepslate_wall' | 'deepslate_tiles' | 'deepslate_tile_stairs' | 'deepslate_tile_slab' | 'deepslate_tile_wall' | 'deepslate_bricks' | 'deepslate_brick_stairs' | 'deepslate_brick_slab' | 'deepslate_brick_wall' | 'chiseled_deepslate' | 'cracked_deepslate_bricks' | 'cracked_deepslate_tiles' | 'infested_deepslate' | 'smooth_basalt' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'potted_azalea_bush' | 'potted_flowering_azalea_bush' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'reinforced_deepslate' | 'decorated_pot';
+export type ItemNames = 'air' | 'stone' | 'granite' | 'polished_granite' | 'diorite' | 'polished_diorite' | 'andesite' | 'polished_andesite' | 'deepslate' | 'cobbled_deepslate' | 'polished_deepslate' | 'calcite' | 'tuff' | 'dripstone_block' | 'grass_block' | 'dirt' | 'coarse_dirt' | 'podzol' | 'rooted_dirt' | 'mud' | 'crimson_nylium' | 'warped_nylium' | 'cobblestone' | 'oak_planks' | 'spruce_planks' | 'birch_planks' | 'jungle_planks' | 'acacia_planks' | 'cherry_planks' | 'dark_oak_planks' | 'mangrove_planks' | 'bamboo_planks' | 'crimson_planks' | 'warped_planks' | 'bamboo_mosaic' | 'oak_sapling' | 'spruce_sapling' | 'birch_sapling' | 'jungle_sapling' | 'acacia_sapling' | 'cherry_sapling' | 'dark_oak_sapling' | 'mangrove_propagule' | 'bedrock' | 'sand' | 'suspicious_sand' | 'suspicious_gravel' | 'red_sand' | 'gravel' | 'coal_ore' | 'deepslate_coal_ore' | 'iron_ore' | 'deepslate_iron_ore' | 'copper_ore' | 'deepslate_copper_ore' | 'gold_ore' | 'deepslate_gold_ore' | 'redstone_ore' | 'deepslate_redstone_ore' | 'emerald_ore' | 'deepslate_emerald_ore' | 'lapis_ore' | 'deepslate_lapis_ore' | 'diamond_ore' | 'deepslate_diamond_ore' | 'nether_gold_ore' | 'nether_quartz_ore' | 'ancient_debris' | 'coal_block' | 'raw_iron_block' | 'raw_copper_block' | 'raw_gold_block' | 'amethyst_block' | 'budding_amethyst' | 'iron_block' | 'copper_block' | 'gold_block' | 'diamond_block' | 'netherite_block' | 'exposed_copper' | 'weathered_copper' | 'oxidized_copper' | 'cut_copper' | 'exposed_cut_copper' | 'weathered_cut_copper' | 'oxidized_cut_copper' | 'cut_copper_stairs' | 'exposed_cut_copper_stairs' | 'weathered_cut_copper_stairs' | 'oxidized_cut_copper_stairs' | 'cut_copper_slab' | 'exposed_cut_copper_slab' | 'weathered_cut_copper_slab' | 'oxidized_cut_copper_slab' | 'waxed_copper_block' | 'waxed_exposed_copper' | 'waxed_weathered_copper' | 'waxed_oxidized_copper' | 'waxed_cut_copper' | 'waxed_exposed_cut_copper' | 'waxed_weathered_cut_copper' | 'waxed_oxidized_cut_copper' | 'waxed_cut_copper_stairs' | 'waxed_exposed_cut_copper_stairs' | 'waxed_weathered_cut_copper_stairs' | 'waxed_oxidized_cut_copper_stairs' | 'waxed_cut_copper_slab' | 'waxed_exposed_cut_copper_slab' | 'waxed_weathered_cut_copper_slab' | 'waxed_oxidized_cut_copper_slab' | 'oak_log' | 'spruce_log' | 'birch_log' | 'jungle_log' | 'acacia_log' | 'cherry_log' | 'dark_oak_log' | 'mangrove_log' | 'mangrove_roots' | 'muddy_mangrove_roots' | 'crimson_stem' | 'warped_stem' | 'bamboo_block' | 'stripped_oak_log' | 'stripped_spruce_log' | 'stripped_birch_log' | 'stripped_jungle_log' | 'stripped_acacia_log' | 'stripped_cherry_log' | 'stripped_dark_oak_log' | 'stripped_mangrove_log' | 'stripped_crimson_stem' | 'stripped_warped_stem' | 'stripped_oak_wood' | 'stripped_spruce_wood' | 'stripped_birch_wood' | 'stripped_jungle_wood' | 'stripped_acacia_wood' | 'stripped_cherry_wood' | 'stripped_dark_oak_wood' | 'stripped_mangrove_wood' | 'stripped_crimson_hyphae' | 'stripped_warped_hyphae' | 'stripped_bamboo_block' | 'oak_wood' | 'spruce_wood' | 'birch_wood' | 'jungle_wood' | 'acacia_wood' | 'cherry_wood' | 'dark_oak_wood' | 'mangrove_wood' | 'crimson_hyphae' | 'warped_hyphae' | 'oak_leaves' | 'spruce_leaves' | 'birch_leaves' | 'jungle_leaves' | 'acacia_leaves' | 'cherry_leaves' | 'dark_oak_leaves' | 'mangrove_leaves' | 'azalea_leaves' | 'flowering_azalea_leaves' | 'sponge' | 'wet_sponge' | 'glass' | 'tinted_glass' | 'lapis_block' | 'sandstone' | 'chiseled_sandstone' | 'cut_sandstone' | 'cobweb' | 'grass' | 'fern' | 'azalea' | 'flowering_azalea' | 'dead_bush' | 'seagrass' | 'sea_pickle' | 'white_wool' | 'orange_wool' | 'magenta_wool' | 'light_blue_wool' | 'yellow_wool' | 'lime_wool' | 'pink_wool' | 'gray_wool' | 'light_gray_wool' | 'cyan_wool' | 'purple_wool' | 'blue_wool' | 'brown_wool' | 'green_wool' | 'red_wool' | 'black_wool' | 'dandelion' | 'poppy' | 'blue_orchid' | 'allium' | 'azure_bluet' | 'red_tulip' | 'orange_tulip' | 'white_tulip' | 'pink_tulip' | 'oxeye_daisy' | 'cornflower' | 'lily_of_the_valley' | 'wither_rose' | 'torchflower' | 'pitcher_plant' | 'spore_blossom' | 'brown_mushroom' | 'red_mushroom' | 'crimson_fungus' | 'warped_fungus' | 'crimson_roots' | 'warped_roots' | 'nether_sprouts' | 'weeping_vines' | 'twisting_vines' | 'sugar_cane' | 'kelp' | 'moss_carpet' | 'pink_petals' | 'moss_block' | 'hanging_roots' | 'big_dripleaf' | 'small_dripleaf' | 'bamboo' | 'oak_slab' | 'spruce_slab' | 'birch_slab' | 'jungle_slab' | 'acacia_slab' | 'cherry_slab' | 'dark_oak_slab' | 'mangrove_slab' | 'bamboo_slab' | 'bamboo_mosaic_slab' | 'crimson_slab' | 'warped_slab' | 'stone_slab' | 'smooth_stone_slab' | 'sandstone_slab' | 'cut_sandstone_slab' | 'petrified_oak_slab' | 'cobblestone_slab' | 'brick_slab' | 'stone_brick_slab' | 'mud_brick_slab' | 'nether_brick_slab' | 'quartz_slab' | 'red_sandstone_slab' | 'cut_red_sandstone_slab' | 'purpur_slab' | 'prismarine_slab' | 'prismarine_brick_slab' | 'dark_prismarine_slab' | 'smooth_quartz' | 'smooth_red_sandstone' | 'smooth_sandstone' | 'smooth_stone' | 'bricks' | 'bookshelf' | 'chiseled_bookshelf' | 'decorated_pot' | 'mossy_cobblestone' | 'obsidian' | 'torch' | 'end_rod' | 'chorus_plant' | 'chorus_flower' | 'purpur_block' | 'purpur_pillar' | 'purpur_stairs' | 'spawner' | 'chest' | 'crafting_table' | 'farmland' | 'furnace' | 'ladder' | 'cobblestone_stairs' | 'snow' | 'ice' | 'snow_block' | 'cactus' | 'clay' | 'jukebox' | 'oak_fence' | 'spruce_fence' | 'birch_fence' | 'jungle_fence' | 'acacia_fence' | 'cherry_fence' | 'dark_oak_fence' | 'mangrove_fence' | 'bamboo_fence' | 'crimson_fence' | 'warped_fence' | 'pumpkin' | 'carved_pumpkin' | 'jack_o_lantern' | 'netherrack' | 'soul_sand' | 'soul_soil' | 'basalt' | 'polished_basalt' | 'smooth_basalt' | 'soul_torch' | 'glowstone' | 'infested_stone' | 'infested_cobblestone' | 'infested_stone_bricks' | 'infested_mossy_stone_bricks' | 'infested_cracked_stone_bricks' | 'infested_chiseled_stone_bricks' | 'infested_deepslate' | 'stone_bricks' | 'mossy_stone_bricks' | 'cracked_stone_bricks' | 'chiseled_stone_bricks' | 'packed_mud' | 'mud_bricks' | 'deepslate_bricks' | 'cracked_deepslate_bricks' | 'deepslate_tiles' | 'cracked_deepslate_tiles' | 'chiseled_deepslate' | 'reinforced_deepslate' | 'brown_mushroom_block' | 'red_mushroom_block' | 'mushroom_stem' | 'iron_bars' | 'chain' | 'glass_pane' | 'melon' | 'vine' | 'glow_lichen' | 'brick_stairs' | 'stone_brick_stairs' | 'mud_brick_stairs' | 'mycelium' | 'lily_pad' | 'nether_bricks' | 'cracked_nether_bricks' | 'chiseled_nether_bricks' | 'nether_brick_fence' | 'nether_brick_stairs' | 'sculk' | 'sculk_vein' | 'sculk_catalyst' | 'sculk_shrieker' | 'enchanting_table' | 'end_portal_frame' | 'end_stone' | 'end_stone_bricks' | 'dragon_egg' | 'sandstone_stairs' | 'ender_chest' | 'emerald_block' | 'oak_stairs' | 'spruce_stairs' | 'birch_stairs' | 'jungle_stairs' | 'acacia_stairs' | 'cherry_stairs' | 'dark_oak_stairs' | 'mangrove_stairs' | 'bamboo_stairs' | 'bamboo_mosaic_stairs' | 'crimson_stairs' | 'warped_stairs' | 'command_block' | 'beacon' | 'cobblestone_wall' | 'mossy_cobblestone_wall' | 'brick_wall' | 'prismarine_wall' | 'red_sandstone_wall' | 'mossy_stone_brick_wall' | 'granite_wall' | 'stone_brick_wall' | 'mud_brick_wall' | 'nether_brick_wall' | 'andesite_wall' | 'red_nether_brick_wall' | 'sandstone_wall' | 'end_stone_brick_wall' | 'diorite_wall' | 'blackstone_wall' | 'polished_blackstone_wall' | 'polished_blackstone_brick_wall' | 'cobbled_deepslate_wall' | 'polished_deepslate_wall' | 'deepslate_brick_wall' | 'deepslate_tile_wall' | 'anvil' | 'chipped_anvil' | 'damaged_anvil' | 'chiseled_quartz_block' | 'quartz_block' | 'quartz_bricks' | 'quartz_pillar' | 'quartz_stairs' | 'white_terracotta' | 'orange_terracotta' | 'magenta_terracotta' | 'light_blue_terracotta' | 'yellow_terracotta' | 'lime_terracotta' | 'pink_terracotta' | 'gray_terracotta' | 'light_gray_terracotta' | 'cyan_terracotta' | 'purple_terracotta' | 'blue_terracotta' | 'brown_terracotta' | 'green_terracotta' | 'red_terracotta' | 'black_terracotta' | 'barrier' | 'light' | 'hay_block' | 'white_carpet' | 'orange_carpet' | 'magenta_carpet' | 'light_blue_carpet' | 'yellow_carpet' | 'lime_carpet' | 'pink_carpet' | 'gray_carpet' | 'light_gray_carpet' | 'cyan_carpet' | 'purple_carpet' | 'blue_carpet' | 'brown_carpet' | 'green_carpet' | 'red_carpet' | 'black_carpet' | 'terracotta' | 'packed_ice' | 'dirt_path' | 'sunflower' | 'lilac' | 'rose_bush' | 'peony' | 'tall_grass' | 'large_fern' | 'white_stained_glass' | 'orange_stained_glass' | 'magenta_stained_glass' | 'light_blue_stained_glass' | 'yellow_stained_glass' | 'lime_stained_glass' | 'pink_stained_glass' | 'gray_stained_glass' | 'light_gray_stained_glass' | 'cyan_stained_glass' | 'purple_stained_glass' | 'blue_stained_glass' | 'brown_stained_glass' | 'green_stained_glass' | 'red_stained_glass' | 'black_stained_glass' | 'white_stained_glass_pane' | 'orange_stained_glass_pane' | 'magenta_stained_glass_pane' | 'light_blue_stained_glass_pane' | 'yellow_stained_glass_pane' | 'lime_stained_glass_pane' | 'pink_stained_glass_pane' | 'gray_stained_glass_pane' | 'light_gray_stained_glass_pane' | 'cyan_stained_glass_pane' | 'purple_stained_glass_pane' | 'blue_stained_glass_pane' | 'brown_stained_glass_pane' | 'green_stained_glass_pane' | 'red_stained_glass_pane' | 'black_stained_glass_pane' | 'prismarine' | 'prismarine_bricks' | 'dark_prismarine' | 'prismarine_stairs' | 'prismarine_brick_stairs' | 'dark_prismarine_stairs' | 'sea_lantern' | 'red_sandstone' | 'chiseled_red_sandstone' | 'cut_red_sandstone' | 'red_sandstone_stairs' | 'repeating_command_block' | 'chain_command_block' | 'magma_block' | 'nether_wart_block' | 'warped_wart_block' | 'red_nether_bricks' | 'bone_block' | 'structure_void' | 'shulker_box' | 'white_shulker_box' | 'orange_shulker_box' | 'magenta_shulker_box' | 'light_blue_shulker_box' | 'yellow_shulker_box' | 'lime_shulker_box' | 'pink_shulker_box' | 'gray_shulker_box' | 'light_gray_shulker_box' | 'cyan_shulker_box' | 'purple_shulker_box' | 'blue_shulker_box' | 'brown_shulker_box' | 'green_shulker_box' | 'red_shulker_box' | 'black_shulker_box' | 'white_glazed_terracotta' | 'orange_glazed_terracotta' | 'magenta_glazed_terracotta' | 'light_blue_glazed_terracotta' | 'yellow_glazed_terracotta' | 'lime_glazed_terracotta' | 'pink_glazed_terracotta' | 'gray_glazed_terracotta' | 'light_gray_glazed_terracotta' | 'cyan_glazed_terracotta' | 'purple_glazed_terracotta' | 'blue_glazed_terracotta' | 'brown_glazed_terracotta' | 'green_glazed_terracotta' | 'red_glazed_terracotta' | 'black_glazed_terracotta' | 'white_concrete' | 'orange_concrete' | 'magenta_concrete' | 'light_blue_concrete' | 'yellow_concrete' | 'lime_concrete' | 'pink_concrete' | 'gray_concrete' | 'light_gray_concrete' | 'cyan_concrete' | 'purple_concrete' | 'blue_concrete' | 'brown_concrete' | 'green_concrete' | 'red_concrete' | 'black_concrete' | 'white_concrete_powder' | 'orange_concrete_powder' | 'magenta_concrete_powder' | 'light_blue_concrete_powder' | 'yellow_concrete_powder' | 'lime_concrete_powder' | 'pink_concrete_powder' | 'gray_concrete_powder' | 'light_gray_concrete_powder' | 'cyan_concrete_powder' | 'purple_concrete_powder' | 'blue_concrete_powder' | 'brown_concrete_powder' | 'green_concrete_powder' | 'red_concrete_powder' | 'black_concrete_powder' | 'turtle_egg' | 'sniffer_egg' | 'dead_tube_coral_block' | 'dead_brain_coral_block' | 'dead_bubble_coral_block' | 'dead_fire_coral_block' | 'dead_horn_coral_block' | 'tube_coral_block' | 'brain_coral_block' | 'bubble_coral_block' | 'fire_coral_block' | 'horn_coral_block' | 'tube_coral' | 'brain_coral' | 'bubble_coral' | 'fire_coral' | 'horn_coral' | 'dead_brain_coral' | 'dead_bubble_coral' | 'dead_fire_coral' | 'dead_horn_coral' | 'dead_tube_coral' | 'tube_coral_fan' | 'brain_coral_fan' | 'bubble_coral_fan' | 'fire_coral_fan' | 'horn_coral_fan' | 'dead_tube_coral_fan' | 'dead_brain_coral_fan' | 'dead_bubble_coral_fan' | 'dead_fire_coral_fan' | 'dead_horn_coral_fan' | 'blue_ice' | 'conduit' | 'polished_granite_stairs' | 'smooth_red_sandstone_stairs' | 'mossy_stone_brick_stairs' | 'polished_diorite_stairs' | 'mossy_cobblestone_stairs' | 'end_stone_brick_stairs' | 'stone_stairs' | 'smooth_sandstone_stairs' | 'smooth_quartz_stairs' | 'granite_stairs' | 'andesite_stairs' | 'red_nether_brick_stairs' | 'polished_andesite_stairs' | 'diorite_stairs' | 'cobbled_deepslate_stairs' | 'polished_deepslate_stairs' | 'deepslate_brick_stairs' | 'deepslate_tile_stairs' | 'polished_granite_slab' | 'smooth_red_sandstone_slab' | 'mossy_stone_brick_slab' | 'polished_diorite_slab' | 'mossy_cobblestone_slab' | 'end_stone_brick_slab' | 'smooth_sandstone_slab' | 'smooth_quartz_slab' | 'granite_slab' | 'andesite_slab' | 'red_nether_brick_slab' | 'polished_andesite_slab' | 'diorite_slab' | 'cobbled_deepslate_slab' | 'polished_deepslate_slab' | 'deepslate_brick_slab' | 'deepslate_tile_slab' | 'scaffolding' | 'redstone' | 'redstone_torch' | 'redstone_block' | 'repeater' | 'comparator' | 'piston' | 'sticky_piston' | 'slime_block' | 'honey_block' | 'observer' | 'hopper' | 'dispenser' | 'dropper' | 'lectern' | 'target' | 'lever' | 'lightning_rod' | 'daylight_detector' | 'sculk_sensor' | 'calibrated_sculk_sensor' | 'tripwire_hook' | 'trapped_chest' | 'tnt' | 'redstone_lamp' | 'note_block' | 'stone_button' | 'polished_blackstone_button' | 'oak_button' | 'spruce_button' | 'birch_button' | 'jungle_button' | 'acacia_button' | 'cherry_button' | 'dark_oak_button' | 'mangrove_button' | 'bamboo_button' | 'crimson_button' | 'warped_button' | 'stone_pressure_plate' | 'polished_blackstone_pressure_plate' | 'light_weighted_pressure_plate' | 'heavy_weighted_pressure_plate' | 'oak_pressure_plate' | 'spruce_pressure_plate' | 'birch_pressure_plate' | 'jungle_pressure_plate' | 'acacia_pressure_plate' | 'cherry_pressure_plate' | 'dark_oak_pressure_plate' | 'mangrove_pressure_plate' | 'bamboo_pressure_plate' | 'crimson_pressure_plate' | 'warped_pressure_plate' | 'iron_door' | 'oak_door' | 'spruce_door' | 'birch_door' | 'jungle_door' | 'acacia_door' | 'cherry_door' | 'dark_oak_door' | 'mangrove_door' | 'bamboo_door' | 'crimson_door' | 'warped_door' | 'iron_trapdoor' | 'oak_trapdoor' | 'spruce_trapdoor' | 'birch_trapdoor' | 'jungle_trapdoor' | 'acacia_trapdoor' | 'cherry_trapdoor' | 'dark_oak_trapdoor' | 'mangrove_trapdoor' | 'bamboo_trapdoor' | 'crimson_trapdoor' | 'warped_trapdoor' | 'oak_fence_gate' | 'spruce_fence_gate' | 'birch_fence_gate' | 'jungle_fence_gate' | 'acacia_fence_gate' | 'cherry_fence_gate' | 'dark_oak_fence_gate' | 'mangrove_fence_gate' | 'bamboo_fence_gate' | 'crimson_fence_gate' | 'warped_fence_gate' | 'powered_rail' | 'detector_rail' | 'rail' | 'activator_rail' | 'saddle' | 'minecart' | 'chest_minecart' | 'furnace_minecart' | 'tnt_minecart' | 'hopper_minecart' | 'carrot_on_a_stick' | 'warped_fungus_on_a_stick' | 'elytra' | 'oak_boat' | 'oak_chest_boat' | 'spruce_boat' | 'spruce_chest_boat' | 'birch_boat' | 'birch_chest_boat' | 'jungle_boat' | 'jungle_chest_boat' | 'acacia_boat' | 'acacia_chest_boat' | 'cherry_boat' | 'cherry_chest_boat' | 'dark_oak_boat' | 'dark_oak_chest_boat' | 'mangrove_boat' | 'mangrove_chest_boat' | 'bamboo_raft' | 'bamboo_chest_raft' | 'structure_block' | 'jigsaw' | 'turtle_helmet' | 'scute' | 'flint_and_steel' | 'apple' | 'bow' | 'arrow' | 'coal' | 'charcoal' | 'diamond' | 'emerald' | 'lapis_lazuli' | 'quartz' | 'amethyst_shard' | 'raw_iron' | 'iron_ingot' | 'raw_copper' | 'copper_ingot' | 'raw_gold' | 'gold_ingot' | 'netherite_ingot' | 'netherite_scrap' | 'wooden_sword' | 'wooden_shovel' | 'wooden_pickaxe' | 'wooden_axe' | 'wooden_hoe' | 'stone_sword' | 'stone_shovel' | 'stone_pickaxe' | 'stone_axe' | 'stone_hoe' | 'golden_sword' | 'golden_shovel' | 'golden_pickaxe' | 'golden_axe' | 'golden_hoe' | 'iron_sword' | 'iron_shovel' | 'iron_pickaxe' | 'iron_axe' | 'iron_hoe' | 'diamond_sword' | 'diamond_shovel' | 'diamond_pickaxe' | 'diamond_axe' | 'diamond_hoe' | 'netherite_sword' | 'netherite_shovel' | 'netherite_pickaxe' | 'netherite_axe' | 'netherite_hoe' | 'stick' | 'bowl' | 'mushroom_stew' | 'string' | 'feather' | 'gunpowder' | 'wheat_seeds' | 'wheat' | 'bread' | 'leather_helmet' | 'leather_chestplate' | 'leather_leggings' | 'leather_boots' | 'chainmail_helmet' | 'chainmail_chestplate' | 'chainmail_leggings' | 'chainmail_boots' | 'iron_helmet' | 'iron_chestplate' | 'iron_leggings' | 'iron_boots' | 'diamond_helmet' | 'diamond_chestplate' | 'diamond_leggings' | 'diamond_boots' | 'golden_helmet' | 'golden_chestplate' | 'golden_leggings' | 'golden_boots' | 'netherite_helmet' | 'netherite_chestplate' | 'netherite_leggings' | 'netherite_boots' | 'flint' | 'porkchop' | 'cooked_porkchop' | 'painting' | 'golden_apple' | 'enchanted_golden_apple' | 'oak_sign' | 'spruce_sign' | 'birch_sign' | 'jungle_sign' | 'acacia_sign' | 'cherry_sign' | 'dark_oak_sign' | 'mangrove_sign' | 'bamboo_sign' | 'crimson_sign' | 'warped_sign' | 'oak_hanging_sign' | 'spruce_hanging_sign' | 'birch_hanging_sign' | 'jungle_hanging_sign' | 'acacia_hanging_sign' | 'cherry_hanging_sign' | 'dark_oak_hanging_sign' | 'mangrove_hanging_sign' | 'bamboo_hanging_sign' | 'crimson_hanging_sign' | 'warped_hanging_sign' | 'bucket' | 'water_bucket' | 'lava_bucket' | 'powder_snow_bucket' | 'snowball' | 'leather' | 'milk_bucket' | 'pufferfish_bucket' | 'salmon_bucket' | 'cod_bucket' | 'tropical_fish_bucket' | 'axolotl_bucket' | 'tadpole_bucket' | 'brick' | 'clay_ball' | 'dried_kelp_block' | 'paper' | 'book' | 'slime_ball' | 'egg' | 'compass' | 'recovery_compass' | 'bundle' | 'fishing_rod' | 'clock' | 'spyglass' | 'glowstone_dust' | 'cod' | 'salmon' | 'tropical_fish' | 'pufferfish' | 'cooked_cod' | 'cooked_salmon' | 'ink_sac' | 'glow_ink_sac' | 'cocoa_beans' | 'white_dye' | 'orange_dye' | 'magenta_dye' | 'light_blue_dye' | 'yellow_dye' | 'lime_dye' | 'pink_dye' | 'gray_dye' | 'light_gray_dye' | 'cyan_dye' | 'purple_dye' | 'blue_dye' | 'brown_dye' | 'green_dye' | 'red_dye' | 'black_dye' | 'bone_meal' | 'bone' | 'sugar' | 'cake' | 'white_bed' | 'orange_bed' | 'magenta_bed' | 'light_blue_bed' | 'yellow_bed' | 'lime_bed' | 'pink_bed' | 'gray_bed' | 'light_gray_bed' | 'cyan_bed' | 'purple_bed' | 'blue_bed' | 'brown_bed' | 'green_bed' | 'red_bed' | 'black_bed' | 'cookie' | 'filled_map' | 'shears' | 'melon_slice' | 'dried_kelp' | 'pumpkin_seeds' | 'melon_seeds' | 'beef' | 'cooked_beef' | 'chicken' | 'cooked_chicken' | 'rotten_flesh' | 'ender_pearl' | 'blaze_rod' | 'ghast_tear' | 'gold_nugget' | 'nether_wart' | 'potion' | 'glass_bottle' | 'spider_eye' | 'fermented_spider_eye' | 'blaze_powder' | 'magma_cream' | 'brewing_stand' | 'cauldron' | 'ender_eye' | 'glistering_melon_slice' | 'allay_spawn_egg' | 'axolotl_spawn_egg' | 'bat_spawn_egg' | 'bee_spawn_egg' | 'blaze_spawn_egg' | 'cat_spawn_egg' | 'camel_spawn_egg' | 'cave_spider_spawn_egg' | 'chicken_spawn_egg' | 'cod_spawn_egg' | 'cow_spawn_egg' | 'creeper_spawn_egg' | 'dolphin_spawn_egg' | 'donkey_spawn_egg' | 'drowned_spawn_egg' | 'elder_guardian_spawn_egg' | 'ender_dragon_spawn_egg' | 'enderman_spawn_egg' | 'endermite_spawn_egg' | 'evoker_spawn_egg' | 'fox_spawn_egg' | 'frog_spawn_egg' | 'ghast_spawn_egg' | 'glow_squid_spawn_egg' | 'goat_spawn_egg' | 'guardian_spawn_egg' | 'hoglin_spawn_egg' | 'horse_spawn_egg' | 'husk_spawn_egg' | 'iron_golem_spawn_egg' | 'llama_spawn_egg' | 'magma_cube_spawn_egg' | 'mooshroom_spawn_egg' | 'mule_spawn_egg' | 'ocelot_spawn_egg' | 'panda_spawn_egg' | 'parrot_spawn_egg' | 'phantom_spawn_egg' | 'pig_spawn_egg' | 'piglin_spawn_egg' | 'piglin_brute_spawn_egg' | 'pillager_spawn_egg' | 'polar_bear_spawn_egg' | 'pufferfish_spawn_egg' | 'rabbit_spawn_egg' | 'ravager_spawn_egg' | 'salmon_spawn_egg' | 'sheep_spawn_egg' | 'shulker_spawn_egg' | 'silverfish_spawn_egg' | 'skeleton_spawn_egg' | 'skeleton_horse_spawn_egg' | 'slime_spawn_egg' | 'sniffer_spawn_egg' | 'snow_golem_spawn_egg' | 'spider_spawn_egg' | 'squid_spawn_egg' | 'stray_spawn_egg' | 'strider_spawn_egg' | 'tadpole_spawn_egg' | 'trader_llama_spawn_egg' | 'tropical_fish_spawn_egg' | 'turtle_spawn_egg' | 'vex_spawn_egg' | 'villager_spawn_egg' | 'vindicator_spawn_egg' | 'wandering_trader_spawn_egg' | 'warden_spawn_egg' | 'witch_spawn_egg' | 'wither_spawn_egg' | 'wither_skeleton_spawn_egg' | 'wolf_spawn_egg' | 'zoglin_spawn_egg' | 'zombie_spawn_egg' | 'zombie_horse_spawn_egg' | 'zombie_villager_spawn_egg' | 'zombified_piglin_spawn_egg' | 'experience_bottle' | 'fire_charge' | 'writable_book' | 'written_book' | 'item_frame' | 'glow_item_frame' | 'flower_pot' | 'carrot' | 'potato' | 'baked_potato' | 'poisonous_potato' | 'map' | 'golden_carrot' | 'skeleton_skull' | 'wither_skeleton_skull' | 'player_head' | 'zombie_head' | 'creeper_head' | 'dragon_head' | 'piglin_head' | 'nether_star' | 'pumpkin_pie' | 'firework_rocket' | 'firework_star' | 'enchanted_book' | 'nether_brick' | 'prismarine_shard' | 'prismarine_crystals' | 'rabbit' | 'cooked_rabbit' | 'rabbit_stew' | 'rabbit_foot' | 'rabbit_hide' | 'armor_stand' | 'iron_horse_armor' | 'golden_horse_armor' | 'diamond_horse_armor' | 'leather_horse_armor' | 'lead' | 'name_tag' | 'command_block_minecart' | 'mutton' | 'cooked_mutton' | 'white_banner' | 'orange_banner' | 'magenta_banner' | 'light_blue_banner' | 'yellow_banner' | 'lime_banner' | 'pink_banner' | 'gray_banner' | 'light_gray_banner' | 'cyan_banner' | 'purple_banner' | 'blue_banner' | 'brown_banner' | 'green_banner' | 'red_banner' | 'black_banner' | 'end_crystal' | 'chorus_fruit' | 'popped_chorus_fruit' | 'torchflower_seeds' | 'pitcher_pod' | 'beetroot' | 'beetroot_seeds' | 'beetroot_soup' | 'dragon_breath' | 'splash_potion' | 'spectral_arrow' | 'tipped_arrow' | 'lingering_potion' | 'shield' | 'totem_of_undying' | 'shulker_shell' | 'iron_nugget' | 'knowledge_book' | 'debug_stick' | 'music_disc_13' | 'music_disc_cat' | 'music_disc_blocks' | 'music_disc_chirp' | 'music_disc_far' | 'music_disc_mall' | 'music_disc_mellohi' | 'music_disc_stal' | 'music_disc_strad' | 'music_disc_ward' | 'music_disc_11' | 'music_disc_wait' | 'music_disc_otherside' | 'music_disc_relic' | 'music_disc_5' | 'music_disc_pigstep' | 'disc_fragment_5' | 'trident' | 'phantom_membrane' | 'nautilus_shell' | 'heart_of_the_sea' | 'crossbow' | 'suspicious_stew' | 'loom' | 'flower_banner_pattern' | 'creeper_banner_pattern' | 'skull_banner_pattern' | 'mojang_banner_pattern' | 'globe_banner_pattern' | 'piglin_banner_pattern' | 'goat_horn' | 'composter' | 'barrel' | 'smoker' | 'blast_furnace' | 'cartography_table' | 'fletching_table' | 'grindstone' | 'smithing_table' | 'stonecutter' | 'bell' | 'lantern' | 'soul_lantern' | 'sweet_berries' | 'glow_berries' | 'campfire' | 'soul_campfire' | 'shroomlight' | 'honeycomb' | 'bee_nest' | 'beehive' | 'honey_bottle' | 'honeycomb_block' | 'lodestone' | 'crying_obsidian' | 'blackstone' | 'blackstone_slab' | 'blackstone_stairs' | 'gilded_blackstone' | 'polished_blackstone' | 'polished_blackstone_slab' | 'polished_blackstone_stairs' | 'chiseled_polished_blackstone' | 'polished_blackstone_bricks' | 'polished_blackstone_brick_slab' | 'polished_blackstone_brick_stairs' | 'cracked_polished_blackstone_bricks' | 'respawn_anchor' | 'candle' | 'white_candle' | 'orange_candle' | 'magenta_candle' | 'light_blue_candle' | 'yellow_candle' | 'lime_candle' | 'pink_candle' | 'gray_candle' | 'light_gray_candle' | 'cyan_candle' | 'purple_candle' | 'blue_candle' | 'brown_candle' | 'green_candle' | 'red_candle' | 'black_candle' | 'small_amethyst_bud' | 'medium_amethyst_bud' | 'large_amethyst_bud' | 'amethyst_cluster' | 'pointed_dripstone' | 'ochre_froglight' | 'verdant_froglight' | 'pearlescent_froglight' | 'frogspawn' | 'echo_shard' | 'brush' | 'netherite_upgrade_smithing_template' | 'sentry_armor_trim_smithing_template' | 'dune_armor_trim_smithing_template' | 'coast_armor_trim_smithing_template' | 'wild_armor_trim_smithing_template' | 'ward_armor_trim_smithing_template' | 'eye_armor_trim_smithing_template' | 'vex_armor_trim_smithing_template' | 'tide_armor_trim_smithing_template' | 'snout_armor_trim_smithing_template' | 'rib_armor_trim_smithing_template' | 'spire_armor_trim_smithing_template' | 'wayfinder_armor_trim_smithing_template' | 'shaper_armor_trim_smithing_template' | 'silence_armor_trim_smithing_template' | 'raiser_armor_trim_smithing_template' | 'host_armor_trim_smithing_template' | 'angler_pottery_sherd' | 'archer_pottery_sherd' | 'arms_up_pottery_sherd' | 'blade_pottery_sherd' | 'brewer_pottery_sherd' | 'burn_pottery_sherd' | 'danger_pottery_sherd' | 'explorer_pottery_sherd' | 'friend_pottery_sherd' | 'heart_pottery_sherd' | 'heartbreak_pottery_sherd' | 'howl_pottery_sherd' | 'miner_pottery_sherd' | 'mourner_pottery_sherd' | 'plenty_pottery_sherd' | 'prize_pottery_sherd' | 'sheaf_pottery_sherd' | 'shelter_pottery_sherd' | 'skull_pottery_sherd' | 'snort_pottery_sherd';
+export type EntityNames = 'allay' | 'area_effect_cloud' | 'armor_stand' | 'arrow' | 'axolotl' | 'bat' | 'bee' | 'blaze' | 'block_display' | 'boat' | 'camel' | 'cat' | 'cave_spider' | 'chest_boat' | 'chest_minecart' | 'chicken' | 'cod' | 'command_block_minecart' | 'cow' | 'creeper' | 'dolphin' | 'donkey' | 'dragon_fireball' | 'drowned' | 'egg' | 'elder_guardian' | 'end_crystal' | 'ender_dragon' | 'ender_pearl' | 'enderman' | 'endermite' | 'evoker' | 'evoker_fangs' | 'experience_bottle' | 'experience_orb' | 'eye_of_ender' | 'falling_block' | 'firework_rocket' | 'fox' | 'frog' | 'furnace_minecart' | 'ghast' | 'giant' | 'glow_item_frame' | 'glow_squid' | 'goat' | 'guardian' | 'hoglin' | 'hopper_minecart' | 'horse' | 'husk' | 'illusioner' | 'interaction' | 'iron_golem' | 'item' | 'item_display' | 'item_frame' | 'fireball' | 'leash_knot' | 'lightning_bolt' | 'llama' | 'llama_spit' | 'magma_cube' | 'marker' | 'minecart' | 'mooshroom' | 'mule' | 'ocelot' | 'painting' | 'panda' | 'parrot' | 'phantom' | 'pig' | 'piglin' | 'piglin_brute' | 'pillager' | 'polar_bear' | 'potion' | 'pufferfish' | 'rabbit' | 'ravager' | 'salmon' | 'sheep' | 'shulker' | 'shulker_bullet' | 'silverfish' | 'skeleton' | 'skeleton_horse' | 'slime' | 'small_fireball' | 'sniffer' | 'snow_golem' | 'snowball' | 'spawner_minecart' | 'spectral_arrow' | 'spider' | 'squid' | 'stray' | 'strider' | 'tadpole' | 'text_display' | 'tnt' | 'tnt_minecart' | 'trader_llama' | 'trident' | 'tropical_fish' | 'turtle' | 'vex' | 'villager' | 'vindicator' | 'wandering_trader' | 'warden' | 'witch' | 'wither' | 'wither_skeleton' | 'wither_skull' | 'wolf' | 'zoglin' | 'zombie' | 'zombie_horse' | 'zombie_villager' | 'zombified_piglin' | 'player' | 'fishing_bobber';
+export type BiomesNames = 'badlands' | 'bamboo_jungle' | 'basalt_deltas' | 'beach' | 'birch_forest' | 'cherry_grove' | 'cold_ocean' | 'crimson_forest' | 'dark_forest' | 'deep_cold_ocean' | 'deep_dark' | 'deep_frozen_ocean' | 'deep_lukewarm_ocean' | 'deep_ocean' | 'desert' | 'dripstone_caves' | 'end_barrens' | 'end_highlands' | 'end_midlands' | 'eroded_badlands' | 'flower_forest' | 'forest' | 'frozen_ocean' | 'frozen_peaks' | 'frozen_river' | 'grove' | 'ice_spikes' | 'jagged_peaks' | 'jungle' | 'lukewarm_ocean' | 'lush_caves' | 'mangrove_swamp' | 'meadow' | 'mushroom_fields' | 'nether_wastes' | 'ocean' | 'old_growth_birch_forest' | 'old_growth_pine_taiga' | 'old_growth_spruce_taiga' | 'plains' | 'river' | 'savanna' | 'savanna_plateau' | 'small_end_islands' | 'snowy_beach' | 'snowy_plains' | 'snowy_slopes' | 'snowy_taiga' | 'soul_sand_valley' | 'sparse_jungle' | 'stony_peaks' | 'stony_shore' | 'sunflower_plains' | 'swamp' | 'taiga' | 'the_end' | 'the_void' | 'warm_ocean' | 'warped_forest' | 'windswept_forest' | 'windswept_gravelly_hills' | 'windswept_hills' | 'windswept_savanna' | 'wooded_badlands';
+export type EnchantmentNames = 'protection' | 'fire_protection' | 'feather_falling' | 'blast_protection' | 'projectile_protection' | 'respiration' | 'aqua_affinity' | 'thorns' | 'depth_strider' | 'frost_walker' | 'binding_curse' | 'soul_speed' | 'swift_sneak' | 'sharpness' | 'smite' | 'bane_of_arthropods' | 'knockback' | 'fire_aspect' | 'looting' | 'sweeping' | 'efficiency' | 'silk_touch' | 'unbreaking' | 'fortune' | 'power' | 'punch' | 'flame' | 'infinity' | 'luck_of_the_sea' | 'lure' | 'loyalty' | 'impaling' | 'riptide' | 'channeling' | 'multishot' | 'quick_charge' | 'piercing' | 'mending' | 'vanishing_curse';
+
+export type EntityMetadataVersions = {
+'Mob': {},'Monster': {},'Creeper': {},'Skeleton': {},'Spider': {},'Giant': {},'Zombie': {},'Slime': {},'Ghast': {},'PigZombie': {},'Enderman': {},'CaveSpider': {},'Silverfish': {},'Blaze': {},'LavaSlime': {},'EnderDragon': {},'WitherBoss': {},'Bat': {},'Witch': {},'Endermite': {},'Guardian': {},'Pig': {},'Sheep': {},'Cow': {},'Chicken': {},'Squid': {},'Wolf': {},'MushroomCow': {},'SnowMan': {},'Ozelot': {},'VillagerGolem': {},'EntityHorse': {},'Rabbit': {},'Villager': {},'Boat': {},'Item': {},'MinecartRideable': {},'PrimedTnt': {},'EnderCrystal': {},'Arrow': {},'Snowball': {},'ThrownEgg': {},'Fireball': {},'SmallFireball': {},'ThrownEnderpearl': {},'WitherSkull': {},'FallingSand': {},'ItemFrame': {},'EyeOfEnderSignal': {},'ThrownPotion': {},'ThrownExpBottle': {},'FireworksRocketEntity': {},'LeashKnot': {},'ArmorStand': {},'Fishing Float': {},'Shulker': {},'XPOrb': {},'Dragon Fireball': {},'item': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item': string;},'xp_orb': {},'area_effect_cloud': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'radius': string;
+/** 1.19.4+ (9) */
+'color': string;
+/** 1.19.4+ (10) */
+'waiting': string;
+/** 1.19.4+ (11) */
+'particle': string;},'elder_guardian': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'moving': string;
+/** 1.19.4+ (17) */
+'attack_target': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'wither_skeleton': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'stray': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'egg': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'leash_knot': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'painting': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'painting_variant': string;},'arrow': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'flags': string;
+/** 1.19.4+ (9) */
+'pierce_level': string;
+/** 1.19.4+ (10) */
+'effect_color': string;},'snowball': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'fireball': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'small_fireball': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'ender_pearl': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'eye_of_ender_signal': {},'potion': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'xp_bottle': {},'item_frame': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item': string;
+/** 1.19.4+ (9) */
+'rotation': string;},'wither_skull': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'dangerous': string;},'tnt': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'fuse': string;
+/** 1.20.3+ (9) */
+'block_state': string;},'falling_block': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'start_pos': string;},'fireworks_rocket': {},'husk': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'special_type': string;
+/** 1.19.4+ (18) */
+'drowned_conversion': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'spectral_arrow': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'flags': string;
+/** 1.19.4+ (9) */
+'pierce_level': string;},'shulker_bullet': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'dragon_fireball': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'zombie_villager': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'special_type': string;
+/** 1.19.4+ (18) */
+'drowned_conversion': string;
+/** 1.19.4+ (19) */
+'converting': string;
+/** 1.19.4+ (20) */
+'villager_data': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'skeleton_horse': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'zombie_horse': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'armor_stand': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'client_flags': string;
+/** 1.19.4+ (16) */
+'head_pose': string;
+/** 1.19.4+ (17) */
+'body_pose': string;
+/** 1.19.4+ (18) */
+'left_arm_pose': string;
+/** 1.19.4+ (19) */
+'right_arm_pose': string;
+/** 1.19.4+ (20) */
+'left_leg_pose': string;
+/** 1.19.4+ (21) */
+'right_leg_pose': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'donkey': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'chest': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'mule': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'chest': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'evocation_fangs': {},'evocation_illager': {},'vex': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'vindication_illager': {},'commandblock_minecart': {},'boat': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'type': string;
+/** 1.19.4+ (12) */
+'paddle_left': string;
+/** 1.19.4+ (13) */
+'paddle_right': string;
+/** 1.19.4+ (14) */
+'bubble_time': string;},'minecart': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'display_block': string;
+/** 1.19.4+ (12) */
+'display_offset': string;
+/** 1.19.4+ (13) */
+'custom_display': string;},'chest_minecart': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'display_block': string;
+/** 1.19.4+ (12) */
+'display_offset': string;
+/** 1.19.4+ (13) */
+'custom_display': string;},'furnace_minecart': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'display_block': string;
+/** 1.19.4+ (12) */
+'display_offset': string;
+/** 1.19.4+ (13) */
+'custom_display': string;
+/** 1.19.4+ (14) */
+'fuel': string;},'tnt_minecart': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'display_block': string;
+/** 1.19.4+ (12) */
+'display_offset': string;
+/** 1.19.4+ (13) */
+'custom_display': string;},'hopper_minecart': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'display_block': string;
+/** 1.19.4+ (12) */
+'display_offset': string;
+/** 1.19.4+ (13) */
+'custom_display': string;},'spawner_minecart': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'display_block': string;
+/** 1.19.4+ (12) */
+'display_offset': string;
+/** 1.19.4+ (13) */
+'custom_display': string;},'creeper': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'swell_dir': string;
+/** 1.19.4+ (17) */
+'is_powered': string;
+/** 1.19.4+ (18) */
+'is_ignited': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'skeleton': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'stray_conversion': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'spider': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'giant': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'zombie': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'special_type': string;
+/** 1.19.4+ (18) */
+'drowned_conversion': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'slime': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'size': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'ghast': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'is_charging': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'zombie_pigman': {},'enderman': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'carry_state': string;
+/** 1.19.4+ (17) */
+'creepy': string;
+/** 1.19.4+ (18) */
+'stared_at': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'cave_spider': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'silverfish': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'blaze': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'magma_cube': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'size': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'ender_dragon': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'phase': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'wither': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'target_a': string;
+/** 1.19.4+ (17) */
+'target_b': string;
+/** 1.19.4+ (18) */
+'target_c': string;
+/** 1.19.4+ (19) */
+'inv': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'bat': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'witch': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'is_celebrating': string;
+/** 1.19.4+ (17) */
+'using_item': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'endermite': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'guardian': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'moving': string;
+/** 1.19.4+ (17) */
+'attack_target': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'shulker': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'attach_face': string;
+/** 1.19.4+ (17) */
+'peek': string;
+/** 1.19.4+ (18) */
+'color': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'pig': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'saddle': string;
+/** 1.19.4+ (18) */
+'boost_time': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'sheep': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'wool': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'cow': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'chicken': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'squid': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'wolf': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'owneruuid': string;
+/** 1.19.4+ (19) */
+'interested': string;
+/** 1.19.4+ (20) */
+'collar_color': string;
+/** 1.19.4+ (21) */
+'remaining_anger_time': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;
+/** 1.20.5+ (22) */
+'variant': string;},'mooshroom': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'type': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'snowman': {},'ocelot': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'trusting': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'villager_golem': {},'horse': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'type_variant': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'rabbit': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'type': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'polar_bear': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'standing': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'llama': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'chest': string;
+/** 1.19.4+ (19) */
+'strength': string;
+/** 1.19.4+ (20) */
+'swag': string;
+/** 1.19.4+ (21) */
+'variant': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'llama_spit': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'villager': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'unhappy_counter': string;
+/** 1.19.4+ (18) */
+'villager_data': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'ender_crystal': {},'Fishing Hook': {},'illusion_illager': {},'parrot': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'owneruuid': string;
+/** 1.19.4+ (19) */
+'variant': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'cod': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'from_bucket': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'dolphin': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'treasure_pos': string;
+/** 1.19.4+ (17) */
+'got_fish': string;
+/** 1.19.4+ (18) */
+'moistness_level': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'drowned': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'special_type': string;
+/** 1.19.4+ (18) */
+'drowned_conversion': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'end_crystal': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'beam_target': string;
+/** 1.19.4+ (9) */
+'show_bottom': string;},'evoker_fangs': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'evoker': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'is_celebrating': string;
+/** 1.19.4+ (17) */
+'spell_casting': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'experience_orb': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'eye_of_ender': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'illusioner': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'is_celebrating': string;
+/** 1.19.4+ (17) */
+'spell_casting': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'pufferfish': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'from_bucket': string;
+/** 1.19.4+ (17) */
+'puff_state': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'salmon': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'from_bucket': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'snow_golem': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'pumpkin': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'tropical_fish': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'from_bucket': string;
+/** 1.19.4+ (17) */
+'type_variant': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'turtle': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'home_pos': string;
+/** 1.19.4+ (18) */
+'has_egg': string;
+/** 1.19.4+ (19) */
+'laying_egg': string;
+/** 1.19.4+ (20) */
+'travel_pos': string;
+/** 1.19.4+ (21) */
+'going_home': string;
+/** 1.19.4+ (22) */
+'travelling': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'experience_bottle': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item_stack': string;},'iron_golem}': {},'vindicator': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'is_celebrating': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'phantom': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'size': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'lightning_bolt': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'player': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'player_absorption': string;
+/** 1.19.4+ (16) */
+'score': string;
+/** 1.19.4+ (17) */
+'player_mode_customisation': string;
+/** 1.19.4+ (18) */
+'player_main_hand': string;
+/** 1.19.4+ (19) */
+'shoulder_left': string;
+/** 1.19.4+ (20) */
+'shoulder_right': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'fishing_bobber': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hooked_entity': string;
+/** 1.19.4+ (9) */
+'biting': string;},'trident': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'flags': string;
+/** 1.19.4+ (9) */
+'pierce_level': string;
+/** 1.19.4+ (10) */
+'loyalty': string;
+/** 1.19.4+ (11) */
+'foil': string;},'item_stack': {},'area_effect cloud': {},'activated_tnt': {},'endercrystal': {},'tipped_arrow': {},'firecharge': {},'thrown_enderpearl': {},'falling_objects': {},'item_frames': {},'eye_of ender': {},'thrown_potion': {},'thrown_exp bottle': {},'firework_rocket': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'fireworks_item': string;
+/** 1.19.4+ (9) */
+'attached_to_target': string;
+/** 1.19.4+ (10) */
+'shot_at_angle': string;},'armorstand': {},'fishing_hook': {},'cat': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'owneruuid': string;
+/** 1.19.4+ (19) */
+'variant': string;
+/** 1.19.4+ (20) */
+'is_lying': string;
+/** 1.19.4+ (21) */
+'relax_state_one': string;
+/** 1.19.4+ (22) */
+'collar_color': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'fox': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'type': string;
+/** 1.19.4+ (18) */
+'flags': string;
+/** 1.19.4+ (19) */
+'trusted_0': string;
+/** 1.19.4+ (20) */
+'trusted_1': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'command_block_minecart': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'display_block': string;
+/** 1.19.4+ (12) */
+'display_offset': string;
+/** 1.19.4+ (13) */
+'custom_display': string;
+/** 1.19.4+ (14) */
+'command_name': string;
+/** 1.19.4+ (15) */
+'last_output': string;},'panda': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'unhappy_counter': string;
+/** 1.19.4+ (18) */
+'sneeze_counter': string;
+/** 1.19.4+ (19) */
+'eat_counter': string;
+/** 1.19.4+ (20) */
+'main_gene': string;
+/** 1.19.4+ (21) */
+'hidden_gene': string;
+/** 1.19.4+ (22) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'trader_llama': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'chest': string;
+/** 1.19.4+ (19) */
+'strength': string;
+/** 1.19.4+ (20) */
+'swag': string;
+/** 1.19.4+ (21) */
+'variant': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'iron_golem': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'pillager': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'is_celebrating': string;
+/** 1.19.4+ (17) */
+'is_charging_crossbow': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'wandering_trader': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'unhappy_counter': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'ravager': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'is_celebrating': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'bee': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'remaining_anger_time': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'hoglin': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'immune_to_zombification': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'piglin': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'immune_to_zombification': string;
+/** 1.19.4+ (17) */
+'baby': string;
+/** 1.19.4+ (18) */
+'is_charging_crossbow': string;
+/** 1.19.4+ (19) */
+'is_dancing': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'strider': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'boost_time': string;
+/** 1.19.4+ (18) */
+'suffocating': string;
+/** 1.19.4+ (19) */
+'saddle': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'zoglin': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'zombified_piglin': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'special_type': string;
+/** 1.19.4+ (18) */
+'drowned_conversion': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'piglin_brute': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'immune_to_zombification': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'axolotl': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'variant': string;
+/** 1.19.4+ (18) */
+'playing_dead': string;
+/** 1.19.4+ (19) */
+'from_bucket': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'glow_item_frame': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'item': string;
+/** 1.19.4+ (9) */
+'rotation': string;},'glow_squid': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'dark_ticks_remaining': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'goat': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'is_screaming_goat': string;
+/** 1.19.4+ (18) */
+'has_left_horn': string;
+/** 1.19.4+ (19) */
+'has_right_horn': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'marker': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;},'allay': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'dancing': string;
+/** 1.19.4+ (17) */
+'can_duplicate': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'chest_boat': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'hurt': string;
+/** 1.19.4+ (9) */
+'hurtdir': string;
+/** 1.19.4+ (10) */
+'damage': string;
+/** 1.19.4+ (11) */
+'type': string;
+/** 1.19.4+ (12) */
+'paddle_left': string;
+/** 1.19.4+ (13) */
+'paddle_right': string;
+/** 1.19.4+ (14) */
+'bubble_time': string;},'frog': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'variant': string;
+/** 1.19.4+ (18) */
+'tongue_target': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'tadpole': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'from_bucket': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'warden': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'client_anger_level': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'camel': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'flags': string;
+/** 1.19.4+ (18) */
+'dash': string;
+/** 1.19.4+ (19) */
+'last_pose_change_tick': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'block_display': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'interpolation_start_delta_ticks': string;
+/** 1.19.4+ (9) */
+'interpolation_duration': string;
+/** 1.19.4+ (10) */
+'translation': string;
+/** 1.19.4+ (11) */
+'scale': string;
+/** 1.19.4+ (12) */
+'left_rotation': string;
+/** 1.19.4+ (13) */
+'right_rotation': string;
+/** 1.19.4+ (14) */
+'billboard_render_constraints': string;
+/** 1.19.4+ (15) */
+'brightness_override': string;
+/** 1.19.4+ (16) */
+'view_range': string;
+/** 1.19.4+ (17) */
+'shadow_radius': string;
+/** 1.19.4+ (18) */
+'shadow_strength': string;
+/** 1.19.4+ (19) */
+'width': string;
+/** 1.19.4+ (20) */
+'height': string;
+/** 1.19.4+ (21) */
+'glow_color_override': string;
+/** 1.19.4+ (22) */
+'block_state': string;
+/** 1.20.2+ (8) */
+'transformation_interpolation_start_delta_ticks': string;
+/** 1.20.2+ (9) */
+'transformation_interpolation_duration': string;
+/** 1.20.2+ (10) */
+'pos_rot_interpolation_duration': string;},'interaction': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'width': string;
+/** 1.19.4+ (9) */
+'height': string;
+/** 1.19.4+ (10) */
+'response': string;},'item_display': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'interpolation_start_delta_ticks': string;
+/** 1.19.4+ (9) */
+'interpolation_duration': string;
+/** 1.19.4+ (10) */
+'translation': string;
+/** 1.19.4+ (11) */
+'scale': string;
+/** 1.19.4+ (12) */
+'left_rotation': string;
+/** 1.19.4+ (13) */
+'right_rotation': string;
+/** 1.19.4+ (14) */
+'billboard_render_constraints': string;
+/** 1.19.4+ (15) */
+'brightness_override': string;
+/** 1.19.4+ (16) */
+'view_range': string;
+/** 1.19.4+ (17) */
+'shadow_radius': string;
+/** 1.19.4+ (18) */
+'shadow_strength': string;
+/** 1.19.4+ (19) */
+'width': string;
+/** 1.19.4+ (20) */
+'height': string;
+/** 1.19.4+ (21) */
+'glow_color_override': string;
+/** 1.19.4+ (22) */
+'item_stack': string;
+/** 1.19.4+ (23) */
+'item_display': string;
+/** 1.20.2+ (8) */
+'transformation_interpolation_start_delta_ticks': string;
+/** 1.20.2+ (9) */
+'transformation_interpolation_duration': string;
+/** 1.20.2+ (10) */
+'pos_rot_interpolation_duration': string;},'sniffer': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'living_entity_flags': string;
+/** 1.19.4+ (9) */
+'health': string;
+/** 1.19.4+ (10) */
+'effect_color': string;
+/** 1.19.4+ (11) */
+'effect_ambience': string;
+/** 1.19.4+ (12) */
+'arrow_count': string;
+/** 1.19.4+ (13) */
+'stinger_count': string;
+/** 1.19.4+ (14) */
+'sleeping_pos': string;
+/** 1.19.4+ (15) */
+'mob_flags': string;
+/** 1.19.4+ (16) */
+'baby': string;
+/** 1.19.4+ (17) */
+'state': string;
+/** 1.19.4+ (18) */
+'drop_seed_at_tick': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'text_display': {
+/** 1.19.4+ (0) */
+'shared_flags': string;
+/** 1.19.4+ (1) */
+'air_supply': string;
+/** 1.19.4+ (2) */
+'custom_name': string;
+/** 1.19.4+ (3) */
+'custom_name_visible': string;
+/** 1.19.4+ (4) */
+'silent': string;
+/** 1.19.4+ (5) */
+'no_gravity': string;
+/** 1.19.4+ (6) */
+'pose': string;
+/** 1.19.4+ (7) */
+'ticks_frozen': string;
+/** 1.19.4+ (8) */
+'interpolation_start_delta_ticks': string;
+/** 1.19.4+ (9) */
+'interpolation_duration': string;
+/** 1.19.4+ (10) */
+'translation': string;
+/** 1.19.4+ (11) */
+'scale': string;
+/** 1.19.4+ (12) */
+'left_rotation': string;
+/** 1.19.4+ (13) */
+'right_rotation': string;
+/** 1.19.4+ (14) */
+'billboard_render_constraints': string;
+/** 1.19.4+ (15) */
+'brightness_override': string;
+/** 1.19.4+ (16) */
+'view_range': string;
+/** 1.19.4+ (17) */
+'shadow_radius': string;
+/** 1.19.4+ (18) */
+'shadow_strength': string;
+/** 1.19.4+ (19) */
+'width': string;
+/** 1.19.4+ (20) */
+'height': string;
+/** 1.19.4+ (21) */
+'glow_color_override': string;
+/** 1.19.4+ (22) */
+'text': string;
+/** 1.19.4+ (23) */
+'line_width': string;
+/** 1.19.4+ (24) */
+'background_color': string;
+/** 1.19.4+ (25) */
+'text_opacity': string;
+/** 1.19.4+ (26) */
+'style_flags': string;
+/** 1.20.2+ (8) */
+'transformation_interpolation_start_delta_ticks': string;
+/** 1.20.2+ (9) */
+'transformation_interpolation_duration': string;
+/** 1.20.2+ (10) */
+'pos_rot_interpolation_duration': string;},'breeze': {
+/** 1.20.3+ (0) */
+'shared_flags': string;
+/** 1.20.3+ (1) */
+'air_supply': string;
+/** 1.20.3+ (2) */
+'custom_name': string;
+/** 1.20.3+ (3) */
+'custom_name_visible': string;
+/** 1.20.3+ (4) */
+'silent': string;
+/** 1.20.3+ (5) */
+'no_gravity': string;
+/** 1.20.3+ (6) */
+'pose': string;
+/** 1.20.3+ (7) */
+'ticks_frozen': string;
+/** 1.20.3+ (8) */
+'living_entity_flags': string;
+/** 1.20.3+ (9) */
+'health': string;
+/** 1.20.3+ (10) */
+'effect_color': string;
+/** 1.20.3+ (11) */
+'effect_ambience': string;
+/** 1.20.3+ (12) */
+'arrow_count': string;
+/** 1.20.3+ (13) */
+'stinger_count': string;
+/** 1.20.3+ (14) */
+'sleeping_pos': string;
+/** 1.20.3+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;},'wind_charge': {
+/** 1.20.3+ (0) */
+'shared_flags': string;
+/** 1.20.3+ (1) */
+'air_supply': string;
+/** 1.20.3+ (2) */
+'custom_name': string;
+/** 1.20.3+ (3) */
+'custom_name_visible': string;
+/** 1.20.3+ (4) */
+'silent': string;
+/** 1.20.3+ (5) */
+'no_gravity': string;
+/** 1.20.3+ (6) */
+'pose': string;
+/** 1.20.3+ (7) */
+'ticks_frozen': string;},'armadillo': {
+/** 1.20.5+ (0) */
+'shared_flags': string;
+/** 1.20.5+ (1) */
+'air_supply': string;
+/** 1.20.5+ (2) */
+'custom_name': string;
+/** 1.20.5+ (3) */
+'custom_name_visible': string;
+/** 1.20.5+ (4) */
+'silent': string;
+/** 1.20.5+ (5) */
+'no_gravity': string;
+/** 1.20.5+ (6) */
+'pose': string;
+/** 1.20.5+ (7) */
+'ticks_frozen': string;
+/** 1.20.5+ (8) */
+'living_entity_flags': string;
+/** 1.20.5+ (9) */
+'health': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;
+/** 1.20.5+ (11) */
+'effect_ambience': string;
+/** 1.20.5+ (12) */
+'arrow_count': string;
+/** 1.20.5+ (13) */
+'stinger_count': string;
+/** 1.20.5+ (14) */
+'sleeping_pos': string;
+/** 1.20.5+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (16) */
+'baby': string;
+/** 1.20.5+ (17) */
+'armadillo_state': string;},'bogged': {
+/** 1.20.5+ (0) */
+'shared_flags': string;
+/** 1.20.5+ (1) */
+'air_supply': string;
+/** 1.20.5+ (2) */
+'custom_name': string;
+/** 1.20.5+ (3) */
+'custom_name_visible': string;
+/** 1.20.5+ (4) */
+'silent': string;
+/** 1.20.5+ (5) */
+'no_gravity': string;
+/** 1.20.5+ (6) */
+'pose': string;
+/** 1.20.5+ (7) */
+'ticks_frozen': string;
+/** 1.20.5+ (8) */
+'living_entity_flags': string;
+/** 1.20.5+ (9) */
+'health': string;
+/** 1.20.5+ (10) */
+'effect_particles': string;
+/** 1.20.5+ (11) */
+'effect_ambience': string;
+/** 1.20.5+ (12) */
+'arrow_count': string;
+/** 1.20.5+ (13) */
+'stinger_count': string;
+/** 1.20.5+ (14) */
+'sleeping_pos': string;
+/** 1.20.5+ (15) */
+'mob_flags': string;
+/** 1.20.5+ (16) */
+'sheared': string;},'breeze_wind_charge': {
+/** 1.20.5+ (0) */
+'shared_flags': string;
+/** 1.20.5+ (1) */
+'air_supply': string;
+/** 1.20.5+ (2) */
+'custom_name': string;
+/** 1.20.5+ (3) */
+'custom_name_visible': string;
+/** 1.20.5+ (4) */
+'silent': string;
+/** 1.20.5+ (5) */
+'no_gravity': string;
+/** 1.20.5+ (6) */
+'pose': string;
+/** 1.20.5+ (7) */
+'ticks_frozen': string;},'ominous_item_spawner': {
+/** 1.20.5+ (0) */
+'shared_flags': string;
+/** 1.20.5+ (1) */
+'air_supply': string;
+/** 1.20.5+ (2) */
+'custom_name': string;
+/** 1.20.5+ (3) */
+'custom_name_visible': string;
+/** 1.20.5+ (4) */
+'silent': string;
+/** 1.20.5+ (5) */
+'no_gravity': string;
+/** 1.20.5+ (6) */
+'pose': string;
+/** 1.20.5+ (7) */
+'ticks_frozen': string;
+/** 1.20.5+ (8) */
+'item': string;},
+}
\ No newline at end of file
diff --git a/src/optionsGuiScheme.tsx b/src/optionsGuiScheme.tsx
index 434ad4846..c6a979c16 100644
--- a/src/optionsGuiScheme.tsx
+++ b/src/optionsGuiScheme.tsx
@@ -89,7 +89,6 @@ export const guiOptionsScheme: {
tooltip: 'Additional distance to keep the chunks loading before unloading them by marking them as too far',
},
handDisplay: {},
- neighborChunkUpdates: {},
renderDebug: {
values: [
'advanced',
@@ -250,6 +249,19 @@ export const guiOptionsScheme: {
],
},
},
+ {
+ custom () {
+ return Map
+ },
+ showMinimap: {
+ text: 'Enable Minimap',
+ values: [
+ 'always',
+ 'singleplayer',
+ 'never'
+ ],
+ },
+ },
{
custom () {
return Experimental
diff --git a/src/optionsStorage.ts b/src/optionsStorage.ts
index 53deb927f..a242107c6 100644
--- a/src/optionsStorage.ts
+++ b/src/optionsStorage.ts
@@ -80,6 +80,7 @@ const defaultOptions = {
autoParkour: false,
vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users
renderDebug: (isDev ? 'advanced' : 'basic') as 'none' | 'advanced' | 'basic',
+ autoVersionSelect: '1.20.4',
// advanced bot options
autoRespawn: false,
@@ -88,6 +89,8 @@ const defaultOptions = {
/** Wether to popup sign editor on server action */
autoSignEditor: true,
wysiwygSignEditor: 'auto' as 'auto' | 'always' | 'never',
+ showMinimap: 'never' as 'always' | 'singleplayer' | 'never',
+ minimapOptimizations: true,
displayBossBars: false, // boss bar overlay was removed for some reason, enable safely
disabledUiParts: [] as string[],
neighborChunkUpdates: true
diff --git a/src/react/AppStatus.tsx b/src/react/AppStatus.tsx
index f9e5217ed..2c24b1539 100644
--- a/src/react/AppStatus.tsx
+++ b/src/react/AppStatus.tsx
@@ -38,10 +38,10 @@ export default ({
return (
diff --git a/src/react/DebugOverlay.tsx b/src/react/DebugOverlay.tsx
index 23f0d7db1..54d8cb404 100644
--- a/src/react/DebugOverlay.tsx
+++ b/src/react/DebugOverlay.tsx
@@ -1,8 +1,8 @@
import { useEffect, useRef, useMemo, useState } from 'react'
import * as THREE from 'three'
+import type { Block } from 'prismarine-block'
import { getFixedFilesize } from '../downloadAndOpenFile'
import { options } from '../optionsStorage'
-import worldInteractions from '../worldInteractions'
import styles from './DebugOverlay.module.css'
export default () => {
@@ -35,10 +35,10 @@ export default () => {
const [day, setDay] = useState(0)
const [entitiesCount, setEntitiesCount] = useState(0)
const [dimension, setDimension] = useState('')
- const [cursorBlock, setCursorBlock] = useState(null)
- const [rendererDevice, setRendererDevice] = useState('')
+ const [cursorBlock, setCursorBlock] = useState(null)
const minecraftYaw = useRef(0)
const minecraftQuad = useRef(0)
+ const { rendererDevice } = viewer.world
const quadsDescription = [
'north (towards negative Z)',
@@ -105,7 +105,7 @@ export default () => {
setBiomeId(bot.world.getBiome(bot.entity.position))
setDimension(bot.game.dimension)
setDay(bot.time.day)
- setCursorBlock(worldInteractions.cursorBlock)
+ setCursorBlock(bot.blockAtCursor(5))
setEntitiesCount(Object.values(bot.entities).length)
}, 100)
@@ -118,13 +118,6 @@ export default () => {
managePackets('sent', name, data)
})
- try {
- const gl = window.renderer.getContext()
- setRendererDevice(gl.getParameter(gl.getExtension('WEBGL_debug_renderer_info')!.UNMASKED_RENDERER_WEBGL))
- } catch (err) {
- console.warn(err)
- }
-
return () => {
document.removeEventListener('keydown', handleF3)
clearInterval(packetsUpdateInterval)
@@ -159,7 +152,7 @@ export default () => {
-
Renderer: {rendererDevice} powered by three.js r{THREE.REVISION}
+
Renderer: {rendererDevice}
{cursorBlock ? (<>
{cursorBlock.name}
diff --git a/src/react/FoodBar.tsx b/src/react/FoodBar.tsx
index 5a131c073..dbed05023 100644
--- a/src/react/FoodBar.tsx
+++ b/src/react/FoodBar.tsx
@@ -25,7 +25,7 @@ export default ({
useEffect(() => {
if (foodRef.current) {
- foodRef.current.classList.toggle('creative', gameMode === 'creative')
+ foodRef.current.classList.toggle('creative', gameMode === 'creative' || gameMode === 'spectator')
}
}, [gameMode])
diff --git a/src/react/Fullmap.css b/src/react/Fullmap.css
new file mode 100644
index 000000000..5b4b37ce8
--- /dev/null
+++ b/src/react/Fullmap.css
@@ -0,0 +1,13 @@
+
+.map {
+ width: 70% !important;
+ height: 80% !important;
+ border: 1px solid black;
+}
+
+@media (max-width: 500px) {
+ .map {
+ width: 100% !important;
+ height: 100% !important;
+ }
+}
diff --git a/src/react/Fullmap.tsx b/src/react/Fullmap.tsx
new file mode 100644
index 000000000..69a2c5148
--- /dev/null
+++ b/src/react/Fullmap.tsx
@@ -0,0 +1,512 @@
+import { Vec3 } from 'vec3'
+import { useRef, useEffect, useState, CSSProperties, Dispatch, SetStateAction } from 'react'
+import { WorldWarp } from 'flying-squid/dist/lib/modules/warps'
+import { TransformWrapper, TransformComponent, ReactZoomPanPinchRef } from 'react-zoom-pan-pinch'
+import { MinimapDrawer, DrawerAdapter, ChunkInfo } from './MinimapDrawer'
+import Button from './Button'
+import Input from './Input'
+import './Fullmap.css'
+
+
+type FullmapProps = {
+ toggleFullMap: () => void,
+ adapter: DrawerAdapter,
+ drawer: MinimapDrawer | null,
+ canvasRef: any
+}
+
+export default ({ toggleFullMap, adapter }: FullmapProps) => {
+ const [grid, setGrid] = useState(() => new Set
())
+ const zoomRef = useRef(null)
+ const redrawCell = useRef(false)
+ const [lastWarpPos, setLastWarpPos] = useState({ x: 0, y: 0, z: 0 })
+ const stateRef = useRef({ scale: 1, positionX: 0, positionY: 0 })
+ const cells = useRef({ columns: 0, rows: 0 })
+ const [isWarpInfoOpened, setIsWarpInfoOpened] = useState(false)
+ const [initWarp, setInitWarp] = useState(undefined)
+ const [warpPreview, setWarpPreview] = useState<{ name: string, x: number, z: number, clientX: number, clientY: number } | undefined>(undefined)
+
+ const updateGrid = () => {
+ const wrapperRect = zoomRef.current?.instance.wrapperComponent?.getBoundingClientRect()
+ if (!wrapperRect) return
+ const cellSize = 64
+ const columns = Math.ceil(wrapperRect.width / (cellSize * stateRef.current.scale))
+ const rows = Math.ceil(wrapperRect.height / (cellSize * stateRef.current.scale))
+ cells.current.rows = rows
+ cells.current.columns = columns
+ const leftBorder = - Math.floor(stateRef.current.positionX / (stateRef.current.scale * cellSize)) * cellSize
+ const topBorder = - Math.floor(stateRef.current.positionY / (stateRef.current.scale * cellSize)) * cellSize
+ const newGrid = new Set()
+ for (let row = -1; row < rows; row += 1) {
+ for (let col = -1; col < columns; col += 1) {
+ const x = leftBorder + col * cellSize
+ const y = topBorder + row * cellSize
+ newGrid.add(`${x},${y}`)
+ }
+ }
+ setGrid(newGrid)
+ }
+
+ useEffect(() => {
+ adapter.full = true
+ console.log('[fullmap] set full property to true')
+ updateGrid()
+ }, [])
+
+ return
+ {window.screen.width > 500 ?
+ :
}
+
{
+ stateRef.current = { ...state }
+ }}
+ onPanningStop={() => {
+ updateGrid()
+ }}
+ onZoomStop={() => {
+ updateGrid()
+ }}
+ >
+
+ {[...grid].map((cellCoords) => {
+ const [x, y] = cellCoords.split(',').map(Number)
+ const playerChunkLeft = Math.floor(adapter.playerPosition.x / 16) * 16
+ const playerChunkTop = Math.floor(adapter.playerPosition.z / 16) * 16
+ const wrapperRect = zoomRef.current?.instance.wrapperComponent?.getBoundingClientRect()
+ const offsetX = Math.floor((wrapperRect?.width ?? 0) / (8 * 16)) * 16
+ const offsetY = Math.floor((wrapperRect?.height ?? 0) / (8 * 16)) * 16
+
+ return
+ })}
+
+
+ {warpPreview &&
+ {warpPreview.name}
+
+ {warpPreview.x} {warpPreview.z}
+
+
}
+ {
+ isWarpInfoOpened &&
{
+ redrawCell.current = !redrawCell.current
+ }}
+ initWarp={initWarp}
+ setInitWarp={setInitWarp}
+ toggleFullMap={toggleFullMap}
+ />
+ }
+
+}
+
+
+const MapChunk = (
+ { x, y, scale, adapter, worldX, worldZ, setIsWarpInfoOpened, setLastWarpPos, redraw, setInitWarp, setWarpPreview }:
+ {
+ x: number,
+ y: number,
+ scale: number,
+ adapter: DrawerAdapter,
+ worldX: number,
+ worldZ: number,
+ setIsWarpInfoOpened: (x: boolean) => void,
+ setLastWarpPos: (obj: { x: number, y: number, z: number }) => void,
+ redraw?: boolean
+ setInitWarp?: (warp: WorldWarp | undefined) => void
+ setWarpPreview?: (warpInfo) => void
+ }
+) => {
+ const containerRef = useRef(null)
+ const drawerRef = useRef(null)
+ const touchTimer = useRef | null>(null)
+ const canvasRef = useRef(null)
+ const [isCanvas, setIsCanvas] = useState(false)
+
+ const longPress = (e) => {
+ touchTimer.current = setTimeout(() => {
+ touchTimer.current = null
+ handleClick(e)
+ }, 500)
+ }
+
+ const cancel = () => {
+ if (touchTimer.current) clearTimeout(touchTimer.current)
+ }
+
+ const handleClick = (e: MouseEvent | TouchEvent) => {
+ // console.log('click:', e)
+ if (!drawerRef.current) return
+ let clientX: number
+ let clientY: number
+ if ('buttons' in e && e.button === 2) {
+ clientX = e.clientX
+ clientY = e.clientY
+ } else if ('changedTouches' in e) {
+ clientX = (e).changedTouches[0].clientX
+ clientY = (e).changedTouches[0].clientY
+ } else { return }
+ const [x, z] = getXZ(clientX, clientY)
+ const mapX = Math.floor(x + worldX)
+ const mapZ = Math.floor(z + worldZ)
+ const y = adapter.getHighestBlockY(mapX, mapZ)
+ drawerRef.current.setWarpPosOnClick(new Vec3(mapX, y, mapZ))
+ setLastWarpPos(drawerRef.current.lastWarpPos)
+ const { lastWarpPos } = drawerRef.current
+ const initWarp = adapter.warps.find(warp => Math.hypot(lastWarpPos.x - warp.x, lastWarpPos.z - warp.z) < 2)
+ setInitWarp?.(initWarp)
+ setIsWarpInfoOpened(true)
+ }
+
+ const getXZ = (clientX: number, clientY: number) => {
+ const rect = canvasRef.current!.getBoundingClientRect()
+ const factor = scale * (drawerRef.current?.mapPixel ?? 1)
+ const x = (clientX - rect.left) / factor
+ const y = (clientY - rect.top) / factor
+ return [x, y]
+ }
+
+ const handleMouseMove = (e: MouseEvent) => {
+ const [x, z] = getXZ(e.clientX, e.clientY)
+ const warp = adapter.warps.find(w => Math.hypot(w.x - x - worldX, w.z - z - worldZ) < 2)
+ setWarpPreview?.(
+ warp ? { name: warp.name, x: warp.x, z: warp.z, clientX: e.clientX, clientY: e.clientY } : undefined
+ )
+ }
+
+ const handleRedraw = (key?: string, chunk?: ChunkInfo) => {
+ if (key !== `${worldX / 16},${worldZ / 16}`) return
+ adapter.mapDrawer.canvas = canvasRef.current!
+ adapter.mapDrawer.full = true
+ // console.log('handle redraw:', key)
+ // if (chunk) {
+ // drawerRef.current?.chunksStore.set(key, chunk)
+ // }
+ if (!adapter.chunksStore.has(key)) {
+ adapter.chunksStore.set(key, 'requested')
+ void adapter.loadChunk(key)
+ return
+ }
+ const timeout = setTimeout(() => {
+ const center = new Vec3(worldX + 8, 0, worldZ + 8)
+ drawerRef.current!.lastBotPos = center
+ drawerRef.current?.drawChunk(key)
+ // drawerRef.current?.drawWarps(center)
+ // drawerRef.current?.drawPlayerPos(center.x, center.z)
+ clearTimeout(timeout)
+ }, 100)
+ }
+
+ useEffect(() => {
+ // if (canvasRef.current && !drawerRef.current) {
+ // drawerRef.current = adapter.mapDrawer
+ // } else if (canvasRef.current && drawerRef.current) {
+ // }
+ if (canvasRef.current) void adapter.drawChunkOnCanvas(`${worldX / 16},${worldZ / 16}`, canvasRef.current)
+ }, [canvasRef.current])
+
+ useEffect(() => {
+ canvasRef.current?.addEventListener('contextmenu', handleClick)
+ canvasRef.current?.addEventListener('touchstart', longPress)
+ canvasRef.current?.addEventListener('touchend', cancel)
+ canvasRef.current?.addEventListener('touchmove', cancel)
+ canvasRef.current?.addEventListener('mousemove', handleMouseMove)
+
+ return () => {
+ canvasRef.current?.removeEventListener('contextmenu', handleClick)
+ canvasRef.current?.removeEventListener('touchstart', longPress)
+ canvasRef.current?.removeEventListener('touchend', cancel)
+ canvasRef.current?.removeEventListener('touchmove', cancel)
+ canvasRef.current?.removeEventListener('mousemove', handleMouseMove)
+ }
+ }, [canvasRef.current, scale])
+
+ useEffect(() => {
+ // handleRedraw()
+ }, [drawerRef.current, redraw])
+
+ useEffect(() => {
+ const intersectionObserver = new IntersectionObserver((entries) => {
+ for (const entry of entries) {
+ if (entry.isIntersecting) {
+ setIsCanvas(true)
+ }
+ }
+ })
+ intersectionObserver.observe(containerRef.current!)
+
+ // adapter.on('chunkReady', handleRedraw)
+
+ return () => {
+ intersectionObserver.disconnect()
+ // adapter.off('chunkReady', handleRedraw)
+ }
+ }, [])
+
+ return
+
+
+}
+
+const WarpInfo = (
+ { adapter, warpPos, setIsWarpInfoOpened, afterWarpIsSet, initWarp, toggleFullMap }:
+ {
+ adapter: DrawerAdapter,
+ warpPos: { x: number, y: number, z: number },
+ setIsWarpInfoOpened: Dispatch>,
+ afterWarpIsSet?: () => void
+ initWarp?: WorldWarp,
+ setInitWarp?: React.Dispatch>,
+ toggleFullMap?: ({ command }: { command: string }) => void
+ }
+) => {
+ const [warp, setWarp] = useState(initWarp ?? {
+ name: '',
+ x: warpPos?.x ?? 100,
+ y: warpPos?.y ?? 100,
+ z: warpPos?.z ?? 100,
+ color: '',
+ disabled: false,
+ world: adapter.world
+ })
+
+ const posInputStyle: CSSProperties = {
+ flexGrow: '1',
+ }
+ const fieldCont: CSSProperties = {
+ display: 'flex',
+ alignItems: 'center',
+ gap: '5px'
+ }
+
+ const updateChunk = () => {
+ for (let i = -1; i < 2; i += 1) {
+ for (let j = -1; j < 2; j += 1) {
+ adapter.emit(
+ 'chunkReady',
+ `${Math.floor(warp.x / 16) + j},${Math.floor(warp.z / 16) + i}`
+ )
+ }
+ }
+ }
+
+ const tpNow = () => {
+ adapter.off('updateChunk', tpNow)
+ }
+
+ const quickTp = () => {
+ toggleFullMap?.({ command: 'ui.toggleMap' })
+ adapter.quickTp?.(warp.x, warp.z)
+ }
+
+ return
+}
diff --git a/src/react/HotbarRenderApp.tsx b/src/react/HotbarRenderApp.tsx
index 5b65f890f..1c94905f4 100644
--- a/src/react/HotbarRenderApp.tsx
+++ b/src/react/HotbarRenderApp.tsx
@@ -73,7 +73,7 @@ const ItemName = ({ itemKey }: { itemKey: string }) => {
}
-export default () => {
+const Inner = () => {
const container = useRef(null!)
const [itemKey, setItemKey] = useState('')
const hasModals = useSnapshot(activeModalStack).length
@@ -221,6 +221,17 @@ export default () => {
}
+export default () => {
+ const [gameMode, setGameMode] = useState(bot.game?.gameMode ?? 'creative')
+ useEffect(() => {
+ bot.on('game', () => {
+ setGameMode(bot.game.gameMode)
+ })
+ }, [])
+
+ return gameMode === 'spectator' ? null :
+}
+
const Portal = ({ children, to = document.body }) => {
return createPortal(children, to)
}
diff --git a/src/react/Input.tsx b/src/react/Input.tsx
index 41dbc7ba8..1da36cc3f 100644
--- a/src/react/Input.tsx
+++ b/src/react/Input.tsx
@@ -9,10 +9,10 @@ interface Props extends React.ComponentProps<'input'> {
validateInput?: (value: string) => CSSProperties | undefined
}
-export default ({ autoFocus, rootStyles, inputRef, validateInput, ...inputProps }: Props) => {
+export default ({ autoFocus, rootStyles, inputRef, validateInput, defaultValue, ...inputProps }: Props) => {
const ref = useRef(null!)
const [validationStyle, setValidationStyle] = useState({})
- const [value, setValue] = useState(inputProps.value ?? '')
+ const [value, setValue] = useState(defaultValue ?? '')
useEffect(() => {
setValue(inputProps.value === '' || inputProps.value ? inputProps.value : value)
diff --git a/src/react/MainMenuRenderApp.tsx b/src/react/MainMenuRenderApp.tsx
index 7c6385dcb..f62cf1652 100644
--- a/src/react/MainMenuRenderApp.tsx
+++ b/src/react/MainMenuRenderApp.tsx
@@ -62,7 +62,7 @@ export default () => {
return
}
const upStatus = () => {
- setVersionStatus(`(${isLatest ? 'latest' : 'new version available'}${mainMenuState.serviceWorkerLoaded ? ' - Available Offline' : ''})`)
+ setVersionStatus(`(${isLatest ? 'latest' : 'new version available'}${mainMenuState.serviceWorkerLoaded ? ', Downloaded' : ''})`)
}
subscribe(mainMenuState, upStatus)
upStatus()
diff --git a/src/react/Minimap.stories.tsx b/src/react/Minimap.stories.tsx
new file mode 100644
index 000000000..5b28a5b99
--- /dev/null
+++ b/src/react/Minimap.stories.tsx
@@ -0,0 +1,74 @@
+import { Vec3 } from 'vec3'
+import type { Meta, StoryObj } from '@storybook/react'
+import { WorldWarp } from 'flying-squid/dist/lib/modules/warps'
+import { TypedEventEmitter } from 'contro-max/build/typedEventEmitter'
+import { useEffect } from 'react'
+
+import Minimap from './Minimap'
+import { DrawerAdapter, MapUpdates } from './MinimapDrawer'
+
+const meta: Meta = {
+ component: Minimap,
+ decorators: [
+ (Story, context) => {
+
+ useEffect(() => {
+ console.log('map updated')
+ adapter.emit('updateMap')
+
+ }, [context.args['fullMap']])
+
+ return
+ }
+ ]
+}
+
+export default meta
+type Story = StoryObj
+
+
+class DrawerAdapterImpl extends TypedEventEmitter {
+ playerPosition: Vec3
+ yaw: number
+ warps: WorldWarp[]
+ chunksStore: any = {}
+ full: boolean
+
+ constructor (pos?: Vec3, warps?: WorldWarp[]) {
+ super()
+ this.playerPosition = pos ?? new Vec3(0, 0, 0)
+ this.warps = warps ?? [] as WorldWarp[]
+ }
+
+ async getHighestBlockColor (x: number, z: number) {
+ console.log('got color')
+ return 'green'
+ }
+
+ getHighestBlockY (x: number, z: number) {
+ return 0
+ }
+
+ setWarp (warp: WorldWarp, remove?: boolean): void {
+ const index = this.warps.findIndex(w => w.name === warp.name)
+ if (index === -1) {
+ this.warps.push(warp)
+ } else {
+ this.warps[index] = warp
+ }
+ this.emit('updateWarps')
+ }
+
+ clearChunksStore (x: number, z: number) { }
+
+ async loadChunk (key: string) {}
+}
+
+const adapter = new DrawerAdapterImpl() as any
+
+export const Primary: Story = {
+ args: {
+ adapter,
+ fullMap: false
+ },
+}
diff --git a/src/react/Minimap.tsx b/src/react/Minimap.tsx
new file mode 100644
index 000000000..1dae0344d
--- /dev/null
+++ b/src/react/Minimap.tsx
@@ -0,0 +1,175 @@
+import { useRef, useEffect, useState } from 'react'
+import { MinimapDrawer, DrawerAdapter, ChunkInfo } from './MinimapDrawer'
+import Fullmap from './Fullmap'
+
+
+export type DisplayMode = 'fullmapOnly' | 'minimapOnly'
+
+export default (
+ { adapter, showMinimap, showFullmap, singleplayer, fullMap, toggleFullMap, displayMode }:
+ {
+ adapter: DrawerAdapter,
+ showMinimap: string,
+ showFullmap: string,
+ singleplayer: boolean,
+ fullMap?: boolean,
+ toggleFullMap?: ({ command }: { command: string }) => void
+ displayMode?: DisplayMode
+ }
+) => {
+ const full = useRef(false)
+ const canvasTick = useRef(0)
+ const canvasRef = useRef(null)
+ const warpsAndPartsCanvasRef = useRef(null)
+ const playerPosCanvasRef = useRef(null)
+ const warpsDrawerRef = useRef(null)
+ const drawerRef = useRef(null)
+ const playerPosDrawerRef = useRef(null)
+ const [position, setPosition] = useState({ x: 0, y: 0, z: 0 })
+
+ const updateMap = () => {
+ setPosition({ x: adapter.playerPosition.x, y: adapter.playerPosition.y, z: adapter.playerPosition.z })
+ if (drawerRef.current) {
+ if (!full.current) {
+ rotateMap()
+ drawerRef.current.draw(adapter.playerPosition)
+ drawerRef.current.drawPlayerPos()
+ drawerRef.current.drawWarps()
+ }
+ if (canvasTick.current % 300 === 0 && !fullMap) {
+ if ('requestIdleCallback' in window) {
+ requestIdleCallback(() => {
+ drawerRef.current?.clearChunksStore()
+ })
+ } else {
+ drawerRef.current.clearChunksStore()
+ }
+ canvasTick.current = 0
+ }
+ }
+ canvasTick.current += 1
+ }
+
+ const updateWarps = () => { }
+
+ const rotateMap = () => {
+ if (!drawerRef.current) return
+ drawerRef.current.canvas.style.transform = `rotate(${adapter.yaw}rad)`
+ if (!warpsDrawerRef.current) return
+ warpsDrawerRef.current.canvas.style.transform = `rotate(${adapter.yaw}rad)`
+ }
+
+ const updateChunkOnMap = (key: string, chunk: ChunkInfo) => {
+ adapter.chunksStore.set(key, chunk)
+ }
+
+ useEffect(() => {
+ if (canvasRef.current && !drawerRef.current) {
+ drawerRef.current = adapter.mapDrawer
+ drawerRef.current.canvas = canvasRef.current
+ // drawerRef.current.adapter.on('chunkReady', updateChunkOnMap)
+ } else if (canvasRef.current && drawerRef.current) {
+ drawerRef.current.canvas = canvasRef.current
+ }
+
+ }, [canvasRef.current])
+
+ // useEffect(() => {
+ // if (warpsAndPartsCanvasRef.current && !warpsDrawerRef.current) {
+ // warpsDrawerRef.current = new MinimapDrawer(warpsAndPartsCanvasRef.current, adapter)
+ // } else if (warpsAndPartsCanvasRef.current && warpsDrawerRef.current) {
+ // warpsDrawerRef.current.canvas = warpsAndPartsCanvasRef.current
+ // }
+ // }, [warpsAndPartsCanvasRef.current])
+
+ // useEffect(() => {
+ // if (playerPosCanvasRef.current && !playerPosDrawerRef.current) {
+ // playerPosDrawerRef.current = new MinimapDrawer(playerPosCanvasRef.current, adapter)
+ // } else if (playerPosCanvasRef.current && playerPosDrawerRef.current) {
+ // playerPosDrawerRef.current.canvas = playerPosCanvasRef.current
+ // }
+ // }, [playerPosCanvasRef.current])
+
+ useEffect(() => {
+ adapter.on('updateMap', updateMap)
+ adapter.on('updateWaprs', updateWarps)
+
+ return () => {
+ adapter.off('updateMap', updateMap)
+ adapter.off('updateWaprs', updateWarps)
+ }
+ }, [adapter])
+
+ useEffect(() => {
+ return () => {
+ // if (drawerRef.current) drawerRef.current.adapter.off('chunkReady', updateChunkOnMap)
+ }
+ }, [])
+
+ const displayFullmap = fullMap && displayMode !== 'minimapOnly' && (showFullmap === 'singleplayer' && singleplayer || showFullmap === 'always')
+ const displayMini = displayMode !== 'fullmapOnly' && (showMinimap === 'singleplayer' && singleplayer || showMinimap === 'always')
+ return displayFullmap
+ ? {
+ toggleFullMap?.({ command: 'ui.toggleMap' })
+ }}
+ adapter={adapter}
+ drawer={drawerRef.current}
+ canvasRef={canvasRef}
+ />
+ : displayMini
+ ? {
+ toggleFullMap?.({ command: 'ui.toggleMap' })
+ }}
+ >
+
+
+
+
+ {position.x.toFixed(2)} {position.y.toFixed(2)} {position.z.toFixed(2)}
+
+
: null
+}
diff --git a/src/react/MinimapDrawer.ts b/src/react/MinimapDrawer.ts
new file mode 100644
index 000000000..935bdd4bb
--- /dev/null
+++ b/src/react/MinimapDrawer.ts
@@ -0,0 +1,324 @@
+import { Vec3 } from 'vec3'
+import { TypedEventEmitter } from 'contro-max/build/typedEventEmitter'
+import { WorldWarp } from 'flying-squid/dist/lib/modules/warps'
+import { Chunk } from 'prismarine-world/types/world'
+
+export type MapUpdates = {
+ updateBlockColor: (pos: Vec3) => void
+ updatePlayerPosition: () => void
+ updateWarps: () => void
+}
+
+export interface DrawerAdapter extends TypedEventEmitter {
+ getHighestBlockY: (x: number, z: number, chunk?: Chunk) => number
+ clearChunksStore: (x: number, z: number) => void
+ chunksStore: Map
+ playerPosition: Vec3
+ warps: WorldWarp[]
+ loadingChunksQueue: Set
+ mapDrawer: MinimapDrawer
+ yaw: number
+ full: boolean
+ world: string
+ setWarp: (warp: WorldWarp, remove?: boolean) => void
+ quickTp?: (x: number, z: number) => void
+ loadChunk: (key: string) => Promise
+ drawChunkOnCanvas: (key: string, canvas: HTMLCanvasElement) => Promise
+}
+
+export type ChunkInfo = {
+ heightmap: Uint8Array,
+ colors: string[],
+}
+
+export class MinimapDrawer {
+ canvasWidthCenterX: number
+ canvasWidthCenterY: number
+ _mapSize: number
+ radius: number
+ ctx: CanvasRenderingContext2D
+ _canvas: HTMLCanvasElement
+ chunksInView = new Set()
+ lastBotPos: Vec3
+ lastWarpPos: Vec3
+ mapPixel: number
+ yaw: number
+ chunksStore = new Map()
+ loadingChunksQueue: undefined | Set
+ warps: WorldWarp[]
+ loadChunk: undefined | ((key: string) => Promise)
+ _full = false
+
+ setMapPixel () {
+ if (this.full) {
+ this.radius = Math.floor(Math.min(this.canvas.width, this.canvas.height) / 2)
+ this._mapSize = 16
+ } else {
+ this.radius = Math.floor(Math.min(this.canvas.width, this.canvas.height) / 2.2)
+ this._mapSize = this.radius * 2
+ }
+ this.mapPixel = Math.floor(this.radius * 2 / this.mapSize)
+ }
+
+ get full () {
+ return this._full
+ }
+
+ set full (full: boolean) {
+ this._full = full
+ this.setMapPixel()
+ }
+
+ get canvas () {
+ return this._canvas
+ }
+
+ set canvas (canvas: HTMLCanvasElement) {
+ this.ctx = canvas.getContext('2d', { willReadFrequently: true })!
+ this.ctx.imageSmoothingEnabled = false
+ this.canvasWidthCenterX = canvas.width / 2
+ this.canvasWidthCenterY = canvas.height / 2
+ this._canvas = canvas
+ this.setMapPixel()
+ }
+
+ get mapSize () {
+ return this._mapSize
+ }
+
+ set mapSize (mapSize: number) {
+ this._mapSize = mapSize
+ this.mapPixel = Math.floor(this.radius * 2 / this.mapSize)
+ this.draw(this.lastBotPos)
+ }
+
+ draw (botPos: Vec3,) {
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
+
+ this.lastBotPos = botPos
+ this.updateChunksInView()
+ for (const key of this.chunksInView) {
+ if (!this.chunksStore.has(key) && !this.loadingChunksQueue?.has(key)) {
+ void this.loadChunk?.(key)
+ }
+ this.drawChunk(key)
+ }
+ if (!this.full) this.drawPartsOfWorld()
+ }
+
+ updateChunksInView (viewX?: number, viewZ?: number) {
+ const worldCenterX = viewX ?? this.lastBotPos.x
+ const worldCenterZ = viewZ ?? this.lastBotPos.z
+
+ const radius = this.mapSize / 2
+ const leftViewBorder = Math.floor((worldCenterX - radius) / 16) - 1
+ const rightViewBorder = Math.ceil((worldCenterX + radius) / 16)
+ const topViewBorder = Math.floor((worldCenterZ - radius) / 16) - 1
+ const bottomViewBorder = Math.ceil((worldCenterZ + radius) / 16)
+
+ this.chunksInView.clear()
+ for (let i = topViewBorder; i <= bottomViewBorder; i += 1) {
+ for (let j = leftViewBorder; j <= rightViewBorder; j += 1) {
+ this.chunksInView.add(`${j},${i}`)
+ }
+ }
+ }
+
+ drawChunk (key: string, chunkInfo?: ChunkInfo | null) {
+ const [chunkX, chunkZ] = key.split(',').map(Number)
+ const chunkWorldX = chunkX * 16
+ const chunkWorldZ = chunkZ * 16
+ const chunkCanvasX = Math.floor((chunkWorldX - this.lastBotPos.x) * this.mapPixel + this.canvasWidthCenterX)
+ const chunkCanvasY = Math.floor((chunkWorldZ - this.lastBotPos.z) * this.mapPixel + this.canvasWidthCenterY)
+ const chunk = chunkInfo ?? this.chunksStore.get(key)
+ if (typeof chunk !== 'object') {
+ const chunkSize = this.mapPixel * 16
+ this.ctx.fillStyle = chunk === 'requested' ? 'rgb(200, 200, 200)' : 'rgba(0, 0, 0, 0.5)'
+ this.ctx.fillRect(chunkCanvasX, chunkCanvasY, chunkSize, chunkSize)
+ return
+ }
+ for (let row = 0; row < 16; row += 1) {
+ for (let col = 0; col < 16; col += 1) {
+ const index = row * 16 + col
+ const color = chunk?.colors[index] ?? 'rgb(255, 0, 0)'
+ const pixelX = chunkCanvasX + this.mapPixel * col
+ const pixelY = chunkCanvasY + this.mapPixel * row
+ this.drawPixel(pixelX, pixelY, color)
+ }
+ }
+ }
+
+ drawPixel (pixelX: number, pixelY: number, color: string) {
+ // if (!this.full && Math.hypot(pixelX - this.canvasWidthCenterX, pixelY - this.canvasWidthCenterY) > this.radius) {
+ // this.ctx.clearRect(pixelX, pixelY, this.mapPixel, this.mapPixel)
+ // return
+ // }
+ this.ctx.fillStyle = color
+ this.ctx.fillRect(
+ pixelX,
+ pixelY,
+ this.mapPixel,
+ this.mapPixel
+ )
+ }
+
+ clearChunksStore () {
+ for (const key of this.chunksStore.keys()) {
+ const [x, z] = key.split(',').map(x => Number(x) * 16)
+ if (Math.hypot((this.lastBotPos.x - x), (this.lastBotPos.z - z)) > this.radius * 5) {
+ this.chunksStore.delete(key)
+ }
+ }
+ }
+
+ setWarpPosOnClick (mousePos: Vec3) {
+ this.lastWarpPos = new Vec3(mousePos.x, mousePos.y, mousePos.z)
+ }
+
+ drawWarps (centerPos?: Vec3) {
+ for (const warp of this.warps) {
+ // if (!full) {
+ // const distance = this.getDistance(
+ // centerPos?.x ?? this.adapter.playerPosition.x,
+ // centerPos?.z ?? this.adapter.playerPosition.z,
+ // warp.x,
+ // warp.z
+ // )
+ // if (distance > this.mapSize) continue
+ // }
+ const offset = this.full ? 0 : this.radius * 0.1
+ const z = Math.floor(
+ (this.mapSize / 2 - (centerPos?.z ?? this.lastBotPos.z) + warp.z) * this.mapPixel
+ ) + offset
+ const x = Math.floor(
+ (this.mapSize / 2 - (centerPos?.x ?? this.lastBotPos.x) + warp.x) * this.mapPixel
+ ) + offset
+ const dz = z - this.canvasWidthCenterX
+ const dx = x - this.canvasWidthCenterY
+ const circleDist = Math.hypot(dx, dz)
+
+ const angle = Math.atan2(dz, dx)
+ const circleZ = circleDist > this.mapSize / 2 && !this.full ?
+ this.canvasWidthCenterX + this.mapSize / 2 * Math.sin(angle)
+ : z
+ const circleX = circleDist > this.mapSize / 2 && !this.full ?
+ this.canvasWidthCenterY + this.mapSize / 2 * Math.cos(angle)
+ : x
+ this.ctx.beginPath()
+ this.ctx.arc(
+ circleX,
+ circleZ,
+ circleDist > this.mapSize / 2 && !this.full
+ ? this.mapPixel * 1.5
+ : this.full ? this.mapPixel : this.mapPixel * 2,
+ 0,
+ Math.PI * 2,
+ false
+ )
+ this.ctx.strokeStyle = 'black'
+ this.ctx.lineWidth = this.mapPixel
+ this.ctx.stroke()
+ this.ctx.fillStyle = warp.disabled ? 'rgba(255, 255, 255, 0.4)' : warp.color ?? '#d3d3d3'
+ this.ctx.fill()
+ this.ctx.closePath()
+ }
+ }
+
+ drawPartsOfWorld () {
+ this.ctx.fillStyle = 'white'
+ this.ctx.shadowOffsetX = 1
+ this.ctx.shadowOffsetY = 1
+ this.ctx.shadowColor = 'black'
+ this.ctx.font = `${this.radius / 4}px serif`
+ this.ctx.textAlign = 'center'
+ this.ctx.textBaseline = 'middle'
+ this.ctx.strokeStyle = 'black'
+ this.ctx.lineWidth = 1
+
+ const angle = - Math.PI / 2
+ const angleS = angle + Math.PI
+ const angleW = angle + Math.PI * 3 / 2
+ const angleE = angle + Math.PI / 2
+
+ this.ctx.strokeText(
+ 'N',
+ this.canvasWidthCenterX + this.radius * Math.cos(angle),
+ this.canvasWidthCenterY + this.radius * Math.sin(angle)
+ )
+ this.ctx.strokeText(
+ 'S',
+ this.canvasWidthCenterX + this.radius * Math.cos(angleS),
+ this.canvasWidthCenterY + this.radius * Math.sin(angleS)
+ )
+ this.ctx.strokeText(
+ 'W',
+ this.canvasWidthCenterX + this.radius * Math.cos(angleW),
+ this.canvasWidthCenterY + this.radius * Math.sin(angleW)
+ )
+ this.ctx.strokeText(
+ 'E',
+ this.canvasWidthCenterX + this.radius * Math.cos(angleE),
+ this.canvasWidthCenterY + this.radius * Math.sin(angleE)
+ )
+ this.ctx.fillText(
+ 'N',
+ this.canvasWidthCenterX + this.radius * Math.cos(angle),
+ this.canvasWidthCenterY + this.radius * Math.sin(angle)
+ )
+ this.ctx.fillText(
+ 'S',
+ this.canvasWidthCenterX + this.radius * Math.cos(angleS),
+ this.canvasWidthCenterY + this.radius * Math.sin(angleS)
+ )
+ this.ctx.fillText(
+ 'W',
+ this.canvasWidthCenterX + this.radius * Math.cos(angleW),
+ this.canvasWidthCenterY + this.radius * Math.sin(angleW)
+ )
+ this.ctx.fillText(
+ 'E',
+ this.canvasWidthCenterX + this.radius * Math.cos(angleE),
+ this.canvasWidthCenterY + this.radius * Math.sin(angleE)
+ )
+
+ this.ctx.shadowOffsetX = 0
+ this.ctx.shadowOffsetY = 0
+ }
+
+ drawPlayerPos (canvasWorldCenterX?: number, canvasWorldCenterZ?: number, disableTurn?: boolean) {
+ this.ctx.setTransform(1, 0, 0, 1, 0, 0)
+
+ const x = (this.lastBotPos.x - (canvasWorldCenterX ?? this.lastBotPos.x)) * this.mapPixel
+ const z = (this.lastBotPos.z - (canvasWorldCenterZ ?? this.lastBotPos.z)) * this.mapPixel
+ const center = this.mapSize / 2 * this.mapPixel + (this.full ? 0 : this.radius * 0.1)
+ this.ctx.translate(center + x, center + z)
+ if (!disableTurn) this.ctx.rotate(-this.yaw)
+
+ const size = 3
+ const factor = this.full ? 2 : 1
+ const width = size * factor
+ const height = size * factor
+
+ this.ctx.beginPath()
+ this.ctx.moveTo(0, -height)
+ this.ctx.lineTo(-width, height)
+ this.ctx.lineTo(width, height)
+ this.ctx.closePath()
+
+ this.ctx.strokeStyle = '#000000'
+ this.ctx.lineWidth = this.full ? 2 : 1
+ this.ctx.stroke()
+ this.ctx.fillStyle = '#FFFFFF'
+ this.ctx.fill()
+
+ // Reset transformations
+ this.ctx.setTransform(1, 0, 0, 1, 0, 0)
+ }
+
+ rotateMap (angle: number) {
+ this.ctx.setTransform(1, 0, 0, 1, 0, 0)
+ this.ctx.translate(this.canvasWidthCenterX, this.canvasWidthCenterY)
+ this.ctx.rotate(angle)
+ this.ctx.translate(-this.canvasWidthCenterX, -this.canvasWidthCenterY)
+ }
+}
diff --git a/src/react/MinimapProvider.tsx b/src/react/MinimapProvider.tsx
new file mode 100644
index 000000000..4b877732b
--- /dev/null
+++ b/src/react/MinimapProvider.tsx
@@ -0,0 +1,610 @@
+import { useEffect, useState } from 'react'
+import { versions } from 'minecraft-data'
+import { simplify } from 'prismarine-nbt'
+import RegionFile from 'prismarine-provider-anvil/src/region'
+import { Vec3 } from 'vec3'
+import { versionToNumber } from 'prismarine-viewer/viewer/prepare/utils'
+import { WorldWarp } from 'flying-squid/dist/lib/modules/warps'
+import { TypedEventEmitter } from 'contro-max/build/typedEventEmitter'
+import { PCChunk } from 'prismarine-chunk'
+import { Chunk } from 'prismarine-world/types/world'
+import { Block } from 'prismarine-block'
+import { INVISIBLE_BLOCKS } from 'prismarine-viewer/viewer/lib/mesher/worldConstants'
+import { getRenamedData } from 'flying-squid/dist/blockRenames'
+import { useSnapshot } from 'valtio'
+import BlockData from '../../prismarine-viewer/viewer/lib/moreBlockDataGenerated.json'
+import preflatMap from '../preflatMap.json'
+import { contro } from '../controls'
+import { gameAdditionalState, showModal, hideModal, miscUiState, loadedGameState, activeModalStack } from '../globalState'
+import { options } from '../optionsStorage'
+import Minimap, { DisplayMode } from './Minimap'
+import { ChunkInfo, DrawerAdapter, MapUpdates, MinimapDrawer } from './MinimapDrawer'
+import { useIsModalActive } from './utilsApp'
+
+const getBlockKey = (x: number, z: number) => {
+ return `${x},${z}`
+}
+
+const findHeightMap = (obj: PCChunk): number[] | undefined => {
+ function search (obj: any): any | undefined {
+ for (const key in obj) {
+ if (['heightmap', 'heightmaps'].includes(key.toLowerCase())) {
+ return obj[key]
+ } else if (typeof obj[key] === 'object' && obj[key] !== null) {
+ const result = search(obj[key])
+ return result
+ }
+ }
+ }
+ return search(obj)
+}
+
+export class DrawerAdapterImpl extends TypedEventEmitter implements DrawerAdapter {
+ playerPosition: Vec3
+ yaw: number
+ mapDrawer = new MinimapDrawer()
+ warps: WorldWarp[]
+ world: string
+ chunksStore = new Map()
+ loadingChunksQueue = new Set()
+ currChunk: PCChunk | undefined
+ currChunkPos: { x: number, z: number } = { x: 0, z: 0 }
+ isOldVersion: boolean
+ blockData: any
+ heightMap: Record = {}
+ regions = new Map()
+ chunksHeightmaps: Record = {}
+ loadChunk: (key: string) => Promise
+ loadChunkFullmap: ((key: string) => Promise) | undefined
+ _full: boolean
+ isBuiltinHeightmapAvailable = false
+
+ constructor (pos?: Vec3) {
+ super()
+ this.full = false
+ this.playerPosition = pos ?? new Vec3(0, 0, 0)
+ this.warps = gameAdditionalState.warps
+ this.mapDrawer.warps = this.warps
+ this.mapDrawer.loadChunk = this.loadChunk
+ this.mapDrawer.loadingChunksQueue = this.loadingChunksQueue
+ this.mapDrawer.chunksStore = this.chunksStore
+
+ // check if should use heightmap
+ if (localServer) {
+ const chunkX = Math.floor(this.playerPosition.x / 16)
+ const chunkZ = Math.floor(this.playerPosition.z / 16)
+ const regionX = Math.floor(chunkX / 32)
+ const regionZ = Math.floor(chunkZ / 32)
+ const regionKey = `${regionX},${regionZ}`
+ const worldFolder = this.getSingleplayerRootPath()
+ if (worldFolder && options.minimapOptimizations) {
+ const path = `${worldFolder}/region/r.${regionX}.${regionZ}.mca`
+ const region = new RegionFile(path)
+ void region.initialize()
+ this.regions.set(regionKey, region)
+ const readX = chunkX % 32
+ const readZ = chunkZ % 32
+ void this.regions.get(regionKey)!.read(readX, readZ).then((rawChunk) => {
+ const chunk = simplify(rawChunk as any)
+ const heightmap = findHeightMap(chunk)
+ if (heightmap) {
+ this.isBuiltinHeightmapAvailable = true
+ this.loadChunkFullmap = this.loadChunkFromRegion
+ console.log('using heightmap')
+ } else {
+ this.isBuiltinHeightmapAvailable = false
+ this.loadChunkFullmap = this.loadChunkNoRegion
+ console.log('[minimap] not using heightmap')
+ }
+ }).catch(err => {
+ console.error(err)
+ this.isBuiltinHeightmapAvailable = false
+ this.loadChunkFullmap = this.loadChunkFromViewer
+ })
+ } else {
+ this.isBuiltinHeightmapAvailable = false
+ this.loadChunkFullmap = this.loadChunkFromViewer
+ }
+ } else {
+ this.isBuiltinHeightmapAvailable = false
+ this.loadChunkFullmap = this.loadChunkFromViewer
+ }
+ // if (localServer) {
+ // this.overwriteWarps(localServer.warps)
+ // this.on('cellReady', (key: string) => {
+ // if (this.loadingChunksQueue.size === 0) return
+ // const [x, z] = this.loadingChunksQueue.values().next().value.split(',').map(Number)
+ // this.loadChunk(x, z)
+ // this.loadingChunksQueue.delete(`${x},${z}`)
+ // })
+ // } else {
+ // const storageWarps = localStorage.getItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp ?? ''}`)
+ // this.overwriteWarps(JSON.parse(storageWarps ?? '[]'))
+ // }
+ this.isOldVersion = versionToNumber(bot.version) < versionToNumber('1.13')
+ this.blockData = {}
+ for (const blockKey of Object.keys(BlockData.colors)) {
+ const renamedKey = getRenamedData('blocks', blockKey, '1.20.2', bot.version)
+ this.blockData[renamedKey as string] = BlockData.colors[blockKey]
+ }
+
+ viewer.world?.renderUpdateEmitter.on('chunkFinished', (key) => {
+ if (!this.loadingChunksQueue.has(key)) return
+ void this.loadChunk(key)
+ this.loadingChunksQueue.delete(key)
+ })
+ }
+
+ get full () {
+ return this._full
+ }
+
+ set full (full: boolean) {
+ console.log('this is minimap')
+ this.loadChunk = this.loadChunkMinimap
+ this.mapDrawer.loadChunk = this.loadChunk
+ this._full = full
+ }
+
+ overwriteWarps (newWarps: WorldWarp[]) {
+ this.warps.splice(0, this.warps.length)
+ for (const warp of newWarps) {
+ this.warps.push({ ...warp })
+ }
+ }
+
+ setWarp (warp: WorldWarp, remove?: boolean): void {
+ this.world = bot.game.dimension
+ const index = this.warps.findIndex(w => w.name === warp.name)
+ if (index === -1) {
+ this.warps.push(warp)
+ } else if (remove && index !== -1) {
+ this.warps.splice(index, 1)
+ } else {
+ this.warps[index] = warp
+ }
+ if (localServer) {
+ // type suppressed until server is updated. It works fine
+ void (localServer as any).setWarp(warp, remove)
+ } else if (remove) {
+ localStorage.removeItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp}`)
+ } else {
+ localStorage.setItem(`warps: ${loadedGameState.username} ${loadedGameState.serverIp}`, JSON.stringify(this.warps))
+ }
+ this.emit('updateWarps')
+ }
+
+ getHighestBlockY (x: number, z: number, chunk?: Chunk) {
+ const chunkX = Math.floor(x / 16) * 16
+ const chunkZ = Math.floor(z / 16) * 16
+ if (this.chunksHeightmaps[`${chunkX},${chunkZ}`]) {
+ return this.chunksHeightmaps[`${chunkX},${chunkZ}`][x - chunkX + (z - chunkZ) * 16] - 1
+ }
+ const source = chunk ?? bot.world
+ const { height, minY } = (bot.game as any)
+ for (let i = height; i > 0; i -= 1) {
+ const block = source.getBlock(new Vec3(x & 15, minY + i, z & 15))
+ if (block && !INVISIBLE_BLOCKS.has(block.name)) {
+ return minY + i
+ }
+ }
+ return minY
+ }
+
+ async getChunkSingleplayer (chunkX: number, chunkZ: number) {
+ // absolute coords
+ const region = (localServer!.overworld.storageProvider as any).getRegion(chunkX * 16, chunkZ * 16)
+ if (!region) return 'unavailable'
+ const chunk = await localServer!.players[0]!.world.getColumn(chunkX, chunkZ)
+ return chunk
+ }
+
+ async loadChunkMinimap (key: string) {
+ const [chunkX, chunkZ] = key.split(',').map(Number)
+ const chunkWorldX = chunkX * 16
+ const chunkWorldZ = chunkZ * 16
+ if (viewer.world.finishedChunks[`${chunkWorldX},${chunkWorldZ}`]) {
+ const heightmap = new Uint8Array(256)
+ const colors = Array.from({ length: 256 }).fill('') as string[]
+ for (let z = 0; z < 16; z += 1) {
+ for (let x = 0; x < 16; x += 1) {
+ const blockX = chunkWorldX + x
+ const blockZ = chunkWorldZ + z
+ const hBlock = viewer.world.highestBlocks.get(`${blockX},${blockZ}`)
+ const block = bot.world.getBlock(new Vec3(blockX, hBlock?.y ?? 0, blockZ))
+ // const block = Block.fromStateId(hBlock?.stateId ?? -1, hBlock?.biomeId ?? -1)
+ const index = z * 16 + x
+ if (!block || !hBlock) {
+ console.warn(`[loadChunk] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`)
+ heightmap[index] = 0
+ colors[index] = 'rgba(0, 0, 0, 0.5)'
+ continue
+ }
+ heightmap[index] = hBlock.y
+ let color: string
+ if (this.isOldVersion) {
+ color = BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')]
+ ?? 'rgb(0, 0, 255)'
+ } else {
+ color = this.blockData[block.name] ?? 'rgb(0, 255, 0)'
+ }
+ colors[index] = color
+ }
+ }
+ const chunk = { heightmap, colors }
+ this.applyShadows(chunk)
+ this.chunksStore.set(key, chunk)
+ this.emit(`chunkReady`, `${chunkX},${chunkZ}`)
+ } else {
+ this.loadingChunksQueue.add(`${chunkX},${chunkZ}`)
+ this.chunksStore.set(key, 'requested')
+ }
+ }
+
+ async loadChunkNoRegion (key: string) {
+ const [chunkX, chunkZ] = key.split(',').map(Number)
+ const chunkWorldX = chunkX * 16
+ const chunkWorldZ = chunkZ * 16
+ const chunkInfo = await this.getChunkSingleplayer(chunkX, chunkZ)
+ if (chunkInfo === 'unavailable') return null
+ const heightmap = new Uint8Array(256)
+ const colors = Array.from({ length: 256 }).fill('') as string[]
+ for (let z = 0; z < 16; z += 1) {
+ for (let x = 0; x < 16; x += 1) {
+ const blockX = chunkWorldX + x
+ const blockZ = chunkWorldZ + z
+ const blockY = this.getHighestBlockY(blockX, blockZ, chunkInfo)
+ const block = chunkInfo.getBlock(new Vec3(blockX & 15, blockY, blockZ & 15))
+ if (!block) {
+ console.warn(`[cannot get the block] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`)
+ return null
+ }
+ const index = z * 16 + x
+ heightmap[index] = blockY
+ const color = this.isOldVersion ? BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] ?? 'rgb(0, 0, 255)' : this.blockData[block.name] ?? 'rgb(0, 255, 0)'
+ colors[index] = color
+ }
+ }
+ const chunk: ChunkInfo = { heightmap, colors }
+ this.applyShadows(chunk)
+ return chunk
+ }
+
+ async loadChunkFromRegion (key: string): Promise {
+ const [chunkX, chunkZ] = key.split(',').map(Number)
+ const chunkWorldX = chunkX * 16
+ const chunkWorldZ = chunkZ * 16
+ const heightmap = await this.getChunkHeightMapFromRegion(chunkX, chunkZ) as unknown as Uint8Array
+ if (!heightmap) return null
+ const chunkInfo = await this.getChunkSingleplayer(chunkX, chunkZ)
+ if (chunkInfo === 'unavailable') return null
+ const colors = Array.from({ length: 256 }).fill('') as string[]
+ for (let z = 0; z < 16; z += 1) {
+ for (let x = 0; x < 16; x += 1) {
+ const blockX = chunkWorldX + x
+ const blockZ = chunkWorldZ + z
+ const index = z * 16 + x
+ heightmap[index] -= 1
+ if (heightmap[index] < 0) heightmap[index] = 0
+ const blockY = heightmap[index]
+ const block = chunkInfo.getBlock(new Vec3(blockX & 15, blockY, blockZ & 15))
+ if (!block) {
+ console.warn(`[cannot get the block] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`)
+ return null
+ }
+ const color = this.isOldVersion ? BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] ?? 'rgb(0, 0, 255)' : this.blockData[block.name] ?? 'rgb(0, 255, 0)'
+ colors[index] = color
+ }
+ }
+ const chunk: ChunkInfo = { heightmap, colors }
+ this.applyShadows(chunk)
+ return chunk
+ }
+
+ getSingleplayerRootPath (): string | undefined {
+ return localServer!.options.worldFolder
+ }
+
+ async getChunkHeightMapFromRegion (chunkX: number, chunkZ: number, cb?: (hm: number[]) => void) {
+ const regionX = Math.floor(chunkX / 32)
+ const regionZ = Math.floor(chunkZ / 32)
+ const regionKey = `${regionX},${regionZ}`
+ if (!this.regions.has(regionKey)) {
+ const worldFolder = this.getSingleplayerRootPath()
+ if (!worldFolder) return
+ const path = `${worldFolder}/region/r.${regionX}.${regionZ}.mca`
+ const region = new RegionFile(path)
+ await region.initialize()
+ this.regions.set(regionKey, region)
+ }
+ const rawChunk = await this.regions.get(regionKey)!.read(chunkX % 32, chunkZ % 32)
+ const chunk = simplify(rawChunk as any)
+ console.log(`chunk ${chunkX}, ${chunkZ}:`, chunk)
+ const heightmap = findHeightMap(chunk)
+ console.log(`heightmap ${chunkX}, ${chunkZ}:`, heightmap)
+ cb?.(heightmap!)
+ return heightmap
+ // this.chunksHeightmaps[`${chunkX},${chunkZ}`] = heightmap
+ }
+
+ async loadChunkFromViewer (key: string) {
+ const [chunkX, chunkZ] = key.split(',').map(Number)
+ const chunkWorldX = chunkX * 16
+ const chunkWorldZ = chunkZ * 16
+ if (viewer.world.finishedChunks[`${chunkWorldX},${chunkWorldZ}`]) {
+ const heightmap = new Uint8Array(256)
+ const colors = Array.from({ length: 256 }).fill('') as string[]
+ for (let z = 0; z < 16; z += 1) {
+ for (let x = 0; x < 16; x += 1) {
+ const blockX = chunkWorldX + x
+ const blockZ = chunkWorldZ + z
+ const hBlock = viewer.world.highestBlocks.get(`${blockX},${blockZ}`)
+ const block = bot.world.getBlock(new Vec3(blockX, hBlock?.y ?? 0, blockZ))
+ // const block = Block.fromStateId(hBlock?.stateId ?? -1, hBlock?.biomeId ?? -1)
+ const index = z * 16 + x
+ if (!block || !hBlock) {
+ console.warn(`[loadChunk] ${chunkX}, ${chunkZ}, ${chunkWorldX + x}, ${chunkWorldZ + z}`)
+ heightmap[index] = 0
+ colors[index] = 'rgba(0, 0, 0, 0.5)'
+ continue
+ }
+ heightmap[index] = hBlock.y
+ const color = this.isOldVersion ? BlockData.colors[preflatMap.blocks[`${block.type}:${block.metadata}`]?.replaceAll(/\[.*?]/g, '')] ?? 'rgb(0, 0, 255)' : this.blockData[block.name] ?? 'rgb(0, 255, 0)'
+ colors[index] = color
+ }
+ }
+ const chunk = { heightmap, colors }
+ this.applyShadows(chunk)
+ return chunk
+ } else {
+ return null
+ }
+ }
+
+ applyShadows (chunk: ChunkInfo) {
+ for (let j = 0; j < 16; j += 1) {
+ for (let i = 0; i < 16; i += 1) {
+ const index = j * 16 + i
+ const color = chunk.colors[index]
+ // if (i === 0 || j === 0 || i === 15 || j === 16) {
+ // const r = Math.floor(Math.random() * 2)
+ // chunk.colors[index] = r===0 ? this.makeDarker(color) : this.makeLighter(color)
+ // continue
+ // }
+
+ const h = chunk.heightmap[index]
+ let isLighterOrDarker = 0
+
+ const r = chunk.heightmap[index + 1] ?? 0
+ const u = chunk.heightmap[index - 16] ?? 0
+ const ur = chunk.heightmap[index - 15] ?? 0
+ if (r > h || u > h || ur > h) {
+ chunk.colors[index] = this.makeDarker(color)
+ isLighterOrDarker -= 1
+ }
+
+ const l = chunk.heightmap[index - 1] ?? 0
+ const d = chunk.heightmap[index + 16] ?? 0
+ const dl = chunk.heightmap[index + 15] ?? 0
+ if (l > h || d > h || dl > h) {
+ chunk.colors[index] = this.makeLighter(color)
+ isLighterOrDarker += 1
+ }
+
+ let linkedIndex: number | undefined
+ if (i === 1) {
+ linkedIndex = index - 1
+ } else if (i === 14) {
+ linkedIndex = index + 1
+ } else if (j === 1) {
+ linkedIndex = index - 16
+ } else if (j === 14) {
+ linkedIndex = index + 16
+ }
+ if (linkedIndex !== undefined) {
+ const linkedColor = chunk.colors[linkedIndex]
+ switch (isLighterOrDarker) {
+ case 1:
+ chunk.colors[linkedIndex] = this.makeLighter(linkedColor)
+ break
+ case -1:
+ chunk.colors[linkedIndex] = this.makeDarker(linkedColor)
+ break
+ default:
+ break
+ }
+ }
+ }
+ }
+ }
+
+ makeDarker (color: string) {
+ let rgbArray = color.match(/\d+/g)?.map(Number) ?? []
+ if (rgbArray.length !== 3) return color
+ rgbArray = rgbArray.map(element => {
+ let newColor = element - 20
+ if (newColor < 0) newColor = 0
+ return newColor
+ })
+ return `rgb(${rgbArray.join(',')})`
+ }
+
+ makeLighter (color: string) {
+ let rgbArray = color.match(/\d+/g)?.map(Number) ?? []
+ if (rgbArray.length !== 3) return color
+ rgbArray = rgbArray.map(element => {
+ let newColor = element + 20
+ if (newColor > 255) newColor = 255
+ return newColor
+ })
+ return `rgb(${rgbArray.join(',')})`
+ }
+
+ clearChunksStore (x: number, z: number) {
+ for (const key of Object.keys(this.chunksStore)) {
+ const [chunkX, chunkZ] = key.split(',').map(Number)
+ if (Math.hypot((chunkX - x), (chunkZ - z)) > 300) {
+ delete this.chunksStore[key]
+ delete this.chunksHeightmaps[key]
+ for (let i = 0; i < 16; i += 1) {
+ for (let j = 0; j < 16; j += 1) {
+ delete this.heightMap[`${chunkX + i},${chunkZ + j}`]
+ }
+ }
+ }
+ }
+ }
+
+ quickTp (x: number, z: number) {
+ const y = this.getHighestBlockY(x, z)
+ bot.chat(`/tp ${x} ${y + 20} ${z}`)
+ const timeout = setTimeout(() => {
+ const y = this.getHighestBlockY(x, z)
+ bot.chat(`/tp ${x} ${y + 20} ${z}`)
+ clearTimeout(timeout)
+ }, 500)
+ }
+
+ async drawChunkOnCanvas (key: string, canvas: HTMLCanvasElement) {
+ // console.log('chunk', key, 'on canvas')
+ if (!this.loadChunkFullmap) {
+ // wait for it to be available
+ await new Promise(resolve => {
+ const interval = setInterval(() => {
+ if (this.loadChunkFullmap) {
+ clearInterval(interval)
+ resolve(undefined)
+ }
+ }, 100)
+ setTimeout(() => {
+ clearInterval(interval)
+ resolve(undefined)
+ }, 10_000)
+ })
+ if (!this.loadChunkFullmap) {
+ throw new Error('loadChunkFullmap not available')
+ }
+ }
+ const chunk = await this.loadChunkFullmap(key)
+ const [worldX, worldZ] = key.split(',').map(x => Number(x) * 16)
+ const center = new Vec3(worldX + 8, 0, worldZ + 8)
+ this.mapDrawer.lastBotPos = center
+ this.mapDrawer.canvas = canvas
+ this.mapDrawer.full = true
+ this.mapDrawer.drawChunk(key, chunk)
+ }
+}
+
+const Inner = (
+ { adapter, displayMode, toggleFullMap }:
+ {
+ adapter: DrawerAdapterImpl
+ displayMode?: DisplayMode,
+ toggleFullMap?: ({ command }: { command?: string }) => void
+ }
+) => {
+
+ const updateWarps = (newWarps: WorldWarp[] | Error) => {
+ if (newWarps instanceof Error) {
+ console.error('An error occurred:', newWarps.message)
+ return
+ }
+
+ adapter.overwriteWarps(newWarps)
+ }
+
+ const updateMap = () => {
+ if (!adapter) return
+ adapter.playerPosition = bot.entity.position
+ adapter.yaw = bot.entity.yaw
+ adapter.emit('updateMap')
+ }
+
+ useEffect(() => {
+ bot.on('move', updateMap)
+ localServer?.on('warpsUpdated' as keyof ServerEvents, updateWarps)
+
+ return () => {
+ bot?.off('move', updateMap)
+ localServer?.off('warpsUpdated' as keyof ServerEvents, updateWarps)
+ }
+ }, [])
+
+ return
+
+
+}
+
+export default ({ displayMode }: { displayMode?: DisplayMode }) => {
+ const [adapter] = useState(() => new DrawerAdapterImpl(bot.entity.position))
+
+ const { showMinimap } = useSnapshot(options)
+ const fullMapOpened = useIsModalActive('full-map')
+
+
+ const readChunksHeightMaps = async () => {
+ const { worldFolder } = localServer!.options
+ const path = `${worldFolder}/region/r.0.0.mca`
+ const region = new RegionFile(path)
+ await region.initialize()
+ const chunks: Record = {}
+ console.log('Reading chunks...')
+ console.log(chunks)
+ let versionDetected = false
+ for (const [i, _] of Array.from({ length: 32 }).entries()) {
+ for (const [k, _] of Array.from({ length: 32 }).entries()) {
+ // todo, may use faster reading, but features is not commonly used
+ // eslint-disable-next-line no-await-in-loop
+ const nbt = await region.read(i, k)
+ chunks[`${i},${k}`] = nbt
+ if (nbt && !versionDetected) {
+ const simplified = simplify(nbt)
+ const version = versions.pc.find(x => x['dataVersion'] === simplified.DataVersion)?.minecraftVersion
+ console.log('Detected version', version ?? 'unknown')
+ versionDetected = true
+ }
+ }
+ }
+ Object.defineProperty(chunks, 'simplified', {
+ get () {
+ const mapped = {}
+ for (const [i, _] of Array.from({ length: 32 }).entries()) {
+ for (const [k, _] of Array.from({ length: 32 }).entries()) {
+ const key = `${i},${k}`
+ const chunk = chunks[key]
+ if (!chunk) continue
+ mapped[key] = simplify(chunk)
+ }
+ }
+ return mapped
+ },
+ })
+ console.log('Done!', chunks)
+ }
+
+ if (
+ displayMode === 'minimapOnly'
+ ? showMinimap === 'never' || (showMinimap === 'singleplayer' && !miscUiState.singleplayer)
+ : !fullMapOpened
+ ) {
+ return null
+ }
+
+ const toggleFullMap = () => {
+ if (activeModalStack.at(-1)?.reactType === 'full-map') {
+ hideModal({ reactType: 'full-map' })
+ } else {
+ showModal({ reactType: 'full-map' })
+ }
+ }
+
+ return
+}
diff --git a/src/react/Screen.tsx b/src/react/Screen.tsx
index c80b880ac..6654e4ddf 100644
--- a/src/react/Screen.tsx
+++ b/src/react/Screen.tsx
@@ -4,15 +4,16 @@ interface Props {
backdrop?: boolean | 'dirt'
style?: React.CSSProperties
className?: string
+ titleSelectable?: boolean
}
-export default ({ title, children, backdrop = true, style, className }: Props) => {
+export default ({ title, children, backdrop = true, style, className, titleSelectable }: Props) => {
return (
<>
{backdrop === 'dirt' ? : backdrop ? : null}
-
{title}
+
{title}
{children}
diff --git a/src/react/ServersListProvider.tsx b/src/react/ServersListProvider.tsx
index f42fb11bb..c5cff9f2f 100644
--- a/src/react/ServersListProvider.tsx
+++ b/src/react/ServersListProvider.tsx
@@ -9,6 +9,7 @@ import AddServerOrConnect, { BaseServerInfo } from './AddServerOrConnect'
import { useDidUpdateEffect } from './utils'
import { useIsModalActive } from './utilsApp'
import { showOptionsModal } from './SelectOption'
+import { useCopyKeybinding } from './simpleHooks'
interface StoreServerItem extends BaseServerInfo {
lastJoined?: number
@@ -92,7 +93,11 @@ const getInitialServersList = () => {
return servers
}
-const setNewServersList = (serversList: StoreServerItem[]) => {
+const serversListQs = new URLSearchParams(window.location.search).get('serversList')
+const proxyQs = new URLSearchParams(window.location.search).get('proxy')
+
+const setNewServersList = (serversList: StoreServerItem[], force = false) => {
+ if (serversListQs && !force) return
localStorage['serversList'] = JSON.stringify(serversList)
// cleanup legacy
@@ -133,13 +138,14 @@ export const updateAuthenticatedAccountData = (callback: (data: AuthenticatedAcc
// todo move to base
const normalizeIp = (ip: string) => ip.replace(/https?:\/\//, '').replace(/\/(:|$)/, '')
-const Inner = ({ hidden }: { hidden?: boolean }) => {
+const Inner = ({ hidden, customServersList }: { hidden?: boolean, customServersList?: string[] }) => {
const [proxies, setProxies] = useState(localStorage['proxies'] ? JSON.parse(localStorage['proxies']) : getInitialProxies())
- const [selectedProxy, setSelectedProxy] = useState(localStorage.getItem('selectedProxy') ?? proxies?.[0] ?? '')
+ const [selectedProxy, setSelectedProxy] = useState(proxyQs ?? localStorage.getItem('selectedProxy') ?? proxies?.[0] ?? '')
const [serverEditScreen, setServerEditScreen] = useState(null) // true for add
const [defaultUsername, _setDefaultUsername] = useState(localStorage['username'] ?? (`mcrafter${Math.floor(Math.random() * 1000)}`))
const [authenticatedAccounts, _setAuthenticatedAccounts] = useState(JSON.parse(localStorage['authenticatedAccounts'] || '[]'))
const [quickConnectIp, setQuickConnectIp] = useState('')
+ const [selectedIndex, setSelectedIndex] = useState(-1)
const setAuthenticatedAccounts = (newState: typeof authenticatedAccounts) => {
_setAuthenticatedAccounts(newState)
@@ -151,18 +157,35 @@ const Inner = ({ hidden }: { hidden?: boolean }) => {
localStorage.setItem('username', newState)
}
+ const saveNewProxy = () => {
+ if (!selectedProxy || proxyQs) return
+ localStorage.setItem('selectedProxy', selectedProxy)
+ }
+
useEffect(() => {
if (proxies.length) {
localStorage.setItem('proxies', JSON.stringify(proxies))
}
- if (selectedProxy) {
- localStorage.setItem('selectedProxy', selectedProxy)
- }
+ saveNewProxy()
}, [proxies])
- const [serversList, setServersList] = useState(() => getInitialServersList())
+ const [serversList, setServersList] = useState(() => (customServersList ? [] : getInitialServersList()))
const [additionalData, setAdditionalData] = useState>({})
+ useEffect(() => {
+ if (customServersList) {
+ setServersList(customServersList.map(row => {
+ const [ip, name] = row.split(' ')
+ const [_ip, _port, version] = ip.split(':')
+ return {
+ ip,
+ versionOverride: version,
+ name,
+ }
+ }))
+ }
+ }, [customServersList])
+
useDidUpdateEffect(() => {
// save data only on user changes
setNewServersList(serversList)
@@ -218,6 +241,16 @@ const Inner = ({ hidden }: { hidden?: boolean }) => {
}
}, [isEditScreenModal])
+ useCopyKeybinding(() => {
+ const item = serversList[selectedIndex]
+ if (!item) return
+ let str = `${item.ip}`
+ if (item.versionOverride) {
+ str += `:${item.versionOverride}`
+ }
+ return str
+ })
+
const editModalJsx = isEditScreenModal ? {
// setProxies([...proxies, selectedProxy])
localStorage.setItem('proxies', JSON.stringify([...proxies, selectedProxy]))
}
- if (selectedProxy) {
- localStorage.setItem('selectedProxy', selectedProxy)
- }
+ saveNewProxy()
},
serverIndex: shouldSave ? serversList.length.toString() : indexOrIp // assume last
} satisfies ConnectOptions
dispatchEvent(new CustomEvent('connect', { detail: options }))
// qsOptions
}}
+ lockedEditing={!!customServersList}
username={defaultUsername}
setUsername={setDefaultUsername}
setQuickConnectIp={setQuickConnectIp}
@@ -377,6 +409,9 @@ const Inner = ({ hidden }: { hidden?: boolean }) => {
setSelectedProxy(selected)
}}
hidden={hidden}
+ onRowSelect={(_, i) => {
+ setSelectedIndex(i)
+ }}
/>
return <>
{serversListJsx}
@@ -385,6 +420,24 @@ const Inner = ({ hidden }: { hidden?: boolean }) => {
}
export default () => {
+ const [customServersList, setCustomServersList] = useState(serversListQs ? [] : undefined)
+
+ useEffect(() => {
+ if (serversListQs) {
+ if (serversListQs.startsWith('http')) {
+ void fetch(serversListQs).then(async r => r.text()).then((text) => {
+ const isJson = serversListQs.endsWith('.json') ? true : serversListQs.endsWith('.txt') ? false : text.startsWith('[')
+ setCustomServersList(isJson ? JSON.parse(text) : text.split('\n').map(x => x.trim()).filter(x => x.trim().length > 0))
+ }).catch((err) => {
+ console.error(err)
+ alert(`Failed to get servers list file: ${err}`)
+ })
+ } else {
+ setCustomServersList(serversListQs.split(','))
+ }
+ }
+ }, [])
+
const modalStack = useSnapshot(activeModalStack)
const hasServersListModal = modalStack.some(x => x.reactType === 'serversList')
const editServerModalActive = useIsModalActive('editServer')
@@ -392,5 +445,5 @@ export default () => {
const eitherModal = isServersListModalActive || editServerModalActive
const render = eitherModal || hasServersListModal
- return render ? : null
+ return render ? : null
}
diff --git a/src/react/Singleplayer.tsx b/src/react/Singleplayer.tsx
index 893385fa6..024f77640 100644
--- a/src/react/Singleplayer.tsx
+++ b/src/react/Singleplayer.tsx
@@ -94,6 +94,7 @@ interface Props {
listStyle?: React.CSSProperties
setListHovered?: (hovered: boolean) => void
secondRowStyles?: React.CSSProperties
+ lockedEditing?: boolean
}
export default ({
@@ -116,7 +117,8 @@ export default ({
defaultSelectedRow,
listStyle,
setListHovered,
- secondRowStyles
+ secondRowStyles,
+ lockedEditing
}: Props) => {
const containerRef = useRef()
const firstButton = useRef(null)
@@ -213,10 +215,10 @@ export default ({
}
- {serversLayout ? : }
-
+ {serversLayout ? : }
+
{serversLayout ?
- :
+ :
}
diff --git a/src/react/mainMenu.module.css b/src/react/mainMenu.module.css
index db072ce1a..dcec47c3e 100644
--- a/src/react/mainMenu.module.css
+++ b/src/react/mainMenu.module.css
@@ -45,7 +45,7 @@
display: block;
position: absolute;
top: 37px;
- left: calc(88px + 5px);
+ left: calc((512px / 2 - 176px / 2) / 2);
background-image: url('../../assets/edition.png');
background-size: 128px;
width: 88px;
diff --git a/src/react/simpleHooks.ts b/src/react/simpleHooks.ts
index 9202bfa2b..da8dd9e0e 100644
--- a/src/react/simpleHooks.ts
+++ b/src/react/simpleHooks.ts
@@ -1,6 +1,27 @@
+import { useUtilsEffect } from '@zardoy/react-util'
import { useMedia } from 'react-use'
const SMALL_SCREEN_MEDIA = '@media (max-width: 440px)'
export const useIsSmallWidth = () => {
return useMedia(SMALL_SCREEN_MEDIA.replace('@media ', ''))
}
+
+export const useCopyKeybinding = (getCopyText: () => string | undefined) => {
+ useUtilsEffect(({ signal }) => {
+ addEventListener('keydown', (e) => {
+ if (e.code === 'KeyC' && (e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {
+ const { activeElement } = document
+ if (activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement) {
+ return
+ }
+ if (window.getSelection()?.toString()) {
+ return
+ }
+ e.preventDefault()
+ const copyText = getCopyText()
+ if (!copyText) return
+ void navigator.clipboard.writeText(copyText)
+ }
+ }, { signal })
+ }, [getCopyText])
+}
diff --git a/src/react/useLongPress.ts b/src/react/useLongPress.ts
index 3807221d0..49a1dec6a 100644
--- a/src/react/useLongPress.ts
+++ b/src/react/useLongPress.ts
@@ -31,9 +31,9 @@ const useLongPress = (
)
const clear = useCallback(
- (event: React.MouseEvent | React.TouchEvent, shouldTriggerClick = true) => {
+ (event: React.MouseEvent | React.TouchEvent) => {
if (timeout.current) clearTimeout(timeout.current)
- if (shouldTriggerClick && !longPressTriggered) onClick()
+ if (!longPressTriggered) onClick()
setLongPressTriggered(false)
if (shouldPreventDefault && target.current) {
target.current.removeEventListener('touchend', preventDefault)
@@ -46,7 +46,7 @@ const useLongPress = (
onMouseDown: (e: React.MouseEvent) => start(e),
onTouchStart: (e: React.TouchEvent) => start(e),
onMouseUp: (e: React.MouseEvent) => clear(e),
- onMouseLeave: (e: React.MouseEvent) => clear(e, false),
+ onMouseLeave: (e: React.MouseEvent) => clear(e),
onTouchEnd: (e: React.TouchEvent) => clear(e)
}
}
@@ -61,4 +61,3 @@ const preventDefault = (event: Event) => {
}
export default useLongPress
-
diff --git a/src/react/utilsApp.ts b/src/react/utilsApp.ts
index 53df4cda0..445007ec7 100644
--- a/src/react/utilsApp.ts
+++ b/src/react/utilsApp.ts
@@ -6,7 +6,8 @@ import { activeModalStack, miscUiState } from '../globalState'
export const watchedModalsFromHooks = new Set
()
// todo should not be there
export const hardcodedKnownModals = [
- 'player_win:'
+ 'player_win:',
+ 'full-map' // todo
]
export const useUsingTouch = () => {
@@ -17,6 +18,7 @@ export const useIsModalActive = (modal: string, useIncludes = false) => {
watchedModalsFromHooks.add(modal)
}, [])
useEffect(() => {
+ // watchedModalsFromHooks.add(modal)
return () => {
watchedModalsFromHooks.delete(modal)
}
diff --git a/src/reactUi.tsx b/src/reactUi.tsx
index 2fb63c197..f0144d140 100644
--- a/src/reactUi.tsx
+++ b/src/reactUi.tsx
@@ -19,6 +19,7 @@ import ScoreboardProvider from './react/ScoreboardProvider'
import SignEditorProvider from './react/SignEditorProvider'
import IndicatorEffectsProvider from './react/IndicatorEffectsProvider'
import PlayerListOverlayProvider from './react/PlayerListOverlayProvider'
+import MinimapProvider from './react/MinimapProvider'
import HudBarsProvider from './react/HudBarsProvider'
import XPBarProvider from './react/XPBarProvider'
import DebugOverlay from './react/DebugOverlay'
@@ -27,7 +28,7 @@ import PauseScreen from './react/PauseScreen'
import SoundMuffler from './react/SoundMuffler'
import TouchControls from './react/TouchControls'
import widgets from './react/widgets'
-import { useIsWidgetActive } from './react/utilsApp'
+import { useIsModalActive, useIsWidgetActive } from './react/utilsApp'
import GlobalSearchInput from './react/GlobalSearchInput'
import TouchAreasControlsProvider from './react/TouchAreasControlsProvider'
import NotificationProvider, { showNotification } from './react/NotificationProvider'
@@ -101,9 +102,13 @@ const InGameComponent = ({ children }) => {
const InGameUi = () => {
const { gameLoaded, showUI: showUIRaw } = useSnapshot(miscUiState)
- const { disabledUiParts, displayBossBars } = useSnapshot(options)
- const hasModals = useSnapshot(activeModalStack).length > 0
+ const { disabledUiParts, displayBossBars, showMinimap } = useSnapshot(options)
+ const modalsSnapshot = useSnapshot(activeModalStack)
+ const hasModals = modalsSnapshot.length > 0
const showUI = showUIRaw || hasModals
+ const displayFullmap = modalsSnapshot.some(modal => modal.reactType === 'full-map')
+ // bot can't be used here
+
if (!gameLoaded || !bot || disabledUiParts.includes('*')) return
return <>
@@ -116,6 +121,7 @@ const InGameUi = () => {
{!disabledUiParts.includes('players-list') && }
{!disabledUiParts.includes('chat') && }
+ {showMinimap !== 'never' && }
{!disabledUiParts.includes('title') && }
{!disabledUiParts.includes('scoreboard') && }
{!disabledUiParts.includes('effects-indicators') && }
@@ -137,6 +143,7 @@ const InGameUi = () => {
+ {displayFullmap && }
{/* because of z-index */}
{showUI && }
diff --git a/src/styles.css b/src/styles.css
index 817fae8ca..2c645ae92 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -119,7 +119,7 @@ body {
@font-face {
font-family: mojangles;
- src: url(../assets/mojangles.ttf);
+ src: url(../assets/mojangles.ttf?inline);
}
#ui-root {
@@ -181,6 +181,10 @@ body::xr-overlay #viewer-canvas {
color: #999;
}
+.text-select {
+ user-select: text;
+}
+
@media screen and (min-width: 430px) {
.span-2 {
grid-column: span 2;
diff --git a/src/topRightStats.ts b/src/topRightStats.ts
index 4bcd7264e..fd717ef48 100644
--- a/src/topRightStats.ts
+++ b/src/topRightStats.ts
@@ -88,13 +88,40 @@ export const statsEnd = () => {
// for advanced debugging, use with watch expression
+window.statsPerSecAvg = {}
+let currentStatsPerSec = {} as Record
+const waitingStatsPerSec = {}
+window.markStart = (label) => {
+ waitingStatsPerSec[label] ??= []
+ waitingStatsPerSec[label][0] = performance.now()
+}
+window.markEnd = (label) => {
+ if (!waitingStatsPerSec[label]?.[0]) return
+ currentStatsPerSec[label] ??= []
+ currentStatsPerSec[label].push(performance.now() - waitingStatsPerSec[label][0])
+ delete waitingStatsPerSec[label]
+}
+const updateStatsPerSecAvg = () => {
+ window.statsPerSecAvg = Object.fromEntries(Object.entries(currentStatsPerSec).map(([key, value]) => {
+ return [key, {
+ avg: value.reduce((a, b) => a + b, 0) / value.length,
+ count: value.length
+ }]
+ }))
+ currentStatsPerSec = {}
+}
+
+
window.statsPerSec = {}
-let statsPerSec = {}
+let statsPerSecCurrent = {}
window.addStatPerSec = (name) => {
- statsPerSec[name] ??= 0
- statsPerSec[name]++
+ statsPerSecCurrent[name] ??= 0
+ statsPerSecCurrent[name]++
}
+window.statsPerSecCurrent = statsPerSecCurrent
setInterval(() => {
- window.statsPerSec = statsPerSec
- statsPerSec = {}
+ window.statsPerSec = statsPerSecCurrent
+ statsPerSecCurrent = {}
+ window.statsPerSecCurrent = statsPerSecCurrent
+ updateStatsPerSecAvg()
}, 1000)
diff --git a/src/watchOptions.ts b/src/watchOptions.ts
index 4b69726c9..84092de27 100644
--- a/src/watchOptions.ts
+++ b/src/watchOptions.ts
@@ -96,6 +96,6 @@ export const watchOptionsAfterWorldViewInit = () => {
watchValue(options, o => {
if (!worldView) return
worldView.keepChunksDistance = o.keepChunksDistance
- worldView.handDisplay = o.handDisplay
+ viewer.world.config.displayHand = o.handDisplay
})
}
diff --git a/src/water.ts b/src/water.ts
index 2d3be46fd..94875e33d 100644
--- a/src/water.ts
+++ b/src/water.ts
@@ -31,9 +31,6 @@ customEvents.on('gameLoaded', () => {
let sceneBg = { r: 0, g: 0, b: 0 }
export const updateBackground = (newSceneBg = sceneBg) => {
sceneBg = newSceneBg
- if (inWater) {
- viewer.scene.background = new THREE.Color(0x00_00_ff)
- } else {
- viewer.scene.background = new THREE.Color(sceneBg.r, sceneBg.g, sceneBg.b)
- }
+ const color: [number, number, number] = inWater ? [0, 0, 1] : [sceneBg.r, sceneBg.g, sceneBg.b]
+ viewer.world.changeBackgroundColor(color)
}
diff --git a/src/worldInteractions.ts b/src/worldInteractions.ts
index dcd5dc3d0..1134d7f89 100644
--- a/src/worldInteractions.ts
+++ b/src/worldInteractions.ts
@@ -4,7 +4,7 @@ import * as THREE from 'three'
// wouldn't better to create atlas instead?
import { Vec3 } from 'vec3'
-import { LineMaterial, Wireframe, LineSegmentsGeometry } from 'three-stdlib'
+import { LineMaterial } from 'three-stdlib'
import { Entity } from 'prismarine-entity'
import destroyStage0 from '../assets/destroy_stage_0.png'
import destroyStage1 from '../assets/destroy_stage_1.png'
@@ -34,7 +34,6 @@ function getViewDirection (pitch, yaw) {
class WorldInteraction {
ready = false
- interactionLines: null | { blockPos; mesh } = null
prevBreakState
currentDigTime
prevOnGround
@@ -44,11 +43,9 @@ class WorldInteraction {
lastButtons = [false, false, false]
breakStartTime: number | undefined = 0
lastDugBlock: Vec3 | null = null
- cursorBlock: import('prismarine-block').Block | null = null
blockBreakMesh: THREE.Mesh
breakTextures: THREE.Texture[]
lastDigged: number
- lineMaterial: LineMaterial
debugDigStatus: string
oneTimeInit () {
@@ -109,10 +106,10 @@ class WorldInteraction {
})
beforeRenderFrame.push(() => {
- if (this.lineMaterial) {
+ if (viewer.world.threejsCursorLineMaterial) {
const { renderer } = viewer
- this.lineMaterial.resolution.set(renderer.domElement.width, renderer.domElement.height)
- this.lineMaterial.dashOffset = performance.now() / 750
+ viewer.world.threejsCursorLineMaterial.resolution.set(renderer.domElement.width, renderer.domElement.height)
+ viewer.world.threejsCursorLineMaterial.dashOffset = performance.now() / 750
}
})
}
@@ -133,7 +130,7 @@ class WorldInteraction {
this.debugDigStatus = 'done'
})
bot.on('diggingAborted', (block) => {
- if (!this.cursorBlock?.position.equals(block.position)) return
+ if (!viewer.world.cursorBlock?.equals(block.position)) return
this.debugDigStatus = 'aborted'
// if (this.lastDugBlock)
this.breakStartTime = undefined
@@ -151,7 +148,7 @@ class WorldInteraction {
const upLineMaterial = () => {
const inCreative = bot.game.gameMode === 'creative'
const pixelRatio = viewer.renderer.getPixelRatio()
- this.lineMaterial = new LineMaterial({
+ viewer.world.threejsCursorLineMaterial = new LineMaterial({
color: inCreative ? 0x40_80_ff : 0x00_00_00,
linewidth: Math.max(pixelRatio * 0.7, 1) * 2,
// dashed: true,
@@ -192,34 +189,6 @@ class WorldInteraction {
}
}
- updateBlockInteractionLines (blockPos: Vec3 | null, shapePositions?: Array<{ position; width; height; depth }>) {
- assertDefined(viewer)
- if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) {
- return
- }
- if (this.interactionLines !== null) {
- viewer.scene.remove(this.interactionLines.mesh)
- this.interactionLines = null
- }
- if (blockPos === null) {
- return
- }
-
- const group = new THREE.Group()
- for (const { position, width, height, depth } of shapePositions ?? []) {
- const scale = [1.0001 * width, 1.0001 * height, 1.0001 * depth] as const
- const geometry = new THREE.BoxGeometry(...scale)
- const lines = new LineSegmentsGeometry().fromEdgesGeometry(new THREE.EdgesGeometry(geometry))
- const wireframe = new Wireframe(lines, this.lineMaterial)
- const pos = blockPos.plus(position)
- wireframe.position.set(pos.x, pos.y, pos.z)
- wireframe.computeLineDistances()
- group.add(wireframe)
- }
- viewer.scene.add(group)
- this.interactionLines = { blockPos, mesh: group }
- }
-
// todo this shouldnt be done in the render loop, migrate the code to dom events to avoid delays on lags
update () {
const inSpectator = bot.game.gameMode === 'spectator'
@@ -232,10 +201,7 @@ class WorldInteraction {
let cursorBlockDiggable = cursorBlock
if (cursorBlock && !bot.canDigBlock(cursorBlock) && bot.game.gameMode !== 'creative') cursorBlockDiggable = null
- let cursorChanged = !cursorBlock !== !this.cursorBlock
- if (cursorBlock && this.cursorBlock) {
- cursorChanged = !cursorBlock.position.equals(this.cursorBlock.position)
- }
+ const cursorChanged = cursorBlock && viewer.world.cursorBlock ? !viewer.world.cursorBlock.equals(cursorBlock.position) : viewer.world.cursorBlock !== cursorBlock
// Place / interact / activate
if (this.buttons[2] && this.lastBlockPlaced >= 4) {
@@ -291,8 +257,8 @@ class WorldInteraction {
bot.lookAt = oldLookAt
}).catch(console.warn)
}
- viewer.world.changeHandSwingingState(true)
- viewer.world.changeHandSwingingState(false)
+ viewer.world.changeHandSwingingState(true, false)
+ viewer.world.changeHandSwingingState(false, false)
} else if (!stop) {
const offhand = activate ? false : activatableItems(bot.inventory.slots[45]?.name ?? '')
bot.activateItem(offhand) // todo offhand
@@ -351,42 +317,36 @@ class WorldInteraction {
})
customEvents.emit('digStart')
this.lastDigged = Date.now()
- viewer.world.changeHandSwingingState(true)
+ viewer.world.changeHandSwingingState(true, false)
} else if (performance.now() - this.lastSwing > 200) {
bot.swingArm('right')
this.lastSwing = performance.now()
}
}
if (!this.buttons[0] && this.lastButtons[0]) {
- viewer.world.changeHandSwingingState(false)
+ viewer.world.changeHandSwingingState(false, false)
}
this.prevOnGround = onGround
// Show cursor
+ const allShapes = [...cursorBlock?.shapes ?? [], ...cursorBlock?.['interactionShapes'] ?? []]
if (cursorBlock) {
- const allShapes = [...cursorBlock.shapes, ...cursorBlock['interactionShapes'] ?? []]
- this.updateBlockInteractionLines(cursorBlock.position, allShapes.map(shape => {
- return getDataFromShape(shape)
- }))
- {
- // union of all values
- const breakShape = allShapes.reduce((acc, cur) => {
- return [
- Math.min(acc[0], cur[0]),
- Math.min(acc[1], cur[1]),
- Math.min(acc[2], cur[2]),
- Math.max(acc[3], cur[3]),
- Math.max(acc[4], cur[4]),
- Math.max(acc[5], cur[5])
- ]
- })
- const { position, width, height, depth } = getDataFromShape(breakShape)
- this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001)
- position.add(cursorBlock.position)
- this.blockBreakMesh.position.set(position.x, position.y, position.z)
- }
- } else {
- this.updateBlockInteractionLines(null)
+ // BREAK MESH
+ // union of all values
+ const breakShape = allShapes.reduce((acc, cur) => {
+ return [
+ Math.min(acc[0], cur[0]),
+ Math.min(acc[1], cur[1]),
+ Math.min(acc[2], cur[2]),
+ Math.max(acc[3], cur[3]),
+ Math.max(acc[4], cur[4]),
+ Math.max(acc[5], cur[5])
+ ]
+ })
+ const { position, width, height, depth } = getDataFromShape(breakShape)
+ this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001)
+ position.add(cursorBlock.position)
+ this.blockBreakMesh.position.set(position.x, position.y, position.z)
}
// Show break animation
@@ -411,7 +371,11 @@ class WorldInteraction {
}
// Update state
- this.cursorBlock = cursorBlock
+ if (cursorChanged) {
+ viewer.world.setHighlightCursorBlock(cursorBlock?.position ?? null, allShapes.map(shape => {
+ return getDataFromShape(shape)
+ }))
+ }
this.lastButtons[0] = this.buttons[0]
this.lastButtons[1] = this.buttons[1]
this.lastButtons[2] = this.buttons[2]
diff --git a/tsconfig.json b/tsconfig.json
index 3c20075c1..addc64f19 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -29,6 +29,6 @@
"prismarine-viewer/examples"
],
"exclude": [
- "node_modules",
+ "node_modules"
]
}