diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index b52b0f09..bc2da395 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -8,6 +8,11 @@
+
+
+
+
+
diff --git a/api/ctjs.api b/api/ctjs.api
index 295bbf0e..d8afafd8 100644
--- a/api/ctjs.api
+++ b/api/ctjs.api
@@ -1013,6 +1013,7 @@ public final class com/chattriggers/ctjs/api/entity/PlayerMP : com/chattriggers/
public final class com/chattriggers/ctjs/api/entity/Team : com/chattriggers/ctjs/api/CTWrapper {
public fun (Lnet/minecraft/scoreboard/Team;)V
public final fun canSeeInvisibleTeammates ()Z
+ public final fun getColor ()Ljava/lang/String;
public final fun getDeathMessageVisibility ()Lcom/chattriggers/ctjs/api/entity/Team$Visibility;
public final fun getFriendlyFire ()Z
public synthetic fun getMcValue ()Ljava/lang/Object;
@@ -1023,6 +1024,7 @@ public final class com/chattriggers/ctjs/api/entity/Team : com/chattriggers/ctjs
public final fun getPrefix ()Ljava/lang/String;
public final fun getRegisteredName ()Ljava/lang/String;
public final fun getSuffix ()Ljava/lang/String;
+ public final fun setColor (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/entity/Team;
public final fun setName (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/entity/Team;
public final fun setName (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Team;
public final fun setPrefix (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/entity/Team;
@@ -1033,6 +1035,10 @@ public final class com/chattriggers/ctjs/api/entity/Team : com/chattriggers/ctjs
public fun toMC ()Lnet/minecraft/scoreboard/Team;
}
+public synthetic class com/chattriggers/ctjs/api/entity/Team$EntriesMappings {
+ public static final synthetic field entries$0 Lkotlin/enums/EnumEntries;
+}
+
public final class com/chattriggers/ctjs/api/entity/Team$Visibility : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper {
public static final field ALWAYS Lcom/chattriggers/ctjs/api/entity/Team$Visibility;
public static final field Companion Lcom/chattriggers/ctjs/api/entity/Team$Visibility$Companion;
@@ -2314,6 +2320,9 @@ public final class com/chattriggers/ctjs/api/world/PotionEffectType {
public final class com/chattriggers/ctjs/api/world/Scoreboard {
public static final field INSTANCE Lcom/chattriggers/ctjs/api/world/Scoreboard;
+ public static final fun addLine (ILcom/chattriggers/ctjs/api/message/TextComponent;)V
+ public static final fun addLine (ILjava/lang/String;)V
+ public static final fun createTeam (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Team;
public static final fun getLineByIndex (I)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score;
public static final fun getLines ()Ljava/util/List;
public static final fun getLines (Z)Ljava/util/List;
@@ -2323,6 +2332,10 @@ public final class com/chattriggers/ctjs/api/world/Scoreboard {
public static final fun getShouldRender ()Z
public static final fun getSidebar ()Lnet/minecraft/scoreboard/ScoreboardObjective;
public static final fun getTitle ()Lcom/chattriggers/ctjs/api/message/TextComponent;
+ public static final fun removeIndex (I)V
+ public static final fun removeIndex (IZ)V
+ public static synthetic fun removeIndex$default (IZILjava/lang/Object;)V
+ public static final fun removeScores (I)V
public static final fun setLine (ILcom/chattriggers/ctjs/api/message/TextComponent;)V
public static final fun setLine (ILcom/chattriggers/ctjs/api/message/TextComponent;Z)V
public static final fun setLine (ILjava/lang/String;)V
@@ -2335,11 +2348,21 @@ public final class com/chattriggers/ctjs/api/world/Scoreboard {
public static final fun toMC ()Lnet/minecraft/scoreboard/Scoreboard;
}
-public final class com/chattriggers/ctjs/api/world/Scoreboard$Score {
- public fun (Lnet/minecraft/scoreboard/ScoreboardEntry;)V
+public final class com/chattriggers/ctjs/api/world/Scoreboard$Score : com/chattriggers/ctjs/api/CTWrapper {
+ public fun (Lnet/minecraft/scoreboard/ScoreAccess;)V
+ public synthetic fun getMcValue ()Ljava/lang/Object;
+ public fun getMcValue ()Lnet/minecraft/scoreboard/ScoreAccess;
public final fun getName ()Lcom/chattriggers/ctjs/api/message/TextComponent;
- public final fun getPoints ()I
- public final fun toMC ()Lnet/minecraft/scoreboard/ScoreboardEntry;
+ public final fun getNumberFormat ()Lnet/minecraft/scoreboard/number/NumberFormat;
+ public final fun getScore ()I
+ public final fun getTeam ()Lcom/chattriggers/ctjs/api/entity/Team;
+ public final fun remove ()V
+ public final fun setName (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score;
+ public final fun setNumberFormat (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score;
+ public final fun setScore (I)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score;
+ public final fun setTeam (Lcom/chattriggers/ctjs/api/entity/Team;)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score;
+ public synthetic fun toMC ()Ljava/lang/Object;
+ public fun toMC ()Lnet/minecraft/scoreboard/ScoreAccess;
public fun toString ()Ljava/lang/String;
}
diff --git a/docs/MIGRATION.md b/docs/MIGRATION.md
index 89c7b799..89da0bb8 100644
--- a/docs/MIGRATION.md
+++ b/docs/MIGRATION.md
@@ -134,7 +134,11 @@ Here is a list of targeted changes for various different APIs:
- `Scoreboard`
- Remove `Scoreboard.getScoreboardTitle()` in favor of the less verbose `Scoreboard.getTitle()`
- `Scoreboard.getTitle()` now returns `TextComponent` instead of `String`
- - `Score.getName()` now returns `TextComponent` instead of `String`
+ - `Score`
+ - is now mutable. You can now edit the score, name, number format, and team
+ - `getPoints`/`setPoints` are renamed to `getScore`/`setScore`
+ - Added `addLine()`, `createTeam()`, `removeIndex()`, `removeScores()` methods
+ - `getLines` now actually sorts by descending instead of ascending
- `Book` now uses `TextComponent` instead of `Message`
- `Settings`
- Renamed all methods in the `skin` object to indicate they return whether the part is enabled, not the actual part themselves (i.e. `getCape()` -> `isCapeEnabled()`)
@@ -195,7 +199,9 @@ Here is a list of targeted changes for various different APIs:
- `TabList`
- Renamed `getHeaderMessage()` to `getHeaderComponent()`, and it now returns a `TextComponent` instead of a `Message`
- Renamed `getFooterMessage()` to `getFooterComponent()`, and it now returns a `TextComponent` instead of a `Message`
-- `Team.getNameTagVisibility()` and `Team.getDeathMessageVisibility()` now return a `Team.Visibility` instead of a string
+- `Team`
+ - `Team.getNameTagVisibility()` and `Team.getDeathMessageVisibility()` now return a `Team.Visibility` instead of a string
+ - Added `setColor()`
- `Client`
- `getChatGUI` was renamed to `getChatGui` to match the naming of `getTabGui`
- Removed `Config.modulesFolder`. Use `ChatTriggers.MODULES_FOLDER` or the string `"./config/ChatTriggers/modules"`
diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java
index 7ed706f6..c42ccf3b 100644
--- a/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java
+++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java
@@ -1,5 +1,6 @@
package com.chattriggers.ctjs.internal.mixins;
+import com.chattriggers.ctjs.api.world.Scoreboard;
import com.chattriggers.ctjs.internal.engine.CTEvents;
import com.chattriggers.ctjs.api.triggers.TriggerType;
import com.chattriggers.ctjs.internal.engine.module.ModuleManager;
@@ -29,8 +30,10 @@ private void injectWorldUnload(ClientWorld world, CallbackInfo ci) {
TriggerType.SERVER_DISCONNECT.triggerAll();
}
- if (this.world != null)
+ if (this.world != null) {
TriggerType.WORLD_UNLOAD.triggerAll();
+ Scoreboard.INSTANCE.clearCustom$ctjs();
+ }
}
@Inject(method = "joinWorld", at = @At("TAIL"))
@@ -46,6 +49,7 @@ private void injectDisconnect(Screen screen, CallbackInfo ci) {
if (this.isIntegratedServerRunning() || this.getCurrentServerEntry() != null) {
TriggerType.WORLD_UNLOAD.triggerAll();
TriggerType.SERVER_DISCONNECT.triggerAll();
+ Scoreboard.INSTANCE.clearCustom$ctjs();
}
}
diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/Scoreboard$1Accessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/Scoreboard$1Accessor.java
new file mode 100644
index 00000000..3c9124bd
--- /dev/null
+++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/Scoreboard$1Accessor.java
@@ -0,0 +1,15 @@
+package com.chattriggers.ctjs.internal.mixins;
+
+import net.minecraft.scoreboard.ScoreHolder;
+import net.minecraft.scoreboard.ScoreboardScore;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(targets = "net.minecraft.scoreboard.Scoreboard$1")
+public interface Scoreboard$1Accessor {
+ @Accessor("field_47543")
+ ScoreboardScore getScore();
+
+ @Accessor("field_47547")
+ ScoreHolder getHolder();
+}
diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ScoreboardObjectiveMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ScoreboardObjectiveMixin.java
new file mode 100644
index 00000000..f8b2cffa
--- /dev/null
+++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/ScoreboardObjectiveMixin.java
@@ -0,0 +1,19 @@
+package com.chattriggers.ctjs.internal.mixins;
+
+import com.chattriggers.ctjs.api.world.Scoreboard;
+import net.minecraft.scoreboard.ScoreboardObjective;
+import net.minecraft.text.Text;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(ScoreboardObjective.class)
+public class ScoreboardObjectiveMixin {
+ @Inject(method = "setDisplayName", at = @At("HEAD"), cancellable = true)
+ private void chattriggers$keepCustomName(Text name, CallbackInfo ci) {
+ if (Scoreboard.INSTANCE.getCustomTitle$ctjs()) {
+ ci.cancel();
+ }
+ }
+}
diff --git a/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt b/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt
index 47a3d14d..7513994d 100644
--- a/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt
+++ b/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt
@@ -9,6 +9,7 @@ import com.chattriggers.ctjs.api.commands.DynamicCommands
import com.chattriggers.ctjs.api.message.ChatLib
import com.chattriggers.ctjs.api.render.Image
import com.chattriggers.ctjs.api.triggers.TriggerType
+import com.chattriggers.ctjs.api.world.Scoreboard
import com.chattriggers.ctjs.api.world.World
import com.chattriggers.ctjs.engine.Console
import com.chattriggers.ctjs.engine.Register
@@ -85,6 +86,7 @@ class CTJS : ClientModInitializer {
fun unload(asCommand: Boolean = true) {
TriggerType.WORLD_UNLOAD.triggerAll()
TriggerType.GAME_UNLOAD.triggerAll()
+ Scoreboard.clearCustom()
isLoaded = false
diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Team.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/Team.kt
index 54f817c1..76f04cd7 100644
--- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Team.kt
+++ b/src/main/kotlin/com/chattriggers/ctjs/api/entity/Team.kt
@@ -3,7 +3,10 @@ package com.chattriggers.ctjs.api.entity
import com.chattriggers.ctjs.api.CTWrapper
import com.chattriggers.ctjs.api.message.TextComponent
import com.chattriggers.ctjs.MCTeam
+import com.chattriggers.ctjs.api.message.ChatLib
import net.minecraft.scoreboard.AbstractTeam
+import net.minecraft.text.TextColor
+import net.minecraft.util.Formatting
class Team(override val mcValue: MCTeam) : CTWrapper {
/**
@@ -79,6 +82,24 @@ class Team(override val mcValue: MCTeam) : CTWrapper {
*/
fun setSuffix(suffix: String) = setSuffix(TextComponent(suffix))
+ fun getColor() = mcValue.color.toString()
+
+ /**
+ * Sets the team color
+ * @param color a string format of a [Formatting], or a hex value
+ * @return the team for method chaining
+ */
+ fun setColor(color: Any?) = apply {
+ mcValue.color = when (color) {
+ is Number -> Formatting.byColorIndex(color.toInt())
+ is CharSequence -> Formatting.entries.find {
+ it.toString() == ChatLib.addColor(color.toString())
+ } ?: Formatting.RESET
+ null -> Formatting.RESET
+ else -> throw IllegalArgumentException("Could not convert type ${color::class.simpleName} to a Formatting")
+ }
+ }
+
/**
* Gets the team's friendly fire setting
*/
diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/message/TextComponent.kt b/src/main/kotlin/com/chattriggers/ctjs/api/message/TextComponent.kt
index fb26d6ed..48e746ea 100644
--- a/src/main/kotlin/com/chattriggers/ctjs/api/message/TextComponent.kt
+++ b/src/main/kotlin/com/chattriggers/ctjs/api/message/TextComponent.kt
@@ -399,12 +399,12 @@ class TextComponent private constructor(
}
}
- private companion object {
+ internal companion object {
private val colorToFormatChar = Formatting.entries.mapNotNull { format ->
TextColor.fromFormatting(format)?.let { it to format }
}.toMap()
- private fun jsObjectToStyle(obj: NativeObject): Style {
+ internal fun jsObjectToStyle(obj: NativeObject): Style {
return Style.EMPTY
.withColor(obj["color"]?.let { color ->
when (color) {
diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/Scoreboard.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/Scoreboard.kt
index 9d718de7..be866833 100644
--- a/src/main/kotlin/com/chattriggers/ctjs/api/world/Scoreboard.kt
+++ b/src/main/kotlin/com/chattriggers/ctjs/api/world/Scoreboard.kt
@@ -1,16 +1,27 @@
package com.chattriggers.ctjs.api.world
-import com.chattriggers.ctjs.api.message.TextComponent
import com.chattriggers.ctjs.MCTeam
-import net.minecraft.scoreboard.ScoreboardEntry
+import com.chattriggers.ctjs.api.CTWrapper
+import com.chattriggers.ctjs.api.entity.Team
+import com.chattriggers.ctjs.api.message.TextComponent
+import com.chattriggers.ctjs.internal.mixins.`Scoreboard$1Accessor`
+import com.chattriggers.ctjs.internal.utils.asMixin
+import gg.essential.elementa.state.BasicState
+import net.minecraft.scoreboard.ScoreAccess
+import net.minecraft.scoreboard.ScoreboardDisplaySlot
import net.minecraft.scoreboard.ScoreboardObjective
import net.minecraft.scoreboard.ScoreboardScore
+import net.minecraft.scoreboard.number.NumberFormat
+import net.minecraft.scoreboard.number.StyledNumberFormat
+import net.minecraft.text.Style
+import org.mozilla.javascript.NativeObject
object Scoreboard {
private var needsUpdate = true
private var scoreboardNames = mutableListOf()
private var scoreboardTitle = TextComponent("")
private var shouldRender = true
+ internal var customTitle = false
@JvmStatic
fun toMC() = World.toMC()?.scoreboard
@@ -20,7 +31,7 @@ object Scoreboard {
fun getScoreboard() = toMC()
@JvmStatic
- fun getSidebar(): ScoreboardObjective? = toMC()?.objectives?.firstOrNull()
+ fun getSidebar(): ScoreboardObjective? = toMC()?.getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR)
/**
* Gets the top-most string which is displayed on the scoreboard. (doesn't have a score on the side).
@@ -46,7 +57,10 @@ object Scoreboard {
*/
@JvmStatic
fun setTitle(title: TextComponent) {
+ customTitle = false
getSidebar()?.displayName = title
+ scoreboardTitle = title
+ customTitle = true
}
@JvmStatic
@@ -89,14 +103,14 @@ object Scoreboard {
*/
@JvmStatic
fun getLinesByScore(score: Int): List = getLines().filter {
- it.getPoints() == score
+ it.getScore() == score
}
/**
* Sets a line in the scoreboard to the specified name and score.
*
* @param score the score value for this item
- * @param line the string to display on said line
+ * @param line the [TextComponent] to display on said line
* @param override whether to remove old lines with the same score
*/
@JvmStatic
@@ -106,17 +120,16 @@ object Scoreboard {
val sidebarObjective = getSidebar() ?: return
if (override) {
- scoreboard.getScoreboardEntries(sidebarObjective).filter {
- it.value == score
- }.forEach {
- scoreboard.removeScore({ it.owner }, sidebarObjective)
- }
+ removeScores(score)
+ addLine(score, line)
+ return
}
scoreboard.knownScoreHolders.forEach {
val scoreboardScore = scoreboard.getScore({ it.nameForScoreboard }, sidebarObjective) as? ScoreboardScore
- if (scoreboardScore?.score == score)
+ if (scoreboardScore?.score == score) {
scoreboardScore.displayText = line
+ }
}
}
@@ -124,6 +137,50 @@ object Scoreboard {
@JvmOverloads
fun setLine(score: Int, line: String, override: Boolean = false) = setLine(score, TextComponent(line), override)
+ /**
+ * Adds a line to the scoreboard
+ *
+ * @param score the score value for this item
+ * @param line the [TextComponent] to display on said line
+ */
+ @JvmStatic
+ fun addLine(score: Int, line: TextComponent) {
+ val scoreboard = toMC() ?: return
+ val sidebarObjective = getSidebar() ?: return
+
+ val newLine = scoreboard.getOrCreateScore({ Math.random().toString() }, sidebarObjective, true)
+ newLine.displayText = line
+ newLine.score = score
+
+ updateNames()
+ }
+
+ @JvmStatic
+ fun addLine(score: Int, line: String) = addLine(score, TextComponent(line))
+
+ /**
+ * Removes all lines from the scoreboard matching with a certain score
+ *
+ * @param score the score of the lines to remove
+ */
+ @JvmStatic
+ fun removeScores(score: Int) {
+ getLinesByScore(score).forEach(Score::remove)
+ }
+
+ /**
+ * Removes the line at a certain index
+ *
+ * @param index the index of the line to remove
+ */
+ @JvmStatic
+ @JvmOverloads
+ fun removeIndex(index: Int, descending: Boolean = true) {
+ val names = if (descending) scoreboardNames else scoreboardNames.asReversed()
+ val line = names.removeAt(index)
+ line.remove()
+ }
+
@JvmStatic
fun setShouldRender(shouldRender: Boolean) {
Scoreboard.shouldRender = shouldRender
@@ -132,45 +189,171 @@ object Scoreboard {
@JvmStatic
fun getShouldRender() = shouldRender
+ /**
+ * Creates or gets a [Team] with a given name
+ *
+ * @param name the name of the team
+ */
+ @JvmStatic
+ fun createTeam(name: String): Team = Team(toMC()!!.addTeam(name))
+
private fun updateNames() {
scoreboardNames.clear()
- scoreboardTitle = TextComponent("")
+
+ if (!customTitle)
+ scoreboardTitle = TextComponent("")
val scoreboard = toMC() ?: return
- val objective = scoreboard.objectives.singleOrNull() ?: return
+ val objective = getSidebar() ?: return
+
+ if (!customTitle)
+ scoreboardTitle = TextComponent(objective.displayName)
+
+ val newScores = scoreboard.knownScoreHolders.asSequence().filter {
+ objective in scoreboard.getScoreHolderObjectives(it)
+ }.map {
+ scoreboard.getOrCreateScore(it, objective, true)
+ }.mapTo(mutableListOf(), ::Score)
- scoreboardTitle = TextComponent(objective.displayName)
- scoreboardNames = scoreboard.getScoreboardEntries(objective).filter {
- it.owner != null && !it.owner.startsWith("#")
- }.map(::Score).sortedBy { it.getPoints() }.toMutableList()
+ scoreboardNames = newScores.sortedWith(compareBy {
+ it.getScore()
+ }.reversed().thenBy {
+ it.getName().formattedText.lowercase()
+ }).toMutableList()
}
internal fun resetCache() {
needsUpdate = true
}
- class Score(private val mcValue: ScoreboardEntry) {
- fun toMC() = mcValue
+ internal fun clearCustom() {
+ scoreboardNames.clear()
+ customTitle = false
+ scoreboardTitle = TextComponent("")
+ }
+
+ class Score(override val mcValue: ScoreAccess) : CTWrapper {
+ private val scoreState = BasicState(mcValue.score)
+ private val nameState = BasicState(mcValue.displayText)
+ private val formatState = BasicState(mcValue.asMixin<`Scoreboard$1Accessor`>().score.numberFormat)
+ private val teamState = run {
+ val scoreboard = Scoreboard.toMC()!!
+ val name = mcValue.asMixin<`Scoreboard$1Accessor`>().holder.nameForScoreboard
+
+ BasicState(scoreboard.getScoreHolderTeam(name))
+ }
+
+ /**
+ * Gets the team associated with this score, if it exists
+ *
+ * @return the team, or null if it does not exist
+ */
+ fun getTeam(): Team? = teamState.get()?.let(::Team)
+
+ /**
+ * Sets the team associated with this score
+ *
+ * @param team the new team to set for this line. Custom teams can be created using [createTeam]
+ * @return the score to allow for method chaining
+ */
+ fun setTeam(team: Team?) = apply {
+ val scoreboard = Scoreboard.toMC()!!
+ val name = mcValue.asMixin<`Scoreboard$1Accessor`>().holder.nameForScoreboard
+
+ if (team == null) {
+ scoreboard.clearTeam(name)
+ } else {
+ scoreboard.addScoreHolderToTeam(name, team.toMC())
+ }
+
+ teamState.set(team?.toMC())
+ }
/**
- * Gets the score point value for this score,
+ * Gets the score value for this score,
* i.e. the number on the right of the board
*
* @return the actual point value
*/
- fun getPoints(): Int = mcValue.value
+ fun getScore(): Int = scoreState.get()
+
+ /**
+ * Sets the score value for this score
+ *
+ * @param score the new point value
+ * @return the score to allow for method chaining
+ */
+ fun setScore(score: Int) = apply {
+ scoreState.set(score)
+ mcValue.score = score
+ }
/**
* Gets the display string of this score
*
* @return the display name
*/
- fun getName() = TextComponent(
- MCTeam.decorateName(
- Scoreboard.toMC()!!.getScoreHolderTeam(mcValue.owner),
- TextComponent(mcValue.owner),
+ fun getName(): TextComponent {
+ val name = mcValue.asMixin<`Scoreboard$1Accessor`>().holder.nameForScoreboard
+
+ return TextComponent(
+ MCTeam.decorateName(
+ getTeam()?.mcValue,
+ TextComponent(nameState.get() ?: name),
+ )
)
- )
+ }
+
+ /**
+ * Sets the name of this score
+ *
+ * @param name the new name
+ * @return the score to allow for method chaining
+ */
+ fun setName(name: TextComponent?) = apply {
+ nameState.set(name)
+ mcValue.displayText = name
+ }
+
+ /**
+ * Gets the number format of this score
+ *
+ * @return the number format
+ */
+ fun getNumberFormat(): NumberFormat? = formatState.get()
+
+ /**
+ * Sets the number format of this score
+ *
+ * @param format either a formatting string, i.e. "&6", style in the form of an object, see [TextComponent], a
+ * [NumberFormat], or hex value
+ * @return the score to allow for method chaining
+ *
+ * @see [TextComponent]
+ */
+ fun setNumberFormat(format: Any?) = apply {
+ val style = when (format) {
+ is CharSequence -> StyledNumberFormat(TextComponent(format.toString()).style)
+ is NativeObject -> StyledNumberFormat(TextComponent.jsObjectToStyle(format))
+ is NumberFormat -> format
+ is Number -> StyledNumberFormat(Style.EMPTY.withColor(format.toInt()))
+ else -> null
+ }
+
+ formatState.set(style)
+ mcValue.setNumberFormat(style)
+ }
+
+ /**
+ * Removes this score from the scoreboard
+ */
+ fun remove() {
+ val scoreboard = Scoreboard.toMC() ?: return
+ val sidebarObjective = getSidebar() ?: return
+
+ scoreboard.removeScore(toMC().asMixin<`Scoreboard$1Accessor`>().holder, sidebarObjective)
+ updateNames()
+ }
override fun toString(): String = getName().formattedText
}
diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt
index 479db26f..9954d38c 100644
--- a/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt
+++ b/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt
@@ -130,7 +130,7 @@ object ConsoleHostProcess : Initializer {
when (val message = Json.decodeFromString(messageText)) {
is EvalTextMessage -> {
- val result = JSLoader.eval(message.string)
+ val result = JSLoader.eval(message.string) ?: continue
trySendMessage(EvalResultMessage(message.id, result))
}
is FontSizeMessage -> {
diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt
index 12c9b528..47e9ef8b 100644
--- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt
+++ b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt
@@ -155,7 +155,7 @@ object JSLoader {
}
}
- fun eval(code: String): String {
+ fun eval(code: String): String? {
return wrapInContext {
ScriptRuntime.doTopCall(
{ cx, scope, thisObj, args ->
@@ -170,7 +170,7 @@ object JSLoader {
evalScope,
emptyArray(),
true,
- ) as String
+ ) as? String
}
}
diff --git a/src/main/resources/chattriggers.mixins.json b/src/main/resources/chattriggers.mixins.json
index ad44393f..487cb788 100644
--- a/src/main/resources/chattriggers.mixins.json
+++ b/src/main/resources/chattriggers.mixins.json
@@ -11,11 +11,9 @@
"ChatHudAccessor",
"ChatHudMixin",
"ChatScreenAccessor",
- "ChunkAccessor",
"ClickableWidgetAccessor",
"ClientChunkManagerAccessor",
"ClientChunkMapAccessor",
- "ClientConnectionMixin",
"ClientPlayerEntityMixin",
"ClientPlayerInteractionManagerMixin",
"ClientWorldAccessor",
@@ -27,37 +25,43 @@
"HandledScreenAccessor",
"HandledScreenMixin",
"InGameHudMixin",
- "ItemStackMixin",
"KeyBindingAccessor",
- "LivingEntityMixin",
"MinecraftClientMixin",
"MouseMixin",
- "NbtCompoundAccessor",
"ParticleAccessor",
"ParticleManagerMixin",
- "PlayerEntityMixin",
"PlayerListHudAccessor",
"PlayerListHudMixin",
- "PlayerScreenHandlerMixin",
"RenderTickCounterMixin",
- "ScreenHandlerMixin",
- "SystemDetailsMixin",
"commands.ClientCommandSourceMixin",
"commands.ClientPlayNetworkHandlerMixin",
- "commands.CommandContextAccessor",
- "commands.CommandDispatcherMixin",
- "commands.CommandNodeAccessor",
- "commands.EntitySelectorAccessor",
"sound.SoundAccessor",
"sound.SoundManagerAccessor",
"sound.SoundSystemAccessor",
"sound.SoundSystemMixin",
- "sound.SourceAccessor",
- "stdio.BootstrapMixin",
- "stdio.LoggerPrintStreamMixin"
+ "sound.SourceAccessor"
],
"injectors": {
"defaultRequire": 1
},
- "plugin": "com.chattriggers.ctjs.internal.launch.CTMixinPlugin"
+ "plugin": "com.chattriggers.ctjs.internal.launch.CTMixinPlugin",
+ "mixins": [
+ "ChunkAccessor",
+ "ClientConnectionMixin",
+ "ItemStackMixin",
+ "LivingEntityMixin",
+ "NbtCompoundAccessor",
+ "PlayerEntityMixin",
+ "PlayerScreenHandlerMixin",
+ "Scoreboard$1Accessor",
+ "ScoreboardObjectiveMixin",
+ "ScreenHandlerMixin",
+ "SystemDetailsMixin",
+ "commands.CommandContextAccessor",
+ "commands.CommandDispatcherMixin",
+ "commands.CommandNodeAccessor",
+ "commands.EntitySelectorAccessor",
+ "stdio.BootstrapMixin",
+ "stdio.LoggerPrintStreamMixin"
+ ]
}