Skip to content

feat: Server + Client Light Engine! #304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 33 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
245300f
init
zardoy Feb 18, 2025
d5c61d8
a working light
zardoy Feb 19, 2025
48ead54
should work.
zardoy Mar 12, 2025
037e297
Merge remote-tracking branch 'origin/next' into light-engine
zardoy Mar 12, 2025
ace45a9
not crash pls
zardoy Mar 13, 2025
ec6b249
Merge remote-tracking branch 'origin/next' into light-engine
zardoy Mar 21, 2025
9f505f8
rm workaround
zardoy Mar 21, 2025
f18b3a1
Merge branch 'next' into light-engine
zardoy Apr 7, 2025
e10f610
humble and terrible progress
zardoy Apr 10, 2025
0fa66e2
Merge remote-tracking branch 'origin/next' into light-engine
zardoy Apr 10, 2025
b1ba2cd
Merge remote-tracking branch 'origin/next' into light-engine
zardoy Apr 12, 2025
3cd1ac3
Merge branch 'next' into light-engine
zardoy Apr 24, 2025
1918c68
finish lighting
zardoy Apr 25, 2025
b4c72db
fix crash opt
zardoy Apr 25, 2025
1f5b682
FINISH OPTIONS, FINISH RECOMPUTE, ADD LIGHT TO WATER
zardoy Apr 28, 2025
5a57d29
Merge branch 'next' into light-engine
zardoy Apr 28, 2025
2f6191a
Merge remote-tracking branch 'origin/next' into light-engine
zardoy Apr 30, 2025
f4eab39
finish lighting
zardoy Apr 30, 2025
79f0fdd
fix lava rendering
zardoy Apr 30, 2025
27c55b1
finish!
zardoy Apr 30, 2025
f4f5edd
fix lighting disabling
zardoy Apr 30, 2025
c97c7e0
finish combined computation, finish settings and strategies
zardoy May 1, 2025
c4b9c33
Update src/optionsStorage.ts
zardoy May 1, 2025
7d224fb
Merge remote-tracking branch 'origin/next' into light-engine
zardoy May 1, 2025
d6f394f
hide cursor block in spectator
zardoy May 2, 2025
ddf0810
final step: move engine to another thread
zardoy May 4, 2025
5720cfa
up light
zardoy May 4, 2025
7dba526
Merge remote-tracking branch 'origin/next' into light-engine
zardoy May 4, 2025
e95f84e
fix lock
zardoy May 4, 2025
90de0d0
up chunk?
zardoy May 4, 2025
f185df9
fix remaining issues with worker bundle with smart approach
zardoy May 8, 2025
6be3c5c
Merge remote-tracking branch 'origin/next' into light-engine
zardoy May 8, 2025
56aee16
Merge branch 'next' into light-engine
zardoy May 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ For building the project yourself / contributing, see [Development, Debugging &

### Big Features

- Connect to Java servers running in both offline (cracked) and online mode* (it's possible because of proxy servers, see below)
- Combined Lighting System - Server Parsing + Client Side Engine for block updates
- Official Mineflayer [plugin integration](https://github.com/zardoy/mcraft-fun-mineflayer-plugin)! View / Control your bot remotely.
- Open any zip world file or even folder in read-write mode!
- Connect to Java servers running in both offline (cracked) and online mode* (it's possible because of proxy servers, see below)
- Integrated JS server clone capable of opening Java world saves in any way (folders, zip, web chunks streaming, etc)
- Singleplayer mode with simple world generations!
- Works offline
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@
"https-browserify": "^1.0.0",
"mc-assets": "^0.2.53",
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next",
"minecraft-lighting": "^0.0.9",
"mineflayer": "github:zardoy/mineflayer#gen-the-master",
"mineflayer-mouse": "^0.1.9",
"mineflayer-pathfinder": "^2.4.4",
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions renderer/viewer/lib/basePlayerState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export interface IPlayerState {
getHeldItem?(isLeftHand: boolean): HandItemBlock | undefined
username?: string
onlineMode?: boolean
lightingDisabled?: boolean
shouldHideHand?: boolean

events: TypedEmitter<PlayerStateEvents>

Expand Down
106 changes: 106 additions & 0 deletions renderer/viewer/lib/lightEngine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock, createPrismarineLightEngineWorker } from 'minecraft-lighting'
import { world } from 'prismarine-world'
// import PrismarineWorker from 'minecraft-lighting/dist/prismarineWorker.worker.js'
import { WorldDataEmitter } from './worldDataEmitter'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Missing dependency resources for light engine worker

The pipeline failures indicate issues with the worker implementation.

The pipeline detected the following errors:

  1. Module 'minecraft-lighting/dist/prismarineWorker.worker.js' cannot be resolved
  2. Export 'createPrismarineLightEngineWorker' was not found in 'minecraft-lighting'

Update the import statements to correctly reference the available APIs or ensure the proper version of 'minecraft-lighting' with worker support is installed.

-import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock, createPrismarineLightEngineWorker } from 'minecraft-lighting'
+import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock } from 'minecraft-lighting'
 import { world } from 'prismarine-world'
-// import PrismarineWorker from 'minecraft-lighting/dist/prismarineWorker.worker.js'
+// Define a fallback implementation for the worker until proper support is available

🌐 Web query:

Does the minecraft-lighting package support worker-based light engines and provide a createPrismarineLightEngineWorker export?

💡 Result:

Based on the search results provided, there is no specific information about a "minecraft-lighting" package that supports worker-based light engines or provides a "createPrismarineLightEngineWorker" export. The search results primarily discuss various Minecraft lighting implementations and mods, but none mention this specific package or export function.

The search results do cover several lighting-related topics in Minecraft:

  1. Various lighting engine mods such as Starlight by PaperMC, which rewrites the light engine to fix lighting issues and improve performance[2].

  2. Alfheim Lighting Engine, a fork/rewrite of previous lighting engines (Hesperus and Phosphor) that aims to improve performance and fix compatibility issues[3].

  3. Custom implementations of lighting in Minecraft clones, including colored lighting and different propagation methods[1][9].

  4. Discussions about dynamic lighting in Minecraft and potential methods to implement it[5].

However, none of these sources specifically mention a "minecraft-lighting" package with worker-based light engines or a "createPrismarineLightEngineWorker" export. If you're looking for this specific functionality, it might be part of a different package than those covered in the search results, or it might not exist at all.

Citations:


Remove unsupported worker imports from lightEngine.ts

The minecraft-lighting package does not expose a createPrismarineLightEngineWorker export nor bundle a prismarineWorker.worker.js, causing build failures:

  • Error: Cannot resolve module minecraft-lighting/dist/prismarineWorker.worker.js
  • Error: Export createPrismarineLightEngineWorker not found in minecraft-lighting

Please update the import and provide a temporary stub or fallback until upstream worker support is available.

Locations to update:

  • renderer/viewer/lib/lightEngine.ts

Proposed diff:

--- a/renderer/viewer/lib/lightEngine.ts
+++ b/renderer/viewer/lib/lightEngine.ts
@@ -1,4 +1,3 @@
-import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock, createPrismarineLightEngineWorker } from 'minecraft-lighting'
+import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock } from 'minecraft-lighting'
 import { world } from 'prismarine-world'
