minecraft-renderer 0.1.34 → 0.1.35

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.
@@ -149,43 +149,49 @@ const addNametag = (entity, options: { fontFamily: string }, mesh, version: stri
149
149
  c.removeFromParent()
150
150
  }
151
151
  }
152
- if (entity.username !== undefined && !entity.username.startsWith('EMPTY')) {
153
- const canvas = getUsernameTexture(entity, options, version)
154
- if (!canvas) return
155
- const tex = new THREE.Texture(canvas)
156
- tex.needsUpdate = true
157
- let nameTag: THREE.Object3D
158
- if (entity.nameTagFixed) {
159
- const geometry = new THREE.PlaneGeometry()
160
- const material = new THREE.MeshBasicMaterial({ map: tex })
161
- material.transparent = true
162
- nameTag = new THREE.Mesh(geometry, material)
163
- nameTag.rotation.set(entity.pitch, THREE.MathUtils.degToRad(entity.yaw + 180), 0)
164
- nameTag.position.y += entity.height + 0.3
165
- } else {
166
- const spriteMat = new THREE.SpriteMaterial({ map: tex })
167
- nameTag = new THREE.Sprite(spriteMat)
168
- nameTag.position.y += entity.height + 0.6
169
- }
170
- nameTag.renderOrder = 1000
171
- nameTag.scale.set(canvas.width * 0.005, canvas.height * 0.005, 1)
172
- if (entity.nameTagRotationRight) {
173
- nameTag.applyQuaternion(entity.nameTagRotationRight)
174
- }
175
- if (entity.nameTagScale) {
176
- nameTag.scale.multiply(entity.nameTagScale)
177
- }
178
- if (entity.nameTagRotationLeft) {
179
- nameTag.applyQuaternion(entity.nameTagRotationLeft)
180
- }
181
- if (entity.nameTagTranslation) {
182
- nameTag.position.add(entity.nameTagTranslation)
183
- }
184
- nameTag.name = 'nametag'
185
-
186
- mesh.add(nameTag)
187
- return nameTag
152
+ if (entity.username === undefined || entity.username === null) return
153
+
154
+ const plainUsername =
155
+ typeof entity.username === 'string'
156
+ ? entity.username
157
+ : new (PrismarineChatLoader(version))(entity.username).toString()
158
+ if (plainUsername.startsWith('EMPTY')) return
159
+
160
+ const canvas = getUsernameTexture(entity, options, version)
161
+ if (!canvas) return
162
+ const tex = new THREE.Texture(canvas)
163
+ tex.needsUpdate = true
164
+ let nameTag: THREE.Object3D
165
+ if (entity.nameTagFixed) {
166
+ const geometry = new THREE.PlaneGeometry()
167
+ const material = new THREE.MeshBasicMaterial({ map: tex })
168
+ material.transparent = true
169
+ nameTag = new THREE.Mesh(geometry, material)
170
+ nameTag.rotation.set(entity.pitch, THREE.MathUtils.degToRad(entity.yaw + 180), 0)
171
+ nameTag.position.y += entity.height + 0.3
172
+ } else {
173
+ const spriteMat = new THREE.SpriteMaterial({ map: tex })
174
+ nameTag = new THREE.Sprite(spriteMat)
175
+ nameTag.position.y += entity.height + 0.6
176
+ }
177
+ nameTag.renderOrder = 1000
178
+ nameTag.scale.set(canvas.width * 0.005, canvas.height * 0.005, 1)
179
+ if (entity.nameTagRotationRight) {
180
+ nameTag.applyQuaternion(entity.nameTagRotationRight)
181
+ }
182
+ if (entity.nameTagScale) {
183
+ nameTag.scale.multiply(entity.nameTagScale)
188
184
  }
185
+ if (entity.nameTagRotationLeft) {
186
+ nameTag.applyQuaternion(entity.nameTagRotationLeft)
187
+ }
188
+ if (entity.nameTagTranslation) {
189
+ nameTag.position.add(entity.nameTagTranslation)
190
+ }
191
+ nameTag.name = 'nametag'
192
+
193
+ mesh.add(nameTag)
194
+ return nameTag
189
195
  }
