render scoreboard score below player name

This commit is contained in:
Moritz Zwerger 2023-11-06 15:26:31 +01:00
parent 9e326271e6
commit 199b8a7587
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
15 changed files with 70 additions and 21 deletions

View File

@ -0,0 +1,46 @@
/*
* Minosoft
* Copyright (C) 2020-2023 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.entities.feature.text
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
import de.bixilon.minosoft.data.scoreboard.ScoreboardPositions
import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.gui.rendering.entities.renderer.living.player.PlayerRenderer
class EntityScoreboardFeature(renderer: PlayerRenderer<*>) : BillboardTextFeature(renderer, null) {
override fun update(millis: Long, delta: Float) {
updateScore()
super.update(millis, delta)
}
private fun updateScore() {
// TODO: self, offset name, render distance (10), performance
this.text = getScore()
}
private fun getScore(): ChatComponent? {
val objective = renderer.renderer.connection.scoreboard.positions[ScoreboardPositions.BELOW_NAME] ?: return null
val score = objective.scores[renderer.entity.unsafeCast<PlayerEntity>().additional.name] ?: return null
val text = BaseComponent()
text += TextComponent(score.value)
text += " "
text += objective.displayName
return text
}
}

View File

@ -22,6 +22,7 @@ import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer
import de.bixilon.minosoft.gui.rendering.entities.factory.RegisteredEntityModelFactory import de.bixilon.minosoft.gui.rendering.entities.factory.RegisteredEntityModelFactory
import de.bixilon.minosoft.gui.rendering.entities.feature.text.EntityScoreboardFeature
import de.bixilon.minosoft.gui.rendering.entities.model.human.PlayerModel import de.bixilon.minosoft.gui.rendering.entities.model.human.PlayerModel
import de.bixilon.minosoft.gui.rendering.entities.renderer.living.LivingEntityRenderer import de.bixilon.minosoft.gui.rendering.entities.renderer.living.LivingEntityRenderer
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader
@ -38,6 +39,8 @@ open class PlayerRenderer<E : PlayerEntity>(renderer: EntitiesRenderer, entity:
var skin: DynamicTexture? = null var skin: DynamicTexture? = null
private var refresh = true private var refresh = true
val scoreboard = EntityScoreboardFeature(this).register()
init { init {
entity.additional::properties.observe(this) { refresh = true } entity.additional::properties.observe(this) { refresh = true }
} }

View File

@ -85,7 +85,7 @@ class PlayConnection(
val registries = Registries().apply { updateFlattened(version.flattened) } val registries = Registries().apply { updateFlattened(version.flattened) }
val world = World(this) val world = World(this)
val tabList = TabList() val tabList = TabList()
val scoreboardManager = ScoreboardManager(this) val scoreboard = ScoreboardManager(this)
val bossbarManager = BossbarManager() val bossbarManager = BossbarManager()
val util = ConnectionUtil(this) val util = ConnectionUtil(this)
val ticker = ConnectionTicker(this) val ticker = ConnectionTicker(this)

View File

@ -26,7 +26,7 @@ class ObjectivePositionS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
private val name: String? = buffer.readNullString() private val name: String? = buffer.readNullString()
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val scoreboardManager = connection.scoreboardManager val scoreboardManager = connection.scoreboard
if (name == null) { if (name == null) {
scoreboardManager.positions -= position scoreboardManager.positions -= position
connection.events.fire(ObjectivePositionSetEvent(connection, position, null)) connection.events.fire(ObjectivePositionSetEvent(connection, position, null))

View File

@ -60,7 +60,7 @@ class CreateObjectiveS2CP(
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val objective = ScoreboardObjective(name, displayName, unit) val objective = ScoreboardObjective(name, displayName, unit)
connection.scoreboardManager.objectives[name] = objective connection.scoreboard.objectives[name] = objective
connection.events.fire(ScoreboardObjectiveCreateEvent(connection, objective)) connection.events.fire(ScoreboardObjectiveCreateEvent(connection, objective))
} }

View File

@ -31,13 +31,13 @@ class RemoveObjectiveS2CP(
} }
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
connection.scoreboardManager.objectives.remove(objective) connection.scoreboard.objectives.remove(objective)
for ((position, objective) in connection.scoreboardManager.positions.toSynchronizedMap()) { for ((position, objective) in connection.scoreboard.positions.toSynchronizedMap()) {
if (objective.name != this.objective) { if (objective.name != this.objective) {
continue continue
} }
connection.scoreboardManager.positions -= position connection.scoreboard.positions -= position
connection.events.fire(ObjectivePositionSetEvent(connection, position, null)) connection.events.fire(ObjectivePositionSetEvent(connection, position, null))
} }
} }

View File

@ -58,7 +58,7 @@ class UpdateObjectiveS2CP(
} }
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val objective = connection.scoreboardManager.objectives[objective] ?: return val objective = connection.scoreboard.objectives[objective] ?: return
objective.displayName = displayName objective.displayName = displayName
objective.unit = unit objective.unit = unit

View File

@ -35,8 +35,8 @@ class PutScoreboardScoreS2CP(
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
check(objective != null) { "Can not update null objective!" } check(objective != null) { "Can not update null objective!" }
val objective = connection.scoreboardManager.objectives[objective] ?: return val objective = connection.scoreboard.objectives[objective] ?: return
val score = ScoreboardScore(entity, objective, connection.scoreboardManager.getTeam(entity), value) val score = ScoreboardScore(entity, objective, connection.scoreboard.getTeam(entity), value)
objective.scores[entity] = score objective.scores[entity] = score
connection.events.fire(ScoreboardScorePutEvent(connection, score)) connection.events.fire(ScoreboardScorePutEvent(connection, score))

View File

@ -28,8 +28,8 @@ class RemoveScoreboardScoreS2CP(
) : ScoreboardScoreS2CP { ) : ScoreboardScoreS2CP {
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val objective = connection.scoreboardManager.objectives[objective] ?: let { val objective = connection.scoreboard.objectives[objective] ?: let {
for ((_, objective) in connection.scoreboardManager.objectives.toSynchronizedMap()) { for ((_, objective) in connection.scoreboard.objectives.toSynchronizedMap()) {
val score = objective.scores.remove(entity) ?: continue val score = objective.scores.remove(entity) ?: continue
connection.events.fire(ScoreboardScoreRemoveEvent(connection, score)) connection.events.fire(ScoreboardScoreRemoveEvent(connection, score))

View File

@ -35,14 +35,14 @@ class AddTeamMemberS2CP(
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val team = connection.scoreboardManager.teams[name] ?: return val team = connection.scoreboard.teams[name] ?: return
team.members += members team.members += members
for (member in members) { for (member in members) {
connection.tabList.name[member]?.team = team connection.tabList.name[member]?.team = team
} }
connection.scoreboardManager.updateScoreTeams(team, members) connection.scoreboard.updateScoreTeams(team, members)
connection.events.fire(TeamMemberAddEvent(connection, team, members)) connection.events.fire(TeamMemberAddEvent(connection, team, members))
} }

View File

@ -118,13 +118,13 @@ class CreateTeamS2CP(
color = color, color = color,
members = members.toSynchronizedSet(), members = members.toSynchronizedSet(),
) )
connection.scoreboardManager.teams[name] = team connection.scoreboard.teams[name] = team
for (member in members) { for (member in members) {
connection.tabList.name[member]?.team = team connection.tabList.name[member]?.team = team
} }
connection.scoreboardManager.updateScoreTeams(team, members) connection.scoreboard.updateScoreTeams(team, members)
connection.events.fire(TeamCreateEvent(connection, team)) connection.events.fire(TeamCreateEvent(connection, team))
} }

View File

@ -35,7 +35,7 @@ class RemoveTeamMemberS2CP(
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val team = connection.scoreboardManager.teams[name] ?: return val team = connection.scoreboard.teams[name] ?: return
team.members -= members team.members -= members
for (member in members) { for (member in members) {
@ -46,7 +46,7 @@ class RemoveTeamMemberS2CP(
item.team = team item.team = team
} }
connection.scoreboardManager.updateScoreTeams(team, members, true) connection.scoreboard.updateScoreTeams(team, members, true)
connection.events.fire(TeamMemberRemoveEvent(connection, team, members)) connection.events.fire(TeamMemberRemoveEvent(connection, team, members))
} }

View File

@ -22,9 +22,9 @@ import de.bixilon.minosoft.util.logging.LogMessageType
class RemoveTeamS2CP(val name: String) : TeamsS2CP { class RemoveTeamS2CP(val name: String) : TeamsS2CP {
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val team = connection.scoreboardManager.teams.remove(name) ?: return val team = connection.scoreboard.teams.remove(name) ?: return
connection.scoreboardManager.updateScoreTeams(team, team.members, true) connection.scoreboard.updateScoreTeams(team, team.members, true)
connection.events.fire(ScoreboardTeamRemoveEvent(connection, team)) connection.events.fire(ScoreboardTeamRemoveEvent(connection, team))
} }

View File

@ -94,7 +94,7 @@ class UpdateTeamS2CP(
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
val team = connection.scoreboardManager.teams[name] ?: return val team = connection.scoreboard.teams[name] ?: return
team.displayName = displayName team.displayName = displayName
team.prefix = prefix team.prefix = prefix

View File

@ -77,7 +77,7 @@ class TabListS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
connection.tabList.uuid[uuid] = item connection.tabList.uuid[uuid] = item
connection.tabList.name[name] = item connection.tabList.name[name] = item
for (team in connection.scoreboardManager.teams.toSynchronizedMap().values) { for (team in connection.scoreboard.teams.toSynchronizedMap().values) {
if (team.members.contains(data.name)) { if (team.members.contains(data.name)) {
item.team = team item.team = team
break break