-// import PrismarineWorker from 'minecraft-lighting/dist/prismarineWorker.worker.js'
+// TODO: implement or stub out a worker-based light engine once supported upstream
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock, createPrismarineLightEngineWorker } from 'minecraft-lighting'
import { world } from 'prismarine-world'
// import PrismarineWorker from 'minecraft-lighting/dist/prismarineWorker.worker.js'
import { WorldDataEmitter } from './worldDataEmitter'
--- a/renderer/viewer/lib/lightEngine.ts
+++ b/renderer/viewer/lib/lightEngine.ts
@@ -1,4 +1,4 @@
-import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock, createPrismarineLightEngineWorker } from 'minecraft-lighting'
+import { LightWorld, createLightEngineForSyncWorld, convertPrismarineBlockToWorldBlock } from 'minecraft-lighting'
import { world } from 'prismarine-world'
-// import PrismarineWorker from 'minecraft-lighting/dist/prismarineWorker.worker.js'
+// TODO: implement or stub out a worker-based light engine once supported upstream
import { WorldDataEmitter } from './worldDataEmitter'


let lightEngine: LightWorld | null = null
let lightEngineNew: ReturnType<typeof createPrismarineLightEngineWorker> | null = null

export const getLightEngine = () => {
if (!lightEngine) throw new Error('Light engine not initialized')
return lightEngine
}
export const getLightEngineSafe = () => {
// return lightEngine
return lightEngineNew
}