190
196
 
191
197
  // todo cleanup
@@ -225,7 +225,7 @@ export const createGraphicsBackendBase = () => {
225
225
  },
226
226
  get left() {
227
227
  return {
228
- 'Geo Memory': worldRenderer?.worldBlockGeometry.getEstimatedMemoryUsage().readable ?? '-'
228
+ 'Geo Memory': worldRenderer?.chunkMeshManager.getEstimatedMemoryUsage().total ?? '-'
229
229
  }
230
230
  },
231
231
  }),
@@ -58,11 +58,9 @@ export class SciFiWorldRevealModule implements RendererModuleController {
58
58
  // Store original methods for patching
59
59
  private originalFinishChunk: ((chunkKey: string) => void) | null = null
60
60
  private originalDestroy: (() => void) | null = null
61
- private originalSceneAdd: ((...object: THREE.Object3D[]) => THREE.Scene) | null = null
61
+ private originalSceneAdd: ((...object: THREE.Object3D[]) => THREE.Group) | null = null
62
62
  private originalHandleWorkerMessage: ((data: { geometry: MesherGeometryOutput; key: string; type: string }) => void) | null = null
63
63
 
64
- private originalWbgHandle: ((data: any) => void) | null = null
65
-
66
64
  private configEnabled = true
67
65
 
68
66
  constructor(private readonly worldRenderer: WorldRendererThree) {
@@ -146,12 +144,10 @@ export class SciFiWorldRevealModule implements RendererModuleController {
146
144
  this.originalDestroy!()
147
145
  }
148
146
 
149
- // Patch handleWorkerMessage
150
- const wbg = wr.worldBlockGeometry
151
- this.originalWbgHandle = wbg.handleWorkerGeometryMessage.bind(wbg)
152
-
153
- wbg.handleWorkerGeometryMessage = (data: any) => {
154
- const result = this.originalWbgHandle!(data)
147
+ // Patch handleWorkerMessage to intercept geometry
148
+ this.originalHandleWorkerMessage = wr.handleWorkerMessage.bind(wr)
149
+ wr.handleWorkerMessage = (data: any) => {
150
+ this.originalHandleWorkerMessage!(data)
155
151
 
156
152
  if (this.enabled && data?.type === 'geometry') {
157
153
  Promise.resolve().then(() => {
@@ -162,14 +158,12 @@ export class SciFiWorldRevealModule implements RendererModuleController {
162
158
  }
163
159
  })
164
160
  }
165
-
166
- return result
167
161
  }
168
162
 
169
163
 
170
164
  // Patch scene.add to intercept mesh additions
171
165
  this.originalSceneAdd = wr.scene.add.bind(wr.scene)
172
- wr.scene.add = (...objects: THREE.Object3D[]): THREE.Scene => {
166
+ wr.scene.add = (...objects: THREE.Object3D[]): THREE.Group => {
173
167
  // Call original add first
174
168
  const result = this.originalSceneAdd!(...objects)
175
169
 
@@ -208,11 +202,6 @@ export class SciFiWorldRevealModule implements RendererModuleController {
208
202
  this.originalSceneAdd = null
209
203
  }
210
204
 
211
- if (this.originalWbgHandle) {
212
- wr.worldBlockGeometry.handleWorkerGeometryMessage = this.originalWbgHandle as any
213
- this.originalWbgHandle = null
214
- }
215
-
216
205
  if (this.onWorldSwitchedCb) {
217
206
  const i = wr.onWorldSwitched.indexOf(this.onWorldSwitchedCb)
218
207
  if (i !== -1) wr.onWorldSwitched.splice(i, 1)
@@ -249,7 +238,7 @@ export class SciFiWorldRevealModule implements RendererModuleController {
249
238
  let current: THREE.Object3D | null = mesh
250
239
  while (current) {
251
240
  const { sectionKey } = (current as any)
252
- if (sectionKey && this.worldRenderer.worldBlockGeometry.sectionObjects[sectionKey] === current) {
241
+ if (sectionKey && this.worldRenderer.chunkMeshManager.sectionObjects[sectionKey] === current) {
253
242
  return sectionKey
254
243
  }
255
244
  current = current.parent
@@ -270,7 +259,7 @@ export class SciFiWorldRevealModule implements RendererModuleController {
270
259
  const derivedKey = `${sectionX},${sectionY},${sectionZ}`
271
260
 
272
261
  // Verify this key exists in sectionObjects
273
- if (this.worldRenderer.worldBlockGeometry.sectionObjects[derivedKey]) {
262
+ if (this.worldRenderer.chunkMeshManager.sectionObjects[derivedKey]) {
274
263
  return derivedKey
275
264
  }
276
265
 
@@ -281,7 +270,7 @@ export class SciFiWorldRevealModule implements RendererModuleController {
281
270
  * Get the scene from world renderer
282
271
  */
283
272
  private get scene(): THREE.Scene {
284
- return this.worldRenderer.scene
273
+ return this.worldRenderer.realScene
285
274
  }
286
275
 
287
276
  /**
@@ -295,7 +284,7 @@ export class SciFiWorldRevealModule implements RendererModuleController {
295
284
  * Get original mesh for a section key
296
285
  */
297
286
  private getOriginalMesh(key: string): THREE.Mesh | null {
298
- const sectionObject = this.worldRenderer.worldBlockGeometry.sectionObjects[key]
287
+ const sectionObject = this.worldRenderer.chunkMeshManager.sectionObjects[key]
299
288
  if (!sectionObject) return null
300
289
  return sectionObject.children.find(child => child.name === 'mesh') as THREE.Mesh | null
301
290
  }
@@ -214,7 +214,7 @@ export class PanoramaRenderer {
214
214
  }
215
215
  )
216
216
  if (this.worldRenderer instanceof WorldRendererThree) {
217
- this.scene = this.worldRenderer.scene
217
+ this.scene = this.worldRenderer.realScene
218
218
  }
219
219
  void worldView.init(initPos)
220
220
 
@@ -13,7 +13,6 @@ import { addNewStat } from '../lib/ui/newStats'
13
13
  import { MesherGeometryOutput } from '../mesher/shared'
14
14
  import { ItemSpecificContextProperties } from '../playerState/types'
15
15
  import { setBlockPosition } from '../mesher/standaloneRenderer'
16
- import { getBannerTexture, createBannerMesh, releaseBannerTexture } from './bannerRenderer'
17
16
  import { getMyHand } from './hand'
18
17
  import { createHoldingBlock } from './holdingBlockFactory'
19
18
  import type { IHoldingBlock } from './holdingBlockTypes'
@@ -34,7 +33,7 @@ import { DEFAULT_TEMPERATURE, SkyboxRenderer } from './skyboxRenderer'
34
33
  import { FireworksManager } from './fireworks'
35
34
  import { SceneOrigin } from './sceneOrigin'
36
35
  import { downloadWorldGeometry } from './worldGeometryExport'
37
- import { WorldBlockGeometry } from './worldBlockGeometry'
36
+ import { ChunkMeshManager } from './chunkMeshManager'
38
37
  import type { RendererModuleManifest, RegisteredModule, RendererModuleController } from './rendererModuleSystem'
39
38
  import { BUILTIN_MODULES } from './modules/index'
40
39
 
@@ -42,16 +41,17 @@ type SectionKey = string
42
41
 
43
42
  export class WorldRendererThree extends WorldRendererCommon {
44
43
  outputFormat = 'threeJs' as const
45
- worldBlockGeometry: WorldBlockGeometry
44
+ chunkMeshManager: ChunkMeshManager
46
45
  get sectionObjects() {
47
- return this.worldBlockGeometry.sectionObjects
46
+ return this.chunkMeshManager.sectionObjects
48
47
  }
49
48
  chunkTextures = new Map<string, { [pos: string]: THREE.Texture }>()
50
49
  signsCache = new Map<string, any>()
51
50
  cameraSectionPos: Vec3 = new Vec3(0, 0, 0)
52
51
  holdingBlock: IHoldingBlock
53
52
  holdingBlockLeft: IHoldingBlock
54
- scene = new THREE.Scene()
53
+ realScene = new THREE.Scene()
54
+ scene = new THREE.Group()
55
55
  ambientLight = new THREE.AmbientLight(0xcc_cc_cc)
56
56
  directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5)
57
57
  entities = new Entities(this, (globalThis as any).mcData)
@@ -65,7 +65,7 @@ export class WorldRendererThree extends WorldRendererCommon {
65
65
  cameraContainer!: THREE.Object3D
66
66
  media: ThreeJsMedia
67
67
  get waitingChunksToDisplay() {
68
- return this.worldBlockGeometry.waitingChunksToDisplay
68
+ return {} as { [chunkKey: string]: string[] }
69
69
  }
70
70
  waypoints: WaypointsRenderer
71
71
  cinimaticScript: CinimaticScriptRunner
@@ -81,7 +81,7 @@ export class WorldRendererThree extends WorldRendererCommon {
81
81
  renderTimeAvg = 0
82
82
  // Memory usage tracking (in bytes)
83
83
  get estimatedMemoryUsage() {
84
- return this.worldBlockGeometry.estimatedMemoryUsage
84
+ return this.chunkMeshManager.getEstimatedMemoryUsage().total
85
85
  }
86
86
  // Module system
87
87
  private modules = {} as Record<string, RegisteredModule>
@@ -107,7 +107,7 @@ export class WorldRendererThree extends WorldRendererCommon {
107
107
  DEBUG_RAYCAST = false
108
108
  skyboxRenderer: SkyboxRenderer
109
109
  fireworks: FireworksManager
110
- sceneOrigin = new SceneOrigin(this.scene)
110
+ sceneOrigin = new SceneOrigin(this.realScene)
111
111
  /** Camera world position stored in float64 (JS number) for precision */
112
112
  cameraWorldPos = { x: 0, y: 0, z: 0 }
113
113
 
@@ -131,11 +131,11 @@ export class WorldRendererThree extends WorldRendererCommon {
131
131
  private readonly _tpChunkWorldPos = new THREE.Vector3()
132
132
 
133
133
  get tilesRendered() {
134
- return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj as any).tilesCount, 0)
134
+ return this.chunkMeshManager.getTotalTiles()
135
135
  }
136
136
 
137
137
  get blocksRendered() {
138
- return Object.values(this.sectionObjects).reduce((acc, obj) => acc + (obj as any).blocksCount, 0)
138
+ return this.chunkMeshManager.getTotalBlocks()
139
139
  }
140
140
 
141
141
  constructor(public renderer: THREE.WebGLRenderer, public initOptions: GraphicsInitOptions, public displayOptions: DisplayWorldOptions) {
@@ -145,8 +145,11 @@ export class WorldRendererThree extends WorldRendererCommon {
145
145
  this.renderer = renderer
146
146
  displayOptions.rendererState.renderer = WorldRendererThree.getRendererInfo(renderer) ?? '...'
147
147
 
148
- // Initialize world block geometry handler
149
- this.worldBlockGeometry = new WorldBlockGeometry(this, this.scene, this.material, displayOptions)
148
+ // Initialize chunk mesh manager
149
+ this.chunkMeshManager = new ChunkMeshManager(this, this.scene, this.material, this.worldSizeParams.worldHeight, this.viewDistance)
150
+ this.onRenderDistanceChanged = (viewDistance) => {
151
+ this.chunkMeshManager.updateViewDistance(viewDistance)
152
+ }
150
153
 
151
154
  this.cursorBlock = new CursorBlock(this)
152
155
  this.holdingBlock = createHoldingBlock(this)
@@ -158,7 +161,7 @@ export class WorldRendererThree extends WorldRendererCommon {
158
161
  }
159
162
 
160
163
  // Initialize skybox renderer
161
- this.skyboxRenderer = new SkyboxRenderer(this.scene, false, null)
164
+ this.skyboxRenderer = new SkyboxRenderer(this.realScene, false, null)
162
165
  void this.skyboxRenderer.init()
163
166
 
164
167
  this.addDebugOverlay()
@@ -181,7 +184,7 @@ export class WorldRendererThree extends WorldRendererCommon {
181
184
  fov: this.camera.fov
182
185
  })
183
186
  )
184
- this.fireworks = new FireworksManager(this.scene, this.sceneOrigin)
187
+ this.fireworks = new FireworksManager(this.realScene, this.sceneOrigin)
185
188
 
186
189
  // this.fountain = new Fountain(this.scene, this.scene, {
187
190
  // position: new THREE.Vector3(0, 10, 0),
@@ -447,19 +450,20 @@ export class WorldRendererThree extends WorldRendererCommon {
447
450
  this.cameraWorldPos.y = 0
448
451
  this.cameraWorldPos.z = 0
449
452
 
450
- this.scene.matrixAutoUpdate = false // for perf
451
- this.scene.background = new THREE.Color(this.initOptions.config.sceneBackground)
452
- this.scene.add(this.ambientLight)
453
+ this.realScene.matrixAutoUpdate = false // for perf
454
+ this.realScene.background = new THREE.Color(this.initOptions.config.sceneBackground)
455
+ this.realScene.add(this.ambientLight)
453
456
  this.directionalLight.position.set(1, 1, 0.5).normalize()
454
457
  this.directionalLight.castShadow = true
455
- this.scene.add(this.directionalLight)
458
+ this.realScene.add(this.directionalLight)
456
459
 
457
460
  const size = this.renderer.getSize(new THREE.Vector2())
458
461
  this.camera = new THREE.PerspectiveCamera(75, size.x / size.y, 0.1, 1000)
459
462
  this._wrapCameraPositionWithWarning()
460
463
  this.cameraContainer = new THREE.Object3D()
461
464
  this.cameraContainer.add(this.camera)
462
- this.scene.add(this.cameraContainer)
465
+ this.realScene.add(this.cameraContainer)
466
+ this.realScene.add(this.scene)
463
467
  }
464
468
 
465
469
  override watchReactivePlayerState() {
@@ -625,7 +629,7 @@ export class WorldRendererThree extends WorldRendererCommon {
625
629
  }
626
630
 
627
631
  changeBackgroundColor(color: [number, number, number]): void {
628
- this.scene.background = new THREE.Color(color[0], color[1], color[2])
632
+ this.realScene.background = new THREE.Color(color[0], color[1], color[2])
629
633
  }
630
634
 
631
635
  timeUpdated(newTime: number): void {
@@ -662,7 +666,7 @@ export class WorldRendererThree extends WorldRendererCommon {
662
666
  setBlockPosition(mesh, pos)
663
667
  const helper = new THREE.BoxHelper(mesh, 0xff_ff_00)
664
668
  mesh.add(helper)
665
- this.scene.add(mesh)
669
+ this.realScene.add(mesh)
666
670
  }
667
671
 
668
672
  demoItem() {
@@ -675,7 +679,7 @@ export class WorldRendererThree extends WorldRendererCommon {
675
679
  // mesh.scale.set(0.5, 0.5, 0.5)
676
680
  const helper = new THREE.BoxHelper(mesh, 0xff_ff_00)
677
681
  mesh.add(helper)
678
- this.scene.add(mesh)
682
+ this.realScene.add(mesh)
679
683
  }
680
684
 
681
685
  debugOverlayAdded = false
@@ -695,7 +699,9 @@ export class WorldRendererThree extends WorldRendererCommon {
695
699
  text += `TE: ${formatBigNumber(this.renderer.info.memory.textures)} `
696
700
  text += `F: ${formatBigNumber(this.tilesRendered)} `
697
701
  text += `B: ${formatBigNumber(this.blocksRendered)} `
698
- text += `MEM: ${this.worldBlockGeometry.getEstimatedMemoryUsage().readable}`
702
+ text += `MEM: ${this.chunkMeshManager.getEstimatedMemoryUsage().total} `
703
+ const poolStats = this.chunkMeshManager.getStats()
704
+ text += `POOL: ${poolStats.activeCount}/${poolStats.poolSize} HR: ${poolStats.hitRate}`
699
705
  pane.updateText(text)
700
706
  this.backendInfoReport = text
701
707
  }
@@ -709,7 +715,8 @@ export class WorldRendererThree extends WorldRendererCommon {
709
715
  const [x, y, z] = key.split(',').map(x => Math.floor(+x / 16))
710
716
  // sum of distances: x + y + z
711
717
  const chunkDistance = Math.abs(x - this.cameraSectionPos.x) + Math.abs(y - this.cameraSectionPos.y) + Math.abs(z - this.cameraSectionPos.z)
712
- const section = this.sectionObjects[key].children.find(child => child.name === 'mesh')!
718
+ const sectionObj = this.sectionObjects[key]
719
+ const section = (sectionObj as any).mesh ?? sectionObj.children.find(child => child.name === 'mesh')!
713
720
  section.renderOrder = 500 - chunkDistance
714
721
  }
715
722
 
@@ -732,12 +739,15 @@ export class WorldRendererThree extends WorldRendererCommon {
732
739
  }
733
740
 
734
741
  finishChunk(chunkKey: string) {
735
- this.worldBlockGeometry.finishChunk(chunkKey)
742
+ // ChunkMeshManager applies updates immediately, no buffering needed
736
743
  }
737
744
 
738
745
  handleWorkerMessage(data: { geometry: MesherGeometryOutput, key, type }): void {
739
746
  if (data.type === 'geometry') {
740
- this.worldBlockGeometry.handleWorkerGeometryMessage(data)
747
+ const chunkCoords = data.key.split(',')
748
+ if (!this.loadedChunks[chunkCoords[0] + ',' + chunkCoords[2]] || !data.geometry.positions.length || !this.active) return
749
+ this.chunkMeshManager.updateSection(data.key, data.geometry)
750
+ this.updatePosDataChunk(data.key)
741
751
  }
742
752
  }
743
753
 
@@ -883,11 +893,11 @@ export class WorldRendererThree extends WorldRendererCommon {
883
893
  private debugRaycast(pos: THREE.Vector3, direction: THREE.Vector3, distance: number) {
884
894
  // Remove existing debug objects
885
895
  if (this.debugRaycastHelper) {
886
- this.scene.remove(this.debugRaycastHelper)
896
+ this.realScene.remove(this.debugRaycastHelper)
887
897
  this.debugRaycastHelper = undefined
888
898
  }
889
899
  if (this.debugHitPoint) {
890
- this.scene.remove(this.debugHitPoint)
900
+ this.realScene.remove(this.debugHitPoint)
891
901
  this.debugHitPoint = undefined
892
902
  }
893
903
 
@@ -907,14 +917,14 @@ export class WorldRendererThree extends WorldRendererCommon {
907
917
  distance * 0.1,
908
918
  distance * 0.05
909
919
  )
910
- this.scene.add(this.debugRaycastHelper)
920
+ this.realScene.add(this.debugRaycastHelper)
911
921
 
912
922
  // Create hit point indicator
913
923
  const hitGeometry = new THREE.SphereGeometry(0.2, 8, 8)
914
924
  const hitMaterial = new THREE.MeshBasicMaterial({ color: 0x00_ff_00 })
915
925
  this.debugHitPoint = new THREE.Mesh(hitGeometry, hitMaterial)
916
926
  this.debugHitPoint.position.copy(scenePos).add(direction.clone().multiplyScalar(distance))
917
- this.scene.add(this.debugHitPoint)
927
+ this.realScene.add(this.debugHitPoint)
918
928
  }
919
929
 
920
930
  prevFramePerspective = null as string | null
@@ -1012,11 +1022,11 @@ export class WorldRendererThree extends WorldRendererCommon {
1012
1022
 
1013
1023
  // remove any debug raycasting
1014
1024
  if (this.debugRaycastHelper) {
1015
- this.scene.remove(this.debugRaycastHelper)
1025
+ this.realScene.remove(this.debugRaycastHelper)
1016
1026
  this.debugRaycastHelper = undefined
1017
1027
  }
1018
1028
  if (this.debugHitPoint) {
1019
- this.scene.remove(this.debugHitPoint)
1029
+ this.realScene.remove(this.debugHitPoint)
1020
1030
  this.debugHitPoint = undefined
1021
1031
  }
1022
1032
  }
@@ -1087,9 +1097,8 @@ export class WorldRendererThree extends WorldRendererCommon {
1087
1097
 
1088
1098
  // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
1089
1099
  const cam = this.cameraGroupVr instanceof THREE.Group ? this.cameraGroupVr.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera
1090
- // Flush buffered geometry updates atomically before rendering
1091
- this.worldBlockGeometry.applyPendingUpdates()
1092
- this.renderer.render(this.scene, cam)
1100
+ // ChunkMeshManager applies updates immediately, no pending updates to flush
1101
+ this.renderer.render(this.realScene, cam)
1093
1102
 
1094
1103
  if (
1095
1104
  this.displayOptions.inWorldRenderingConfig.showHand &&
@@ -1118,6 +1127,9 @@ export class WorldRendererThree extends WorldRendererCommon {
1118
1127
  }
1119
1128
  const end = performance.now()
1120
1129
  const totalTime = end - start
1130
+ if (this.worldRendererConfig.autoLowerRenderDistance) {
1131
+ this.chunkMeshManager.recordRenderTime(totalTime)
1132
+ }
1121
1133
  this.renderTimeAvgCount++
1122
1134
  this.renderTimeAvg = ((this.renderTimeAvg * (this.renderTimeAvgCount - 1)) + totalTime) / this.renderTimeAvgCount
1123
1135
  this.renderTimeMax = Math.max(this.renderTimeMax, totalTime)
@@ -1233,15 +1245,16 @@ export class WorldRendererThree extends WorldRendererCommon {
1233
1245
  resetWorld() {
1234
1246
  super.resetWorld()
1235
1247
 
1236
- this.worldBlockGeometry.resetWorld()
1248
+ this.chunkMeshManager.dispose()
1249
+ this.chunkMeshManager = new ChunkMeshManager(this, this.scene, this.material, this.worldSizeParams.worldHeight, this.viewDistance)
1237
1250
 
1238
1251
  // Clean up debug objects
1239
1252
  if (this.debugRaycastHelper) {
1240
- this.scene.remove(this.debugRaycastHelper)
1253
+ this.realScene.remove(this.debugRaycastHelper)
1241
1254
  this.debugRaycastHelper = undefined
1242
1255
  }
1243
1256
  if (this.debugHitPoint) {
1244
- this.scene.remove(this.debugHitPoint)
1257
+ this.realScene.remove(this.debugHitPoint)
1245
1258
  this.debugHitPoint = undefined
1246
1259
  }
1247
1260
  }
@@ -1286,7 +1299,14 @@ export class WorldRendererThree extends WorldRendererCommon {
1286
1299
  super.removeColumn(x, z)
1287
1300
 
1288
1301
  this.cleanChunkTextures(x, z)
1289
- this.worldBlockGeometry.removeColumn(x, z)
1302
+ const sectionHeight = this.getSectionHeight()
1303
+ const worldMinY = this.worldMinYRender
1304
+ for (let y = worldMinY; y < this.worldSizeParams.worldHeight; y += sectionHeight) {
1305
+ const key = `${x},${y},${z}`
1306
+ if (this.chunkMeshManager.sectionObjects[key]) {
1307
+ this.chunkMeshManager.releaseSection(key)
1308
+ }
1309
+ }
1290
1310
  }
1291
1311
 
1292
1312
  setSectionDirty(...args: Parameters<WorldRendererCommon['setSectionDirty']>) {
@@ -1309,6 +1329,7 @@ export class WorldRendererThree extends WorldRendererCommon {
1309
1329
  }
1310
1330
 
1311
1331
  destroy(): void {
1332
+ this.chunkMeshManager.dispose()
1312
1333
  this.disposeModules()
1313
1334
  this.fireworksLegacy.destroy()
1314
1335
  super.destroy()