feat: Support nameTagVisibility option of teams (#373)

This commit is contained in:
Max Lee 2025-07-03 15:15:24 +00:00 committed by GitHub
commit 4277c3a262
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 93 additions and 3 deletions

View file

@ -1,5 +1,5 @@
import { ItemSelector } from 'mc-assets/dist/itemDefinitions'
import { GameMode } from 'mineflayer'
import { GameMode, Team } from 'mineflayer'
import { proxy } from 'valtio'
import type { HandItemBlock } from '../three/holdingBlock'
@ -50,6 +50,8 @@ export const getInitialPlayerState = () => proxy({
perspective: 'first_person' as CameraPerspective,
cameraSpectatingEntity: undefined as number | undefined,
team: undefined as Team | undefined,
})
export const getPlayerStateUtils = (reactive: PlayerStateReactive) => ({

View file

@ -104,6 +104,7 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter<Wo
...e,
pos: e.position,
username: e.username,
team: bot.teamMap[e.username] || bot.teamMap[e.uuid],
// set debugTree (obj) {
// e.debugTree = obj
// }

View file

@ -16,6 +16,7 @@ import { Item } from 'prismarine-item'
import { BlockModel } from 'mc-assets'
import { isEntityAttackable } from 'mineflayer-mouse/dist/attackableEntity'
import { Vec3 } from 'vec3'
import { Team } from 'mineflayer'
import { EntityMetadataVersions } from '../../../src/mcDataTypes'
import { ItemSpecificContextProperties } from '../lib/basePlayerState'
import { loadSkinImage, loadSkinFromUsername, stevePngUrl, steveTexture, createCanvas } from '../lib/utils/skins'
@ -209,7 +210,7 @@ export type SceneEntity = THREE.Object3D & {
username?: string
uuid?: string
additionalCleanup?: () => void
originalEntity: import('prismarine-entity').Entity & { delete?; pos?, name }
originalEntity: import('prismarine-entity').Entity & { delete?; pos?, name, team?: Team }
}
export class Entities {
@ -900,6 +901,8 @@ export class Entities {
nameTag.position.y = playerObject.position.y + playerObject.scale.y * 16 + 3
nameTag.renderOrder = 1000
nameTag.name = 'nametag'
//@ts-expect-error
wrapper.add(nameTag)
}
@ -1111,10 +1114,12 @@ export class Entities {
}
}
if (entity.username) {
if (entity.username !== undefined) {
e.username = entity.username
}
this.updateNameTagVisibility(e)
this.updateEntityPosition(entity, justAdded, overrides)
}
@ -1183,6 +1188,20 @@ export class Entities {
}
}
updateNameTagVisibility (entity: SceneEntity) {
const playerTeam = this.worldRenderer.playerStateReactive.team
const entityTeam = entity.originalEntity.team
const nameTagVisibility = entityTeam?.nameTagVisibility || 'always'
const showNameTag = nameTagVisibility === 'always' ||
(nameTagVisibility === 'hideForOwnTeam' && entityTeam?.team !== playerTeam?.team) ||
(nameTagVisibility === 'hideForOtherTeams' && (entityTeam?.team === playerTeam?.team || playerTeam === undefined))
entity.traverse(c => {
if (c.name === 'nametag') {
c.visible = showNameTag
}
})
}
addMapModel (entityMesh: THREE.Object3D, mapNumber: number, rotation: number) {
const imageData = this.cachedMapsImages?.[mapNumber]
let texture: THREE.Texture | null = null

View file

@ -4,6 +4,7 @@ import tracker from '@nxg-org/mineflayer-tracker'
import { loader as autoJumpPlugin } from '@nxg-org/mineflayer-auto-jump'
import { subscribeKey } from 'valtio/utils'
import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods'
import { Team } from 'mineflayer'
import { options, watchValue } from './optionsStorage'
import { gameAdditionalState, miscUiState } from './globalState'
import { EntityStatus } from './mineflayer/entityStatus'
@ -237,4 +238,67 @@ customEvents.on('gameLoaded', () => {
}
})
bot.on('teamUpdated', (team: Team) => {
for (const entity of Object.values(bot.entities)) {
if (entity.type === 'player' && entity.username && team.members.includes(entity.username) || entity.uuid && team.members.includes(entity.uuid)) {
bot.emit('entityUpdate', entity)
}
}
})
const updateEntityNameTags = (team: Team) => {
for (const entity of Object.values(bot.entities)) {
const entityTeam = entity.type === 'player' && entity.username ? bot.teamMap[entity.username] : entity.uuid ? bot.teamMap[entity.uuid] : undefined
if ((entityTeam?.nameTagVisibility === 'hideForOwnTeam' && entityTeam.name === team.name)
|| (entityTeam?.nameTagVisibility === 'hideForOtherTeams' && entityTeam.name !== team.name)) {
bot.emit('entityUpdate', entity)
}
}
}
const doEntitiesNeedUpdating = (team: Team) => {
return team.nameTagVisibility === 'never'
|| (team.nameTagVisibility === 'hideForOtherTeams' && appViewer.playerState.reactive.team?.team !== team.team)
|| (team.nameTagVisibility === 'hideForOwnTeam' && appViewer.playerState.reactive.team?.team === team.team)
}
bot.on('teamMemberAdded', (team: Team, members: string[]) => {
if (members.includes(bot.username) && appViewer.playerState.reactive.team?.team !== team.team) {
appViewer.playerState.reactive.team = team
// Player was added to a team, need to check if any entities need updating
updateEntityNameTags(team)
} else if (doEntitiesNeedUpdating(team)) {
// Need to update all entities that were added
for (const entity of Object.values(bot.entities)) {
if (entity.type === 'player' && entity.username && members.includes(entity.username) || entity.uuid && members.includes(entity.uuid)) {
bot.emit('entityUpdate', entity)
}
}
}
})
bot.on('teamMemberRemoved', (team: Team, members: string[]) => {
if (members.includes(bot.username) && appViewer.playerState.reactive.team?.team === team.team) {
appViewer.playerState.reactive.team = undefined
// Player was removed from a team, need to check if any entities need updating
updateEntityNameTags(team)
} else if (doEntitiesNeedUpdating(team)) {
// Need to update all entities that were removed
for (const entity of Object.values(bot.entities)) {
if (entity.type === 'player' && entity.username && members.includes(entity.username) || entity.uuid && members.includes(entity.uuid)) {
bot.emit('entityUpdate', entity)
}
}
}
})
bot.on('teamRemoved', (team: Team) => {
if (appViewer.playerState.reactive.team?.team === team.team) {
appViewer.playerState.reactive.team = undefined
// Player's team was removed, need to update all entities that are in a team
updateEntityNameTags(team)
}
})
})

View file

@ -99,6 +99,10 @@ export class PlayerStateControllerMain {
})
this.reactive.gameMode = bot.game?.gameMode
customEvents.on('gameLoaded', () => {
this.reactive.team = bot.teamMap[bot.username]
})
this.watchReactive()
}