mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 10:25:06 -04:00
hud: wip scoreboard, fixes
This commit is contained in:
parent
489cbfc412
commit
5f28cceb49
@ -12,9 +12,12 @@
|
||||
*/
|
||||
package de.bixilon.minosoft.data.scoreboard
|
||||
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreTeamChangeEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||
|
||||
class ScoreboardManager {
|
||||
class ScoreboardManager(private val connection: PlayConnection) {
|
||||
val teams: MutableMap<String, Team> = synchronizedMapOf()
|
||||
val objectives: MutableMap<String, ScoreboardObjective> = synchronizedMapOf()
|
||||
|
||||
@ -24,7 +27,7 @@ class ScoreboardManager {
|
||||
fun getTeamsOf(member: String): Set<Team> {
|
||||
val teams: MutableSet<Team> = mutableSetOf()
|
||||
|
||||
for ((name, team) in this.teams) {
|
||||
for ((_, team) in this.teams) {
|
||||
if (!team.members.contains(member)) {
|
||||
continue
|
||||
}
|
||||
@ -34,15 +37,19 @@ class ScoreboardManager {
|
||||
return teams
|
||||
}
|
||||
|
||||
fun updateScoreTeams(team: Team, members: Set<String>, remove: Boolean = false) {
|
||||
for ((_, objective) in objectives) {
|
||||
for ((_, score) in objective.scores) {
|
||||
fun updateScoreTeams(team: Team, members: Set<String>, remove: Boolean = false, fireEvent: Boolean = true) {
|
||||
for ((_, objective) in objectives.toSynchronizedMap()) {
|
||||
for ((_, score) in objective.scores.toSynchronizedMap()) {
|
||||
if (score.entity in members) {
|
||||
if (remove) {
|
||||
score.teams -= team
|
||||
} else {
|
||||
score.teams += team
|
||||
}
|
||||
if (!fireEvent) {
|
||||
continue
|
||||
}
|
||||
connection.fireEvent(ScoreTeamChangeEvent(connection, objective, score, team, remove))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,17 @@ package de.bixilon.minosoft.data.scoreboard
|
||||
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.objective.CreateScoreboardObjectiveS2CP
|
||||
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||
|
||||
class ScoreboardObjective(
|
||||
val name: String,
|
||||
var displayName: ChatComponent,
|
||||
var unit: CreateScoreboardObjectiveS2CP.ObjectiveUnits,
|
||||
) {
|
||||
val scores: MutableMap<String, ScoreboardScore> = mutableMapOf()
|
||||
val scores: MutableMap<String, ScoreboardScore> = synchronizedMapOf()
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,10 @@ import de.bixilon.minosoft.util.KUtil
|
||||
import de.bixilon.minosoft.util.enum.ValuesEnum
|
||||
|
||||
enum class ScoreboardPositions {
|
||||
LIST,
|
||||
TAB_LIST,
|
||||
SIDEBAR,
|
||||
BELOW_NAME,
|
||||
|
||||
TEAM_BLACK,
|
||||
TEAM_DARK_BLUE,
|
||||
TEAM_DARK_GREEN,
|
||||
|
@ -121,12 +121,13 @@ abstract class Element(val hudRenderer: HUDRenderer) {
|
||||
* @return The number of z layers used
|
||||
*/
|
||||
fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
||||
val offset = Vec2i(offset)
|
||||
if (RenderConstants.DISABLE_GUI_CACHE || !cacheEnabled) {
|
||||
return forceRender(offset, z, consumer, options)
|
||||
}
|
||||
if (!cacheUpToDate || cache.offset != offset || hudRenderer.matrixChange || cache.matrix !== hudRenderer.matrix || z != cache.z) {
|
||||
val cache = GUIMeshCache(hudRenderer.matrix)
|
||||
cache.offset = offset
|
||||
cache.offset = Vec2i(offset)
|
||||
cache.z = z
|
||||
val maxZ = forceRender(offset, z, cache, options)
|
||||
cache.maxZ = maxZ
|
||||
|
@ -89,7 +89,7 @@ open class RowLayout(
|
||||
if (exceedsY(childSize.y)) {
|
||||
break
|
||||
}
|
||||
val childZ = child.render(Vec2i(offset.x + margin.left + childAlignment.getOffset(size.x - margin.horizontal, childSize.x), offset.y + childYOffset), z, consumer, options)
|
||||
val childZ = child.render(offset + Vec2i(margin.left + childAlignment.getOffset(size.x - margin.horizontal, childSize.x), childYOffset), z, consumer, options)
|
||||
if (maxZ < childZ) {
|
||||
maxZ = childZ
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class TextFlowElement(
|
||||
yOffset += Font.TOTAL_CHAR_HEIGHT
|
||||
}
|
||||
|
||||
background.render(Vec2i(offset), z, consumer, options)
|
||||
background.render(offset, z, consumer, options)
|
||||
return LAYERS
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import de.bixilon.minosoft.gui.rendering.gui.hud.elements.other.BreakProgressHUD
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.other.CrosshairHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.other.DebugHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.other.WorldInfoHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.scoreboard.ScoreboardHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.tab.TabListHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.title.TitleHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
||||
@ -104,6 +105,7 @@ class HUDRenderer(
|
||||
registerElement(HotbarHUDElement)
|
||||
registerElement(WorldInfoHUDElement)
|
||||
registerElement(TitleHUDElement)
|
||||
registerElement(ScoreboardHUDElement)
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
|
@ -0,0 +1,69 @@
|
||||
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.scoreboard
|
||||
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.scoreboard.ScoreboardPositions
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.LayoutedHUDElement
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.*
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.team.TeamUpdateEvent
|
||||
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class ScoreboardHUDElement(hudRenderer: HUDRenderer) : LayoutedHUDElement<ScoreboardSideElement>(hudRenderer) {
|
||||
private val connection = hudRenderer.connection
|
||||
override val layout = ScoreboardSideElement(hudRenderer)
|
||||
|
||||
override val layoutOffset: Vec2i
|
||||
get() = Vec2i(hudRenderer.scaledSize.x - layout.size.x, (hudRenderer.scaledSize.y - layout.size.y) / 2)
|
||||
|
||||
override fun init() {
|
||||
connection.registerEvent(CallbackEventInvoker.of<ObjectivePositionSetEvent> {
|
||||
if (it.position != ScoreboardPositions.SIDEBAR) {
|
||||
return@of
|
||||
}
|
||||
|
||||
layout.objective = it.objective
|
||||
})
|
||||
connection.registerEvent(CallbackEventInvoker.of<ScoreboardObjectiveUpdateEvent> {
|
||||
if (it.objective != layout.objective) {
|
||||
return@of
|
||||
}
|
||||
layout.updateName()
|
||||
})
|
||||
connection.registerEvent(CallbackEventInvoker.of<ScoreboardScoreRemoveEvent> {
|
||||
if (it.score.objective != layout.objective) {
|
||||
return@of
|
||||
}
|
||||
layout.removeScore(it.score)
|
||||
})
|
||||
connection.registerEvent(CallbackEventInvoker.of<ScoreboardScorePutEvent> {
|
||||
if (it.score.objective != layout.objective) {
|
||||
return@of
|
||||
}
|
||||
layout.updateScore(it.score)
|
||||
})
|
||||
connection.registerEvent(CallbackEventInvoker.of<ScoreTeamChangeEvent> {
|
||||
val objective = layout.objective ?: return@of
|
||||
layout.updateScore(it.score)
|
||||
})
|
||||
connection.registerEvent(CallbackEventInvoker.of<TeamUpdateEvent> {
|
||||
val objective = layout.objective ?: return@of
|
||||
for ((_, score) in objective.scores) {
|
||||
if (it.team !in score.teams) {
|
||||
continue
|
||||
}
|
||||
layout.updateScore(score)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object : HUDBuilder<ScoreboardHUDElement> {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = "minosoft:scoreboard".toResourceLocation()
|
||||
|
||||
override fun build(hudRenderer: HUDRenderer): ScoreboardHUDElement {
|
||||
return ScoreboardHUDElement(hudRenderer)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.scoreboard
|
||||
|
||||
import de.bixilon.minosoft.data.scoreboard.ScoreboardScore
|
||||
import de.bixilon.minosoft.data.text.BaseComponent
|
||||
import de.bixilon.minosoft.data.text.ChatColors
|
||||
import de.bixilon.minosoft.data.text.TextComponent
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class ScoreboardScoreElement(
|
||||
hudRenderer: HUDRenderer,
|
||||
val score: ScoreboardScore,
|
||||
parent: Element?,
|
||||
) : Element(hudRenderer) {
|
||||
private val nameElement = TextElement(hudRenderer, "", background = false, parent = this)
|
||||
private val scoreElement = TextElement(hudRenderer, "", background = false, parent = this)
|
||||
|
||||
init {
|
||||
nameElement.prefMaxSize = Vec2i(-1, ScoreboardSideElement.SCORE_HEIGHT)
|
||||
scoreElement.prefMaxSize = Vec2i(-1, ScoreboardSideElement.SCORE_HEIGHT)
|
||||
forceSilentApply()
|
||||
_parent = parent
|
||||
}
|
||||
|
||||
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
||||
nameElement.render(offset, z, consumer, options)
|
||||
|
||||
scoreElement.render(offset + Vec2i(HorizontalAlignments.RIGHT.getOffset(size.x, scoreElement.size.x), 0), z, consumer, options)
|
||||
|
||||
return TextElement.LAYERS
|
||||
}
|
||||
|
||||
override fun silentApply(): Boolean {
|
||||
forceSilentApply()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun forceSilentApply() {
|
||||
val name = BaseComponent()
|
||||
|
||||
// ToDo: Can a score (entity; whatever) can have multiple teams?
|
||||
score.teams.iterator().apply {
|
||||
if (!hasNext()) {
|
||||
return@apply
|
||||
}
|
||||
val team = next()
|
||||
name += team.prefix
|
||||
name += team.suffix
|
||||
}
|
||||
name += score.entity
|
||||
|
||||
nameElement.text = name
|
||||
|
||||
scoreElement.text = TextComponent(score.value).color(ChatColors.RED)
|
||||
|
||||
_prefSize = Vec2i(nameElement.size.x + scoreElement.size.x + SCORE_MIN_MARGIN, ScoreboardSideElement.SCORE_HEIGHT)
|
||||
cacheUpToDate = false
|
||||
}
|
||||
|
||||
fun applySize() {
|
||||
_size = parent?.size?.let { return@let Vec2i(it.x, ScoreboardSideElement.SCORE_HEIGHT) } ?: _prefSize
|
||||
}
|
||||
|
||||
override fun onChildChange(child: Element) = Unit
|
||||
|
||||
|
||||
companion object {
|
||||
private const val SCORE_MIN_MARGIN = 5
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package de.bixilon.minosoft.gui.rendering.gui.hud.elements.scoreboard
|
||||
|
||||
import de.bixilon.minosoft.data.scoreboard.ScoreboardObjective
|
||||
import de.bixilon.minosoft.data.scoreboard.ScoreboardScore
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.Element
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.primitive.ColorElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.elements.text.TextElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.Vec2Util.EMPTY
|
||||
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||
import glm_.vec2.Vec2i
|
||||
|
||||
class ScoreboardSideElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
|
||||
private val backgroundElement = ColorElement(hudRenderer, size = Vec2i.EMPTY, color = RenderConstants.TEXT_BACKGROUND_COLOR)
|
||||
private val nameBackgroundElement = ColorElement(hudRenderer, size = Vec2i.EMPTY, color = RenderConstants.TEXT_BACKGROUND_COLOR)
|
||||
private val nameElement = TextElement(hudRenderer, "", background = false, parent = this)
|
||||
private val scores: MutableMap<ScoreboardScore, ScoreboardScoreElement> = synchronizedMapOf()
|
||||
|
||||
|
||||
var objective: ScoreboardObjective? = null
|
||||
set(value) {
|
||||
if (field == value) {
|
||||
return
|
||||
}
|
||||
field = value
|
||||
scores.clear()
|
||||
forceSilentApply()
|
||||
}
|
||||
|
||||
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
||||
recalculateSize()
|
||||
backgroundElement.render(offset, z, consumer, options)
|
||||
nameBackgroundElement.render(offset, z + 1, consumer, options)
|
||||
|
||||
nameElement.render(offset + Vec2i(HorizontalAlignments.CENTER.getOffset(size.x, nameElement.size.x), 0), z + 2, consumer, options)
|
||||
offset.y += Font.TOTAL_CHAR_HEIGHT
|
||||
|
||||
val scores = scores.toSynchronizedMap().toSortedMap { a, b -> b.value - a.value }
|
||||
for ((_, score) in scores) {
|
||||
score.render(offset, z + 2, consumer, options)
|
||||
offset.y += score.size.y
|
||||
}
|
||||
|
||||
return TextElement.LAYERS + 2 // 2 backgrounds
|
||||
}
|
||||
|
||||
override fun forceSilentApply() {
|
||||
val objective = objective
|
||||
if (objective == null) {
|
||||
_size = Vec2i.EMPTY
|
||||
return
|
||||
}
|
||||
|
||||
this.scores.clear()
|
||||
|
||||
updateName()
|
||||
|
||||
queueSizeRecalculation()
|
||||
}
|
||||
|
||||
private fun recalculateSize() {
|
||||
val size = Vec2i(MIN_WIDTH, Font.TOTAL_CHAR_HEIGHT)
|
||||
size.x = maxOf(size.x, nameElement.size.x)
|
||||
|
||||
val scores = scores.toSynchronizedMap()
|
||||
|
||||
|
||||
for ((_, element) in scores) {
|
||||
element.forceSilentApply()
|
||||
size.x = maxOf(size.x, element.prefSize.x)
|
||||
}
|
||||
|
||||
size.y += SCORE_HEIGHT * scores.size
|
||||
|
||||
|
||||
|
||||
_size = size
|
||||
nameBackgroundElement.size = Vec2i(size.x, SCORE_HEIGHT)
|
||||
backgroundElement.size = size
|
||||
|
||||
|
||||
for ((_, element) in scores) {
|
||||
element.applySize()
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun queueSizeRecalculation() {
|
||||
cacheUpToDate = false
|
||||
}
|
||||
|
||||
fun removeScore(score: ScoreboardScore) {
|
||||
scores.remove(score) ?: return
|
||||
queueSizeRecalculation()
|
||||
}
|
||||
|
||||
fun updateScore(score: ScoreboardScore) {
|
||||
scores.getOrPut(score) { ScoreboardScoreElement(hudRenderer, score, this) }
|
||||
queueSizeRecalculation()
|
||||
}
|
||||
|
||||
fun updateName() {
|
||||
nameElement.text = objective?.displayName ?: return
|
||||
queueSizeRecalculation()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MIN_WIDTH = 30
|
||||
const val SCORE_HEIGHT = Font.TOTAL_CHAR_HEIGHT
|
||||
}
|
||||
}
|
@ -51,7 +51,7 @@ class TabListElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
|
||||
)
|
||||
|
||||
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
||||
background.render(Vec2i(offset), z, consumer, options)
|
||||
background.render(offset, z, consumer, options)
|
||||
offset += BACKGROUND_PADDING
|
||||
|
||||
val size = size
|
||||
@ -71,7 +71,7 @@ class TabListElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
|
||||
}
|
||||
|
||||
for ((index, entry) in toRender.withIndex()) {
|
||||
entry.render(Vec2i(offset), z + 1, consumer, options)
|
||||
entry.render(offset, z + 1, consumer, options)
|
||||
offset.y += TabListEntryElement.HEIGHT + ENTRY_VERTICAL_SPACING
|
||||
if ((index + 1) % ENTRIES_PER_COLUMN == 0) {
|
||||
offset.x += entry.width + ENTRY_HORIZONTAL_SPACING
|
||||
|
@ -72,8 +72,8 @@ class TabListEntryElement(
|
||||
}
|
||||
|
||||
override fun forceRender(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
||||
background.render(Vec2i(offset), z, consumer, options)
|
||||
nameElement.render(Vec2i(offset), z, consumer, options)
|
||||
background.render(offset, z, consumer, options)
|
||||
nameElement.render(offset, z, consumer, options)
|
||||
pingElement.render(offset + Vec2i(HorizontalAlignments.RIGHT.getOffset(maxSize.x, pingElement.size.x + PADDING), PADDING), z + 1, consumer, options)
|
||||
|
||||
return TextElement.LAYERS
|
||||
|
@ -0,0 +1,15 @@
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard
|
||||
|
||||
import de.bixilon.minosoft.data.scoreboard.ScoreboardObjective
|
||||
import de.bixilon.minosoft.data.scoreboard.ScoreboardScore
|
||||
import de.bixilon.minosoft.data.scoreboard.Team
|
||||
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class ScoreTeamChangeEvent(
|
||||
connection: PlayConnection,
|
||||
val objective: ScoreboardObjective,
|
||||
val score: ScoreboardScore,
|
||||
val team: Team,
|
||||
val remove: Boolean,
|
||||
) : PlayConnectionEvent(connection)
|
@ -1,10 +1,10 @@
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard.team
|
||||
|
||||
import de.bixilon.minosoft.data.scoreboard.Team
|
||||
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class ScoreboardTeamCreateEvent(
|
||||
class TeamCreateEvent(
|
||||
connection: PlayConnection,
|
||||
val team: Team,
|
||||
) : PlayConnectionEvent(connection)
|
@ -1,9 +1,10 @@
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard.team
|
||||
|
||||
import de.bixilon.minosoft.data.scoreboard.Team
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardTeamMemberEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class ScoreboardTeamMemberAddEvent(
|
||||
class TeamMemberAddEvent(
|
||||
connection: PlayConnection,
|
||||
team: Team,
|
||||
members: Set<String>,
|
@ -1,9 +1,10 @@
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard.team
|
||||
|
||||
import de.bixilon.minosoft.data.scoreboard.Team
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardTeamMemberEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class ScoreboardTeamMemberRemoveEvent(
|
||||
class TeamMemberRemoveEvent(
|
||||
connection: PlayConnection,
|
||||
team: Team,
|
||||
members: Set<String>,
|
@ -0,0 +1,10 @@
|
||||
package de.bixilon.minosoft.modding.event.events.scoreboard.team
|
||||
|
||||
import de.bixilon.minosoft.data.scoreboard.Team
|
||||
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class TeamUpdateEvent(
|
||||
connection: PlayConnection,
|
||||
val team: Team,
|
||||
) : PlayConnectionEvent(connection)
|
@ -71,7 +71,7 @@ class PlayConnection(
|
||||
val recipes = Recipes()
|
||||
val world = World(this)
|
||||
val tabList = TabList()
|
||||
val scoreboardManager = ScoreboardManager()
|
||||
val scoreboardManager = ScoreboardManager(this)
|
||||
val bossbarManager = BossbarManager()
|
||||
|
||||
@Deprecated(message = "PacketSender is deprecated")
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.objective
|
||||
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.ObjectivePositionSetEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
@ -35,6 +36,7 @@ class RemoveScoreboardObjectiveS2CP(val objective: String, buffer: PlayInByteBuf
|
||||
continue
|
||||
}
|
||||
connection.scoreboardManager.positions -= position
|
||||
connection.fireEvent(ObjectivePositionSetEvent(connection, position, null))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardScoreRemove
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import de.bixilon.minosoft.util.logging.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
@ -24,7 +25,14 @@ import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
class RemoveScoreboardScoreS2CP(val entity: String, val objective: String?, buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
|
||||
override fun handle(connection: PlayConnection) {
|
||||
val objective = connection.scoreboardManager.objectives[objective] ?: return
|
||||
val objective = connection.scoreboardManager.objectives[objective] ?: let {
|
||||
for ((_, objective) in connection.scoreboardManager.objectives.toSynchronizedMap()) {
|
||||
val score = objective.scores.remove(entity) ?: continue
|
||||
|
||||
connection.fireEvent(ScoreboardScoreRemoveEvent(connection, score))
|
||||
}
|
||||
return
|
||||
}
|
||||
val score = objective.scores.remove(entity) ?: return
|
||||
|
||||
connection.fireEvent(ScoreboardScoreRemoveEvent(connection, score))
|
||||
|
@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.scoreboard.Team
|
||||
import de.bixilon.minosoft.data.scoreboard.TeamCollisionRules
|
||||
import de.bixilon.minosoft.data.text.ChatCode
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardTeamCreateEvent
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.team.TeamCreateEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
@ -123,7 +123,7 @@ class TeamCreateS2CP(val name: String, buffer: PlayInByteBuffer) : PlayS2CPacket
|
||||
|
||||
connection.scoreboardManager.updateScoreTeams(team, members)
|
||||
|
||||
connection.fireEvent(ScoreboardTeamCreateEvent(connection, team))
|
||||
connection.fireEvent(TeamCreateEvent(connection, team))
|
||||
}
|
||||
|
||||
override fun log() {
|
||||
|
@ -14,7 +14,7 @@
|
||||
package de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.teams
|
||||
|
||||
import de.bixilon.minosoft.Minosoft
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardTeamMemberAddEvent
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.team.TeamMemberAddEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
@ -41,7 +41,7 @@ class TeamMemberAddS2CP(val name: String, buffer: PlayInByteBuffer) : PlayS2CPac
|
||||
}
|
||||
|
||||
connection.scoreboardManager.updateScoreTeams(team, members)
|
||||
connection.fireEvent(ScoreboardTeamMemberAddEvent(connection, team, members))
|
||||
connection.fireEvent(TeamMemberAddEvent(connection, team, members))
|
||||
}
|
||||
|
||||
override fun log() {
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
package de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.teams
|
||||
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardTeamMemberRemoveEvent
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.team.TeamMemberRemoveEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
@ -44,7 +44,7 @@ class TeamMemberRemoveS2CP(val name: String, buffer: PlayInByteBuffer) : PlayS2C
|
||||
}
|
||||
|
||||
connection.scoreboardManager.updateScoreTeams(team, members, true)
|
||||
connection.fireEvent(ScoreboardTeamMemberRemoveEvent(connection, team, members))
|
||||
connection.fireEvent(TeamMemberRemoveEvent(connection, team, members))
|
||||
}
|
||||
|
||||
override fun log() {
|
||||
|
@ -18,6 +18,7 @@ import de.bixilon.minosoft.data.scoreboard.NameTagVisibilities
|
||||
import de.bixilon.minosoft.data.scoreboard.TeamCollisionRules
|
||||
import de.bixilon.minosoft.data.text.ChatCode
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.modding.event.events.scoreboard.team.TeamUpdateEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
@ -91,16 +92,18 @@ class TeamUpdateS2CP(val name: String, buffer: PlayInByteBuffer) : PlayS2CPacket
|
||||
|
||||
|
||||
override fun handle(connection: PlayConnection) {
|
||||
connection.scoreboardManager.teams[name]?.let {
|
||||
it.displayName = displayName
|
||||
it.prefix = prefix
|
||||
it.suffix = suffix
|
||||
it.friendlyFire = friendlyFire
|
||||
it.canSeeInvisibleTeam = canSeeInvisibleTeam
|
||||
it.collisionRule = collisionRule
|
||||
it.nameTagVisibility = nameTagVisibility
|
||||
it.formattingCode = formattingCode
|
||||
}
|
||||
val team = connection.scoreboardManager.teams[name] ?: return
|
||||
|
||||
team.displayName = displayName
|
||||
team.prefix = prefix
|
||||
team.suffix = suffix
|
||||
team.friendlyFire = friendlyFire
|
||||
team.canSeeInvisibleTeam = canSeeInvisibleTeam
|
||||
team.collisionRule = collisionRule
|
||||
team.nameTagVisibility = nameTagVisibility
|
||||
team.formattingCode = formattingCode
|
||||
|
||||
connection.fireEvent(TeamUpdateEvent(connection, team))
|
||||
}
|
||||
|
||||
override fun log() {
|
||||
|
@ -231,17 +231,17 @@ class PacketTypes {
|
||||
PLAY_CAMERA({ CameraS2CP(it) }),
|
||||
PLAY_HOTBAR_SLOT_SET({ HotbarSlotSetS2CP(it) }),
|
||||
PLAY_CHUNK_CENTER_SET({ ChunkCenterSetS2CP(it) }),
|
||||
PLAY_OBJECTIVE_POSITION_SET({ ObjectivePositionSetS2CP(it) }),
|
||||
PLAY_OBJECTIVE_POSITION_SET({ ObjectivePositionSetS2CP(it) }, isThreadSafe = false),
|
||||
PLAY_ENTITY_METADATA({ EntityMetadataS2CP(it) }, isThreadSafe = false),
|
||||
PLAY_ENTITY_ATTACH({ EntityAttachS2CP(it) }),
|
||||
PLAY_ENTITY_VELOCITY({ EntityVelocityS2CP(it) }),
|
||||
PLAY_ENTITY_EQUIPMENT({ EntityEquipmentS2CP(it) }),
|
||||
PLAY_EXPERIENCE_SET({ ExperienceSetS2CP(it) }),
|
||||
PLAY_HEALTH_SET({ HealthSetS2CP(it) }),
|
||||
PLAY_SCOREBOARD_OBJECTIVE({ ScoreboardObjectiveS2CF.createPacket(it) }),
|
||||
PLAY_SCOREBOARD_OBJECTIVE({ ScoreboardObjectiveS2CF.createPacket(it) }, isThreadSafe = false),
|
||||
PLAY_ENTITY_PASSENGER_SET({ EntityPassengerSetS2CP(it) }),
|
||||
PLAY_TEAMS({ TeamsS2CF.createPacket(it) }),
|
||||
PLAY_UPDATE_SCORE({ ScoreboardScoreS2CF.createPacket(it) }),
|
||||
PLAY_UPDATE_SCORE({ ScoreboardScoreS2CF.createPacket(it) }, isThreadSafe = false),
|
||||
PLAY_COMPASS_POSITION_SET({ CompassPositionSetS2CP(it) }),
|
||||
PLAY_WORLD_TIME_SET({ WorldTimeSetS2CP(it) }),
|
||||
PLAY_ENTITY_SOUND_EVENT({ EntitySoundEventS2CP(it) }),
|
||||
|
@ -95,16 +95,21 @@ object KUtil {
|
||||
return Collections.synchronizedList(mutableListOf(*values))
|
||||
}
|
||||
|
||||
private fun <K> Any.synchronizedCopy(copier: () -> K): K {
|
||||
private fun <K> Any.synchronizedCopy(lock: Object? = null, copier: () -> K): K {
|
||||
val ret: K
|
||||
synchronized(this) {
|
||||
synchronized(lock ?: this) {
|
||||
ret = copier()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
fun <K, V> Map<K, V>.toSynchronizedMap(): SynchronizedMap<K, V> {
|
||||
return synchronizedCopy { SynchronizedMap(this.toMutableMap()) }
|
||||
val lock = if (this is SynchronizedMap<*, *>) {
|
||||
this.lock
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return synchronizedCopy(lock) { SynchronizedMap(this.toMutableMap()) }
|
||||
}
|
||||
|
||||
fun <V> Collection<V>.toSynchronizedList(): MutableList<V> {
|
||||
|
@ -22,7 +22,7 @@ import java.util.function.Function
|
||||
class SynchronizedMap<K, V>(
|
||||
private val original: MutableMap<K, V>,
|
||||
) : MutableMap<K, V> {
|
||||
private val lock = Object()
|
||||
internal val lock = Object()
|
||||
override val size: Int
|
||||
get() = synchronized(lock) { original.size }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user