export const createLightEngineIfNeeded = (worldView: WorldDataEmitter) => {
if (lightEngine) return
lightEngine = createLightEngineForSyncWorld(worldView.world as unknown as world.WorldSync, loadedData, {
minY: worldView.minY,
height: worldView.minY + worldView.worldHeight,
// writeLightToOriginalWorld: true,
// enableSkyLight: false,
})
lightEngine.externalWorld.setBlock = () => {}
lightEngine.PARALLEL_CHUNK_PROCESSING = false
globalThis.lightEngine = lightEngine
}

export const createLightEngineIfNeededNew = (worldView: WorldDataEmitter) => {
if (lightEngineNew) return
const worker = new Worker(new URL('minecraft-lighting/dist/prismarineWorker.worker.js', import.meta.url))
lightEngineNew = createPrismarineLightEngineWorker(worker, worldView.world as unknown as world.WorldSync, loadedData)
lightEngineNew.initialize({
minY: worldView.minY,
height: worldView.minY + worldView.worldHeight,
// writeLightToOriginalWorld: true,
// enableSkyLight: false,
})

globalThis.lightEngine = lightEngineNew
}

export const processLightChunk = async (x: number, z: number, doLighting: boolean) => {
const engine = getLightEngineSafe()
if (!engine) return

const chunkX = Math.floor(x / 16)
const chunkZ = Math.floor(z / 16)
// fillColumnWithZeroLight(engine.externalWorld, chunkX, chunkZ)

const updated = await engine.loadChunk(chunkX, chunkZ, doLighting)
return updated
}

export const dumpLightData = (x: number, z: number) => {
const engine = getLightEngineSafe()
// return engine?.worldLightHolder.dumpChunk(Math.floor(x / 16), Math.floor(z / 16))
}

export const getDebugLightValues = (x: number, y: number, z: number) => {
const engine = getLightEngineSafe()
// return {
// blockLight: engine?.worldLightHolder.getBlockLight(x, y, z) ?? -1,
// skyLight: engine?.worldLightHolder.getSkyLight(x, y, z) ?? -1,
// }
}

