minecraft-renderer 0.1.92 → 0.1.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/minecraft-renderer.js +68 -68
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +522 -522
- package/package.json +1 -1
- package/src/graphicsBackend/appViewer.ts +4 -3
- package/src/graphicsBackend/config.ts +1 -1
- package/src/graphicsBackend/types.ts +4 -1
- package/src/lib/worldrendererCommon.ts +3 -3
- package/src/three/entities.ts +329 -43
- package/src/three/entity/EntityMesh.ts +8 -3
- package/src/three/entity/animations.js +37 -25
- package/src/three/entity/animations.test.ts +249 -0
- package/src/three/entity/boatModelRotation.test.ts +29 -0
- package/src/three/entity/boatModelRotation.ts +14 -0
- package/src/three/entity/boatPaddleAnimation.test.ts +108 -0
- package/src/three/entity/boatPaddleAnimation.ts +104 -0
- package/src/three/entity/boatPassengerRendering.ts +20 -0
- package/src/three/entity/boatPassengerRotation.test.ts +166 -0
- package/src/three/entity/boatPassengerRotation.ts +71 -0
- package/src/three/entity/boatRenderSetup.test.ts +236 -0
- package/src/three/entity/boatRenderSetup.ts +214 -0
- package/src/three/entity/entityHeadPose.test.ts +15 -0
- package/src/three/entity/entityHeadPose.ts +22 -0
- package/src/three/entity/horseEntityScale.test.ts +11 -0
- package/src/three/entity/horseEntityScale.ts +9 -0
- package/src/three/entity/horseHeadAnimation.test.ts +159 -0
- package/src/three/entity/horseHeadAnimation.ts +151 -0
- package/src/three/entity/horsePassengerRendering.test.ts +77 -0
- package/src/three/entity/interpolationPolicy.test.ts +259 -0
- package/src/three/entity/interpolationPolicy.ts +187 -0
- package/src/three/entity/localHorseCameraYawLock.test.ts +72 -0
- package/src/three/entity/localVehicleRendering.integration.test.ts +247 -0
- package/src/three/entity/minecartLocalPassengerRendering.test.ts +208 -0
- package/src/three/entity/networkHeadPitchRendering.test.ts +102 -0
- package/src/three/entity/networkHeadPitchRendering.ts +44 -0
- package/src/three/entity/remoteBoatPassengerRotation.integration.test.ts +227 -0
- package/src/three/entity/remoteBoatPassengerRotation.ts +128 -0
- package/src/three/entity/vehiclePassengerProduction.test.ts +214 -0
- package/src/three/entity/vehiclePassengerRendering.ts +56 -0
- package/src/three/entity/vehiclePassengerUpdate.ts +82 -0
- package/src/three/graphicsBackendBase.ts +5 -5
- package/src/three/graphicsBackendOffThread.ts +2 -2
- package/src/three/worldRendererThree.ts +54 -27
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { isBoatEntityName } from './boatModelRotation'
|
|
3
|
+
import {
|
|
4
|
+
getBoatPassengerWorldPosition,
|
|
5
|
+
getHorsePassengerWorldPosition,
|
|
6
|
+
getMinecartPassengerWorldPosition,
|
|
7
|
+
isRideableHorseEntityName,
|
|
8
|
+
isRideableMinecartEntityName,
|
|
9
|
+
type EntityRenderHints,
|
|
10
|
+
type Vec3Like
|
|
11
|
+
} from './interpolationPolicy'
|
|
12
|
+
import {
|
|
13
|
+
anchorVehiclePassengerPosition,
|
|
14
|
+
isFiniteVec3,
|
|
15
|
+
releaseVehiclePassengerPosition,
|
|
16
|
+
shouldSkipLocalPassengerAnchoring,
|
|
17
|
+
type VehiclePassengerRenderState
|
|
18
|
+
} from './vehiclePassengerRendering'
|
|
19
|
+
|
|
20
|
+
export type VehiclePassengerSceneEntity = VehiclePassengerRenderState & {
|
|
21
|
+
playerObject?: unknown
|
|
22
|
+
originalEntity: { id: number }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type VehiclePassengerVehicle = {
|
|
26
|
+
originalEntity: { id: number | string; name: string; height?: number }
|
|
27
|
+
userData: { renderHints?: EntityRenderHints }
|
|
28
|
+
rotation: { y: number }
|
|
29
|
+
realName?: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function updateVehiclePassengerPositions(args: {
|
|
33
|
+
entities: Record<string, VehiclePassengerSceneEntity | VehiclePassengerVehicle>
|
|
34
|
+
localPlayer: VehiclePassengerSceneEntity | null
|
|
35
|
+
getWorldPosition: (target: unknown) => Vec3Like | undefined
|
|
36
|
+
}): Set<VehiclePassengerSceneEntity> {
|
|
37
|
+
const attachedPassengers = new Set<VehiclePassengerSceneEntity>()
|
|
38
|
+
|
|
39
|
+
for (const entity of Object.values(args.entities)) {
|
|
40
|
+
const vehicle = entity as VehiclePassengerVehicle
|
|
41
|
+
const renderHints = vehicle.userData.renderHints
|
|
42
|
+
const passengerIds = renderHints?.passengerIds ?? renderHints?.boatPassengerIds
|
|
43
|
+
if (!Array.isArray(passengerIds) || passengerIds.length === 0) continue
|
|
44
|
+
|
|
45
|
+
const vehicleName = vehicle.realName ?? vehicle.originalEntity.name
|
|
46
|
+
const layout = renderHints?.passengerLayout ?? (isBoatEntityName(vehicleName) ? 'boat' : undefined)
|
|
47
|
+
if (layout !== 'boat' && layout !== 'minecart' && layout !== 'horse') continue
|
|
48
|
+
if (layout === 'boat' && !isBoatEntityName(vehicleName)) continue
|
|
49
|
+
if (layout === 'minecart' && !isRideableMinecartEntityName(vehicleName)) continue
|
|
50
|
+
if (layout === 'horse' && !isRideableHorseEntityName(vehicleName)) continue
|
|
51
|
+
|
|
52
|
+
const vehicleWorldPos = args.getWorldPosition(vehicle)
|
|
53
|
+
if (!isFiniteVec3(vehicleWorldPos)) continue
|
|
54
|
+
const vehicleId = String(vehicle.originalEntity.id)
|
|
55
|
+
|
|
56
|
+
for (const [passengerIndex, passengerId] of passengerIds.entries()) {
|
|
57
|
+
const isLocalPassenger = passengerId === args.localPlayer?.originalEntity.id
|
|
58
|
+
const passenger = isLocalPassenger ? args.localPlayer : (args.entities[passengerId] as VehiclePassengerSceneEntity | undefined)
|
|
59
|
+
if (!passenger?.playerObject) continue
|
|
60
|
+
if (passenger === args.localPlayer && shouldSkipLocalPassengerAnchoring(layout)) continue
|
|
61
|
+
|
|
62
|
+
const passengerWorldPos =
|
|
63
|
+
layout === 'minecart'
|
|
64
|
+
? getMinecartPassengerWorldPosition(vehicleWorldPos)
|
|
65
|
+
: layout === 'horse'
|
|
66
|
+
? getHorsePassengerWorldPosition(vehicleWorldPos, vehicleName, vehicle.originalEntity.height ?? 1.6)
|
|
67
|
+
: getBoatPassengerWorldPosition(vehicleWorldPos, vehicle.rotation.y, passengerIndex, passengerIds.length)
|
|
68
|
+
|
|
69
|
+
if (!isFiniteVec3(passengerWorldPos)) continue
|
|
70
|
+
anchorVehiclePassengerPosition(passenger, passengerWorldPos, vehicleId)
|
|
71
|
+
attachedPassengers.add(passenger)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
for (const passenger of [...Object.values(args.entities), ...(args.localPlayer ? [args.localPlayer] : [])] as VehiclePassengerSceneEntity[]) {
|
|
76
|
+
const vehicleId = passenger.userData._passengerVehicleId ?? (passenger.userData._boatPassengerVehicleId as string | undefined)
|
|
77
|
+
if (vehicleId === undefined || attachedPassengers.has(passenger)) continue
|
|
78
|
+
releaseVehiclePassengerPosition(passenger, vehicleId, args.getWorldPosition(passenger))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return attachedPassengers
|
|
82
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import * as THREE from 'three'
|
|
10
10
|
import { Vec3 } from 'vec3'
|
|
11
|
-
import type { GraphicsBackend, GraphicsInitOptions, DisplayWorldOptions } from '../graphicsBackend'
|
|
11
|
+
import type { GraphicsBackend, GraphicsInitOptions, DisplayWorldOptions, UpdateCameraOptions } from '../graphicsBackend'
|
|
12
12
|
import { createWorkerProxy, restoreTransferred } from '../lib/workerProxy'
|
|
13
13
|
import { ResourcesManager } from '../resourcesManager'
|
|
14
14
|
import { FrameTimingCollector } from '../lib/frameTimingCollector'
|
|
@@ -280,10 +280,10 @@ export const createGraphicsBackendBase = () => {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
}),
|
|
283
|
-
updateCamera(pos: Vec3 | null, yaw: number, pitch: number) {
|
|
283
|
+
updateCamera(pos: Vec3 | null, yaw: number, pitch: number, options?: UpdateCameraOptions) {
|
|
284
284
|
// Mark camera update event for frame timing visualization
|
|
285
285
|
frameTimingCollector?.markCameraUpdate(!pos)
|
|
286
|
-
worldRenderer?.setFirstPersonCamera(pos, yaw, pitch)
|
|
286
|
+
worldRenderer?.setFirstPersonCamera(pos, yaw, pitch, options)
|
|
287
287
|
},
|
|
288
288
|
get soundSystem() {
|
|
289
289
|
return worldRenderer?.soundSystem
|
|
@@ -311,10 +311,10 @@ export const createGraphicsBackendBase = () => {
|
|
|
311
311
|
startWorld,
|
|
312
312
|
disconnect,
|
|
313
313
|
setRendering: backend.setRendering,
|
|
314
|
-
updateCamera(pos, yaw, pitch) {
|
|
314
|
+
updateCamera(pos, yaw, pitch, options?: UpdateCameraOptions) {
|
|
315
315
|
const posVec = pos ? new Vec3(pos.x, pos.y, pos.z) : null
|
|
316
316
|
frameTimingCollector?.markCameraUpdate(!posVec)
|
|
317
|
-
backend.updateCamera(posVec, yaw, pitch)
|
|
317
|
+
backend.updateCamera(posVec, yaw, pitch, options)
|
|
318
318
|
},
|
|
319
319
|
async callBackendMethod<K extends keyof ThreeJsBackendMethods>(
|
|
320
320
|
method: K,
|
|
@@ -154,8 +154,8 @@ export const createGraphicsBackendOffThread: GraphicsBackendLoader = async initO
|
|
|
154
154
|
setRendering(rendering) {
|
|
155
155
|
proxy.setRendering(rendering)
|
|
156
156
|
},
|
|
157
|
-
updateCamera(pos, yaw, pitch) {
|
|
158
|
-
proxy.updateCamera(pos ? { x: pos.x, y: pos.y, z: pos.z } : null, yaw, pitch)
|
|
157
|
+
updateCamera(pos, yaw, pitch, options) {
|
|
158
|
+
proxy.updateCamera(pos ? { x: pos.x, y: pos.y, z: pos.z } : null, yaw, pitch, options)
|
|
159
159
|
},
|
|
160
160
|
soundSystem: undefined,
|
|
161
161
|
backendMethods: backendMethodsProxy
|
|
@@ -16,11 +16,18 @@ import { getMyHand } from './hand'
|
|
|
16
16
|
import { createHoldingBlock } from './holdingBlockFactory'
|
|
17
17
|
import type { IHoldingBlock } from './holdingBlockTypes'
|
|
18
18
|
import { getMesh } from './entity/EntityMesh'
|
|
19
|
+
import { resolveEntityHeadPose } from './entity/entityHeadPose'
|
|
19
20
|
import { armorModel } from './entity/armorModels'
|
|
20
21
|
import { disposeObject, loadThreeJsTextureFromBitmap } from './threeJsUtils'
|
|
21
22
|
import { CursorBlock } from './world/cursorBlock'
|
|
22
23
|
import { getItemUv } from './appShared'
|
|
23
24
|
import { Entities } from './entities'
|
|
25
|
+
import {
|
|
26
|
+
getCameraMovementTweenDurationMs,
|
|
27
|
+
shouldRestartCameraPositionTween,
|
|
28
|
+
type CameraMovementMode,
|
|
29
|
+
type UpdateCameraOptions
|
|
30
|
+
} from './entity/interpolationPolicy'
|
|
24
31
|
import { ThreeJsSound } from './threeJsSound'
|
|
25
32
|
import { CameraShake } from './cameraShake'
|
|
26
33
|
import { ThreeJsMedia } from './threeJsMedia'
|
|
@@ -160,6 +167,8 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
160
167
|
|
|
161
168
|
private currentPosTween?: tweenJs.Tween<{ x: number; y: number; z: number }>
|
|
162
169
|
private currentRotTween?: tweenJs.Tween<{ pitch: number; yaw: number }>
|
|
170
|
+
private currentCameraTarget: { x: number; y: number; z: number } | null = null
|
|
171
|
+
private currentCameraMovementMode: CameraMovementMode | null = null
|
|
163
172
|
|
|
164
173
|
// Pre-allocated objects for getThirdPersonCamera (avoid per-frame allocs)
|
|
165
174
|
private readonly _tpDirection = new THREE.Vector3()
|
|
@@ -492,17 +501,18 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
492
501
|
}
|
|
493
502
|
|
|
494
503
|
updateEntity(e, isPosUpdate = false) {
|
|
504
|
+
const headPose = resolveEntityHeadPose(e)
|
|
495
505
|
const overrides = {
|
|
496
506
|
rotation: {
|
|
497
507
|
head: {
|
|
498
|
-
x:
|
|
499
|
-
y:
|
|
508
|
+
x: headPose.pitch,
|
|
509
|
+
y: headPose.headYaw,
|
|
500
510
|
z: 0
|
|
501
511
|
}
|
|
502
512
|
}
|
|
503
513
|
}
|
|
504
514
|
if (isPosUpdate) {
|
|
505
|
-
this.entities.updateEntityPosition(e, false, overrides)
|
|
515
|
+
this.entities.updateEntityPosition(e, false, overrides, e.headRotationOnly === true)
|
|
506
516
|
} else {
|
|
507
517
|
this.entities.update(e, overrides)
|
|
508
518
|
}
|
|
@@ -584,6 +594,9 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
584
594
|
this.onReactiveConfigUpdated('futuristicReveal', () => {
|
|
585
595
|
this.updateModulesFromConfig()
|
|
586
596
|
})
|
|
597
|
+
this.onReactiveDebugUpdated('disableEntities', () => {
|
|
598
|
+
this.entities.syncSceneAttachment()
|
|
599
|
+
})
|
|
587
600
|
|
|
588
601
|
let currentHandRenderer = this.displayOptions.inWorldRenderingConfig.handRenderer
|
|
589
602
|
this.onReactiveConfigUpdated('handRenderer', value => {
|
|
@@ -990,10 +1003,10 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
990
1003
|
}
|
|
991
1004
|
}
|
|
992
1005
|
|
|
993
|
-
setFirstPersonCamera(pos: Vec3 | null, yaw: number, pitch: number) {
|
|
1006
|
+
setFirstPersonCamera(pos: Vec3 | null, yaw: number, pitch: number, options?: UpdateCameraOptions) {
|
|
994
1007
|
const yOffset = this.playerStateReactive.eyeHeight
|
|
995
1008
|
|
|
996
|
-
this.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch)
|
|
1009
|
+
this.updateCamera(pos?.offset(0, yOffset, 0) ?? null, yaw, pitch, options)
|
|
997
1010
|
// this.media.tryIntersectMedia()
|
|
998
1011
|
this.updateCameraSectionPos()
|
|
999
1012
|
}
|
|
@@ -1149,34 +1162,50 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
1149
1162
|
}
|
|
1150
1163
|
}
|
|
1151
1164
|
|
|
1152
|
-
updateCamera(pos: Vec3 | null, yaw: number, pitch: number): void {
|
|
1165
|
+
updateCamera(pos: Vec3 | null, yaw: number, pitch: number, options?: UpdateCameraOptions): void {
|
|
1153
1166
|
// Skip position/rotation updates if cinematic script is running
|
|
1154
1167
|
if (this.cinimaticScript.running) {
|
|
1155
1168
|
return
|
|
1156
1169
|
}
|
|
1157
1170
|
|
|
1158
|
-
// if (this.freeFlyMode) {
|
|
1159
|
-
// pos = this.freeFlyState.position
|
|
1160
|
-
// pitch = this.freeFlyState.pitch
|
|
1161
|
-
// yaw = this.freeFlyState.yaw
|
|
1162
|
-
// }
|
|
1163
|
-
|
|
1164
1171
|
if (pos) {
|
|
1165
1172
|
if (this.renderer.xr.isPresenting) {
|
|
1166
1173
|
pos.y -= this.camera.position.y // Fix Y position of camera in world
|
|
1167
1174
|
}
|
|
1168
1175
|
|
|
1169
|
-
this.
|
|
1170
|
-
|
|
1171
|
-
const
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
.
|
|
1175
|
-
|
|
1176
|
+
const movementMode: CameraMovementMode = this.playerStateUtils.isSpectatingEntity() ? 'spectating' : (options?.movementMode ?? 'local-player')
|
|
1177
|
+
const instant = options?.instant === true || this.displayOptions.inWorldRenderingConfig.instantCameraUpdate === true
|
|
1178
|
+
const target = { x: pos.x, y: pos.y, z: pos.z }
|
|
1179
|
+
const restartTween = shouldRestartCameraPositionTween({
|
|
1180
|
+
target,
|
|
1181
|
+
currentTarget: this.currentCameraTarget,
|
|
1182
|
+
movementMode,
|
|
1183
|
+
previousMovementMode: this.currentCameraMovementMode,
|
|
1184
|
+
instant
|
|
1185
|
+
})
|
|
1186
|
+
const tweenDelay = getCameraMovementTweenDurationMs(movementMode, instant)
|
|
1187
|
+
|
|
1188
|
+
if (restartTween) {
|
|
1189
|
+
this.currentCameraTarget = { ...target }
|
|
1190
|
+
this.currentCameraMovementMode = movementMode
|
|
1191
|
+
this.currentPosTween?.stop()
|
|
1192
|
+
if (instant || tweenDelay === 0) {
|
|
1193
|
+
this.cameraWorldPos.x = target.x
|
|
1194
|
+
this.cameraWorldPos.y = target.y
|
|
1195
|
+
this.cameraWorldPos.z = target.z
|
|
1196
|
+
this.sceneOrigin.update(target.x, target.y, target.z)
|
|
1176
1197
|
this.cameraObject.position.set(0, 0, 0)
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1198
|
+
this.currentPosTween = undefined
|
|
1199
|
+
} else {
|
|
1200
|
+
this.currentPosTween = new tweenJs.Tween(this.cameraWorldPos)
|
|
1201
|
+
.to(target, tweenDelay)
|
|
1202
|
+
.onUpdate(() => {
|
|
1203
|
+
this.sceneOrigin.update(this.cameraWorldPos.x, this.cameraWorldPos.y, this.cameraWorldPos.z)
|
|
1204
|
+
this.cameraObject.position.set(0, 0, 0)
|
|
1205
|
+
})
|
|
1206
|
+
.start()
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1180
1209
|
}
|
|
1181
1210
|
|
|
1182
1211
|
if (this.playerStateUtils.isSpectatingEntity()) {
|
|
@@ -1363,11 +1392,9 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|
|
1363
1392
|
this.chunkMeshManager.clearCullDirty()
|
|
1364
1393
|
}
|
|
1365
1394
|
this.chunkMeshManager.updateCaveCullingDebug(this.reactiveDebugParams.caveCullingDebug, smartCull)
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
entitiesRenderMs = performance.now() - entitiesStart
|
|
1370
|
-
}
|
|
1395
|
+
const entitiesStart = performance.now()
|
|
1396
|
+
this.entities.render()
|
|
1397
|
+
entitiesRenderMs = performance.now() - entitiesStart
|
|
1371
1398
|
this.chunkMeshManager.sortVisibleBlendSections(camX, camY, camZ)
|
|
1372
1399
|
if (!didBlendAllAttrUpload && globalLegacyBlendBuffer?.hasPendingIndexUploads()) {
|
|
1373
1400
|
globalLegacyBlendBuffer.uploadDirtyIndexRange()
|