Skip to content

Commit 4277c3a

Browse files
authored
feat: Support nameTagVisibility option of teams (#373)
1 parent 9f3d3f9 commit 4277c3a

File tree

5 files changed

+93
-3
lines changed

5 files changed

+93
-3
lines changed

renderer/viewer/lib/basePlayerState.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ItemSelector } from 'mc-assets/dist/itemDefinitions'
2-
import { GameMode } from 'mineflayer'
2+
import { GameMode, Team } from 'mineflayer'
33
import { proxy } from 'valtio'
44
import type { HandItemBlock } from '../three/holdingBlock'
55

@@ -50,6 +50,8 @@ export const getInitialPlayerState = () => proxy({
5050
perspective: 'first_person' as CameraPerspective,
5151

5252
cameraSpectatingEntity: undefined as number | undefined,
53+
54+
team: undefined as Team | undefined,
5355
})
5456

5557
export const getPlayerStateUtils = (reactive: PlayerStateReactive) => ({

renderer/viewer/lib/worldDataEmitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter<Wo
104104
...e,
105105
pos: e.position,
106106
username: e.username,
107+
team: bot.teamMap[e.username] || bot.teamMap[e.uuid],
107108
// set debugTree (obj) {
108109
// e.debugTree = obj
109110
// }

renderer/viewer/three/entities.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Item } from 'prismarine-item'
1616
import { BlockModel } from 'mc-assets'
1717
import { isEntityAttackable } from 'mineflayer-mouse/dist/attackableEntity'
1818
import { Vec3 } from 'vec3'
19+
import { Team } from 'mineflayer'
1920
import { EntityMetadataVersions } from '../../../src/mcDataTypes'
2021
import { ItemSpecificContextProperties } from '../lib/basePlayerState'
2122
import { loadSkinImage, loadSkinFromUsername, stevePngUrl, steveTexture, createCanvas } from '../lib/utils/skins'
@@ -209,7 +210,7 @@ export type SceneEntity = THREE.Object3D & {
209210
username?: string
210211
uuid?: string
211212
additionalCleanup?: () => void
212-
originalEntity: import('prismarine-entity').Entity & { delete?; pos?, name }
213+
originalEntity: import('prismarine-entity').Entity & { delete?; pos?, name, team?: Team }
213214
}
214215

215216
export class Entities {
@@ -900,6 +901,8 @@ export class Entities {
900901
nameTag.position.y = playerObject.position.y + playerObject.scale.y * 16 + 3
901902
nameTag.renderOrder = 1000
902903

904+
nameTag.name = 'nametag'
905+
903906
//@ts-expect-error
904907
wrapper.add(nameTag)
905908
}
@@ -1111,10 +1114,12 @@ export class Entities {
11111114
}
11121115
}
11131116

1114-
if (entity.username) {
1117+
if (entity.username !== undefined) {
11151118
e.username = entity.username
11161119
}
11171120

1121+
this.updateNameTagVisibility(e)
1122+
11181123
this.updateEntityPosition(entity, justAdded, overrides)
11191124
}
11201125

@@ -1183,6 +1188,20 @@ export class Entities {
11831188
}
11841189
}
11851190