export const updateBlockLight = async (x: number, y: number, z: number, stateId: number, distance: number) => {
if (distance > 16) return []
const chunkX = Math.floor(x / 16) * 16
const chunkZ = Math.floor(z / 16) * 16
const engine = getLightEngineSafe()
if (!engine) return
const start = performance.now()
const result = await engine.setBlock(x, y, z, stateId)
const end = performance.now()
console.log(`[light engine] updateBlockLight (${x}, ${y}, ${z}) took`, Math.round(end - start), 'ms', result.length, 'chunks')
return result
Comment on lines +57 to +67
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for light engine operations

The updateBlockLight function logs performance data but doesn't handle errors.

Add try/catch block to handle potential errors from the light engine:

export const updateBlockLight = async (x: number, y: number, z: number, stateId: number, distance: number) => {
  if (distance > 16) return []
  const chunkX = Math.floor(x / 16) * 16
  const chunkZ = Math.floor(z / 16) * 16
  const engine = getLightEngineSafe()
  if (!engine) return
  const start = performance.now()
+  try {
    const result = await engine.setBlock(x, y, z, stateId)
    const end = performance.now()
    console.log(`[light engine] updateBlockLight (${x}, ${y}, ${z}) took`, Math.round(end - start), 'ms', result.length, 'chunks')
    return result
+  } catch (error) {
+    console.error(`[light engine] Error updating block light at (${x}, ${y}, ${z}):`, error)
+    return []
+  }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const updateBlockLight = async (x: number, y: number, z: number, stateId: number, distance: number) => {
if (distance > 16) return []
const chunkX = Math.floor(x / 16) * 16
const chunkZ = Math.floor(z / 16) * 16
const engine = getLightEngineSafe()
if (!engine) return
const start = performance.now()
const result = await engine.setBlock(x, y, z, stateId)
const end = performance.now()
console.log(`[light engine] updateBlockLight (${x}, ${y}, ${z}) took`, Math.round(end - start), 'ms', result.length, 'chunks')
return result
export const updateBlockLight = async (
x: number,
y: number,
z: number,
stateId: number,
distance: number
) => {
if (distance > 16) return []
const chunkX = Math.floor(x / 16) * 16
const chunkZ = Math.floor(z / 16) * 16
const engine = getLightEngineSafe()
if (!engine) return
const start = performance.now()
try {
const result = await engine.setBlock(x, y, z, stateId)
const end = performance.now()
console.log(
`[light engine] updateBlockLight (${x}, ${y}, ${z}) took`,
Math.round(end - start),
'ms',
result.length,
'chunks'
)
return result
} catch (error) {
console.error(
`[light engine] Error updating block light at (${x}, ${y}, ${z}):`,
error
)
return []
}
}


// const engine = getLightEngineSafe()
// if (!engine) return
// const affected = engine['affectedChunksTimestamps'] as Map<string, number>
// const noAffected = affected.size === 0
// engine.setBlock(x, y, z, convertPrismarineBlockToWorldBlock(stateId, loadedData))

// if (affected.size > 0) {
// const chunks = [...affected.keys()].map(key => {
// return key.split(',').map(Number) as [number, number]
// })
// affected.clear()
// return chunks
// }
}

export const lightRemoveColumn = (x: number, z: number) => {
const engine = getLightEngineSafe()
if (!engine) return
engine.unloadChunk(Math.floor(x / 16), Math.floor(z / 16))
}

export const destroyLightEngine = () => {
lightEngine = null
globalThis.lightEngine = null
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incomplete light engine cleanup

The destroyLightEngine function only destroys the synchronous engine and not the worker-based one.

Update the function to clean up both engine types:

export const destroyLightEngine = () => {
+  if (lightEngineNew) {
+    lightEngineNew.destroy?.()
+    lightEngineNew = null
+  }
  lightEngine = null
  globalThis.lightEngine = null
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const destroyLightEngine = () => {
lightEngine = null
globalThis.lightEngine = null
}
export const destroyLightEngine = () => {
if (lightEngineNew) {
lightEngineNew.destroy?.()
lightEngineNew = null
}
lightEngine = null
globalThis.lightEngine = null
}

3 changes: 3 additions & 0 deletions renderer/viewer/lib/mesher/mesher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ const handleMessage = data => {
}
case 'chunk': {
world.addColumn(data.x, data.z, data.chunk)
if (data.lightData) {
world.lightHolder.loadChunk(data.lightData)
}
if (data.customBlockModels) {
const chunkKey = `${data.x},${data.z}`
world.customBlockModels.set(chunkKey, data.customBlockModels)
Expand Down
41 changes: 39 additions & 2 deletions renderer/viewer/lib/mesher/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ const isCube = (block: Block) => {
}))
}

const getVec = (v: Vec3, dir: Vec3) => {
for (const coord of ['x', 'y', 'z']) {
if (Math.abs(dir[coord]) > 0) v[coord] = 0
}
return v.plus(dir)
}

function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, type: number, biome: string, water: boolean, attr: Record<string, any>, isRealWater: boolean) {
const heights: number[] = []
for (let z = -1; z <= 1; z++) {
Expand All @@ -142,7 +149,7 @@ function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, typ

// eslint-disable-next-line guard-for-in
for (const face in elemFaces) {
const { dir, corners } = elemFaces[face]
const { dir, corners, mask1, mask2 } = elemFaces[face]
const isUp = dir[1] === 1

const neighborPos = cursor.offset(...dir as [number, number, number])
Expand Down Expand Up @@ -180,6 +187,9 @@ function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, typ
const { su } = texture
const { sv } = texture

// Get base light value for the face
const baseLight = world.getLight(neighborPos, undefined, undefined, water ? 'water' : 'lava') / 15

for (const pos of corners) {
const height = cornerHeights[pos[2] * 2 + pos[0]]
attr.t_positions.push(
Expand All @@ -189,7 +199,31 @@ function renderLiquid (world: World, cursor: Vec3, texture: any | undefined, typ
)
attr.t_normals.push(...dir)
attr.t_uvs.push(pos[3] * su + u, pos[4] * sv * (pos[1] ? 1 : height) + v)
attr.t_colors.push(tint[0], tint[1], tint[2])

let cornerLightResult = baseLight
if (world.config.smoothLighting) {
const dx = pos[0] * 2 - 1
const dy = pos[1] * 2 - 1
const dz = pos[2] * 2 - 1
const cornerDir: [number, number, number] = [dx, dy, dz]
const side1Dir: [number, number, number] = [dx * mask1[0], dy * mask1[1], dz * mask1[2]]
const side2Dir: [number, number, number] = [dx * mask2[0], dy * mask2[1], dz * mask2[2]]

const dirVec = new Vec3(...dir as [number, number, number])

const side1LightDir = getVec(new Vec3(...side1Dir), dirVec)
const side1Light = world.getLight(cursor.plus(side1LightDir)) / 15
const side2DirLight = getVec(new Vec3(...side2Dir), dirVec)
const side2Light = world.getLight(cursor.plus(side2DirLight)) / 15
const cornerLightDir = getVec(new Vec3(...cornerDir), dirVec)
const cornerLight = world.getLight(cursor.plus(cornerLightDir)) / 15
// interpolate
const lights = [side1Light, side2Light, cornerLight, baseLight]
cornerLightResult = lights.reduce((acc, cur) => acc + cur, 0) / lights.length
}

// Apply light value to tint
attr.t_colors.push(tint[0] * cornerLightResult, tint[1] * cornerLightResult, tint[2] * cornerLightResult)
}
}
}
Expand Down Expand Up @@ -454,6 +488,7 @@ const isBlockWaterlogged = (block: Block) => {

let unknownBlockModel: BlockModelPartsResolved
export function getSectionGeometry (sx, sy, sz, world: World) {
world.hadSkyLight = false
let delayedRender = [] as Array<() => void>

const attr: MesherGeometryOutput = {
Expand Down Expand Up @@ -657,6 +692,8 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
delete attr.uvs
}

attr.hasSkylight = world.hadSkyLight

return attr
}

Expand Down
5 changes: 5 additions & 0 deletions renderer/viewer/lib/mesher/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import { BlockType } from '../../../playground/shared'
// only here for easier testing
export const defaultMesherConfig = {
version: '',

enableLighting: true,
skyLight: 15,
smoothLighting: true,
usingCustomLightHolder: false,
flyingSquidWorkarounds: false,

outputFormat: 'threeJs' as 'threeJs' | 'webgpu',
textureSize: 1024, // for testing
debugModelVariant: undefined as undefined | number[],
Expand Down Expand Up @@ -44,6 +48,7 @@ export type MesherGeometryOutput = {
hadErrors: boolean
blocksCount: number
customBlockModels?: CustomBlockModels
hasSkylight?: boolean
}

export type HighestBlockInfo = { y: number, stateId: number | undefined, biomeId: number | undefined }
Expand Down
84 changes: 60 additions & 24 deletions renderer/viewer/lib/mesher/world.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { WorldLightHolder } from 'minecraft-lighting/dist/worldLightHolder'
import Chunks from 'prismarine-chunk'
import mcData from 'minecraft-data'
import { Block } from 'prismarine-block'
Expand Down Expand Up @@ -32,6 +33,8 @@ export type WorldBlock = Omit<Block, 'position'> & {
}

export class World {
hadSkyLight = false
lightHolder = new WorldLightHolder(0, 0)
config = defaultMesherConfig
Chunk: typeof import('prismarine-chunk/types/index').PCChunk
columns = {} as { [key: string]: import('prismarine-chunk/types/index').PCChunk }
Expand All @@ -53,38 +56,71 @@ export class World {
getLight (pos: Vec3, isNeighbor = false, skipMoreChecks = false, curBlockName = '') {
// for easier testing
if (!(pos instanceof Vec3)) pos = new Vec3(...pos as [number, number, number])
const { enableLighting, skyLight } = this.config

const IS_USING_LOCAL_SERVER_LIGHTING = this.config.flyingSquidWorkarounds
// const IS_USING_SERVER_LIGHTING = false

const { enableLighting, skyLight, usingCustomLightHolder } = this.config
if (!enableLighting) return 15
// const key = `${pos.x},${pos.y},${pos.z}`
// if (lightsCache.has(key)) return lightsCache.get(key)
const column = this.getColumnByPos(pos)
if (!column || !hasChunkSection(column, pos)) return 15
let result = Math.min(
15,
Math.max(
column.getBlockLight(posInChunk(pos)),
Math.min(skyLight, column.getSkyLight(posInChunk(pos)))
) + 2
if (!column) return 15
if (!usingCustomLightHolder && !hasChunkSection(column, pos)) return 2
let result = Math.max(
2,
Math.min(
15,
Math.max(
this.getBlockLight(pos),
Math.min(skyLight, this.getSkyLight(pos))
)
)
)
// lightsCache.set(key, result)
if (result === 2 && [this.getBlock(pos)?.name ?? '', curBlockName].some(x => /_stairs|slab|glass_pane/.exec(x)) && !skipMoreChecks) { // todo this is obviously wrong
const lights = [
this.getLight(pos.offset(0, 1, 0), undefined, true),
this.getLight(pos.offset(0, -1, 0), undefined, true),
this.getLight(pos.offset(0, 0, 1), undefined, true),
this.getLight(pos.offset(0, 0, -1), undefined, true),
this.getLight(pos.offset(1, 0, 0), undefined, true),
this.getLight(pos.offset(-1, 0, 0), undefined, true)
].filter(x => x !== 2)
if (lights.length) {
const min = Math.min(...lights)
result = min
if (result === 2 && IS_USING_LOCAL_SERVER_LIGHTING) {
if ([this.getBlock(pos)?.name ?? '', curBlockName].some(x => /_stairs|slab|glass_pane/.exec(x)) && !skipMoreChecks) { // todo this is obviously wrong
const lights = [
this.getLight(pos.offset(0, 1, 0), undefined, true),
this.getLight(pos.offset(0, -1, 0), undefined, true),
this.getLight(pos.offset(0, 0, 1), undefined, true),
this.getLight(pos.offset(0, 0, -1), undefined, true),
this.getLight(pos.offset(1, 0, 0), undefined, true),
this.getLight(pos.offset(-1, 0, 0), undefined, true)
].filter(x => x !== 2)
if (lights.length) {
const min = Math.min(...lights)
result = min
}
}
if (isNeighbor) result = 15 // TODO
}
if (isNeighbor && result === 2) result = 15 // TODO
return result
}

getBlockLight (pos: Vec3) {
// if (this.config.clientSideLighting) {
// return this.lightHolder.getBlockLight(pos.x, pos.y, pos.z)
// }

const column = this.getColumnByPos(pos)
if (!column) return 15
return column.getBlockLight(posInChunk(pos))
}

getSkyLight (pos: Vec3) {
const result = this.getSkyLightInner(pos)
if (result > 2) this.hadSkyLight = true
return result
}

getSkyLightInner (pos: Vec3) {
// if (this.config.clientSideLighting) {
// return this.lightHolder.getSkyLight(pos.x, pos.y, pos.z)
// }

const column = this.getColumnByPos(pos)
if (!column) return 15
return column.getSkyLight(posInChunk(pos))
}

addColumn (x, z, json) {
const chunk = this.Chunk.fromJson(json)
this.columns[columnKey(x, z)] = chunk as any
Expand Down
Loading
Loading