Skip to content

Commit

Permalink
release very soon (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
zardoy authored Sep 5, 2024
2 parents 396c65b + d6964b8 commit e222e7f
Show file tree
Hide file tree
Showing 19 changed files with 363 additions and 102 deletions.
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<meta name="darkreader-lock">
<script>
window.startLoad = Date.now()
</script>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"esbuild-plugin-polyfill-node": "^0.3.0",
"express": "^4.18.2",
"filesize": "^10.0.12",
"flying-squid": "npm:@zardoy/flying-squid@^0.0.36",
"flying-squid": "npm:@zardoy/flying-squid@^0.0.38",
"fs-extra": "^11.1.1",
"google-drive-browserfs": "github:zardoy/browserfs#google-drive",
"jszip": "^3.10.1",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

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

Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ import { disposeObject } from './threeJsUtils'

export const TWEEN_DURATION = 120

/**
* @param {string} username
*/
function getUsernameTexture(username, { fontFamily = 'sans-serif' }) {
type PlayerObjectType = PlayerObject & { animation?: PlayerAnimation }

function getUsernameTexture (username: string, { fontFamily = 'sans-serif' }: any) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if (!ctx) throw new Error('Could not get 2d context')
Expand Down Expand Up @@ -64,7 +63,7 @@ const addNametag = (entity, options, mesh) => {
// todo cleanup
const nametags = {}

function getEntityMesh(entity, scene, options, overrides) {
function getEntityMesh (entity, scene, options, overrides) {
if (entity.name) {
try {
// https://github.com/PrismarineJS/prismarine-viewer/pull/410
Expand Down Expand Up @@ -94,34 +93,52 @@ function getEntityMesh(entity, scene, options, overrides) {
return cube
}

export type SceneEntity = THREE.Object3D & {
playerObject?: PlayerObject & {
animation?: PlayerAnimation
}
username?: string
additionalCleanup?: () => void
}

export class Entities extends EventEmitter {
constructor(scene) {
entities = {} as Record<string, SceneEntity>
entitiesOptions: {
fontFamily?: string
} = {}
debugMode: string
onSkinUpdate: () => void
clock = new THREE.Clock()
rendering = true
itemsTexture: THREE.Texture | null = null
getItemUv: undefined | ((idOrName: number | string) => {
texture: THREE.Texture;
u: number;
v: number;
su?: number;
sv?: number;
size?: number;
})

constructor (public scene: THREE.Scene) {
super()
/** @type {THREE.Scene} */
this.scene = scene
this.entities = {}
this.entitiesOptions = {}
this.debugMode = 'none'
this.onSkinUpdate = () => { }
this.clock = new THREE.Clock()
this.rendering = true
/** @type {THREE.Texture | null} */
this.itemsTexture = null
this.getItemUv = undefined
}

clear() {
clear () {
for (const mesh of Object.values(this.entities)) {
this.scene.remove(mesh)
disposeObject(mesh)
}
this.entities = {}
}

setDebugMode(mode, /** @type {THREE.Object3D?} */entity = null) {
setDebugMode (mode: string, entity: THREE.Object3D | null = null) {
this.debugMode = mode
for (const mesh of entity ? [entity] : Object.values(this.entities)) {
const boxHelper = mesh.children.find(c => c.name === 'debug')
const boxHelper = mesh.children.find(c => c.name === 'debug')!
boxHelper.visible = false
if (this.debugMode === 'basic') {
boxHelper.visible = true
Expand All @@ -130,7 +147,7 @@ export class Entities extends EventEmitter {
}
}

setRendering(rendering, /** @type {THREE.Object3D?} */entity = null) {
setRendering (rendering: boolean, entity: THREE.Object3D | null = null) {
this.rendering = rendering
for (const ent of entity ? [entity] : Object.values(this.entities)) {
if (rendering) {
Expand All @@ -141,7 +158,7 @@ export class Entities extends EventEmitter {
}
}

render() {
render () {
const dt = this.clock.getDelta()
for (const entityId of Object.keys(this.entities)) {
const playerObject = this.getPlayerObject(entityId)
Expand All @@ -151,17 +168,16 @@ export class Entities extends EventEmitter {
}
}

getPlayerObject(entityId) {
/** @type {(PlayerObject & { animation?: PlayerAnimation }) | undefined} */
const playerObject = this.entities[entityId]?.playerObject
getPlayerObject (entityId: string | number) {
const playerObject = this.entities[entityId]?.playerObject as PlayerObjectType | undefined
return playerObject
}

// fixme workaround
defaultSteveTexture

// true means use default skin url
updatePlayerSkin(entityId, username, /** @type {string | true} */skinUrl, /** @type {string | true | undefined} */capeUrl = undefined) {
updatePlayerSkin (entityId: string | number, username: string | undefined, skinUrl: string | true, capeUrl: string | true | undefined = undefined) {
let playerObject = this.getPlayerObject(entityId)
if (!playerObject) return
// const username = this.entities[entityId].username
Expand All @@ -188,7 +204,6 @@ export class Entities extends EventEmitter {
skinTexture.magFilter = THREE.NearestFilter
skinTexture.minFilter = THREE.NearestFilter
skinTexture.needsUpdate = true
//@ts-expect-error
playerObject.skin.map = skinTexture
playerObject.skin.modelType = inferModelType(skinTexture.image)

Expand Down Expand Up @@ -244,14 +259,14 @@ export class Entities extends EventEmitter {
playerObject.cape.map = null
}

function isCanvasBlank(canvas) {
function isCanvasBlank (canvas) {
return !canvas.getContext('2d')
.getImageData(0, 0, canvas.width, canvas.height).data
.some(channel => channel !== 0)
}
}

playAnimation(entityPlayerId, /** @type {'walking' | 'running' | 'oneSwing' | 'idle'} */animation) {
playAnimation (entityPlayerId, animation: 'walking' | 'running' | 'oneSwing' | 'idle') {
const playerObject = this.getPlayerObject(entityPlayerId)
if (!playerObject) return

Expand All @@ -271,7 +286,7 @@ export class Entities extends EventEmitter {

}

parseEntityLabel(jsonLike) {
parseEntityLabel (jsonLike) {
if (!jsonLike) return
try {
const parsed = typeof jsonLike === 'string' ? mojangson.simplify(mojangson.parse(jsonLike)) : nbt.simplify(jsonLike)
Expand All @@ -282,22 +297,24 @@ export class Entities extends EventEmitter {
}
}

getItemMesh(item) {
getItemMesh (item) {
const textureUv = this.getItemUv?.(item.itemId ?? item.blockId)
if (textureUv) {
// todo use geometry buffer uv instead!
const { u, v, size, su, sv, texture } = textureUv
const itemsTexture = texture.clone()
itemsTexture.flipY = true
itemsTexture.offset.set(u, 1 - v - (sv ?? size))
itemsTexture.repeat.set(su ?? size, sv ?? size)
const sizeY = (sv ?? size)!
const sizeX = (su ?? size)!
itemsTexture.offset.set(u, 1 - v - sizeY)
itemsTexture.repeat.set(sizeX, sizeY)
itemsTexture.needsUpdate = true
itemsTexture.magFilter = THREE.NearestFilter
itemsTexture.minFilter = THREE.NearestFilter
const itemsTextureFlipped = itemsTexture.clone()
itemsTextureFlipped.repeat.x *= -1
itemsTextureFlipped.needsUpdate = true
itemsTextureFlipped.offset.set(u + (su ?? size), 1 - v - (sv ?? size))
itemsTextureFlipped.offset.set(u + (sizeX), 1 - v - sizeY)
const material = new THREE.MeshStandardMaterial({
map: itemsTexture,
transparent: true,
Expand All @@ -322,7 +339,7 @@ export class Entities extends EventEmitter {
}
}

update(/** @type {import('prismarine-entity').Entity & {delete?, pos}} */entity, overrides) {
update (entity: import('prismarine-entity').Entity & { delete?; pos }, overrides) {
let isPlayerModel = entity.name === 'player'
if (entity.name === 'zombie' || entity.name === 'zombie_villager' || entity.name === 'husk') {
isPlayerModel = true
Expand All @@ -332,21 +349,20 @@ export class Entities extends EventEmitter {
const group = new THREE.Group()
let mesh
if (entity.name === 'item') {
/** @type {any} */
//@ts-expect-error
const item = entity.metadata?.find(m => typeof m === 'object' && m?.itemCount)
const item = entity.metadata?.find((m: any) => typeof m === 'object' && m?.itemCount)
if (item) {
const object = this.getItemMesh(item)
if (object) {
object.scale.set(0.5, 0.5, 0.5)
object.position.set(0, 0.2, 0)
mesh = object.mesh
mesh.scale.set(0.5, 0.5, 0.5)
mesh.position.set(0, 0.2, 0)
// set faces
// mesh.position.set(targetPos.x + 0.5 + 2, targetPos.y + 0.5, targetPos.z + 0.5)
// viewer.scene.add(mesh)
const clock = new THREE.Clock()
object.onBeforeRender = () => {
mesh.onBeforeRender = () => {
const delta = clock.getDelta()
object.rotation.y += delta
mesh.rotation.y += delta
}
//@ts-expect-error
group.additionalCleanup = () => {
Expand All @@ -359,8 +375,7 @@ export class Entities extends EventEmitter {
} else if (isPlayerModel) {
// CREATE NEW PLAYER ENTITY
const wrapper = new THREE.Group()
/** @type {PlayerObject & { animation?: PlayerAnimation }} */
const playerObject = new PlayerObject()
const playerObject = new PlayerObject() as PlayerObjectType
playerObject.position.set(0, 16, 0)

//@ts-expect-error
Expand Down Expand Up @@ -470,9 +485,7 @@ export class Entities extends EventEmitter {
}

if (e?.playerObject && overrides?.rotation?.head) {
/** @type {PlayerObject} */
// eslint-disable-next-line prefer-destructuring
const playerObject = e.playerObject
const playerObject = e.playerObject as PlayerObjectType
const headRotationDiff = overrides.rotation.head.y ? overrides.rotation.head.y - entity.yaw : 0
playerObject.skin.head.rotation.y = -headRotationDiff
playerObject.skin.head.rotation.x = overrides.rotation.head.x ? - overrides.rotation.head.x : 0
Expand All @@ -497,7 +510,7 @@ export class Entities extends EventEmitter {
}
}

handleDamageEvent(entityId, damageAmount) {
handleDamageEvent (entityId, damageAmount) {
const entityMesh = this.entities[entityId]?.children.find(c => c.name === 'mesh')
if (entityMesh) {
entityMesh.traverse((child) => {
Expand Down
10 changes: 7 additions & 3 deletions prismarine-viewer/viewer/lib/mesher/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO:

const aos: number[] = []
const neighborPos = position.plus(new Vec3(...dir))
// 10%
const baseLight = world.getLight(neighborPos, undefined, undefined, block.name) / 15
for (const pos of corners) {
let vertex = [
Expand All @@ -290,7 +291,7 @@ function renderElement (world: World, cursor: Vec3, element: BlockElement, doAO:
(pos[2] ? maxz : minz)
]

if (!needTiles) {
if (!needTiles) { // 10%
vertex = vecadd3(matmul3(localMatrix, vertex), localShift)
vertex = vecadd3(matmul3(globalMatrix, vertex), globalShift)
vertex = vertex.map(v => v / 16)
Expand Down Expand Up @@ -411,7 +412,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
// todo this can be removed here
signs: {},
// isFull: true,
highestBlocks: {},
highestBlocks: {}, // todo migrate to map for 2% boost perf
hadErrors: false
}

Expand Down Expand Up @@ -449,7 +450,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
}
const biome = block.biome.name

if (world.preflat) {
if (world.preflat) { // 10% perf
const patchProperties = preflatBlockCalculation(block, world, cursor)
if (patchProperties) {
block._originalProperties ??= block._properties
Expand Down Expand Up @@ -505,6 +506,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
const model = modelVars[useVariant] ?? modelVars[0]
if (!model) continue

// #region 10%
let globalMatrix = null as any
let globalShift = null as any
for (const axis of ['x', 'y', 'z'] as const) {
Expand All @@ -518,6 +520,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
globalShift = [8, 8, 8]
globalShift = vecsub3(globalShift, matmul3(globalMatrix, globalShift))
}
// #endregion

for (const element of model.elements ?? []) {
const ao = model.ao ?? true
Expand All @@ -527,6 +530,7 @@ export function getSectionGeometry (sx, sy, sz, world: World) {
renderElement(world, pos, element, ao, attr, globalMatrix, globalShift, block, biome)
})
} else {
// 60%
renderElement(world, cursor, element, ao, attr, globalMatrix, globalShift, block, biome)
}
}
Expand Down
4 changes: 0 additions & 4 deletions prismarine-viewer/viewer/lib/worldrendererThree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ export class WorldRendererThree extends WorldRendererCommon {
super(config)
this.starField = new StarField(scene)
this.holdingBlock = new HoldingBlock(this.scene)
this.onHandItemSwitch({
name: 'furnace',
properties: {}
})

this.renderUpdateEmitter.on('textureDownloaded', () => {
if (this.holdingBlock.toBeRenderedItem) {
Expand Down
4 changes: 2 additions & 2 deletions src/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ customEvents.on('gameLoaded', () => {
window.debugEntityMetadata ??= {}
window.debugEntityMetadata[e.username] = e
// todo entity spawn timing issue, check perf
if (viewer.entities.entities[e.id]?.playerObject) {
const playerObject = viewer.entities.entities[e.id]?.playerObject
if (playerObject) {
// todo throttle!
bot.tracker.trackEntity(e)
const { playerObject } = viewer.entities.entities[e.id]
playerObject.backEquipment = e.equipment.some((item) => item?.name === 'elytra') ? 'elytra' : 'cape'
if (playerObject.cape.map === null) {
playerObject.cape.visible = false
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ viewer.entities.getItemUv = (idOrName: number | string) => {
u: 0,
v: 0,
size: 16 / viewer.world.material.map!.image.width,
texture: viewer.world.material.map
texture: viewer.world.material.map!
}
}
}
Expand Down
Loading

0 comments on commit e222e7f

Please sign in to comment.