Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Vitaly Turovsky
83cdc1e01f a 2025-09-20 02:52:59 +03:00
Cursor Agent
0e82a64faf feat: Add metadata to waypoints and restrict arrow direction
Co-authored-by: vital2580 <vital2580@icloud.com>
2025-09-19 05:07:03 +00:00
3 changed files with 49 additions and 8 deletions

View file

@ -16,7 +16,7 @@ export const WAYPOINT_CONFIG = {
CANVAS_SCALE: 2,
ARROW: {
enabledDefault: false,
pixelSize: 30,
pixelSize: 50,
paddingPx: 50,
},
}
@ -50,6 +50,7 @@ export function createWaypointSprite (options: {
depthTest?: boolean,
// Y offset in world units used by updateScaleWorld only (screen-pixel API ignores this)
labelYOffset?: number,
metadata?: any,
}): WaypointSprite {
const color = options.color ?? 0xFF_00_00
const depthTest = options.depthTest ?? false
@ -131,16 +132,22 @@ export function createWaypointSprite (options: {
canvas.height = size
const ctx = canvas.getContext('2d')!
ctx.clearRect(0, 0, size, size)
// Draw arrow shape
ctx.beginPath()
ctx.moveTo(size * 0.2, size * 0.5)
ctx.lineTo(size * 0.8, size * 0.5)
ctx.lineTo(size * 0.5, size * 0.2)
ctx.moveTo(size * 0.15, size * 0.5)
ctx.lineTo(size * 0.85, size * 0.5)
ctx.lineTo(size * 0.5, size * 0.15)
ctx.closePath()
ctx.lineWidth = 4
// Use waypoint color for arrow
const colorHex = `#${color.toString(16).padStart(6, '0')}`
ctx.lineWidth = 6
ctx.strokeStyle = 'black'
ctx.stroke()
ctx.fillStyle = 'white'
ctx.fillStyle = colorHex
ctx.fill()
const texture = new THREE.CanvasTexture(canvas)
const material = new THREE.SpriteMaterial({ map: texture, transparent: true, depthTest: false, depthWrite: false })
arrowSprite = new THREE.Sprite(material)
@ -169,6 +176,9 @@ export function createWaypointSprite (options: {
ensureArrow()
if (!arrowSprite) return true
// Check if onlyLeftRight is enabled in metadata
const onlyLeftRight = options.metadata?.onlyLeftRight === true
// Build camera basis using camera.up to respect custom orientations
const forward = new THREE.Vector3()
camera.getWorldDirection(forward) // camera look direction
@ -213,6 +223,20 @@ export function createWaypointSprite (options: {
}
}
// Apply onlyLeftRight logic - restrict arrows to left/right edges only
if (onlyLeftRight) {
// Force the arrow to appear only on left or right edges
if (Math.abs(rx) > Math.abs(ry)) {
// Horizontal direction is dominant, keep it
ry = 0
} else {
// Vertical direction is dominant, but we want only left/right
// So choose left or right based on the sign of rx
rx = rx >= 0 ? 1 : -1
ry = 0
}
}
// Place on the rectangle border [-1,1]x[-1,1]
const s = Math.max(Math.abs(rx), Math.abs(ry)) || 1
let ndcX = rx / s

View file

@ -17,6 +17,7 @@ interface WaypointOptions {
color?: number
label?: string
minDistance?: number
metadata?: any
}
export class WaypointsRenderer {
@ -71,13 +72,14 @@ export class WaypointsRenderer {
this.removeWaypoint(id)
const color = options.color ?? 0xFF_00_00
const { label } = options
const { label, metadata } = options
const minDistance = options.minDistance ?? 0
const sprite = createWaypointSprite({
position: new THREE.Vector3(x, y, z),
color,
label: (label || id),
metadata,
})
sprite.enableOffscreenArrow(true)
sprite.setArrowParent(this.waypointScene)

View file

@ -82,15 +82,30 @@ const registerWaypointChannels = () => {
{
name: 'color',
type: 'i32'
},
{
name: 'metadataJson',
type: ['pstring', { countType: 'i16' }]
}
]
]
registerChannel('minecraft-web-client:waypoint-add', packetStructure, (data) => {
// Parse metadata if provided
let metadata: any = {}
if (data.metadataJson && data.metadataJson.trim() !== '') {
try {
metadata = JSON.parse(data.metadataJson)
} catch (error) {
console.warn('Failed to parse waypoint metadataJson:', error)
}
}
getThreeJsRendererMethods()?.addWaypoint(data.id, data.x, data.y, data.z, {
minDistance: data.minDistance,
label: data.label || undefined,
color: data.color || undefined
color: data.color || undefined,
metadata
})
})