Compare commits
13 commits
next
...
cursor/upd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ceeef1d1f8 | ||
|
|
c6440b1b17 | ||
|
|
ba2fb3b731 | ||
|
|
8723f9092f | ||
|
|
b7b196bf74 | ||
|
|
258361300c | ||
|
|
1c894ea9d2 | ||
|
|
720577904a | ||
|
|
4fb57503b7 | ||
|
|
3d3aef0fc4 | ||
|
|
68aa0a37bc | ||
|
|
5b9e21d0ae | ||
|
|
782d311259 |
6 changed files with 761 additions and 1 deletions
|
|
@ -48,6 +48,7 @@ export const getInitialPlayerState = () => proxy({
|
|||
heldItemMain: undefined as HandItemBlock | undefined,
|
||||
heldItemOff: undefined as HandItemBlock | undefined,
|
||||
perspective: 'first_person' as CameraPerspective,
|
||||
onFire: false,
|
||||
|
||||
cameraSpectatingEntity: undefined as number | undefined,
|
||||
})
|
||||
|
|
|
|||
159
renderer/viewer/three/firstPersonEffects.ts
Normal file
159
renderer/viewer/three/firstPersonEffects.ts
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
import * as THREE from 'three'
|
||||
import type { AtlasParser, TextureInfo } from 'mc-assets'
|
||||
import { getLoadedImage } from 'mc-assets/dist/utils'
|
||||
import { LoadedResourcesTransferrable, ResourcesManager } from '../../../src/resourcesManager'
|
||||
import { WorldRendererThree } from './worldrendererThree'
|
||||
|
||||
export class FirstPersonEffects {
|
||||
private readonly fireSprite: THREE.Sprite
|
||||
private fireTextures: THREE.Texture[] = []
|
||||
private currentTextureIndex = 0
|
||||
private lastTextureUpdate = 0
|
||||
private readonly TEXTURE_UPDATE_INTERVAL = 200 // 5 times per second
|
||||
private readonly cameraGroup = new THREE.Group()
|
||||
private readonly effectsGroup = new THREE.Group()
|
||||
updateCameraGroup = true
|
||||
|
||||
constructor (private readonly worldRenderer: WorldRendererThree) {
|
||||
this.worldRenderer.scene.add(this.cameraGroup)
|
||||
this.cameraGroup.add(this.effectsGroup)
|
||||
|
||||
if (this.worldRenderer.resourcesManager.currentResources) {
|
||||
void this.loadTextures()
|
||||
}
|
||||
this.worldRenderer.resourcesManager.on('assetsTexturesUpdated', () => {
|
||||
void this.loadTextures()
|
||||
})
|
||||
|
||||
// Create sprite
|
||||
const spriteMaterial = new THREE.SpriteMaterial({
|
||||
map: null,
|
||||
transparent: true,
|
||||
alphaTest: 0.1,
|
||||
blending: THREE.AdditiveBlending, // Makes fire glow effect
|
||||
depthTest: false, // Ensures fire always renders in front
|
||||
depthWrite: false,
|
||||
color: new THREE.Color(1, 0.8, 0.4), // Slightly warm tint
|
||||
})
|
||||
|
||||
this.fireSprite = new THREE.Sprite(spriteMaterial)
|
||||
this.fireSprite.visible = false
|
||||
this.effectsGroup.add(this.fireSprite)
|
||||
|
||||
this.worldRenderer.onRender.push(() => {
|
||||
this.update()
|
||||
})
|
||||
}
|
||||
|
||||
async loadTextures () {
|
||||
const fireImageBase64 = [] as string[]
|
||||
|
||||
const resources = this.worldRenderer.resourcesManager.currentResources
|
||||
if (!resources) {
|
||||
console.warn('FirstPersonEffects: No resources available for loading fire textures')
|
||||
return
|
||||
}
|
||||
|
||||
// Cast resourcesManager to access blocksAtlasParser using proper types
|
||||
const resourcesManager = this.worldRenderer.resourcesManager as ResourcesManager
|
||||
const blocksAtlasParser = resourcesManager.blocksAtlasParser as AtlasParser
|
||||
if (!blocksAtlasParser?.atlas?.latest) {
|
||||
console.warn('FirstPersonEffects: Blocks atlas parser not available')
|
||||
return
|
||||
}
|
||||
|
||||
// Load all fire animation frames (fire_0, fire_1, etc.)
|
||||
for (let i = 0; i < 32; i++) {
|
||||
try {
|
||||
const textureInfo = blocksAtlasParser.getTextureInfo(`fire_${i}`)
|
||||
if (!textureInfo) break // Stop when no more frames available
|
||||
|
||||
const { atlas } = blocksAtlasParser
|
||||
const defaultSize = atlas.latest.tileSize || 16
|
||||
const { width: imageWidth = 256, height: imageHeight = 256 } = atlas.latest
|
||||
|
||||
const canvas = new OffscreenCanvas(
|
||||
textureInfo.width ?? defaultSize,
|
||||
textureInfo.height ?? defaultSize
|
||||
)
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (ctx && blocksAtlasParser.latestImage) {
|
||||
const image = await getLoadedImage(blocksAtlasParser.latestImage)
|
||||
const sourceX = textureInfo.u * imageWidth
|
||||
const sourceY = textureInfo.v * imageHeight
|
||||
const sourceWidth = textureInfo.width ?? defaultSize
|
||||
const sourceHeight = textureInfo.height ?? defaultSize
|
||||
|
||||
ctx.drawImage(
|
||||
image,
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceWidth,
|
||||
sourceHeight,
|
||||
0,
|
||||
0,
|
||||
sourceWidth,
|
||||
sourceHeight
|
||||
)
|
||||
|
||||
const blob = await canvas.convertToBlob()
|
||||
const url = URL.createObjectURL(blob)
|
||||
fireImageBase64.push(url)
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`FirstPersonEffects: Error loading fire texture ${i}:`, error)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Create textures from base64 images
|
||||
this.fireTextures = fireImageBase64.map(base64 => {
|
||||
const texture = new THREE.TextureLoader().load(base64)
|
||||
texture.minFilter = THREE.NearestFilter
|
||||
texture.magFilter = THREE.NearestFilter
|
||||
return texture
|
||||
})
|
||||
|
||||
console.log(`FirstPersonEffects: Loaded ${this.fireTextures.length} fire animation frames`)
|
||||
}
|
||||
|
||||
setIsOnFire (isOnFire: boolean) {
|
||||
this.fireSprite.visible = isOnFire
|
||||
}
|
||||
|
||||
update () {
|
||||
if (!this.fireSprite.visible || this.fireTextures.length === 0) return
|
||||
|
||||
const now = Date.now()
|
||||
if (now - this.lastTextureUpdate >= this.TEXTURE_UPDATE_INTERVAL) {
|
||||
this.currentTextureIndex = (this.currentTextureIndex + 1) % this.fireTextures.length
|
||||
this.fireSprite.material.map = this.fireTextures[this.currentTextureIndex]
|
||||
this.lastTextureUpdate = now
|
||||
}
|
||||
|
||||
// Update camera group position and rotation
|
||||
const { camera } = this.worldRenderer
|
||||
if (this.updateCameraGroup && camera) {
|
||||
this.cameraGroup.position.copy(camera.position)
|
||||
this.cameraGroup.rotation.copy(camera.rotation)
|
||||
}
|
||||
|
||||
// Position fire overlay in front of camera but fill the screen like in Minecraft
|
||||
const distance = 0.1 // Very close to camera for overlay effect
|
||||
this.effectsGroup.position.set(0, 0, -distance)
|
||||
|
||||
// Scale sprite to fill most of the screen like Minecraft's fire overlay
|
||||
const { innerWidth, innerHeight } = window
|
||||
const aspect = innerWidth / innerHeight
|
||||
const { fov } = camera
|
||||
const fovRadians = (fov * Math.PI) / 180
|
||||
const height = 2 * Math.tan(fovRadians / 2) * distance
|
||||
const width = height * aspect
|
||||
|
||||
// Make fire overlay larger to create immersive burning effect
|
||||
this.fireSprite.scale.set(width * 1.8, height * 1.8, 1)
|
||||
|
||||
// Slightly offset the fire to the bottom of the screen like in Minecraft
|
||||
this.fireSprite.position.set(0, -height * 0.3, 0)
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ import { getItemUv } from './appShared'
|
|||
import { Entities } from './entities'
|
||||
import { ThreeJsSound } from './threeJsSound'
|
||||
import { CameraShake } from './cameraShake'
|
||||
import { FirstPersonEffects } from './firstPersonEffects'
|
||||
import { ThreeJsMedia } from './threeJsMedia'
|
||||
import { Fountain } from './threeJsParticles'
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|||
cameraContainer: THREE.Object3D
|
||||
media: ThreeJsMedia
|
||||
waitingChunksToDisplay = {} as { [chunkKey: string]: SectionKey[] }
|
||||
firstPersonEffects: FirstPersonEffects
|
||||
camera: THREE.PerspectiveCamera
|
||||
renderTimeAvg = 0
|
||||
sectionsOffsetsAnimations = {} as {
|
||||
|
|
@ -99,6 +101,7 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|||
|
||||
this.soundSystem = new ThreeJsSound(this)
|
||||
this.cameraShake = new CameraShake(this, this.onRender)
|
||||
this.firstPersonEffects = new FirstPersonEffects(this)
|
||||
this.media = new ThreeJsMedia(this)
|
||||
// this.fountain = new Fountain(this.scene, this.scene, {
|
||||
// position: new THREE.Vector3(0, 10, 0),
|
||||
|
|
@ -184,6 +187,10 @@ export class WorldRendererThree extends WorldRendererCommon {
|
|||
this.updateCamera(vecPos, this.cameraShake.getBaseRotation().yaw, this.cameraShake.getBaseRotation().pitch)
|
||||
// todo also update camera when block within camera was changed
|
||||
})
|
||||
this.onReactivePlayerStateUpdated('onFire', (value) => {
|
||||
// Update fire effect when player fire status changes
|
||||
this.firstPersonEffects.setIsOnFire(value)
|
||||
})
|
||||
}
|
||||
|
||||
override watchReactiveConfig () {
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ export class PlayerStateControllerMain {
|
|||
bot.on('physicsTick', () => {
|
||||
if (this.isUsingItem) this.reactive.itemUsageTicks++
|
||||
updateSneakingOrFlying()
|
||||
// Update fire status
|
||||
this.updateFireStatus()
|
||||
})
|
||||
// todo move from gameAdditionalState to reactive directly
|
||||
subscribeKey(gameAdditionalState, 'isSneaking', () => {
|
||||
|
|
@ -188,6 +190,53 @@ export class PlayerStateControllerMain {
|
|||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Fire Status
|
||||
private updateFireStatus () {
|
||||
if (!bot?.entity || this.disableStateUpdates) return
|
||||
|
||||
// Check if player is on fire by looking for burning-related effects and entity metadata
|
||||
let isOnFire = false
|
||||
|
||||
// Method 1: Check entity metadata/properties for fire status
|
||||
try {
|
||||
// These are the most common ways fire status is tracked in Minecraft
|
||||
isOnFire = (bot.entity as any).onFire ||
|
||||
(bot.entity as any).fireTicks > 0 ||
|
||||
(bot.entity as any).fire > 0 ||
|
||||
false
|
||||
} catch {
|
||||
// Fallback if properties don't exist
|
||||
}
|
||||
|
||||
// Method 2: Check for fire-related damage effects (when fire resistance is not active)
|
||||
if (!isOnFire) {
|
||||
const hasFireResistance = Object.values(bot.entity.effects ?? {}).some((effect: any) => loadedData.effects?.[effect.id]?.name === 'fire_resistance')
|
||||
|
||||
// If no fire resistance and recently took damage, might be on fire
|
||||
// This is a heuristic approach since we don't have direct fire status
|
||||
if (!hasFireResistance) {
|
||||
// Could add more sophisticated fire detection here based on damage patterns
|
||||
}
|
||||
}
|
||||
|
||||
// Debug mode: Allow manually triggering fire effect for testing
|
||||
// You can test the fire effect by running: window.playerState.setOnFire(true)
|
||||
if ((window as any).debugFireEffect !== undefined) {
|
||||
isOnFire = (window as any).debugFireEffect
|
||||
}
|
||||
|
||||
if (this.reactive.onFire !== isOnFire) {
|
||||
this.reactive.onFire = isOnFire
|
||||
}
|
||||
}
|
||||
|
||||
// Debug method to manually set fire status for testing
|
||||
setOnFire (value: boolean) {
|
||||
(window as any).debugFireEffect = value
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
|
||||
export const playerState = new PlayerStateControllerMain()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default () => {
|
|||
if (!isModalActive/* || conflicts.length === 0 */) return null
|
||||
|
||||
const clampText = (text: string) => {
|
||||
if (typeof text !== "string") text = JSON.stringify(text)
|
||||
if (typeof text !== 'string') text = JSON.stringify(text)
|
||||
return text.length > 30 ? text.slice(0, 30) + '...' : text
|
||||
}
|
||||
|
||||
|
|
|
|||
544
src/types/modules.d.ts
vendored
Normal file
544
src/types/modules.d.ts
vendored
Normal file
|
|
@ -0,0 +1,544 @@
|
|||
/**
|
||||
* Enhanced module declarations for better type safety in the Minecraft web client
|
||||
* Provides type definitions for external modules and enhances existing ones
|
||||
*/
|
||||
|
||||
// Enhanced THREE.js type augmentations
|
||||
declare module 'three' {
|
||||
interface Material {
|
||||
map?: Texture | null
|
||||
}
|
||||
|
||||
interface SpriteMaterial extends Material {
|
||||
map?: Texture | null
|
||||
transparent?: boolean
|
||||
alphaTest?: number
|
||||
blending?: Blending
|
||||
depthTest?: boolean
|
||||
depthWrite?: boolean
|
||||
color?: Color
|
||||
}
|
||||
}
|
||||
|
||||
// Vec3 module declarations
|
||||
declare module 'vec3' {
|
||||
export class Vec3 {
|
||||
constructor (x?: number, y?: number, z?: number)
|
||||
x: number
|
||||
y: number
|
||||
z: number
|
||||
|
||||
set (x: number, y: number, z: number): this
|
||||
add (other: Vec3): Vec3
|
||||
subtract (other: Vec3): Vec3
|
||||
multiply (scalar: number): Vec3
|
||||
divide (scalar: number): Vec3
|
||||
dot (other: Vec3): number
|
||||
cross (other: Vec3): Vec3
|
||||
length (): number
|
||||
normalize (): Vec3
|
||||
distance (other: Vec3): number
|
||||
equals (other: Vec3): boolean
|
||||
clone (): Vec3
|
||||
offset (dx: number, dy: number, dz: number): Vec3
|
||||
plus (other: Vec3): Vec3
|
||||
minus (other: Vec3): Vec3
|
||||
scaled (scalar: number): Vec3
|
||||
abs (): Vec3
|
||||
floor (): Vec3
|
||||
ceil (): Vec3
|
||||
round (): Vec3
|
||||
translate (dx: number, dy: number, dz: number): Vec3
|
||||
toString (): string
|
||||
toArray (): [number, number, number]
|
||||
|
||||
static fromArray (arr: [number, number, number]): Vec3
|
||||
}
|
||||
export default Vec3
|
||||
}
|
||||
|
||||
// Prismarine-nbt module declarations
|
||||
declare module 'prismarine-nbt' {
|
||||
export interface NBTData {
|
||||
name: string
|
||||
value: any
|
||||
type: string
|
||||
}
|
||||
|
||||
export interface ParsedNBT {
|
||||
parsed: NBTData
|
||||
type: string
|
||||
metadata: any
|
||||
}
|
||||
|
||||
export function parse (buffer: Buffer, littleEndian?: boolean): Promise<ParsedNBT>
|
||||
export function parseUncompressed (buffer: Buffer, littleEndian?: boolean): ParsedNBT
|
||||
export function writeUncompressed (value: any, littleEndian?: boolean): Buffer
|
||||
export function simplify (data: any): any
|
||||
export function serialize (nbt: any): Buffer
|
||||
|
||||
export class Writer {
|
||||
constructor (littleEndian?: boolean)
|
||||
writeTag (tag: any): void
|
||||
getBuffer (): Buffer
|
||||
}
|
||||
|
||||
export class Reader {
|
||||
constructor (buffer: Buffer, littleEndian?: boolean)
|
||||
readTag (): any
|
||||
}
|
||||
|
||||
export default {
|
||||
parse,
|
||||
parseUncompressed,
|
||||
writeUncompressed,
|
||||
simplify,
|
||||
serialize,
|
||||
Writer,
|
||||
Reader
|
||||
}
|
||||
}
|
||||
|
||||
// @tweenjs/tween.js module declarations
|
||||
declare module '@tweenjs/tween.js' {
|
||||
export interface TweenEasing {
|
||||
Linear: {
|
||||
None (k: number): number
|
||||
}
|
||||
Quadratic: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Cubic: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Quartic: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Quintic: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Sinusoidal: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Exponential: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Circular: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Elastic: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Back: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
Bounce: {
|
||||
In (k: number): number
|
||||
Out (k: number): number
|
||||
InOut (k: number): number
|
||||
}
|
||||
}
|
||||
|
||||
export class Tween<T extends Record<string, any>> {
|
||||
constructor (object: T, group?: Group)
|
||||
to (properties: Partial<T>, duration: number): this
|
||||
start (time?: number): this
|
||||
stop (): this
|
||||
end (): this
|
||||
stopChainedTweens (): this
|
||||
group (group: Group): this
|
||||
delay (amount: number): this
|
||||
repeat (times: number): this
|
||||
repeatDelay (amount: number): this
|
||||
yoyo (yoyo: boolean): this
|
||||
easing (easingFunction: (k: number) => number): this
|
||||
interpolation (interpolationFunction: (v: number[], k: number) => number): this
|
||||
chain (...tweens: Tween<any>[]): this
|
||||
onStart (callback: (object: T) => void): this
|
||||
onUpdate (callback: (object: T, elapsed: number) => void): this
|
||||
onRepeat (callback: (object: T) => void): this
|
||||
onComplete (callback: (object: T) => void): this
|
||||
onStop (callback: (object: T) => void): this
|
||||
update (time: number): boolean
|
||||
isPlaying (): boolean
|
||||
isPaused (): boolean
|
||||
pause (time?: number): this
|
||||
resume (time?: number): this
|
||||
duration (duration?: number): number
|
||||
getDuration (): number
|
||||
getId (): number
|
||||
}
|
||||
|
||||
export class Group {
|
||||
constructor ()
|
||||
getAll (): Tween<any>[]
|
||||
removeAll (): void
|
||||
add (tween: Tween<any>): void
|
||||
remove (tween: Tween<any>): void
|
||||
update (time?: number): boolean
|
||||
}
|
||||
|
||||
export const Easing: TweenEasing
|
||||
|
||||
export function update (time?: number): boolean
|
||||
export function getAll (): Tween<any>[]
|
||||
export function removeAll (): void
|
||||
export function add (tween: Tween<any>): void
|
||||
export function remove (tween: Tween<any>): void
|
||||
export function now (): number
|
||||
|
||||
export default {
|
||||
Tween,
|
||||
Group,
|
||||
Easing,
|
||||
update,
|
||||
getAll,
|
||||
removeAll,
|
||||
add,
|
||||
remove,
|
||||
now
|
||||
}
|
||||
}
|
||||
|
||||
// mc-assets module declarations with enhanced types
|
||||
declare module 'mc-assets' {
|
||||
export interface AtlasParser {
|
||||
atlas: {
|
||||
latest: {
|
||||
tileSize: number
|
||||
width: number
|
||||
height: number
|
||||
textures: Record<string, TextureInfo>
|
||||
suSv: number
|
||||
}
|
||||
}
|
||||
latestImage?: string
|
||||
getTextureInfo(name: string): TextureInfo | null | undefined
|
||||
createDebugImage(includeText?: boolean): Promise<string>
|
||||
makeNewAtlas(...args: any[]): Promise<{ atlas: any, canvas: HTMLCanvasElement }>
|
||||
}
|
||||
|
||||
export interface TextureInfo {
|
||||
u: number
|
||||
v: number
|
||||
width?: number
|
||||
height?: number
|
||||
su?: number
|
||||
sv?: number
|
||||
}
|
||||
|
||||
export interface BlockModel {
|
||||
elements?: any[]
|
||||
textures?: Record<string, string>
|
||||
display?: Record<string, any>
|
||||
gui_light?: string
|
||||
tints?: any
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface ItemsAtlasesOutputJson {
|
||||
tileSize: number
|
||||
width: number
|
||||
height: number
|
||||
textures: Record<string, TextureInfo>
|
||||
suSv: number
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'mc-assets/dist/utils' {
|
||||
export function getLoadedImage(src: string | HTMLImageElement): Promise<HTMLImageElement>
|
||||
export function versionToNumber(version: string): number
|
||||
}
|
||||
|
||||
declare module 'mc-assets/dist/atlasParser' {
|
||||
export { AtlasParser, ItemsAtlasesOutputJson } from 'mc-assets'
|
||||
}
|
||||
|
||||
declare module 'mc-assets/dist/worldBlockProvider' {
|
||||
export interface WorldBlockProvider {
|
||||
getBlockModel(name: string): any
|
||||
getTextureUV(textureName: string): number[] | undefined
|
||||
}
|
||||
|
||||
export default function worldBlockProvider(
|
||||
blockstatesModels: any,
|
||||
atlas: any,
|
||||
version: string
|
||||
): WorldBlockProvider
|
||||
}
|
||||
|
||||
declare module 'mc-assets/dist/itemsRenderer' {
|
||||
export interface ItemsRendererConstructor {
|
||||
new (
|
||||
version: string,
|
||||
blockstatesModels: any,
|
||||
itemsAtlasParser: any,
|
||||
blocksAtlasParser: any
|
||||
): any
|
||||
}
|
||||
export const ItemsRenderer: ItemsRendererConstructor
|
||||
}
|
||||
|
||||
declare module 'mc-assets/dist/itemDefinitions' {
|
||||
export interface ItemSelector {
|
||||
properties?: {
|
||||
'minecraft:using_item'?: boolean
|
||||
'minecraft:use_duration'?: number
|
||||
'minecraft:use_cycle'?: number
|
||||
'minecraft:display_context'?: string
|
||||
}
|
||||
}
|
||||
|
||||
export function getItemDefinition(store: any, selector: any): any
|
||||
export function getLoadedItemDefinitionsStore(data: any): any
|
||||
}
|
||||
|
||||
// Enhanced valtio type declarations
|
||||
declare module 'valtio' {
|
||||
export function proxy<T extends object>(initialObject: T): T
|
||||
export function subscribe<T>(proxy: T, callback: (ops: any[]) => void): () => void
|
||||
export function ref<T>(obj: T): T
|
||||
export function useSnapshot<T extends object>(proxy: T): Readonly<T>
|
||||
}
|
||||
|
||||
declare module 'valtio/utils' {
|
||||
export function subscribeKey<T extends object, K extends keyof T>(
|
||||
proxy: T,
|
||||
key: K,
|
||||
callback: (value: T[K]) => void
|
||||
): () => void
|
||||
}
|
||||
|
||||
declare module 'valtio/vanilla' {
|
||||
export function proxy<T extends object>(initialObject: T): T
|
||||
export function subscribe<T>(proxy: T, callback: (ops: any[]) => void): () => void
|
||||
export function snapshot<T extends object>(proxy: T): Readonly<T>
|
||||
}
|
||||
|
||||
// Three.js addon modules
|
||||
declare module 'three/examples/jsm/controls/OrbitControls.js' {
|
||||
import { Camera, EventDispatcher } from 'three'
|
||||
|
||||
export interface OrbitControlsConstructor {
|
||||
new (object: Camera, domElement?: HTMLElement): OrbitControlsInstance
|
||||
}
|
||||
|
||||
export interface OrbitControlsInstance extends EventDispatcher {
|
||||
enabled: boolean
|
||||
enableDamping: boolean
|
||||
dampingFactor: number
|
||||
update(): boolean
|
||||
dispose(): void
|
||||
}
|
||||
|
||||
export const OrbitControls: OrbitControlsConstructor
|
||||
}
|
||||
|
||||
declare module 'three/examples/jsm/webxr/VRButton.js' {
|
||||
import { WebGLRenderer } from 'three'
|
||||
|
||||
export const VRButton: {
|
||||
createButton(renderer: WebGLRenderer): HTMLElement
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'three/addons/controls/OrbitControls.js' {
|
||||
export { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
|
||||
}
|
||||
|
||||
declare module 'three-stdlib' {
|
||||
import { Material, Object3D, BufferGeometry, Vector2 } from 'three'
|
||||
|
||||
export class LineMaterial extends Material {
|
||||
constructor (parameters?: any)
|
||||
color: any
|
||||
linewidth: number
|
||||
resolution: Vector2
|
||||
dashOffset: number
|
||||
}
|
||||
|
||||
export class LineSegmentsGeometry extends BufferGeometry {
|
||||
constructor ()
|
||||
setPositions (positions: number[]): this
|
||||
fromEdgesGeometry (geometry: BufferGeometry): this
|
||||
}
|
||||
|
||||
export class Wireframe extends Object3D {
|
||||
constructor (geometry?: BufferGeometry, material?: Material)
|
||||
computeLineDistances (): void
|
||||
}
|
||||
|
||||
export class OBJLoader {
|
||||
constructor ()
|
||||
load (url: string, onLoad?: (object: any) => void): void
|
||||
parse (data: string): Object3D
|
||||
}
|
||||
}
|
||||
|
||||
// Additional commonly used modules
|
||||
declare module 'stats.js' {
|
||||
export default class Stats {
|
||||
constructor ()
|
||||
dom: HTMLDivElement
|
||||
begin (): void
|
||||
end (): void
|
||||
update (): void
|
||||
setMode (mode: number): void
|
||||
showPanel (panel: number): void
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'debug' {
|
||||
interface Debug {
|
||||
(namespace: string): Debugger
|
||||
enabled (namespaces: string): boolean
|
||||
humanize (val: number): string
|
||||
names: RegExp[]
|
||||
skips: RegExp[]
|
||||
formatters: Record<string, (v: any) => string>
|
||||
}
|
||||
|
||||
interface Debugger {
|
||||
(formatter: any, ...args: any[]): void
|
||||
enabled: boolean
|
||||
log: (...args: any[]) => any
|
||||
namespace: string
|
||||
destroy (): boolean
|
||||
extend (namespace: string, delimiter?: string): Debugger
|
||||
}
|
||||
|
||||
const debug: Debug
|
||||
export = debug
|
||||
}
|
||||
|
||||
// Enhanced events module with missing methods
|
||||
declare module 'events' {
|
||||
export class EventEmitter {
|
||||
static defaultMaxListeners: number
|
||||
|
||||
constructor ()
|
||||
on (event: string, listener: (...args: any[]) => void): this
|
||||
once (event: string, listener: (...args: any[]) => void): this
|
||||
emit (event: string, ...args: any[]): boolean
|
||||
off (event: string, listener: (...args: any[]) => void): this
|
||||
removeListener (event: string, listener: (...args: any[]) => void): this
|
||||
removeAllListeners (event?: string): this
|
||||
listeners (event: string): Function[]
|
||||
listenerCount (event: string): number
|
||||
addListener (event: string, listener: (...args: any[]) => void): this
|
||||
prependListener (event: string, listener: (...args: any[]) => void): this
|
||||
prependOnceListener (event: string, listener: (...args: any[]) => void): this
|
||||
setMaxListeners (n: number): this
|
||||
getMaxListeners (): number
|
||||
eventNames (): Array<string | symbol>
|
||||
rawListeners (event: string): Function[]
|
||||
}
|
||||
}
|
||||
|
||||
// Browser API enhancements
|
||||
interface Window {
|
||||
playerState?: {
|
||||
setOnFire(value: boolean): void
|
||||
reactive: {
|
||||
onFire: boolean
|
||||
}
|
||||
}
|
||||
debugFireEffect?: boolean
|
||||
}
|
||||
|
||||
// Enhanced canvas and WebGL types
|
||||
interface OffscreenCanvas {
|
||||
convertToBlob(options?: { type?: string, quality?: number }): Promise<Blob>
|
||||
getContext(contextId: '2d'): OffscreenCanvasRenderingContext2D | null
|
||||
getContext(contextId: 'webgl' | 'webgl2'): WebGLRenderingContext | null
|
||||
}
|
||||
|
||||
interface OffscreenCanvasRenderingContext2D {
|
||||
drawImage(
|
||||
image: HTMLImageElement | ImageBitmap,
|
||||
sx: number, sy: number, sw: number, sh: number,
|
||||
dx: number, dy: number, dw: number, dh: number
|
||||
): void
|
||||
drawImage(image: HTMLImageElement | ImageBitmap, dx: number, dy: number): void
|
||||
}
|
||||
|
||||
// Bot entity type enhancements for fire detection
|
||||
interface BotEntity {
|
||||
onFire?: boolean
|
||||
fireTicks?: number
|
||||
fire?: number
|
||||
effects?: Record<string, { id: number }>
|
||||
position: { x: number, y: number, z: number }
|
||||
yaw: number
|
||||
pitch: number
|
||||
onGround: boolean
|
||||
velocity: { x: number, y: number, z: number }
|
||||
}
|
||||
|
||||
// Enhanced bot client interface
|
||||
interface BotClient {
|
||||
on (event: string, callback: (...args: any[]) => void): void
|
||||
prependListener (event: string, callback: (...args: any[]) => void): void
|
||||
write<T extends keyof any> (name: T, data: any): Buffer
|
||||
}
|
||||
|
||||
// Global bot interface enhancement
|
||||
declare global {
|
||||
const bot: {
|
||||
entity?: BotEntity
|
||||
_client?: BotClient
|
||||
game?: {
|
||||
gameMode?: string
|
||||
dimension?: string
|
||||
}
|
||||
username?: string
|
||||
inventory?: {
|
||||
slots: any[]
|
||||
}
|
||||
heldItem?: any
|
||||
controlState?: {
|
||||
sneak: boolean
|
||||
}
|
||||
on(event: string, callback: (...args: any[]) => void): void
|
||||
}
|
||||
|
||||
const loadedData: {
|
||||
effects?: Record<number, { name: string }>
|
||||
blocksByName?: Record<string, any>
|
||||
items?: Record<number, { name: string }>
|
||||
blocksByStateId?: Record<number, { name: string }>
|
||||
}
|
||||
|
||||
const customEvents: {
|
||||
on(event: string, callback: (...args: any[]) => void): void
|
||||
}
|
||||
|
||||
const appViewer: {
|
||||
backend?: {
|
||||
updateCamera(position: any, yaw: number, pitch: number): void
|
||||
}
|
||||
resourcesManager: any
|
||||
}
|
||||
|
||||
const PrismarineBlock: any
|
||||
}
|
||||
|
||||
export {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue