Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM eclipse-temurin:17-jdk-jammy

USER root

# set working directory
WORKDIR /workspaces/RPKit
4 changes: 4 additions & 0 deletions .devcontainer/start_dev_container.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
REM This script is meant to be run from the .devcontainer directory.

docker build . -t rpk-dev-container
docker run -it -v %cd%\..\:/workspaces/RPKit rpk-dev-container /bin/bash
4 changes: 4 additions & 0 deletions .devcontainer/start_dev_container.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This script is meant to be run from the .devcontainer directory.

docker build . -t rpk-dev-container
docker run -it -v %cd%\..\:/workspaces/RPKit rpk-dev-container /bin/bash
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.rpkit.chat.bukkit.command.listchatchannels.ListChatChannelsCommand
import com.rpkit.chat.bukkit.command.message.MessageCommand
import com.rpkit.chat.bukkit.command.mute.MuteCommand
import com.rpkit.chat.bukkit.command.reply.ReplyCommand
import com.rpkit.chat.bukkit.command.setchatnamecolor.SetChatNameColorCommand
import com.rpkit.chat.bukkit.command.snoop.SnoopCommand
import com.rpkit.chat.bukkit.command.unmute.UnmuteCommand
import com.rpkit.chat.bukkit.database.table.*
Expand Down Expand Up @@ -182,6 +183,7 @@ class RPKChatBukkit : JavaPlugin(), RPKPlugin {
database.addTable(RPKChatGroupMemberTable(database, this))
database.addTable(RPKLastUsedChatGroupTable(database, this))
database.addTable(RPKSnooperTable(database, this))
database.addTable(RPKChatNameColorTable(database, this))

// Class loader needs to be the plugin's class loader in order for ServiceLoader in slf4j to be able to find
// the SLF4JLoggerProvider implementation, as the remapped slf4j-jdk14 is loaded by the plugin's class loader
Expand Down Expand Up @@ -233,6 +235,7 @@ class RPKChatBukkit : JavaPlugin(), RPKPlugin {
getCommand("message")?.setExecutor(MessageCommand(this))
getCommand("reply")?.setExecutor(ReplyCommand(this))
getCommand("snoop")?.setExecutor(SnoopCommand(this))
getCommand("setchatnamecolor")?.setExecutor(SetChatNameColorCommand(this))
Services[RPKChatChannelService::class.java]?.chatChannels?.forEach { chatChannel ->
getDynamicCommand(chatChannel.name.value).setExecutor(QuickChatChannelCommand(this, chatChannel).toBukkit())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import com.rpkit.chat.bukkit.chatchannel.context.DirectedPostFormatMessageContex
import com.rpkit.chat.bukkit.chatchannel.context.DirectedPreFormatMessageContextImpl
import com.rpkit.chat.bukkit.chatchannel.context.UndirectedMessageContextImpl
import com.rpkit.chat.bukkit.chatchannel.format.FormatPart
import com.rpkit.chat.bukkit.chatchannel.format.part.SenderCharacterNamePart
import com.rpkit.chat.bukkit.chatchannel.pipeline.DirectedPostFormatPipelineComponent
import com.rpkit.chat.bukkit.chatchannel.pipeline.DirectedPreFormatPipelineComponent
import com.rpkit.chat.bukkit.chatchannel.pipeline.UndirectedPipelineComponent
import com.rpkit.chat.bukkit.context.DirectedPostFormatMessageContext
import com.rpkit.chat.bukkit.context.DirectedPreFormatMessageContext
import com.rpkit.chat.bukkit.context.UndirectedMessageContext
import com.rpkit.chat.bukkit.database.table.RPKChatNameColorTable
import com.rpkit.chat.bukkit.event.chatchannel.RPKBukkitChatChannelMessageEvent
import com.rpkit.chat.bukkit.mute.RPKChatChannelMuteService
import com.rpkit.chat.bukkit.speaker.RPKChatChannelSpeakerService
Expand Down Expand Up @@ -169,6 +171,9 @@ class RPKChatChannelImpl(
format.flatMap { part -> part.toChatComponents(preFormatContext).join().toList() }.toTypedArray(),
preFormatContext.isCancelled
)
if (senderMinecraftProfile != null) {
setSenderCharacterNamePartColor(senderMinecraftProfile)
};
directedPostFormatPipeline.forEach { component ->
postFormatContext = component.process(postFormatContext).join()
}
Expand All @@ -190,4 +195,25 @@ class RPKChatChannelImpl(
})
}

private fun setSenderCharacterNamePartColor(senderMinecraftProfile: RPKMinecraftProfile) {
val minecraftProfileId = senderMinecraftProfile.id ?: return
val recordExists = plugin.database.getTable(RPKChatNameColorTable::class.java)[minecraftProfileId].join() != null
if (recordExists) {
val senderCharacterNamePart = getSenderCharacterNamePart() ?: return
val chatNameColorRecord = plugin.database.getTable(RPKChatNameColorTable::class.java)[minecraftProfileId].join()
if (chatNameColorRecord != null) {
senderCharacterNamePart.color = chatNameColorRecord.chatNameColor
}
}
}

private fun getSenderCharacterNamePart(): SenderCharacterNamePart? {
for (part in format) {
if (part is SenderCharacterNamePart) {
return part
}
}
return null
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import java.util.logging.Level
abstract class GenericTextPart(
private val plugin: RPKChatBukkit,
val font: String? = null,
val color: String? = null,
var color: String? = null,
val isBold: Boolean? = null,
val isItalic: Boolean? = null,
val isUnderlined: Boolean? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright 2020 Ren Binden
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.rpkit.chat.bukkit.command.setchatnamecolor

import com.rpkit.chat.bukkit.RPKChatBukkit
import com.rpkit.chat.bukkit.database.table.RPKChatNameColorTable
import com.rpkit.core.service.Services
import com.rpkit.players.bukkit.profile.minecraft.RPKMinecraftProfileId
import com.rpkit.players.bukkit.profile.minecraft.RPKMinecraftProfileService
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletableFuture.runAsync

/**
* SetChatNameColor command.
* Sets the chat color name for a player.
*/
class SetChatNameColorCommand(private val plugin: RPKChatBukkit) : CommandExecutor {

override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
if (!sender.hasPermission("rpkit.chat.command.setchatnamecolor")) {
sender.sendMessage(plugin.messages["no-permission-setchatnamecolor"])
return true
}
if (sender !is Player) {
sender.sendMessage(plugin.messages["not-from-console"])
return true
}
val minecraftProfileService = Services[RPKMinecraftProfileService::class.java]
if (minecraftProfileService == null) {
sender.sendMessage(plugin.messages["no-minecraft-profile-service"])
return true
}
val minecraftProfile = minecraftProfileService.getPreloadedMinecraftProfile(sender)
if (minecraftProfile == null) {
sender.sendMessage(plugin.messages["no-minecraft-profile"])
return true
}

// if no arguments
if (args.isEmpty()) {
sender.sendMessage(plugin.messages["setchatnamecolor-usage"])
return true
}

// retrieve desired chat name color
val chatNameColor = args[0]
if (isInputTooLong(chatNameColor)) {
sender.sendMessage(plugin.messages["setchatnamecolor-too-long"])
return true
}

if (!isHexColorCodeValid(chatNameColor)) {
sender.sendMessage(plugin.messages["setchatnamecolor-invalid-color-code"])
return true
}

val minecraftProfileId = minecraftProfile.id
if (minecraftProfileId == null) {
sender.sendMessage(plugin.messages["no-minecraft-profile"])
return true
}

setChatNameColorAsync(minecraftProfileId, chatNameColor).thenRun {
sender.sendMessage(plugin.messages["setchatnamecolor-chat-name-color-has-been-set"])
}.exceptionally { exception ->
plugin.logger.severe("Failed to set chat name color for ${minecraftProfile.name}")
plugin.logger.severe(exception.message)
sender.sendMessage(plugin.messages["setchatnamecolor-something-went-wrong"])
return@exceptionally null
}
return true
}

/**
* Checks if the input is too long. The maximum length for a chat name color is 16 characters.
* @param name the input to check
* @return true if the input is too long, false otherwise
*/
private fun isInputTooLong(name: String): Boolean {
return name.length > 16
}

/**
* Checks if the input is a valid hex color code. A valid hex color code is a string that starts with a '#' followed by 6 characters that are either digits or letters from a to f.
* @param colorCode the color code to check
* @return true if the color code is valid, false otherwise
*/
private fun isHexColorCodeValid(colorCode: String): Boolean {
return colorCode.matches(Regex("#[0-9a-fA-F]{6}"))
}

/**
* Sets the chat name color for a player asynchronously.
* @param minecraftProfileId the ID of the player's Minecraft profile
* @param chatNameColor the chat name color to set
* @return a string indicating the result of the operation
*/
private fun setChatNameColorAsync(minecraftProfileId: RPKMinecraftProfileId, chatNameColor: String) : CompletableFuture<Void> {
return runAsync {
val recordExists = plugin.database.getTable(RPKChatNameColorTable::class.java)[minecraftProfileId].join() != null
if (recordExists) {
plugin.database.getTable(RPKChatNameColorTable::class.java).update(minecraftProfileId, chatNameColor)
} else {
plugin.database.getTable(RPKChatNameColorTable::class.java).insert(minecraftProfileId, chatNameColor)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright 2021 Ren Binden
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.rpkit.chat.bukkit.database.table

import com.rpkit.chat.bukkit.RPKChatBukkit
import com.rpkit.chat.bukkit.database.create
import com.rpkit.chat.bukkit.database.jooq.Tables.RPKIT_CHAT_NAME_COLOR
import com.rpkit.core.database.Database
import com.rpkit.core.database.Table
import java.util.concurrent.CompletableFuture
import com.rpkit.chat.bukkit.database.jooq.tables.records.RpkitChatNameColorRecord
import com.rpkit.players.bukkit.profile.minecraft.RPKMinecraftProfileId
import java.util.concurrent.CompletableFuture.runAsync
import java.util.logging.Level.SEVERE

/**
* Represents the chat name color table.
*/
class RPKChatNameColorTable(private val database: Database, private val plugin: RPKChatBukkit) : Table {

fun insert(id: RPKMinecraftProfileId?, chatNameColor: String): CompletableFuture<Void> {
// insert id -> chat name color record into database
return runAsync {
database.create
.insertInto(
RPKIT_CHAT_NAME_COLOR,
RPKIT_CHAT_NAME_COLOR.MINECRAFT_PROFILE_ID,
RPKIT_CHAT_NAME_COLOR.CHAT_NAME_COLOR
)
.values(
id?.value,
chatNameColor
)
.execute()
}.exceptionally { e ->
plugin.logger.log(SEVERE, "Failed to insert chat name color record for Minecraft profile ${id?.value} and chat name color $chatNameColor", e)
throw e
}
}

fun update(minecraftProfileId: RPKMinecraftProfileId, chatNameColor: String): CompletableFuture<Void> {
// update chat name color record in database
return runAsync {
database.create
.update(RPKIT_CHAT_NAME_COLOR)
.set(RPKIT_CHAT_NAME_COLOR.CHAT_NAME_COLOR, chatNameColor)
.where(RPKIT_CHAT_NAME_COLOR.MINECRAFT_PROFILE_ID.eq(minecraftProfileId.value))
.execute()
}.exceptionally { e ->
plugin.logger.log(SEVERE, "Failed to update chat name color record for Minecraft profile ${minecraftProfileId.value} and chat name color $chatNameColor", e)
throw e
}
}

operator fun get(id: RPKMinecraftProfileId): CompletableFuture<RpkitChatNameColorRecord?> {
// get chat name color record from database by id
return CompletableFuture.supplyAsync {
database.create
.selectFrom(RPKIT_CHAT_NAME_COLOR)
.where(RPKIT_CHAT_NAME_COLOR.MINECRAFT_PROFILE_ID.eq(id.value))
.fetchOne()
}.exceptionally { e ->
plugin.logger.log(SEVERE, "Failed to get chat name color record for Minecraft profile ${id.value}", e)
null
}
}

fun delete(): CompletableFuture<Void> {
// delete chat name color record from database
return runAsync {
database.create
.deleteFrom(RPKIT_CHAT_NAME_COLOR)
.execute()
}.exceptionally { e ->
plugin.logger.log(SEVERE, "Failed to delete chat name color records", e)
throw e
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2020 Ren Binden
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

-- table to keep track of profile id -> chat name color
CREATE TABLE `rpkit_chat_name_color`
(
`minecraft_profile_id` int NOT NULL,
`chat_name_color` varchar(256) NOT NULL
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2020 Ren Binden
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

-- table to keep track of profile id -> chat name color
CREATE TABLE `rpkit_chat_name_color`
(
`minecraft_profile_id` int NOT NULL,
`chat_name_color` varchar(256) NOT NULL
);
8 changes: 7 additions & 1 deletion bukkit/rpk-chat-bukkit/src/main/resources/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,10 @@ plugin-website: 'Website: ${website}'
plugin-author: 'Author: ${author}'
plugin-authors: 'Authors: ${authors}'
plugin-contributors: 'Contributors: ${contributors}'
server-version: 'This server is running ${name} version ${version} (Implementing API version ${api_version})'
server-version: 'This server is running ${name} version ${version} (Implementing API version ${api_version})'
no-permission-setchatnamecolor: '&cYou do not have permission to set the color of your name in chat.'
setchatnamecolor-usage: '&cUsage: /setchatnamecolor [color]'
setchatnamecolor-too-long: '&cThat color is too long. Expected something like #ffffff.'
setchatnamecolor-invalid-color-code: '&cThat color is not a valid color code. Expected something like #ffffff.'
setchatnamecolor-chat-name-color-has-been-set: '&aYour chat name color has been set.'
setchatnamecolor-something-went-wrong: '&cSomething went wrong while setting your chat name color.'
Loading