mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 18:34:56 -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
|
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.synchronizedMapOf
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||||
|
|
||||||
class ScoreboardManager {
|
class ScoreboardManager(private val connection: PlayConnection) {
|
||||||
val teams: MutableMap<String, Team> = synchronizedMapOf()
|
val teams: MutableMap<String, Team> = synchronizedMapOf()
|
||||||
val objectives: MutableMap<String, ScoreboardObjective> = synchronizedMapOf()
|
val objectives: MutableMap<String, ScoreboardObjective> = synchronizedMapOf()
|
||||||
|
|
||||||
@ -24,7 +27,7 @@ class ScoreboardManager {
|
|||||||
fun getTeamsOf(member: String): Set<Team> {
|
fun getTeamsOf(member: String): Set<Team> {
|
||||||
val teams: MutableSet<Team> = mutableSetOf()
|
val teams: MutableSet<Team> = mutableSetOf()
|
||||||
|
|
||||||
for ((name, team) in this.teams) {
|
for ((_, team) in this.teams) {
|
||||||
if (!team.members.contains(member)) {
|
if (!team.members.contains(member)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -34,15 +37,19 @@ class ScoreboardManager {
|
|||||||
return teams
|
return teams
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateScoreTeams(team: Team, members: Set<String>, remove: Boolean = false) {
|
fun updateScoreTeams(team: Team, members: Set<String>, remove: Boolean = false, fireEvent: Boolean = true) {
|
||||||
for ((_, objective) in objectives) {
|
for ((_, objective) in objectives.toSynchronizedMap()) {
|
||||||
for ((_, score) in objective.scores) {
|
for ((_, score) in objective.scores.toSynchronizedMap()) {
|
||||||
if (score.entity in members) {
|
if (score.entity in members) {
|
||||||
if (remove) {
|
if (remove) {
|
||||||
score.teams -= team
|
score.teams -= team
|
||||||
} else {
|
} else {
|
||||||
score.teams += team
|
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.data.text.ChatComponent
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.objective.CreateScoreboardObjectiveS2CP
|
import de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.objective.CreateScoreboardObjectiveS2CP
|
||||||
|
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
|
||||||
|
|
||||||
class ScoreboardObjective(
|
class ScoreboardObjective(
|
||||||
val name: String,
|
val name: String,
|
||||||
var displayName: ChatComponent,
|
var displayName: ChatComponent,
|
||||||
var unit: CreateScoreboardObjectiveS2CP.ObjectiveUnits,
|
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
|
import de.bixilon.minosoft.util.enum.ValuesEnum
|
||||||
|
|
||||||
enum class ScoreboardPositions {
|
enum class ScoreboardPositions {
|
||||||
LIST,
|
TAB_LIST,
|
||||||
SIDEBAR,
|
SIDEBAR,
|
||||||
BELOW_NAME,
|
BELOW_NAME,
|
||||||
|
|
||||||
TEAM_BLACK,
|
TEAM_BLACK,
|
||||||
TEAM_DARK_BLUE,
|
TEAM_DARK_BLUE,
|
||||||
TEAM_DARK_GREEN,
|
TEAM_DARK_GREEN,
|
||||||
|
@ -121,12 +121,13 @@ abstract class Element(val hudRenderer: HUDRenderer) {
|
|||||||
* @return The number of z layers used
|
* @return The number of z layers used
|
||||||
*/
|
*/
|
||||||
fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
fun render(offset: Vec2i, z: Int, consumer: GUIVertexConsumer, options: GUIVertexOptions?): Int {
|
||||||
|
val offset = Vec2i(offset)
|
||||||
if (RenderConstants.DISABLE_GUI_CACHE || !cacheEnabled) {
|
if (RenderConstants.DISABLE_GUI_CACHE || !cacheEnabled) {
|
||||||
return forceRender(offset, z, consumer, options)
|
return forceRender(offset, z, consumer, options)
|
||||||
}
|
}
|
||||||
if (!cacheUpToDate || cache.offset != offset || hudRenderer.matrixChange || cache.matrix !== hudRenderer.matrix || z != cache.z) {
|
if (!cacheUpToDate || cache.offset != offset || hudRenderer.matrixChange || cache.matrix !== hudRenderer.matrix || z != cache.z) {
|
||||||
val cache = GUIMeshCache(hudRenderer.matrix)
|
val cache = GUIMeshCache(hudRenderer.matrix)
|
||||||
cache.offset = offset
|
cache.offset = Vec2i(offset)
|
||||||
cache.z = z
|
cache.z = z
|
||||||
val maxZ = forceRender(offset, z, cache, options)
|
val maxZ = forceRender(offset, z, cache, options)
|
||||||
cache.maxZ = maxZ
|
cache.maxZ = maxZ
|
||||||
|
@ -89,7 +89,7 @@ open class RowLayout(
|
|||||||
if (exceedsY(childSize.y)) {
|
if (exceedsY(childSize.y)) {
|
||||||
break
|
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) {
|
if (maxZ < childZ) {
|
||||||
maxZ = childZ
|
maxZ = childZ
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ class TextFlowElement(
|
|||||||
yOffset += Font.TOTAL_CHAR_HEIGHT
|
yOffset += Font.TOTAL_CHAR_HEIGHT
|
||||||
}
|
}
|
||||||
|
|
||||||
background.render(Vec2i(offset), z, consumer, options)
|
background.render(offset, z, consumer, options)
|
||||||
return LAYERS
|
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.CrosshairHUDElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.other.DebugHUDElement
|
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.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.tab.TabListHUDElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.title.TitleHUDElement
|
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.title.TitleHUDElement
|
||||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
||||||
@ -104,6 +105,7 @@ class HUDRenderer(
|
|||||||
registerElement(HotbarHUDElement)
|
registerElement(HotbarHUDElement)
|
||||||
registerElement(WorldInfoHUDElement)
|
registerElement(WorldInfoHUDElement)
|
||||||
registerElement(TitleHUDElement)
|
registerElement(TitleHUDElement)
|
||||||
|
registerElement(ScoreboardHUDElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun init() {
|
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 {
|
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
|
offset += BACKGROUND_PADDING
|
||||||
|
|
||||||
val size = size
|
val size = size
|
||||||
@ -71,7 +71,7 @@ class TabListElement(hudRenderer: HUDRenderer) : Element(hudRenderer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ((index, entry) in toRender.withIndex()) {
|
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
|
offset.y += TabListEntryElement.HEIGHT + ENTRY_VERTICAL_SPACING
|
||||||
if ((index + 1) % ENTRIES_PER_COLUMN == 0) {
|
if ((index + 1) % ENTRIES_PER_COLUMN == 0) {
|
||||||
offset.x += entry.width + ENTRY_HORIZONTAL_SPACING
|
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 {
|
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)
|
||||||
nameElement.render(Vec2i(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)
|
pingElement.render(offset + Vec2i(HorizontalAlignments.RIGHT.getOffset(maxSize.x, pingElement.size.x + PADDING), PADDING), z + 1, consumer, options)
|
||||||
|
|
||||||
return TextElement.LAYERS
|
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.data.scoreboard.Team
|
||||||
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
|
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
|
|
||||||
class ScoreboardTeamCreateEvent(
|
class TeamCreateEvent(
|
||||||
connection: PlayConnection,
|
connection: PlayConnection,
|
||||||
val team: Team,
|
val team: Team,
|
||||||
) : PlayConnectionEvent(connection)
|
) : 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.data.scoreboard.Team
|
||||||
|
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardTeamMemberEvent
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
|
|
||||||
class ScoreboardTeamMemberAddEvent(
|
class TeamMemberAddEvent(
|
||||||
connection: PlayConnection,
|
connection: PlayConnection,
|
||||||
team: Team,
|
team: Team,
|
||||||
members: Set<String>,
|
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.data.scoreboard.Team
|
||||||
|
import de.bixilon.minosoft.modding.event.events.scoreboard.ScoreboardTeamMemberEvent
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
|
|
||||||
class ScoreboardTeamMemberRemoveEvent(
|
class TeamMemberRemoveEvent(
|
||||||
connection: PlayConnection,
|
connection: PlayConnection,
|
||||||
team: Team,
|
team: Team,
|
||||||
members: Set<String>,
|
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 recipes = Recipes()
|
||||||
val world = World(this)
|
val world = World(this)
|
||||||
val tabList = TabList()
|
val tabList = TabList()
|
||||||
val scoreboardManager = ScoreboardManager()
|
val scoreboardManager = ScoreboardManager(this)
|
||||||
val bossbarManager = BossbarManager()
|
val bossbarManager = BossbarManager()
|
||||||
|
|
||||||
@Deprecated(message = "PacketSender is deprecated")
|
@Deprecated(message = "PacketSender is deprecated")
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.objective
|
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.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
@ -35,6 +36,7 @@ class RemoveScoreboardObjectiveS2CP(val objective: String, buffer: PlayInByteBuf
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
connection.scoreboardManager.positions -= position
|
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.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
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.Log
|
||||||
import de.bixilon.minosoft.util.logging.LogLevels
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
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() {
|
class RemoveScoreboardScoreS2CP(val entity: String, val objective: String?, buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||||
|
|
||||||
override fun handle(connection: PlayConnection) {
|
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
|
val score = objective.scores.remove(entity) ?: return
|
||||||
|
|
||||||
connection.fireEvent(ScoreboardScoreRemoveEvent(connection, score))
|
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.scoreboard.TeamCollisionRules
|
||||||
import de.bixilon.minosoft.data.text.ChatCode
|
import de.bixilon.minosoft.data.text.ChatCode
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
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.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
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.scoreboardManager.updateScoreTeams(team, members)
|
||||||
|
|
||||||
connection.fireEvent(ScoreboardTeamCreateEvent(connection, team))
|
connection.fireEvent(TeamCreateEvent(connection, team))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log() {
|
override fun log() {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
package de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.teams
|
package de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.teams
|
||||||
|
|
||||||
import de.bixilon.minosoft.Minosoft
|
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.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
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.scoreboardManager.updateScoreTeams(team, members)
|
||||||
connection.fireEvent(ScoreboardTeamMemberAddEvent(connection, team, members))
|
connection.fireEvent(TeamMemberAddEvent(connection, team, members))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log() {
|
override fun log() {
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.protocol.packets.s2c.play.scoreboard.teams
|
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.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
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.scoreboardManager.updateScoreTeams(team, members, true)
|
||||||
connection.fireEvent(ScoreboardTeamMemberRemoveEvent(connection, team, members))
|
connection.fireEvent(TeamMemberRemoveEvent(connection, team, members))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log() {
|
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.scoreboard.TeamCollisionRules
|
||||||
import de.bixilon.minosoft.data.text.ChatCode
|
import de.bixilon.minosoft.data.text.ChatCode
|
||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
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.network.connection.play.PlayConnection
|
||||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||||
@ -91,16 +92,18 @@ class TeamUpdateS2CP(val name: String, buffer: PlayInByteBuffer) : PlayS2CPacket
|
|||||||
|
|
||||||
|
|
||||||
override fun handle(connection: PlayConnection) {
|
override fun handle(connection: PlayConnection) {
|
||||||
connection.scoreboardManager.teams[name]?.let {
|
val team = connection.scoreboardManager.teams[name] ?: return
|
||||||
it.displayName = displayName
|
|
||||||
it.prefix = prefix
|
team.displayName = displayName
|
||||||
it.suffix = suffix
|
team.prefix = prefix
|
||||||
it.friendlyFire = friendlyFire
|
team.suffix = suffix
|
||||||
it.canSeeInvisibleTeam = canSeeInvisibleTeam
|
team.friendlyFire = friendlyFire
|
||||||
it.collisionRule = collisionRule
|
team.canSeeInvisibleTeam = canSeeInvisibleTeam
|
||||||
it.nameTagVisibility = nameTagVisibility
|
team.collisionRule = collisionRule
|
||||||
it.formattingCode = formattingCode
|
team.nameTagVisibility = nameTagVisibility
|
||||||
}
|
team.formattingCode = formattingCode
|
||||||
|
|
||||||
|
connection.fireEvent(TeamUpdateEvent(connection, team))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun log() {
|
override fun log() {
|
||||||
|
@ -231,17 +231,17 @@ class PacketTypes {
|
|||||||
PLAY_CAMERA({ CameraS2CP(it) }),
|
PLAY_CAMERA({ CameraS2CP(it) }),
|
||||||
PLAY_HOTBAR_SLOT_SET({ HotbarSlotSetS2CP(it) }),
|
PLAY_HOTBAR_SLOT_SET({ HotbarSlotSetS2CP(it) }),
|
||||||
PLAY_CHUNK_CENTER_SET({ ChunkCenterSetS2CP(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_METADATA({ EntityMetadataS2CP(it) }, isThreadSafe = false),
|
||||||
PLAY_ENTITY_ATTACH({ EntityAttachS2CP(it) }),
|
PLAY_ENTITY_ATTACH({ EntityAttachS2CP(it) }),
|
||||||
PLAY_ENTITY_VELOCITY({ EntityVelocityS2CP(it) }),
|
PLAY_ENTITY_VELOCITY({ EntityVelocityS2CP(it) }),
|
||||||
PLAY_ENTITY_EQUIPMENT({ EntityEquipmentS2CP(it) }),
|
PLAY_ENTITY_EQUIPMENT({ EntityEquipmentS2CP(it) }),
|
||||||
PLAY_EXPERIENCE_SET({ ExperienceSetS2CP(it) }),
|
PLAY_EXPERIENCE_SET({ ExperienceSetS2CP(it) }),
|
||||||
PLAY_HEALTH_SET({ HealthSetS2CP(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_ENTITY_PASSENGER_SET({ EntityPassengerSetS2CP(it) }),
|
||||||
PLAY_TEAMS({ TeamsS2CF.createPacket(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_COMPASS_POSITION_SET({ CompassPositionSetS2CP(it) }),
|
||||||
PLAY_WORLD_TIME_SET({ WorldTimeSetS2CP(it) }),
|
PLAY_WORLD_TIME_SET({ WorldTimeSetS2CP(it) }),
|
||||||
PLAY_ENTITY_SOUND_EVENT({ EntitySoundEventS2CP(it) }),
|
PLAY_ENTITY_SOUND_EVENT({ EntitySoundEventS2CP(it) }),
|
||||||
|
@ -95,16 +95,21 @@ object KUtil {
|
|||||||
return Collections.synchronizedList(mutableListOf(*values))
|
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
|
val ret: K
|
||||||
synchronized(this) {
|
synchronized(lock ?: this) {
|
||||||
ret = copier()
|
ret = copier()
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <K, V> Map<K, V>.toSynchronizedMap(): SynchronizedMap<K, V> {
|
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> {
|
fun <V> Collection<V>.toSynchronizedList(): MutableList<V> {
|
||||||
|
@ -22,7 +22,7 @@ import java.util.function.Function
|
|||||||
class SynchronizedMap<K, V>(
|
class SynchronizedMap<K, V>(
|
||||||
private val original: MutableMap<K, V>,
|
private val original: MutableMap<K, V>,
|
||||||
) : MutableMap<K, V> {
|
) : MutableMap<K, V> {
|
||||||
private val lock = Object()
|
internal val lock = Object()
|
||||||
override val size: Int
|
override val size: Int
|
||||||
get() = synchronized(lock) { original.size }
|
get() = synchronized(lock) { original.size }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user