From 7d67171ef2a8d6eebfc91d751cae06a9ab0e45a1 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Sat, 6 Jan 2024 04:00:58 +0530 Subject: [PATCH] fix: rework block interaction display (use temporary experimental styles) --- prismarine-viewer/viewer/lib/models.ts | 9 ++- src/globals.d.ts | 3 +- src/index.ts | 4 +- ...ldInteractions.js => worldInteractions.ts} | 76 ++++++++++++------- 4 files changed, 62 insertions(+), 30 deletions(-) rename src/{worldInteractions.js => worldInteractions.ts} (86%) diff --git a/prismarine-viewer/viewer/lib/models.ts b/prismarine-viewer/viewer/lib/models.ts index 6ec70bd2..07147aa4 100644 --- a/prismarine-viewer/viewer/lib/models.ts +++ b/prismarine-viewer/viewer/lib/models.ts @@ -6,7 +6,12 @@ import { Block } from 'prismarine-block' const tints: any = {} let blockStates: BlockStatesOutput -const tintsData = require('esbuild-data').tints +let tintsData +try { + tintsData = require('esbuild-data').tints +} catch (err) { + tintsData = require("minecraft-data/minecraft-data/data/pc/1.16.2/tints.json") +} for (const key of Object.keys(tintsData)) { tints[key] = prepareTints(tintsData[key]) } @@ -391,7 +396,7 @@ 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++) { const block = world.getBlock(cursor)! - if (block.name.includes('sign')) { + if (block.name.includes('_sign')) { const key = `${cursor.x},${cursor.y},${cursor.z}` const props: any = block.getProperties() const facingRotationMap = { diff --git a/src/globals.d.ts b/src/globals.d.ts index e7753d1a..aae0c3f9 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -12,8 +12,9 @@ declare const mcData: Record declare const loadedData: import('minecraft-data').IndexedData declare const customEvents: import('typed-emitter').default<{ singleplayer (): void - digStart() + digStart () }> +declare const beforeRenderFrame: Array<() => void> declare interface Document { getElementById (id): any diff --git a/src/index.ts b/src/index.ts index 7d6f8f62..3fdeaf0e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -89,6 +89,7 @@ import EventEmitter from 'events' window.debug = debug window.THREE = THREE window.customEvents = new EventEmitter() +window.beforeRenderFrame = [] // ACTUAL CODE @@ -134,6 +135,7 @@ let max = 0 let rendered = 0 const renderFrame = (time: DOMHighResTimeStamp) => { if (window.stopLoop) return + for (const fn of beforeRenderFrame) fn() window.requestAnimationFrame(renderFrame) if (window.stopRender || renderer.xr.isPresenting) return if (renderInterval) { @@ -510,7 +512,7 @@ async function connect (connectOptions: { onBotCreate() bot.once('login', () => { - worldInteractions.init() + worldInteractions.initBot() // server is ok, add it to the history if (!connectOptions.server) return diff --git a/src/worldInteractions.js b/src/worldInteractions.ts similarity index 86% rename from src/worldInteractions.js rename to src/worldInteractions.ts index c86680f7..23abb520 100644 --- a/src/worldInteractions.js +++ b/src/worldInteractions.ts @@ -13,6 +13,7 @@ import destroyStage8 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/de import destroyStage9 from 'minecraft-assets/minecraft-assets/data/1.10/blocks/destroy_stage_9.png' import { Vec3 } from 'vec3' +import { LineMaterial, Wireframe, LineSegmentsGeometry } from 'three-stdlib' import { isGameActive } from './globalState' import { assertDefined } from './utils' @@ -25,33 +26,22 @@ function getViewDirection (pitch, yaw) { } class WorldInteraction { - static instance = null // todo implement - /** @type {null | {blockPos,mesh}} */ - interactionLines = null + ready = false + interactionLines: null | { blockPos; mesh } = null prevBreakState currentDigTime prevOnGround - /** @type {number} */ - lastBlockPlaced + lastBlockPlaced: number buttons = [false, false, false] lastButtons = [false, false, false] - /** @type {number | undefined} */ - breakStartTime = 0 - /** @type {import('prismarine-block').Block | null} */ - cursorBlock = null - /** @type {THREE.Mesh} */ - blockBreakMesh - - init () { - assertDefined(viewer) - bot.on('physicsTick', () => { if (this.lastBlockPlaced < 4) this.lastBlockPlaced++ }) - bot.on('diggingCompleted', () => { - this.breakStartTime = undefined - }) - bot.on('diggingAborted', () => { - this.breakStartTime = undefined - }) + breakStartTime: number | undefined = 0 + cursorBlock: import('prismarine-block').Block | null = null + blockBreakMesh: THREE.Mesh + breakTextures: THREE.Texture[] + lastDigged: number + lineMaterial: LineMaterial + oneTimeInit () { const loader = new THREE.TextureLoader() this.breakTextures = [] const destroyStagesImages = [ @@ -118,9 +108,32 @@ class WorldInteraction { bot.attack(entity) } }) + + beforeRenderFrame.push(() => { + if (this.lineMaterial) { + const { renderer } = viewer + this.lineMaterial.resolution.set(renderer.domElement.width, renderer.domElement.height) + this.lineMaterial.dashOffset = performance.now() / 750 + } + }) } - updateBlockInteractionLines (/** @type {Vec3 | null} */blockPos, /** @type {{position, width, height, depth}[] | undefined} */shapePositions = undefined) { + initBot () { + if (!this.ready) { + this.ready = true + this.oneTimeInit() + } + assertDefined(viewer) + bot.on('physicsTick', () => { if (this.lastBlockPlaced < 4) this.lastBlockPlaced++ }) + bot.on('diggingCompleted', () => { + this.breakStartTime = undefined + }) + bot.on('diggingAborted', () => { + this.breakStartTime = undefined + }) + } + + updateBlockInteractionLines (blockPos: Vec3 | null, shapePositions?: Array<{ position; width; height; depth }>) { assertDefined(viewer) if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) { return @@ -136,11 +149,22 @@ class WorldInteraction { const group = new THREE.Group() //@ts-expect-error for (const { position, width, height, depth } of shapePositions) { - const geometry = new THREE.BoxGeometry(1.001 * width, 1.001 * height, 1.001 * depth) - const mesh = new THREE.LineSegments(new THREE.EdgesGeometry(geometry), new THREE.LineBasicMaterial({ color: 0 })) + 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 inSelect = true + this.lineMaterial ??= new LineMaterial({ + color: inSelect ? 0x40_80_ff : 0x00_00_00, + linewidth: 8, + dashed: true, + dashSize: 5, + }) + const wireframe = new Wireframe(lines, this.lineMaterial) const pos = blockPos.plus(position) - mesh.position.set(pos.x, pos.y, pos.z) - group.add(mesh) + wireframe.position.set(pos.x, pos.y, pos.z) + wireframe.computeLineDistances() + wireframe.scale.set(...scale) + group.add(wireframe) } viewer.scene.add(group) this.interactionLines = { blockPos, mesh: group }