Skip to content

Commit e14e955

Browse files
authored
Release (#475)
2 parents 45f698d + 62820bc commit e14e955

19 files changed

Lines changed: 266 additions & 120 deletions

config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"ip": "wss://ws.fuchsmc.net"
1919
},
2020
{
21-
"ip": "wss://play2.mcraft.fun"
21+
"ip": "wss://play3.mcraft.fun"
2222
},
2323
{
2424
"ip": "wss://play-creative.mcraft.fun",

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
"jszip": "^3.10.1",
8888
"lodash-es": "^4.17.21",
8989
"mcraft-fun-mineflayer": "^0.1.23",
90-
"minecraft-data": "3.98.0",
90+
"minecraft-data": "3.103.0",
9191
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master",
9292
"mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader",
9393
"mojangson": "^2.0.4",
@@ -157,7 +157,7 @@
157157
"mc-assets": "^0.2.72",
158158
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next",
159159
"mineflayer": "github:zardoy/mineflayer#gen-the-master",
160-
"mineflayer-mouse": "^0.1.24",
160+
"mineflayer-mouse": "^0.1.25",
161161
"npm-run-all": "^4.1.5",
162162
"os-browserify": "^0.3.0",
163163
"path-browserify": "^1.0.1",
@@ -205,7 +205,7 @@
205205
"diamond-square": "github:zardoy/diamond-square",
206206
"prismarine-block": "github:zardoy/prismarine-block#next-era",
207207
"prismarine-world": "github:zardoy/prismarine-world#next-era",
208-
"minecraft-data": "3.98.0",
208+
"minecraft-data": "3.103.0",
209209
"prismarine-provider-anvil": "github:zardoy/prismarine-provider-anvil#everything",
210210
"prismarine-physics": "github:zardoy/prismarine-physics",
211211
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master",
@@ -222,7 +222,8 @@
222222
"patchedDependencies": {
223223
"pixelarticons@1.8.1": "patches/pixelarticons@1.8.1.patch",
224224
"mineflayer-item-map-downloader@1.2.0": "patches/mineflayer-item-map-downloader@1.2.0.patch",
225-
"minecraft-protocol": "patches/minecraft-protocol.patch"
225+
"minecraft-protocol": "patches/minecraft-protocol.patch",
226+
"@nxg-org/mineflayer-physics-util": "patches/@nxg-org__mineflayer-physics-util.patch"
226227
},
227228
"ignoredBuiltDependencies": [
228229
"canvas",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
diff --git a/dist/physics/states/playerState.js b/dist/physics/states/playerState.js
2+
index df1bdc854473599014f398993b7ccfb9123c38c4..eaf20b44c26a469ac3306d572d35628e56ad0fa5 100644
3+
--- a/dist/physics/states/playerState.js
4+
+++ b/dist/physics/states/playerState.js
5+
@@ -288,7 +288,7 @@ class PlayerState {
6+
break;
7+
case "survival":
8+
case "adventure":
9+
- this.flySpeed = 0;
10+
+ this.flySpeed = 0.05;
11+
this.mayFly = bot.entity.canFly;
12+
break;
13+
default:

pnpm-lock.yaml

Lines changed: 116 additions & 77 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

renderer/viewer/lib/mesher/models.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ import { Vec3 } from 'vec3'
22
import worldBlockProvider, { WorldBlockProvider } from 'mc-assets/dist/worldBlockProvider'
33
import legacyJson from '../../../../src/preflatMap.json'
44
import { BlockType } from '../../../playground/shared'
5-
import { World, BlockModelPartsResolved, WorldBlock as Block, WorldBlock } from './world'
6-
import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon'
5+
import moreBlockData from '../moreBlockDataGenerated.json'
76
import { INVISIBLE_BLOCKS } from './worldConstants'
87
import { MesherGeometryOutput, HighestBlockInfo } from './shared'
8+
import { BlockElement, buildRotationMatrix, elemFaces, matmul3, matmulmat3, vecadd3, vecsub3 } from './modelsGeometryCommon'
9+
import { World, BlockModelPartsResolved, WorldBlock as Block, WorldBlock } from './world'
910

1011

1112
let blockProvider: WorldBlockProvider
1213

1314
const tints: any = {}
1415
let needTiles = false
16+
let semiTransparentBlocks: string[] = []
1517

1618
let tintsData
1719
try {
@@ -536,6 +538,7 @@ export function getSectionGeometry (sx: number, sy: number, sz: number, world: W
536538
t_uvs: [],
537539
indices: [],
538540
indicesCount: 0, // Track current index position
541+
transparentIndicesStart: 0, // Will be set after opaque geometry
539542
using32Array: true,
540543
tiles: {},
541544
// todo this can be removed here
@@ -664,7 +667,7 @@ export function getSectionGeometry (sx: number, sy: number, sz: number, world: W
664667

665668
for (const element of model.elements ?? []) {
666669
const ao = model.ao ?? block.boundingBox !== 'empty'
667-
if (block.transparent) {
670+
if (block.transparent && semiTransparentBlocks.includes(block.name)) {
668671
const pos = cursor.clone()
669672
delayedRender.push(() => {
670673
renderElement(world, pos, element, ao, attr, globalMatrix, globalShift, block, biome)
@@ -681,6 +684,10 @@ export function getSectionGeometry (sx: number, sy: number, sz: number, world: W
681684
}
682685
}
683686

687+
// Track where transparent indices start (for separate material rendering)
688+
// This must be set BEFORE delayedRender executes, as those are semi-transparent blocks
689+
attr.transparentIndicesStart = attr.indicesCount
690+
684691
for (const render of delayedRender) {
685692
render()
686693
}
@@ -750,12 +757,36 @@ function arrayNeedsUint32 (array) {
750757

751758
}
752759

753-
export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true, version = 'latest') => {
760+
export const setBlockStatesData = (blockstatesModels, blocksAtlas: any, _needTiles = false, useUnknownBlockModel = true, version = 'latest', mcData = (globalThis as any).mcData) => {
754761
blockProvider = worldBlockProvider(blockstatesModels, blocksAtlas, version)
755762
globalThis.blockProvider = blockProvider
756763
if (useUnknownBlockModel) {
757764
unknownBlockModel = blockProvider.getAllResolvedModels0_1({ name: 'unknown', properties: {} })
758765
}
759766

760767
needTiles = _needTiles
768+
769+
// Cache semi-transparent blocks based on regex patterns from moreBlockDataGenerated.json
770+
const regexPatterns = Object.keys(moreBlockData.hasSemiTransparentTextuersRegex || {})
771+
semiTransparentBlocks = []
772+
773+
// Get all block names from blockstatesModels
774+
if (!Array.isArray(mcData.blocks)) throw new Error('mcData.blocks is not an array')
775+
const allBlockNames = mcData.blocks.map(block => block.name)
776+
777+
// Filter blocks that match any of the regex patterns
778+
for (const blockName of allBlockNames) {
779+
for (const pattern of regexPatterns) {
780+
try {
781+
const regex = new RegExp(pattern)
782+
if (regex.test(blockName)) {
783+
semiTransparentBlocks.push(blockName)
784+
break // Only add once per block
785+
}
786+
} catch (err) {
787+
// Invalid regex pattern, skip
788+
console.warn('Invalid regex pattern in hasSemiTransparentTextuersRegex:', pattern)
789+
}
790+
}
791+
}
761792
}

renderer/viewer/lib/mesher/shared.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export type MesherGeometryOutput = {
3737

3838
indices: Uint32Array | Uint16Array | number[],
3939
indicesCount: number,
40+
transparentIndicesStart: number, // Index where transparent geometry starts
4041
using32Array: boolean,
4142
tiles: Record<string, BlockType>,
4243
heads: Record<string, any>,

renderer/viewer/lib/mesher/test/mesherTester.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const setup = (version, initialBlocks: Array<[number[], string]>) => {
3333
}
3434
}
3535

36-
setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false, version)
36+
setBlockStatesData(blockStatesModels, blocksAtlasesJson, true, false, version, { blocks: mcData.blocksArray })
3737
const reload = () => {
3838
mesherWorld.removeColumn(0, 0)
3939
mesherWorld.addColumn(0, 0, chunk1.toJson())

renderer/viewer/lib/moreBlockDataGenerated.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,5 +710,13 @@
710710
"frogspawn": "rgb(64, 64, 255)",
711711
"reinforced_deepslate": "rgb(100, 100, 100)",
712712
"decorated_pot": "rgb(142, 60, 46)"
713+
},
714+
"hasSemiTransparentTextuersRegex": {
715+
"_stained_glass$": true,
716+
"_stained_glass_pane$": true,
717+
"^ice$": true,
718+
"^tinted_glass$": true,
719+
"^slime_block$": true,
720+
"^honey_block$": true
713721
}
714722
}

renderer/viewer/three/waypointSprite.ts

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export const WAYPOINT_CONFIG = {
1919
pixelSize: 50,
2020
paddingPx: 50,
2121
},
22+
// Default visual scale factor (can be overridden globally or per-waypoint)
23+
DEFAULT_VISUAL_SCALE: 1,
24+
// Default opacity (can be overridden globally or per-waypoint)
25+
DEFAULT_OPACITY: 1,
2226
}
2327

2428
export type WaypointSprite = {
@@ -51,14 +55,31 @@ export function createWaypointSprite (options: {
5155
// Y offset in world units used by updateScaleWorld only (screen-pixel API ignores this)
5256
labelYOffset?: number,
5357
metadata?: any,
58+
visualScale?: number,
59+
opacity?: number,
5460
}): WaypointSprite {
5561
const color = options.color ?? 0xFF_00_00
5662
const depthTest = options.depthTest ?? false
5763
const labelYOffset = options.labelYOffset ?? 1.5
5864

65+
// Get visual scale from options, metadata, server metadata, or default
66+
// Priority: options.visualScale > metadata.visualScale > window.serverMetadata?.waypointVisualScale > DEFAULT
67+
const visualScale = options.visualScale
68+
?? options.metadata?.visualScale
69+
?? (typeof window === 'undefined' ? undefined : (window as any).serverMetadata?.waypointVisualScale)
70+
?? WAYPOINT_CONFIG.DEFAULT_VISUAL_SCALE
71+
72+
// Get opacity from options, metadata, server metadata, or default
73+
// Priority: options.opacity > metadata.opacity > window.serverMetadata?.waypointOpacity > DEFAULT
74+
const opacity = options.opacity
75+
?? options.metadata?.opacity
76+
?? (typeof window === 'undefined' ? undefined : (window as any).serverMetadata?.waypointOpacity)
77+
?? WAYPOINT_CONFIG.DEFAULT_OPACITY
78+
5979
// Build combined sprite
60-
const sprite = createCombinedSprite(color, options.label ?? '', '0m', depthTest)
80+
const sprite = createCombinedSprite(color, options.label ?? '', '0m', depthTest, visualScale)
6181
sprite.renderOrder = 10
82+
sprite.material.opacity = opacity
6283
let currentLabel = options.label ?? ''
6384

6485
// Performance optimization: cache distance text to avoid unnecessary updates
@@ -79,7 +100,7 @@ export function createWaypointSprite (options: {
79100
group.position.set(x, y, z)
80101

81102
function setColor (newColor: number) {
82-
const canvas = drawCombinedCanvas(newColor, currentLabel, '0m')
103+
const canvas = drawCombinedCanvas(newColor, currentLabel, '0m', visualScale)
83104
const texture = new THREE.CanvasTexture(canvas)
84105
const mat = sprite.material
85106
mat.map?.dispose()
@@ -89,7 +110,7 @@ export function createWaypointSprite (options: {
89110

90111
function setLabel (newLabel?: string) {
91112
currentLabel = newLabel ?? ''
92-
const canvas = drawCombinedCanvas(color, currentLabel, '0m')
113+
const canvas = drawCombinedCanvas(color, currentLabel, '0m', visualScale)
93114
const texture = new THREE.CanvasTexture(canvas)
94115
const mat = sprite.material
95116
mat.map?.dispose()
@@ -104,7 +125,7 @@ export function createWaypointSprite (options: {
104125
}
105126
lastDistanceText = distanceText
106127

107-
const canvas = drawCombinedCanvas(color, label, distanceText)
128+
const canvas = drawCombinedCanvas(color, label, distanceText, visualScale)
108129
const texture = new THREE.CanvasTexture(canvas)
109130
const mat = sprite.material
110131
mat.map?.dispose()
@@ -129,8 +150,8 @@ export function createWaypointSprite (options: {
129150
) {
130151
const vFovRad = cameraFov * Math.PI / 180
131152
const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * distance
132-
// Use configured target screen size
133-
const scale = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.TARGET_SCREEN_PX / viewportHeightPx)
153+
// Use configured target screen size with visual scale multiplier
154+
const scale = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.TARGET_SCREEN_PX * visualScale / viewportHeightPx)
134155
sprite.scale.set(scale, scale, 1)
135156
}
136157

@@ -159,7 +180,7 @@ export function createWaypointSprite (options: {
159180
ctx.fill()
160181

161182
const texture = new THREE.CanvasTexture(canvas)
162-
const material = new THREE.SpriteMaterial({ map: texture, transparent: true, depthTest: false, depthWrite: false })
183+
const material = new THREE.SpriteMaterial({ map: texture, transparent: true, depthTest: false, depthWrite: false, opacity })
163184
arrowSprite = new THREE.Sprite(material)
164185
arrowSprite.renderOrder = 12
165186
arrowSprite.visible = false
@@ -278,9 +299,9 @@ export function createWaypointSprite (options: {
278299
const angle = Math.atan2(ry, rx)
279300
arrowSprite.material.rotation = angle - Math.PI / 2
280301

281-
// Constant pixel size for arrow (use fixed placement distance)
302+
// Constant pixel size for arrow (use fixed placement distance) with visual scale
282303
const worldUnitsPerScreenHeightAtDist = Math.tan(vFovRad / 2) * 2 * placeDist
283-
const sPx = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.ARROW.pixelSize / viewportHeightPx)
304+
const sPx = worldUnitsPerScreenHeightAtDist * (WAYPOINT_CONFIG.ARROW.pixelSize * visualScale / viewportHeightPx)
284305
arrowSprite.scale.set(sPx, sPx, 1)
285306
return false
286307
}
@@ -343,7 +364,7 @@ export function createWaypointSprite (options: {
343364
}
344365

345366
// Internal helpers
346-
function drawCombinedCanvas (color: number, id: string, distance: string): HTMLCanvasElement {
367+
function drawCombinedCanvas (color: number, id: string, distance: string, visualScale = 1): HTMLCanvasElement {
347368
const scale = WAYPOINT_CONFIG.CANVAS_SCALE * (globalThis.devicePixelRatio || 1)
348369
const size = WAYPOINT_CONFIG.CANVAS_SIZE * scale
349370
const canvas = document.createElement('canvas')
@@ -354,11 +375,11 @@ function drawCombinedCanvas (color: number, id: string, distance: string): HTMLC
354375
// Clear canvas
355376
ctx.clearRect(0, 0, size, size)
356377

357-
// Draw dot
378+
// Draw dot with visual scale applied
358379
const centerX = size / 2
359380
const dotY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.DOT_Y)
360-
const radius = Math.round(size * 0.05) // Dot takes up ~12% of canvas height
361-
const borderWidth = Math.max(2, Math.round(4 * scale))
381+
const radius = Math.round(size * 0.05 * visualScale) // Dot takes up ~5% of canvas height, scaled
382+
const borderWidth = Math.max(2, Math.round(4 * scale * visualScale))
362383

363384
// Outer border (black)
364385
ctx.beginPath()
@@ -376,21 +397,21 @@ function drawCombinedCanvas (color: number, id: string, distance: string): HTMLC
376397
ctx.textAlign = 'center'
377398
ctx.textBaseline = 'middle'
378399

379-
// Title
380-
const nameFontPx = Math.round(size * 0.08) // ~8% of canvas height
381-
const distanceFontPx = Math.round(size * 0.06) // ~6% of canvas height
400+
// Title with visual scale applied
401+
const nameFontPx = Math.round(size * 0.08 * visualScale) // ~8% of canvas height, scaled
402+
const distanceFontPx = Math.round(size * 0.06 * visualScale) // ~6% of canvas height, scaled
382403
ctx.font = `bold ${nameFontPx}px mojangles`
383-
ctx.lineWidth = Math.max(2, Math.round(3 * scale))
404+
ctx.lineWidth = Math.max(2, Math.round(3 * scale * visualScale))
384405
const nameY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.NAME_Y)
385406

386407
ctx.strokeStyle = 'black'
387408
ctx.strokeText(id, centerX, nameY)
388409
ctx.fillStyle = 'white'
389410
ctx.fillText(id, centerX, nameY)
390411

391-
// Distance
412+
// Distance with visual scale applied
392413
ctx.font = `bold ${distanceFontPx}px mojangles`
393-
ctx.lineWidth = Math.max(2, Math.round(2 * scale))
414+
ctx.lineWidth = Math.max(2, Math.round(2 * scale * visualScale))
394415
const distanceY = Math.round(size * WAYPOINT_CONFIG.LAYOUT.DISTANCE_Y)
395416

396417
ctx.strokeStyle = 'black'
@@ -401,8 +422,8 @@ function drawCombinedCanvas (color: number, id: string, distance: string): HTMLC
401422
return canvas
402423
}
403424

404-
function createCombinedSprite (color: number, id: string, distance: string, depthTest: boolean): THREE.Sprite {
405-
const canvas = drawCombinedCanvas(color, id, distance)
425+
function createCombinedSprite (color: number, id: string, distance: string, depthTest: boolean, visualScale = 1): THREE.Sprite {
426+
const canvas = drawCombinedCanvas(color, id, distance, visualScale)
406427
const texture = new THREE.CanvasTexture(canvas)
407428
texture.anisotropy = 1
408429
texture.magFilter = THREE.LinearFilter

renderer/viewer/three/worldrendererThree.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export class WorldRendererThree extends WorldRendererCommon {
4747
entities = new Entities(this)
4848
cameraGroupVr?: THREE.Object3D
4949
material = new THREE.MeshLambertMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1 })
50+
// Separate material for semi-transparent blocks (like stained glass) - disables depth write for correct alpha blending
51+
transparentMaterial = new THREE.MeshLambertMaterial({ vertexColors: true, transparent: true, alphaTest: 0.1, depthWrite: false })
5052
itemsTexture: THREE.Texture
5153
cursorBlock: CursorBlock
5254
onRender: Array<() => void> = []
@@ -241,6 +243,7 @@ export class WorldRendererThree extends WorldRendererCommon {
241243
texture.needsUpdate = true
242244
texture.flipY = false
243245
this.material.map = texture
246+
this.transparentMaterial.map = texture
244247

245248
const itemsTexture = loadThreeJsTextureFromBitmap(resources.itemsAtlasImage)
246249
itemsTexture.needsUpdate = true
@@ -415,7 +418,24 @@ export class WorldRendererThree extends WorldRendererCommon {
415418
geometry.setAttribute('uv', new THREE.BufferAttribute(data.geometry.uvs, 2))
416419
geometry.index = new THREE.BufferAttribute(data.geometry.indices as Uint32Array | Uint16Array, 1)
417420

418-
const mesh = new THREE.Mesh(geometry, this.material)
421+
// Use draw groups to separate opaque and transparent geometry for proper alpha blending
422+
const { transparentIndicesStart } = data.geometry
423+
const totalIndices = data.geometry.indices.length
424+
const hasTransparent = transparentIndicesStart < totalIndices
425+
426+
let mesh: THREE.Mesh
427+
if (hasTransparent && transparentIndicesStart > 0) {
428+
// Both opaque and transparent geometry - use multi-material with groups
429+
geometry.addGroup(0, transparentIndicesStart, 0) // Opaque group
430+
geometry.addGroup(transparentIndicesStart, totalIndices - transparentIndicesStart, 1) // Transparent group
431+
mesh = new THREE.Mesh(geometry, [this.material, this.transparentMaterial])
432+
} else if (hasTransparent) {
433+
// Only transparent geometry
434+
mesh = new THREE.Mesh(geometry, this.transparentMaterial)
435+
} else {
436+
// Only opaque geometry
437+
mesh = new THREE.Mesh(geometry, this.material)
438+
}
419439
mesh.position.set(data.geometry.sx, data.geometry.sy, data.geometry.sz)
420440
mesh.name = 'mesh'
421441
object = new THREE.Group()

0 commit comments

Comments
 (0)