Skip to content

Commit 5adbce3

Browse files
committed
pick changes from webgpu:
fix cursor lines fix background color change
1 parent 0b72ea6 commit 5adbce3

File tree

13 files changed

+151
-44
lines changed

13 files changed

+151
-44
lines changed

renderer/buildMesherWorker.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const buildOptions = {
2222
},
2323
platform: 'browser',
2424
entryPoints: [path.join(__dirname, './viewer/lib/mesher/mesher.ts')],
25-
minify: true,
25+
minify: !watch,
2626
logLevel: 'info',
2727
drop: !watch ? [
2828
'debugger'
@@ -39,7 +39,7 @@ const buildOptions = {
3939
...mesherSharedPlugins,
4040
{
4141
name: 'external-json',
42-
setup (build) {
42+
setup(build) {
4343
build.onResolve({ filter: /\.json$/ }, args => {
4444
const fileName = args.path.split('/').pop().replace('.json', '')
4545
if (args.resolveDir.includes('minecraft-data')) {

renderer/playground.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@
1111

1212
html, body {
1313
height: 100%;
14+
touch-action: none;
1415

1516
margin: 0;
1617
padding: 0;
1718
}
1819

20+
* {
21+
user-select: none;
22+
-webkit-user-select: none;
23+
}
24+
1925
canvas {
2026
height: 100%;
2127
width: 100%;

renderer/viewer/lib/basePlayerState.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export type PlayerStateEvents = {
1414
heldItemChanged: (item: HandItemBlock | undefined, isLeftHand: boolean) => void
1515
}
1616

17+
export type BlockShape = { position: any; width: any; height: any; depth: any; }
18+
export type BlocksShapes = BlockShape[]
19+
1720
export interface IPlayerState {
1821
getEyeHeight(): number
1922
getMovementState(): MovementState
@@ -39,6 +42,21 @@ export interface IPlayerState {
3942
ambientLight: number
4043
directionalLight: number
4144
gameMode?: GameMode
45+
lookingAtBlock?: {
46+
x: number
47+
y: number
48+
z: number
49+
face?: number
50+
shapes: BlocksShapes
51+
}
52+
diggingBlock?: {
53+
x: number
54+
y: number
55+
z: number
56+
stage: number
57+
face?: number
58+
mergedShape?: BlockShape
59+
}
4260
}
4361
}
4462

renderer/viewer/lib/ui/newStats.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ let lastY = 40
77
export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) => {
88
const pane = document.createElement('div')
99
pane.style.position = 'fixed'
10-
pane.style.top = `${y}px`
10+
pane.style.top = `${y ?? lastY}px`
1111
pane.style.right = `${x}px`
1212
// gray bg
1313
pane.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'
@@ -19,7 +19,7 @@ export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) =
1919
pane.style.pointerEvents = 'none'
2020
document.body.appendChild(pane)
2121
stats[id] = pane
22-
if (y === 0) { // otherwise it's a custom position
22+
if (y === undefined && x === rightOffset) { // otherwise it's a custom position
2323
// rightOffset += width
2424
lastY += 20
2525
}
@@ -35,6 +35,50 @@ export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) =
3535
}
3636
}
3737

38+
export const addNewStat2 = (id: string, { top, bottom, right, left, displayOnlyWhenWider }: { top?: number, bottom?: number, right?: number, left?: number, displayOnlyWhenWider?: number }) => {
39+
if (top === undefined && bottom === undefined) top = 0
40+
const pane = document.createElement('div')
41+
pane.style.position = 'fixed'
42+
if (top !== undefined) {
43+
pane.style.top = `${top}px`
44+
}
45+
if (bottom !== undefined) {
46+
pane.style.bottom = `${bottom}px`
47+
}
48+
if (left !== undefined) {
49+
pane.style.left = `${left}px`
50+
}
51+
if (right !== undefined) {
52+
pane.style.right = `${right}px`
53+
}
54+
// gray bg
55+
pane.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'
56+
pane.style.color = 'white'
57+
pane.style.padding = '2px'
58+
pane.style.fontFamily = 'monospace'
59+
pane.style.fontSize = '12px'
60+
pane.style.zIndex = '10000'
61+
pane.style.pointerEvents = 'none'
62+
document.body.appendChild(pane)
63+
stats[id] = pane
64+
65+
const resizeCheck = () => {
66+
if (!displayOnlyWhenWider) return
67+
pane.style.display = window.innerWidth > displayOnlyWhenWider ? 'block' : 'none'
68+
}
69+
window.addEventListener('resize', resizeCheck)
70+
resizeCheck()
71+
72+
return {
73+
updateText (text: string) {
74+
pane.innerText = text
75+
},
76+
setVisibility (visible: boolean) {
77+
pane.style.display = visible ? 'block' : 'none'
78+
}
79+
}
80+
}
81+
3882
export const updateStatText = (id, text) => {
3983
if (!stats[id]) return
4084
stats[id].innerText = text

renderer/viewer/lib/workerProxy.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
export function createWorkerProxy<T extends Record<string, (...args: any[]) => void>> (handlers: T): { __workerProxy: T } {
2-
addEventListener('message', (event) => {
1+
export function createWorkerProxy<T extends Record<string, (...args: any[]) => void>> (handlers: T, channel?: MessagePort): { __workerProxy: T } {
2+
const target = channel ?? globalThis
3+
target.addEventListener('message', (event: any) => {
34
const { type, args } = event.data
45
if (handlers[type]) {
56
handlers[type](...args)
@@ -19,7 +20,7 @@ export function createWorkerProxy<T extends Record<string, (...args: any[]) => v
1920
* const workerChannel = useWorkerProxy<typeof importedTypeWorkerProxy>(worker)
2021
* ```
2122
*/
22-
export const useWorkerProxy = <T extends { __workerProxy: Record<string, (...args: any[]) => void> }> (worker: Worker, autoTransfer = true): T['__workerProxy'] & {
23+
export const useWorkerProxy = <T extends { __workerProxy: Record<string, (...args: any[]) => void> }> (worker: Worker | MessagePort, autoTransfer = true): T['__workerProxy'] & {
2324
transfer: (...args: Transferable[]) => T['__workerProxy']
2425
} => {
2526
// in main thread
@@ -40,11 +41,11 @@ export const useWorkerProxy = <T extends { __workerProxy: Record<string, (...arg
4041
}
4142
}
4243
return (...args: any[]) => {
43-
const transfer = autoTransfer ? args.filter(arg => arg instanceof ArrayBuffer || arg instanceof MessagePort || arg instanceof ImageBitmap || arg instanceof OffscreenCanvas) : []
44+
const transfer = autoTransfer ? args.filter(arg => arg instanceof ArrayBuffer || arg instanceof MessagePort || arg instanceof ImageBitmap || arg instanceof OffscreenCanvas || arg instanceof ImageData) : []
4445
worker.postMessage({
4546
type: prop,
4647
args,
47-
}, transfer)
48+
}, transfer as any[])
4849
}
4950
}
5051
})

renderer/viewer/lib/worldrendererCommon.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export const defaultWorldRendererConfig = {
5353
export type WorldRendererConfig = typeof defaultWorldRendererConfig
5454

5555
export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any> {
56+
timeOfTheDay = 0
5657
worldSizeParams = { minY: 0, worldHeight: 256 }
5758

5859
active = false
@@ -184,7 +185,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
184185
if (this.mainThreadRendering) {
185186
this.fpsUpdate()
186187
}
187-
}, 1000)
188+
}, 500)
188189
}
189190

190191
fpsUpdate () {
@@ -495,10 +496,23 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
495496
}
496497

497498
getMesherConfig (): MesherConfig {
499+
let skyLight = 15
500+
const timeOfDay = this.timeOfTheDay
501+
if (timeOfDay < 0 || timeOfDay > 24_000) {
502+
//
503+
} else if (timeOfDay <= 6000 || timeOfDay >= 18_000) {
504+
skyLight = 15
505+
} else if (timeOfDay > 6000 && timeOfDay < 12_000) {
506+
skyLight = 15 - ((timeOfDay - 6000) / 6000) * 15
507+
} else if (timeOfDay >= 12_000 && timeOfDay < 18_000) {
508+
skyLight = ((timeOfDay - 12_000) / 6000) * 15
509+
}
510+
511+
skyLight = Math.floor(skyLight)
498512
return {
499513
version: this.version,
500514
enableLighting: this.worldRendererConfig.enableLighting,
501-
skyLight: 15,
515+
skyLight,
502516
smoothLighting: this.worldRendererConfig.smoothLighting,
503517
outputFormat: this.outputFormat,
504518
textureSize: this.resourcesManager.currentResources!.blocksAtlasParser.atlas.latest.width,
@@ -608,7 +622,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
608622
this.logWorkerWork(`-> unloadChunk ${JSON.stringify({ x, z })}`)
609623
delete this.finishedChunks[`${x},${z}`]
610624
this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength
611-
if (!this.allChunksFinished) {
625+
if (Object.keys(this.finishedChunks).length === 0) {
612626
this.allLoadedIn = undefined
613627
this.initialChunkLoadWasStartedIn = undefined
614628
}
@@ -735,18 +749,11 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
735749
worldEmitter.on('time', (timeOfDay) => {
736750
this.timeUpdated?.(timeOfDay)
737751

738-
let skyLight = 15
739752
if (timeOfDay < 0 || timeOfDay > 24_000) {
740753
throw new Error('Invalid time of day. It should be between 0 and 24000.')
741-
} else if (timeOfDay <= 6000 || timeOfDay >= 18_000) {
742-
skyLight = 15
743-
} else if (timeOfDay > 6000 && timeOfDay < 12_000) {
744-
skyLight = 15 - ((timeOfDay - 6000) / 6000) * 15
745-
} else if (timeOfDay >= 12_000 && timeOfDay < 18_000) {
746-
skyLight = ((timeOfDay - 12_000) / 6000) * 15
747754
}
748755

749-
skyLight = Math.floor(skyLight) // todo: remove this after optimization
756+
this.timeOfTheDay = timeOfDay
750757

751758
// if (this.worldRendererConfig.skyLight === skyLight) return
752759
// this.worldRendererConfig.skyLight = skyLight

renderer/viewer/three/graphicsBackend.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ const getBackendMethods = (worldRenderer: WorldRendererThree) => {
1919
playEntityAnimation: worldRenderer.entities.playAnimation.bind(worldRenderer.entities),
2020
damageEntity: worldRenderer.entities.handleDamageEvent.bind(worldRenderer.entities),
2121
updatePlayerSkin: worldRenderer.entities.updatePlayerSkin.bind(worldRenderer.entities),
22-
setHighlightCursorBlock: worldRenderer.cursorBlock.setHighlightCursorBlock.bind(worldRenderer.cursorBlock),
23-
updateBreakAnimation: worldRenderer.cursorBlock.updateBreakAnimation.bind(worldRenderer.cursorBlock),
2422
changeHandSwingingState: worldRenderer.changeHandSwingingState.bind(worldRenderer),
2523
getHighestBlocks: worldRenderer.getHighestBlocks.bind(worldRenderer),
2624
rerenderAllChunks: worldRenderer.rerenderAllChunks.bind(worldRenderer),

renderer/viewer/three/world/cursorBlock.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { LineMaterial, LineSegmentsGeometry, Wireframe } from 'three-stdlib'
33
import { Vec3 } from 'vec3'
44
import { subscribeKey } from 'valtio/utils'
55
import { Block } from 'prismarine-block'
6+
import { BlockShape, BlocksShapes } from 'renderer/viewer/lib/basePlayerState'
67
import { WorldRendererThree } from '../worldrendererThree'
78
import destroyStage0 from '../../../../assets/destroy_stage_0.png'
89
import destroyStage1 from '../../../../assets/destroy_stage_1.png'
@@ -89,15 +90,13 @@ export class CursorBlock {
8990
this.prevColor = this.worldRenderer.worldRendererConfig.highlightBlockColor
9091
}
9192

92-
updateBreakAnimation (block: Block | undefined, stage: number | null) {
93+
updateBreakAnimation (blockPosition: { x: number, y: number, z: number } | undefined, stage: number | null, mergedShape?: BlockShape) {
9394
this.hideBreakAnimation()
94-
if (stage === null || !block) return
95+
if (stage === null || !blockPosition || !mergedShape) return
9596

96-
const mergedShape = bot.mouse.getMergedCursorShape(block)
97-
if (!mergedShape) return
98-
const { position, width, height, depth } = bot.mouse.getDataFromShape(mergedShape)
97+
const { position, width, height, depth } = mergedShape
9998
this.blockBreakMesh.scale.set(width * 1.001, height * 1.001, depth * 1.001)
100-
position.add(block.position)
99+
position.add(blockPosition)
101100
this.blockBreakMesh.position.set(position.x, position.y, position.z)
102101
this.blockBreakMesh.visible = true;
103102

@@ -119,7 +118,7 @@ export class CursorBlock {
119118
}
120119
}
121120

122-
setHighlightCursorBlock (blockPos: Vec3 | null, shapePositions?: Array<{ position: any; width: any; height: any; depth: any; }>): void {
121+
setHighlightCursorBlock (blockPos: Vec3 | null, shapePositions?: BlocksShapes): void {
123122
if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) {
124123
return
125124
}
@@ -143,7 +142,7 @@ export class CursorBlock {
143142
group.add(wireframe)
144143
}
145144
this.worldRenderer.scene.add(group)
146-
group.visible = this.cursorLinesHidden
145+
group.visible = !this.cursorLinesHidden
147146
this.interactionLines = { blockPos, mesh: group }
148147
}
149148

renderer/viewer/three/worldrendererThree.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ export class WorldRendererThree extends WorldRendererCommon {
140140
}
141141

142142
override watchReactivePlayerState () {
143+
super.watchReactivePlayerState()
143144
this.onReactiveValueUpdated('inWater', (value) => {
144145
this.scene.fog = value ? new THREE.Fog(0x00_00_ff, 0.1, this.displayOptions.playerState.reactive.waterBreathing ? 100 : 20) : null
145146
})
@@ -151,6 +152,12 @@ export class WorldRendererThree extends WorldRendererCommon {
151152
if (!value) return
152153
this.directionalLight.intensity = value
153154
})
155+
this.onReactiveValueUpdated('lookingAtBlock', (value) => {
156+
this.cursorBlock.setHighlightCursorBlock(value ? new Vec3(value.x, value.y, value.z) : null, value?.shapes)
157+
})
158+
this.onReactiveValueUpdated('diggingBlock', (value) => {
159+
this.cursorBlock.updateBreakAnimation(value ? { x: value.x, y: value.y, z: value.z } : undefined, value?.stage ?? null, value?.mergedShape)
160+
})
154161
}
155162

156163
changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) {

src/appViewer.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ export class AppViewer {
155155
}
156156
}
157157

158+
async startWithBot () {
159+
const renderDistance = miscUiState.singleplayer ? options.renderDistance : options.multiplayerRenderDistance
160+
await this.startWorld(bot.world, renderDistance)
161+
this.worldView!.listenToBot(bot)
162+
}
163+
158164
async startWorld (world, renderDistance: number, playerStateSend: IPlayerState = this.playerState) {
159165
if (this.currentDisplay === 'world') throw new Error('World already started')
160166
this.currentDisplay = 'world'
@@ -185,11 +191,7 @@ export class AppViewer {
185191
}
186192

187193
resetBackend (cleanState = false) {
188-
if (cleanState) {
189-
this.currentState = undefined
190-
this.currentDisplay = null
191-
this.worldView = undefined
192-
}
194+
this.disconnectBackend(cleanState)
193195
if (this.backendLoader) {
194196
this.loadBackend(this.backendLoader)
195197
}
@@ -216,7 +218,12 @@ export class AppViewer {
216218
this.resourcesManager.destroy()
217219
}
218220

219-
disconnectBackend () {
221+
disconnectBackend (cleanState = false) {
222+
if (cleanState) {
223+
this.currentState = undefined
224+
this.currentDisplay = null
225+
this.worldView = undefined
226+
}
220227
if (this.backend) {
221228
this.backend.disconnect()
222229
this.backend = undefined
@@ -225,7 +232,7 @@ export class AppViewer {
225232
const { promise, resolve } = Promise.withResolvers<void>()
226233
this.worldReady = promise
227234
this.resolveWorldReady = resolve
228-
Object.assign(this.rendererState, getDefaultRendererState())
235+
this.rendererState = proxy(getDefaultRendererState())
229236
// this.queuedDisplay = undefined
230237
}
231238

src/appViewerLoad.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@ const animLoop = () => {
3737
requestAnimationFrame(animLoop)
3838

3939
watchOptionsAfterViewerInit()
40+
41+
// reset backend when renderer changes
42+
43+
subscribeKey(options, 'activeRenderer', () => {
44+
if (appViewer.currentDisplay === 'world' && bot) {
45+
appViewer.resetBackend(true)
46+
loadBackend()
47+
void appViewer.startWithBot()
48+
}
49+
})

0 commit comments

Comments
 (0)