1191+
updateNameTagVisibility (entity: SceneEntity) {
1192+
const playerTeam = this.worldRenderer.playerStateReactive.team
1193+
const entityTeam = entity.originalEntity.team
1194+
const nameTagVisibility = entityTeam?.nameTagVisibility || 'always'
1195+
const showNameTag = nameTagVisibility === 'always' ||
1196+
(nameTagVisibility === 'hideForOwnTeam' && entityTeam?.team !== playerTeam?.team) ||
1197+
(nameTagVisibility === 'hideForOtherTeams' && (entityTeam?.team === playerTeam?.team || playerTeam === undefined))
1198+
entity.traverse(c => {
1199+
if (c.name === 'nametag') {
1200+
c.visible = showNameTag
1201+
}
1202+
})
1203+
}
1204+
11861205
addMapModel (entityMesh: THREE.Object3D, mapNumber: number, rotation: number) {
11871206
const imageData = this.cachedMapsImages?.[mapNumber]
11881207
let texture: THREE.Texture | null = null

src/entities.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import tracker from '@nxg-org/mineflayer-tracker'
44
import { loader as autoJumpPlugin } from '@nxg-org/mineflayer-auto-jump'
55
import { subscribeKey } from 'valtio/utils'
66
import { getThreeJsRendererMethods } from 'renderer/viewer/three/threeJsMethods'
7+
import { Team } from 'mineflayer'
78
import { options, watchValue } from './optionsStorage'
89
import { gameAdditionalState, miscUiState } from './globalState'
910
import { EntityStatus } from './mineflayer/entityStatus'
@@ -237,4 +238,67 @@ customEvents.on('gameLoaded', () => {
237238
}
238239

239240
})
241+
242+
bot.on('teamUpdated', (team: Team) => {
243+
for (const entity of Object.values(bot.entities)) {
244+
if (entity.type === 'player' && entity.username && team.members.includes(entity.username) || entity.uuid && team.members.includes(entity.uuid)) {
245+
bot.emit('entityUpdate', entity)
246+
}
247+
}
248+
})
249+
250+
const updateEntityNameTags = (team: Team) => {
251+
for (const entity of Object.values(bot.entities)) {
252+
const entityTeam = entity.type === 'player' && entity.username ? bot.teamMap[entity.username] : entity.uuid ? bot.teamMap[entity.uuid] : undefined
253+
if ((entityTeam?.nameTagVisibility === 'hideForOwnTeam' && entityTeam.name === team.name)
254+
|| (entityTeam?.nameTagVisibility === 'hideForOtherTeams' && entityTeam.name !== team.name)) {
255+
bot.emit('entityUpdate', entity)
256+
}
257+
}
258+
}
259+
260+
const doEntitiesNeedUpdating = (team: Team) => {
261+
return team.nameTagVisibility === 'never'
262+
|| (team.nameTagVisibility === 'hideForOtherTeams' && appViewer.playerState.reactive.team?.team !== team.team)
263+
|| (team.nameTagVisibility === 'hideForOwnTeam' && appViewer.playerState.reactive.team?.team === team.team)
264+
}
265+
266+
bot.on('teamMemberAdded', (team: Team, members: string[]) => {
267+
if (members.includes(bot.username) && appViewer.playerState.reactive.team?.team !== team.team) {
268+
appViewer.playerState.reactive.team = team
269+
// Player was added to a team, need to check if any entities need updating
270+
updateEntityNameTags(team)
271+
} else if (doEntitiesNeedUpdating(team)) {
272+
// Need to update all entities that were added
273+
for (const entity of Object.values(bot.entities)) {
274+
if (entity.type === 'player' && entity.username && members.includes(entity.username) || entity.uuid && members.includes(entity.uuid)) {
275+
bot.emit('entityUpdate', entity)
276+
}
277+
}
278+
}
279+
})
280+
281+
bot.on('teamMemberRemoved', (team: Team, members: string[]) => {
282+
if (members.includes(bot.username) && appViewer.playerState.reactive.team?.team === team.team) {
283+
appViewer.playerState.reactive.team = undefined
284+
// Player was removed from a team, need to check if any entities need updating
285+
updateEntityNameTags(team)
286+
} else if (doEntitiesNeedUpdating(team)) {
287+
// Need to update all entities that were removed
288+
for (const entity of Object.values(bot.entities)) {
289+
if (entity.type === 'player' && entity.username && members.includes(entity.username) || entity.uuid && members.includes(entity.uuid)) {
290+
bot.emit('entityUpdate', entity)
291+
}
292+
}
293+
}
294+
})
295+
296+
bot.on('teamRemoved', (team: Team) => {
297+
if (appViewer.playerState.reactive.team?.team === team.team) {
298+
appViewer.playerState.reactive.team = undefined
299+
// Player's team was removed, need to update all entities that are in a team
300+
updateEntityNameTags(team)
301+
}
302+
})
303+
240304
})

src/mineflayer/playerState.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ export class PlayerStateControllerMain {
9999
})
100100
this.reactive.gameMode = bot.game?.gameMode
101101

102+
customEvents.on('gameLoaded', () => {
103+
this.reactive.team = bot.teamMap[bot.username]
104+
})
105+
102106
this.watchReactive()
103107
}
104108

0 commit comments

Comments
 (0)