minecraft-renderer 0.1.46 → 0.1.48

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.
@@ -22,6 +22,19 @@ export type RendererOptionMeta = {
22
22
 
23
23
  export type RendererDefaultOptionKey = keyof typeof RENDERER_DEFAULT_OPTIONS
24
24
 
25
+ export type RendererMesherPipeline = 'wasm' | 'legacy-js'
26
+
27
+ export type RendererGpuPreference = 'default' | 'high-performance' | 'low-power'
28
+
29
+ /** Maps stored `gpuPreference` to WebGL `powerPreference` (undefined = browser default). */
30
+ export function gpuPreferenceToWebGLPowerPreference(
31
+ preference: RendererGpuPreference
32
+ ): 'high-performance' | 'low-power' | undefined {
33
+ if (preference === 'high-performance') return 'high-performance'
34
+ if (preference === 'low-power') return 'low-power'
35
+ return undefined
36
+ }
37
+
25
38
  const MB = MENU_BACKGROUND_OPTION_DEFAULTS
26
39
 
27
40
  /** Default values for options owned by minecraft-renderer (spread into app `defaultOptions`). */
@@ -39,9 +52,53 @@ export const RENDERER_DEFAULT_OPTIONS = {
39
52
  menuBackgroundFuturisticBlockSpeed: MB.futuristicBlockSpeedPercent,
40
53
  rendererFuturisticReveal: false,
41
54
  rendererPerfDebugOverlay: false,
42
- disableBlockEntityTextures: false
55
+ disableBlockEntityTextures: false,
56
+ rendererMesher: 'wasm' as RendererMesherPipeline,
57
+ showChunkBorders: false,
58
+ renderEntities: true,
59
+ renderDebug: 'basic' as 'none' | 'basic' | 'advanced',
60
+ frameLimit: false as number | false,
61
+ backgroundRendering: '20fps' as 'full' | '20fps' | '5fps',
62
+ vanillaLook: false,
63
+ smoothLighting: true,
64
+ newVersionsLighting: false,
65
+ vrSupport: true,
66
+ vrPageGameRendering: false,
67
+ clipWorldBelowY: undefined as number | undefined,
68
+ highlightBlockColor: 'auto' as 'auto' | 'blue' | 'classic',
69
+ loadPlayerSkins: true,
70
+ renderEars: true,
71
+ showHand: true,
72
+ viewBobbing: true,
73
+ dayCycleAndLighting: true,
74
+ keepChunksDistance: 1,
75
+ gpuPreference: 'default' as RendererGpuPreference,
76
+ fov: 75
43
77
  } as const
44
78
 
79
+ /** App options storage shape for renderer-owned keys. */
80
+ export type RendererStorageOptions = typeof RENDERER_DEFAULT_OPTIONS
81
+
82
+ /**
83
+ * Migrate persisted / legacy option keys into current {@link RENDERER_DEFAULT_OPTIONS} shape.
84
+ * Call when loading saved settings (safe to run on every load).
85
+ */
86
+ export function migrateRendererOptions(saved: Record<string, unknown>): void {
87
+ if (saved.highPerformanceGpu) {
88
+ saved.gpuPreference = 'high-performance'
89
+ delete saved.highPerformanceGpu
90
+ }
91
+ if (saved.rendererMesher !== 'wasm' && saved.rendererMesher !== 'legacy-js') {
92
+ if (typeof saved.rendererWasmMesher === 'boolean') {
93
+ saved.rendererMesher = saved.rendererWasmMesher ? 'wasm' : 'legacy-js'
94
+ } else if (typeof saved.wasmExperimentalMesher === 'boolean') {
95
+ saved.rendererMesher = saved.wasmExperimentalMesher ? 'wasm' : 'legacy-js'
96
+ }
97
+ }
98
+ delete saved.wasmExperimentalMesher
99
+ delete saved.rendererWasmMesher
100
+ }
101
+
45
102
  /** Settings UI metadata for {@link RENDERER_DEFAULT_OPTIONS} keys. */
46
103
  export const RENDERER_OPTIONS_META: Partial<Record<RendererDefaultOptionKey, RendererOptionMeta>> = {
47
104
  menuBackgroundMode: {
@@ -102,6 +159,89 @@ export const RENDERER_OPTIONS_META: Partial<Record<RendererDefaultOptionKey, Ren
102
159
  disableBlockEntityTextures: {
103
160
  text: 'Disable block entity textures',
104
161
  tooltip: 'Skips signs, banners, heads, maps, etc.'
162
+ },
163
+ rendererMesher: {
164
+ possibleValues: [['wasm', 'WASM'], ['legacy-js', 'Legacy JS']],
165
+ text: 'Mesher pipeline',
166
+ tooltip: 'WASM is faster. Use JS if WASM is not working. Requires reload.',
167
+ requiresRestart: true
168
+ },
169
+ showChunkBorders: {
170
+ text: 'Chunk borders'
171
+ },
172
+ renderEntities: {
173
+ text: 'Render entities'
174
+ },
175
+ renderDebug: {
176
+ possibleValues: ['advanced', 'basic', 'none']
177
+ },
178
+ frameLimit: {
179
+ text: 'Frame limit',
180
+ tooltip: 'false = VSync / unlimited when focused'
181
+ },
182
+ backgroundRendering: {
183
+ text: 'Background FPS limit',
184
+ possibleValues: [
185
+ ['full', 'NO'],
186
+ ['5fps', '5 FPS'],
187
+ ['20fps', '20 FPS']
188
+ ]
189
+ },
190
+ vanillaLook: {
191
+ text: 'Vanilla shading',
192
+ tooltip: 'On: Minecraft-style face shading. Off: higher-contrast client shading.'
193
+ },
194
+ smoothLighting: {},
195
+ newVersionsLighting: {
196
+ text: 'Lighting in newer versions'
197
+ },
198
+ vrSupport: {
199
+ text: 'VR support',
200
+ tooltip: 'Shows VR entry; does not force VR on.'
201
+ },
202
+ vrPageGameRendering: {
203
+ text: 'VR page game rendering'
204
+ },
205
+ clipWorldBelowY: {
206
+ text: 'Clip world below Y'
207
+ },
208
+ highlightBlockColor: {
209
+ possibleValues: [
210
+ ['auto', 'Auto'],
211
+ ['blue', 'Blue'],
212
+ ['classic', 'Classic']
213
+ ]
214
+ },
215
+ loadPlayerSkins: {},
216
+ renderEars: {
217
+ tooltip: 'Deadmau5 ears when the skin texture includes them'
218
+ },
219
+ showHand: {},
220
+ viewBobbing: {},
221
+ dayCycleAndLighting: {
222
+ text: 'Day cycle'
223
+ },
224
+ keepChunksDistance: {
225
+ text: 'Keep chunks distance',
226
+ tooltip: 'Extra distance before unloading chunks',
227
+ max: 5,
228
+ unit: ''
229
+ },
230
+ fov: {
231
+ min: 30,
232
+ max: 110,
233
+ unit: '°',
234
+ text: 'Field of view'
235
+ },
236
+ gpuPreference: {
237
+ text: 'GPU preference',
238
+ tooltip: 'WebGL power preference. Requires reload / backend restart to apply.',
239
+ requiresRestart: true,
240
+ possibleValues: [
241
+ ['default', 'Auto'],
242
+ ['high-performance', 'Dedicated'],
243
+ ['low-power', 'Low power']
244
+ ]
105
245
  }
106
246
  }
107
247
 
@@ -110,32 +250,58 @@ export const RENDERER_RENDER_GUI_SECTIONS: ReadonlyArray<{
110
250
  title: string
111
251
  keys: readonly RendererDefaultOptionKey[]
112
252
  }> = [
113
- {
114
- title: 'Menu background',
115
- keys: [
116
- 'menuBackgroundMode',
117
- 'menuBackgroundMinecraftTextures',
118
- 'menuBackgroundFuturisticScene',
119
- 'menuBackgroundFuturisticCamera',
120
- 'menuBackgroundFuturisticBlockGroup',
121
- 'menuBackgroundFuturisticCameraSpeed',
122
- 'menuBackgroundFuturisticBlockSpeed'
123
- ]
124
- },
125
- {
126
- title: 'World rendering',
127
- keys: [
128
- 'rendererWorldPerformance',
129
- 'starfieldRendering',
130
- 'defaultSkybox',
131
- 'disableBlockEntityTextures'
132
- ]
133
- },
134
- {
135
- title: 'Renderer debug',
136
- keys: [
137
- 'rendererFuturisticReveal',
138
- 'rendererPerfDebugOverlay'
139
- ]
140
- }
141
- ]
253
+ {
254
+ title: 'World rendering',
255
+ keys: [
256
+ 'rendererWorldPerformance',
257
+ 'starfieldRendering',
258
+ 'defaultSkybox',
259
+ 'disableBlockEntityTextures',
260
+ 'showChunkBorders',
261
+ 'renderEntities',
262
+ 'smoothLighting',
263
+ 'vanillaLook',
264
+ 'newVersionsLighting',
265
+ 'dayCycleAndLighting',
266
+ 'loadPlayerSkins',
267
+ 'renderEars',
268
+ 'showHand',
269
+ 'viewBobbing',
270
+ 'fov',
271
+ 'keepChunksDistance',
272
+ 'highlightBlockColor',
273
+ 'clipWorldBelowY'
274
+ ]
275
+ },
276
+ {
277
+ title: 'Frame pacing',
278
+ keys: ['frameLimit', 'backgroundRendering', 'renderDebug', 'gpuPreference']
279
+ },
280
+ {
281
+ title: 'VR',
282
+ keys: ['vrSupport', 'vrPageGameRendering']
283
+ },
284
+ {
285
+ title: 'Menu background',
286
+ keys: [
287
+ 'menuBackgroundMode',
288
+ 'menuBackgroundMinecraftTextures',
289
+ 'menuBackgroundFuturisticScene',
290
+ 'menuBackgroundFuturisticCamera',
291
+ 'menuBackgroundFuturisticBlockGroup',
292
+ 'menuBackgroundFuturisticCameraSpeed',
293
+ 'menuBackgroundFuturisticBlockSpeed'
294
+ ]
295
+ },
296
+ {
297
+ title: 'Mesher',
298
+ keys: ['rendererMesher']
299
+ },
300
+ {
301
+ title: 'Renderer debug',
302
+ keys: [
303
+ 'rendererFuturisticReveal',
304
+ 'rendererPerfDebugOverlay'
305
+ ]
306
+ }
307
+ ]
@@ -31,6 +31,14 @@ export {
31
31
  export {
32
32
  RENDERER_DEFAULT_OPTIONS,
33
33
  RENDERER_OPTIONS_META,
34
- RENDERER_RENDER_GUI_SECTIONS
34
+ RENDERER_RENDER_GUI_SECTIONS,
35
+ migrateRendererOptions
35
36
  } from './defaultOptions'
36
- export type { RendererDefaultOptionKey, RendererOptionMeta } from './defaultOptions'
37
+ export type {
38
+ RendererDefaultOptionKey,
39
+ RendererGpuPreference,
40
+ RendererMesherPipeline,
41
+ RendererOptionMeta,
42
+ RendererStorageOptions
43
+ } from './defaultOptions'
44
+ export { gpuPreferenceToWebGLPowerPreference } from './defaultOptions'
@@ -1,32 +1,11 @@
1
1
  //@ts-nocheck
2
2
  import * as THREE from 'three'
3
3
  import type { WorldRendererThree } from './worldRendererThree'
4
+ import type { ExportedSection, ExportedWorldGeometry } from '../mesher-shared/exportedGeometryTypes'
4
5
 
5
- const GEOMETRY_EXPORT_GROUP_NAME = 'geometry-export-root'
6
-
7
- // Format for exported world geometry
8
- export interface ExportedWorldGeometry {
9
- version: string
10
- exportedAt: string
11
- camera: {
12
- position: { x: number, y: number, z: number }
13
- rotation: { pitch: number, yaw: number }
14
- }
15
- sections: ExportedSection[]
16
- textureAtlasDataUrl?: string
17
- }
6
+ export type { ExportedSection, ExportedWorldGeometry } from '../mesher-shared/exportedGeometryTypes'
18
7
 
19
- export interface ExportedSection {
20
- key: string
21
- position: { x: number, y: number, z: number }
22
- geometry: {
23
- positions: number[]
24
- normals: number[]
25
- colors: number[]
26
- uvs: number[]
27
- indices: number[]
28
- }
29
- }
8
+ const GEOMETRY_EXPORT_GROUP_NAME = 'geometry-export-root'
30
9
 
31
10
  /**
32
11
  * Export world geometry to a downloadable file
@@ -65,6 +65,9 @@ export class WorldRendererThree extends WorldRendererCommon {
65
65
  cursorBlock: CursorBlock
66
66
  onRender: Array<(deltaTime: number) => void> = []
67
67
  private lastRenderTime = 0
68
+ private animatedFov = 0
69
+ private lastFovAnimTime = 0
70
+ private static readonly FOV_TRANSITION_MS = 200
68
71
  cameraShake: CameraShake
69
72
  cameraContainer!: THREE.Object3D
70
73
  media: ThreeJsMedia
@@ -1055,10 +1058,42 @@ export class WorldRendererThree extends WorldRendererCommon {
1055
1058
  }
1056
1059
 
1057
1060
  setCinimaticFov(fov: number): void {
1061
+ this.animatedFov = fov
1058
1062
  this.camera.fov = fov
1059
1063
  this.camera.updateProjectionMatrix()
1060
1064
  }
1061
1065
 
1066
+ private updateSmoothFov(): void {
1067
+ if (this.cinimaticScript.running) return
1068
+
1069
+ const baseFov = this.displayOptions.inWorldRenderingConfig.fov
1070
+ const mult = this.playerStateReactive.fovMultiplier
1071
+ const targetFov = baseFov * (Number.isFinite(mult) ? mult : 1)
1072
+
1073
+ const now = performance.now()
1074
+ if (this.animatedFov === 0) {
1075
+ this.animatedFov = targetFov
1076
+ }
1077
+
1078
+ if (Math.abs(this.animatedFov - targetFov) >= 0.01) {
1079
+ const elapsed = now - this.lastFovAnimTime
1080
+ const progress = Math.min(elapsed / WorldRendererThree.FOV_TRANSITION_MS, 1)
1081
+ const easeOutCubic = (t: number) => 1 - (1 - t) ** 3
1082
+ this.animatedFov += (targetFov - this.animatedFov) * easeOutCubic(progress)
1083
+ if (Math.abs(this.animatedFov - targetFov) < 0.01) {
1084
+ this.animatedFov = targetFov
1085
+ }
1086
+ } else {
1087
+ this.animatedFov = targetFov
1088
+ }
1089
+ this.lastFovAnimTime = now
1090
+
1091
+ if (this.camera.fov !== this.animatedFov) {
1092
+ this.camera.fov = this.animatedFov
1093
+ this.camera.updateProjectionMatrix()
1094
+ }
1095
+ }
1096
+
1062
1097
  updateCamera(pos: Vec3 | null, yaw: number, pitch: number): void {
1063
1098
  // Skip position/rotation updates if cinematic script is running
1064
1099
  if (this.cinimaticScript.running) {
@@ -1200,11 +1235,10 @@ export class WorldRendererThree extends WorldRendererCommon {
1200
1235
  const cameraPos = this.getCameraPosition()
1201
1236
  this.skyboxRenderer.update(cameraPos, this.viewDistance)
1202
1237
 
1203
- const sizeOrFovChanged = sizeChanged || this.displayOptions.inWorldRenderingConfig.fov !== this.camera.fov
1204
- if (sizeOrFovChanged) {
1238
+ this.updateSmoothFov()
1239
+ if (sizeChanged) {
1205
1240
  const size = this.renderer.getSize(new THREE.Vector2())
1206
1241
  this.camera.aspect = size.width / size.height
1207
- this.camera.fov = this.displayOptions.inWorldRenderingConfig.fov
1208
1242
  this.camera.updateProjectionMatrix()
1209
1243
  }
1210
1244
 
@@ -10,11 +10,12 @@ import MinecraftData from 'minecraft-data'
10
10
  import PrismarineBlockLoader from 'prismarine-block'
11
11
  import { Vec3 } from 'vec3'
12
12
  import { elemFaces, buildRotationMatrix, matmul3, matmulmat3, vecadd3, vecsub3 } from '../../mesher-shared/modelsGeometryCommon'
13
- import type { ExportedWorldGeometry, ExportedSection } from '../../three/worldGeometryExport'
13
+ import type { ExportedWorldGeometry, ExportedSection } from '../../mesher-shared/exportedGeometryTypes'
14
14
  import type { MesherGeometryOutput } from '../../mesher-shared/shared'
15
15
  import type { World } from '../../mesher-shared/world'
16
- import { resolveBlockPropertiesForMeshing } from '../../mesher-shared/models'
16
+ import { resolveBlockPropertiesForMeshing } from '../../mesher-shared/blockPropertiesForMeshing'
17
17
  import { getSideShading, vertexLightFromAo } from '../../mesher-shared/vertexShading'
18
+ import tintsJson from 'minecraft-data/minecraft-data/data/pc/1.16.2/tints.json'
18
19
 
19
20
  // Handle both default and named export
20
21
  const worldBlockProvider = (worldBlockProviderModule as any).default || worldBlockProviderModule
@@ -25,14 +26,8 @@ let tintsInitialized = false
25
26
 
26
27
  function initializeTints() {
27
28
  if (tintsInitialized) return
28
- let tintsData
29
- try {
30
- tintsData = require('esbuild-data').tints
31
- } catch (err) {
32
- tintsData = require('minecraft-data/minecraft-data/data/pc/1.16.2/tints.json')
33
- }
34
- for (const key of Object.keys(tintsData)) {
35
- tints[key] = prepareTints(tintsData[key])
29
+ for (const key of Object.keys(tintsJson as Record<string, unknown>)) {
30
+ tints[key] = prepareTints((tintsJson as Record<string, unknown>)[key])
36
31
  }
37
32
  tintsInitialized = true
38
33
  }