diff --git a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignStateManager.kt b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignStateManager.kt index e5a897c..6cfb522 100644 --- a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignStateManager.kt +++ b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignStateManager.kt @@ -2,7 +2,6 @@ package app.simplecloud.plugin.sign.paper import app.simplecloud.plugin.sign.paper.dispatcher.PaperPlatformDispatcher import app.simplecloud.plugin.sign.shared.command.SignStateManager -import app.simplecloud.plugin.sign.shared.config.location.SignLocation import kotlinx.coroutines.withContext import net.kyori.adventure.text.Component import org.bukkit.Location @@ -31,20 +30,4 @@ class PaperSignStateManager( sign.update(true) } } - - override suspend fun updateSign(location: SignLocation, lines: List) { - withContext(dispatcher.getDispatcher()) { - val mappedLocation = bootstrap.signManager.map(location) - - (mappedLocation as? Sign)?.apply { - arrayOf(Side.FRONT, Side.BACK).forEach { side -> - getSide(side).apply { - lines().indices.forEach { i -> line(i, lines[i]) } - } - } - - update(true) - } - } - } } \ No newline at end of file diff --git a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignsPluginBootstrap.kt b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignsPluginBootstrap.kt index 1874568..46349d0 100644 --- a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignsPluginBootstrap.kt +++ b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/PaperSignsPluginBootstrap.kt @@ -7,6 +7,7 @@ import app.simplecloud.plugin.sign.paper.rule.PlayerRuleContext import app.simplecloud.plugin.sign.paper.sender.PaperCommandSender import app.simplecloud.plugin.sign.paper.sender.PaperCommandSenderMapper import app.simplecloud.plugin.sign.paper.service.PaperSignService +import app.simplecloud.plugin.sign.paper.util.signFacing import app.simplecloud.plugin.sign.shared.CloudSign import app.simplecloud.plugin.sign.shared.SignManager import app.simplecloud.plugin.sign.shared.command.SignCommand @@ -26,7 +27,6 @@ import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.Sign import org.bukkit.block.sign.Side -import org.bukkit.block.data.Directional import org.bukkit.plugin.java.JavaPlugin import org.incendo.cloud.execution.ExecutionCoordinator import org.incendo.cloud.paper.PaperCommandManager @@ -139,8 +139,8 @@ class PaperSignsPluginBootstrap : PluginBootstrap { return } - val directional = sign.block.blockData as? Directional ?: return - val behindBlock = sign.block.getRelative(directional.facing.oppositeFace) + val facing = sign.block.blockData.signFacing() ?: return + val behindBlock = sign.block.getRelative(facing.oppositeFace) if (behindBlock.type != material) { behindBlock.type = material diff --git a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/sender/PaperCommandSender.kt b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/sender/PaperCommandSender.kt index 65d53e7..81f256f 100644 --- a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/sender/PaperCommandSender.kt +++ b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/sender/PaperCommandSender.kt @@ -1,6 +1,7 @@ package app.simplecloud.plugin.sign.paper.sender import app.simplecloud.plugin.sign.paper.PaperSignsPlugin +import app.simplecloud.plugin.sign.paper.util.resolveSignDirection import app.simplecloud.plugin.sign.shared.config.location.SignLocation import app.simplecloud.plugin.sign.shared.sender.SignCommandSender import app.simplecloud.plugin.sign.shared.utils.SignCommandMessages @@ -8,11 +9,12 @@ import io.papermc.paper.command.brigadier.CommandSourceStack import kotlinx.coroutines.withContext import net.kyori.adventure.text.Component import net.kyori.adventure.text.minimessage.MiniMessage +import org.bukkit.Bukkit import org.bukkit.FluidCollisionMode +import org.bukkit.Location import org.bukkit.block.Sign import org.bukkit.entity.Player -@Suppress("UnstableApiUsage") class PaperCommandSender( val sourceStack: CommandSourceStack ) : SignCommandSender { @@ -24,10 +26,9 @@ class PaperCommandSender( val player = sourceStack.sender as? Player ?: return null return withContext(PaperSignsPlugin.instance.bootstrap.platformDispatcher.getDispatcher()) { - val targetBlock = - player.getTargetBlockExact(maxDistance, FluidCollisionMode.NEVER) ?: return@withContext null + val targetBlock = player.getTargetBlockExact(maxDistance, FluidCollisionMode.NEVER) - if (targetBlock.state !is Sign) { + if (targetBlock == null || targetBlock.state !is Sign) { player.sendMessage(MiniMessage.miniMessage().deserialize(SignCommandMessages.SIGN_NOT_FOUND)) return@withContext null } @@ -36,8 +37,18 @@ class PaperCommandSender( world = targetBlock.world.name, x = targetBlock.x.toDouble(), y = targetBlock.y.toDouble(), - z = targetBlock.z.toDouble() + z = targetBlock.z.toDouble(), + direction = targetBlock.blockData.resolveSignDirection() ) } } + + override suspend fun teleport(location: SignLocation): Boolean { + val player = sourceStack.sender as? Player ?: return false + val world = Bukkit.getWorld(location.world) ?: return false + + return withContext(PaperSignsPlugin.instance.bootstrap.platformDispatcher.getDispatcher()) { + player.teleport(Location(world, location.x, location.y, location.z)) + } + } } \ No newline at end of file diff --git a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/service/PaperSignService.kt b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/service/PaperSignService.kt index 6a3aa29..2f7cb9b 100644 --- a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/service/PaperSignService.kt +++ b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/service/PaperSignService.kt @@ -2,6 +2,7 @@ package app.simplecloud.plugin.sign.paper.service import app.simplecloud.api.CloudApi import app.simplecloud.plugin.sign.paper.PaperSignsPluginBootstrap +import app.simplecloud.plugin.sign.paper.util.resolveSignDirection import app.simplecloud.plugin.sign.shared.CloudSign import app.simplecloud.plugin.sign.shared.LocationMapper import app.simplecloud.plugin.sign.shared.config.location.LocationsConfig @@ -55,6 +56,7 @@ class PaperSignService(private val bootstrap: PaperSignsPluginBootstrap) : SignS location.world.name, location.x, location.y, - location.z + location.z, + location.block.blockData.resolveSignDirection() ) } diff --git a/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/util/SignFacing.kt b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/util/SignFacing.kt new file mode 100644 index 0000000..b000f1c --- /dev/null +++ b/sign-paper/src/main/kotlin/app/simplecloud/plugin/sign/paper/util/SignFacing.kt @@ -0,0 +1,42 @@ +package app.simplecloud.plugin.sign.paper.util + +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Rotatable +import org.bukkit.block.data.type.WallSign + +/** + * Resolves the direction a sign block is facing, independent of whether it's a + * wall sign (6-way facing) or a standing sign (16-way rotation). + */ +fun BlockData.signFacing(): BlockFace? = when (this) { + is WallSign -> facing + is Rotatable -> rotation.toCardinal() + else -> null +} + +fun BlockData.resolveSignDirection(): String? = when (this) { + is WallSign -> "WALL:${facing.name}" + is Rotatable -> "STANDING:${rotation.name}" + else -> null +} + +/** + * Standing-sign rotation is 16-way; snaps it down to the nearest of the 4 + * horizontal cardinal faces so it can be used to find an adjacent block. + */ +private fun BlockFace.toCardinal(): BlockFace = when (this) { + BlockFace.NORTH_NORTH_WEST, BlockFace.NORTH, BlockFace.NORTH_NORTH_EAST, BlockFace.NORTH_WEST -> + BlockFace.NORTH + + BlockFace.EAST_NORTH_EAST, BlockFace.EAST, BlockFace.EAST_SOUTH_EAST, BlockFace.NORTH_EAST -> + BlockFace.EAST + + BlockFace.SOUTH_SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_SOUTH_WEST, BlockFace.SOUTH_EAST -> + BlockFace.SOUTH + + BlockFace.WEST_SOUTH_WEST, BlockFace.WEST, BlockFace.WEST_NORTH_WEST, BlockFace.SOUTH_WEST -> + BlockFace.WEST + + else -> BlockFace.NORTH +} diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/SignManager.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/SignManager.kt index 08fc94b..84a3c7f 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/SignManager.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/SignManager.kt @@ -40,6 +40,7 @@ class SignManager( ) private val layoutRepository = LayoutRepository( directoryPath.resolve("layouts"), + ruleRegistry, ) private val serializers = TypeSerializerCollection.defaults().childBuilder().apply { @@ -160,16 +161,16 @@ class SignManager( private fun startUpdateSignJob() { updateJob = scope.launch { - try { - while (isActive) { + while (isActive) { + try { updateLayoutIndexes() updateSigns() - delay(UPDATE_INTERVAL) + } catch (exception: CancellationException) { + throw exception + } catch (exception: Exception) { + logger.error("Error in update job", exception) } - } catch (exception: CancellationException) { - throw exception - } catch (exception: Exception) { - logger.error("Error in update job", exception) + delay(UPDATE_INTERVAL) } } } @@ -264,6 +265,7 @@ class SignManager( private suspend fun updateLayoutIndexes() { layoutRepository.getAll().forEach { layout -> + if (layout.frames.isEmpty()) return@forEach if (state.shouldUpdateFrame(layout.name, layout.frameUpdateInterval)) { state.updateFrameIndex(layout.name, layout.frames.size) } diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignCommand.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignCommand.kt index 1eb1738..61e9170 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignCommand.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignCommand.kt @@ -8,6 +8,7 @@ import app.simplecloud.plugin.sign.shared.sender.SignCommandSender import app.simplecloud.plugin.sign.shared.service.SignService import app.simplecloud.plugin.sign.shared.utils.SignCommandMessages import app.simplecloud.plugin.sign.shared.utils.SignCommandPermission +import com.google.common.base.Suppliers import com.google.common.cache.CacheBuilder import kotlinx.coroutines.* import kotlinx.coroutines.future.await @@ -17,6 +18,7 @@ import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder import org.incendo.cloud.Command import org.incendo.cloud.CommandManager import org.incendo.cloud.description.Description +import org.incendo.cloud.parser.standard.DoubleParser import org.incendo.cloud.parser.standard.IntegerParser import org.incendo.cloud.parser.standard.StringParser import org.incendo.cloud.suggestion.BlockingSuggestionProvider @@ -41,6 +43,13 @@ class SignCommand( .expireAfterWrite(5, TimeUnit.MINUTES) .build() + private val groupSuggestionsSupplier = Suppliers.memoizeWithExpiration( + { fetchGroupSuggestions() }, 10, TimeUnit.SECONDS + ) + private val persistentServerSuggestionsSupplier = Suppliers.memoizeWithExpiration( + { fetchPersistentServerSuggestions() }, 10, TimeUnit.SECONDS + ) + companion object { private const val LOCATIONS_PER_PAGE = 5 private const val MAX_SIGN_DISTANCE = 8 @@ -72,6 +81,7 @@ class SignCommand( createAddPersistentCommand(baseCommand), createRemoveCommand(baseCommand), createRemoveGroupCommand(baseCommand), + createTpCommand(baseCommand), ).forEach { command(it) } } } @@ -123,7 +133,7 @@ class SignCommand( commandScope.launch { handleSignOperation( context.sender(), - context.get("group"), + context["group"], SignOperation.ADD ) { location, group -> executeAddGroupSign(location, group) @@ -159,7 +169,7 @@ class SignCommand( .commandDescription(Description.of("Unregister a SimpleCloud Sign")) .permission(SignCommandPermission.REMOVE.node) .handler { context -> - CoroutineScope(Dispatchers.IO).launch { + commandScope.launch { handleSignOperation( context.sender(), operation = SignOperation.REMOVE @@ -183,6 +193,30 @@ class SignCommand( handleRemoveGroupCommand(context.sender(), context.getOrDefault("group", "")) } + private fun createTpCommand(baseCommand: Command.Builder) = + baseCommand.literal("tp") + .commandDescription(Description.of("Teleport to a registered CloudSign")) + .required("world", StringParser.stringParser()) + .required("x", DoubleParser.doubleParser()) + .required("y", DoubleParser.doubleParser()) + .required("z", DoubleParser.doubleParser()) + .permission(SignCommandPermission.TP.node) + .handler { context -> + commandScope.launch { + val location = SignLocation( + world = context["world"], + x = context.get("x"), + y = context.get("y"), + z = context.get("z"), + ) + + val success = context.sender().teleport(location) + if (!success) { + sendMessage(context.sender(), SignCommandMessages.TP_FAILED) + } + } + } + private fun handleListCommand(sender: SignCommandSender, group: String, page: Int = 1) { commandScope.launch { runCatching { @@ -243,7 +277,7 @@ class SignCommand( val paginatedLocations = groupedLocations.subList(startIndex, endIndex) val locationInformation = paginatedLocations.joinToString("\n") { (group, location) -> - """ + """ └─ Group: ${group} ├─ World: ${location.world} ├─ X: ${location.x} @@ -308,7 +342,7 @@ $navigationButtons val paginatedLocations = locations.subList(startIndex, endIndex) val locationInformation = paginatedLocations.joinToString("\n") { location -> - """ + """ └─ World: ${location.world} ├─ X: ${location.x} ├─ Y: ${location.y} @@ -375,6 +409,7 @@ $navigationButtons private suspend fun executeAddGroupSign(location: T, group: String): CommandResult { return runCatching { + if (signService.getCloudSign(location) != null) { return CommandResult.Error(SignCommandMessages.SIGN_ALREADY_REGISTERED) } @@ -542,7 +577,6 @@ $navigationButtons } } - private fun registeredGroupSuggestions(): BlockingSuggestionProvider = BlockingSuggestionProvider { _, _ -> signService.getAllConfigs() @@ -550,23 +584,23 @@ $navigationButtons } private fun groupSuggestions(): BlockingSuggestionProvider = - BlockingSuggestionProvider { _, _ -> - runBlocking { - signService.controllerApi.group().allGroups - .await() - .filterNot { it.type == GroupServerType.PROXY } - .map { Suggestion.suggestion(it.name) } - } - } + BlockingSuggestionProvider { _, _ -> groupSuggestionsSupplier.get() } private fun persistentServerSuggestions(): BlockingSuggestionProvider = - BlockingSuggestionProvider { _, _ -> - runBlocking { - signService.controllerApi.persistentServer().getAllPersistentServers() - .await() - .map { Suggestion.suggestion(it.name) } - } - } + BlockingSuggestionProvider { _, _ -> persistentServerSuggestionsSupplier.get() } + + private fun fetchGroupSuggestions(): List = runBlocking { + signService.controllerApi.group().allGroups + .await() + .filterNot { it.type == GroupServerType.PROXY } + .map { Suggestion.suggestion(it.name) } + } + + private fun fetchPersistentServerSuggestions(): List = runBlocking { + signService.controllerApi.persistentServer().allPersistentServers + .await() + .map { Suggestion.suggestion(it.name) } + } fun cleanup() { commandScope.cancel() diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignStateManager.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignStateManager.kt index a1eb35a..3626caf 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignStateManager.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/command/SignStateManager.kt @@ -1,11 +1,7 @@ package app.simplecloud.plugin.sign.shared.command -import app.simplecloud.plugin.sign.shared.config.location.SignLocation -import net.kyori.adventure.text.Component - interface SignStateManager { suspend fun clearSign(location: T) - suspend fun updateSign(location: SignLocation, lines: List) } \ No newline at end of file diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/SignMessageConfig.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/SignMessageConfig.kt deleted file mode 100644 index 2438424..0000000 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/SignMessageConfig.kt +++ /dev/null @@ -1,24 +0,0 @@ -package app.simplecloud.plugin.sign.shared.config - -class SignMessageConfig { - - companion object { - private const val PREFIX = "" - - const val GROUP_NOT_FOUND = - "$PREFIX There is no group named ''" - const val SIGN_NOT_FOUND = - "$PREFIX To execute this command, you need to be looking at a sign" - const val SIGN_ALREADY_REGISTERED = "$PREFIX Sign is already registered" - const val SIGN_CREATE_SUCCESS = - "$PREFIX Sign for group '' was successfully created" - const val SIGN_REMOVE_NOT_REGISTERED = "$PREFIX Sign is not registered as a CloudSign" - const val SIGN_REMOVE_SUCCESS = - "$PREFIX CloudSign successfully removed" - const val SIGN_REMOVE_GROUP_NOT_REGISTERED = - "$PREFIX No Signs were found for group ''" - const val SIGN_REMOVE_GROUP_SUCCESS = - "$PREFIX Successfully removed CloudSign(s) for group ''" - } - -} \ No newline at end of file diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/layout/LayoutConfig.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/layout/LayoutConfig.kt index 799719b..101d1b5 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/layout/LayoutConfig.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/layout/LayoutConfig.kt @@ -4,7 +4,6 @@ import app.simplecloud.api.server.Server import app.simplecloud.plugin.sign.shared.SignManager import app.simplecloud.plugin.sign.shared.config.matcher.MatcherConfigEntry import app.simplecloud.plugin.sign.shared.config.matcher.MatcherType -import app.simplecloud.plugin.sign.shared.rule.RuleRegistry import app.simplecloud.plugin.sign.shared.rule.SignRule import org.spongepowered.configurate.objectmapping.ConfigSerializable import org.spongepowered.configurate.objectmapping.meta.Setting @@ -29,14 +28,6 @@ data class LayoutConfig( get() = SignManager.getRuleRegistry()?.getRule(ruleName) ?: throw SerializationException("Rule $ruleName not found") - companion object { - private var ruleRegistry: RuleRegistry? = null - - fun setRegistry(registry: RuleRegistry) { - ruleRegistry = registry - } - } - fun constructName(server: Server): String { val baseName = when { server.isFromGroup -> "${server.group?.name ?: server.serverGroupId}-${server.numericalId}" diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/location/SignLocation.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/location/SignLocation.kt index 267dcd4..82dbedf 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/location/SignLocation.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/config/location/SignLocation.kt @@ -8,4 +8,5 @@ data class SignLocation( val x: Double = 0.0, val y: Double = 0.0, val z: Double = 0.0, + val direction: String? = null, ) diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/base/YamlDirectoryRepository.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/base/YamlDirectoryRepository.kt index d1a1bc1..3732203 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/base/YamlDirectoryRepository.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/base/YamlDirectoryRepository.kt @@ -2,20 +2,18 @@ package app.simplecloud.plugin.sign.shared.repository.base import app.simplecloud.plugin.sign.shared.rule.RuleRegistry import app.simplecloud.plugin.sign.shared.rule.SignRule +import app.simplecloud.plugin.sign.shared.rule.serialize.SignRuleSerializer import io.leangen.geantyref.TypeToken import kotlinx.coroutines.* -import org.spongepowered.configurate.ConfigurationNode +import org.slf4j.LoggerFactory +import org.spongepowered.configurate.ConfigurateException import org.spongepowered.configurate.ConfigurationOptions import org.spongepowered.configurate.kotlin.objectMapperFactory -import org.spongepowered.configurate.loader.ParsingException -import org.spongepowered.configurate.serialize.SerializationException -import org.spongepowered.configurate.serialize.TypeSerializer import org.spongepowered.configurate.serialize.TypeSerializerCollection import org.spongepowered.configurate.yaml.NodeStyle import org.spongepowered.configurate.yaml.YamlConfigurationLoader import java.io.File import java.io.FileOutputStream -import java.lang.reflect.Type import java.net.URL import java.nio.file.FileSystems import java.nio.file.Files @@ -31,6 +29,7 @@ abstract class YamlDirectoryRepository( private val ruleRegistry: RuleRegistry? = null ) : LoadableRepository { + private val logger = LoggerFactory.getLogger(javaClass) private val watchService = FileSystems.getDefault().newWatchService() private val loaders = mutableMapOf() protected val entities = mutableMapOf() @@ -39,6 +38,12 @@ abstract class YamlDirectoryRepository( abstract fun getFileName(identifier: I): String + /** + * Override to reject an otherwise well-formed entity. Return an error message to + * reject it, or null to accept it. + */ + protected open fun validate(entity: E): String? = null + override fun delete(element: E): Boolean { val file = entities.keys.find { entities[it] == element } ?: return false return deleteFile(file) @@ -65,19 +70,23 @@ abstract class YamlDirectoryRepository( } private fun load(file: File): E? { - try { + return try { val loader = getOrCreateLoader(file) val node = loader.load(ConfigurationOptions.defaults()) val entity = node.get(clazz) ?: return null - entities[file] = entity - return entity - } catch (ex: ParsingException) { - val existedBefore = entities.containsKey(file) - if (existedBefore) { + + val validationError = validate(entity) + if (validationError != null) { + logger.error("Skipping invalid config file '{}': {}", file.name, validationError) + entities.remove(file) return null } - return null + entities[file] = entity + entity + } catch (ex: ConfigurateException) { + logger.error("Failed to load config file '{}': {}", file.name, ex.message) + null } } @@ -106,21 +115,7 @@ abstract class YamlDirectoryRepository( serializers?.let { builder.registerAll(it) } ruleRegistry?.let { registry -> - builder.register(TypeToken.get(SignRule::class.java), object : TypeSerializer { - override fun deserialize(type: Type, node: ConfigurationNode): SignRule { - val ruleName = - node.string ?: throw SerializationException("Rule name cannot be null") - - return registry.getRule(ruleName) - ?: throw SerializationException("Unknown rule: $ruleName") - } - - override fun serialize(type: Type, obj: SignRule?, node: ConfigurationNode) { - if (obj != null) { - node.set(obj.getRuleName()) - } - } - }) + builder.register(TypeToken.get(SignRule::class.java), SignRuleSerializer(registry)) } builder.registerAnnotatedObjects(objectMapperFactory()) @@ -222,4 +217,4 @@ abstract class YamlDirectoryRepository( e.printStackTrace() } } -} \ No newline at end of file +} diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/layout/LayoutRepository.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/layout/LayoutRepository.kt index 78bd45d..beac775 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/layout/LayoutRepository.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/repository/layout/LayoutRepository.kt @@ -8,8 +8,8 @@ import java.nio.file.Path @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") class LayoutRepository( directoryPath: Path, - -) : YamlDirectoryRepository(directoryPath, LayoutConfig::class.java) { + private val ruleRegistry: RuleRegistry, +) : YamlDirectoryRepository(directoryPath, LayoutConfig::class.java, ruleRegistry) { override fun save(element: LayoutConfig) { save(getFileName(element.name), element) @@ -22,4 +22,11 @@ class LayoutRepository( override fun find(name: String): LayoutConfig? { return entities.values.find { it.name == name } } + + override fun validate(entity: LayoutConfig): String? { + if (ruleRegistry.getRule(entity.ruleName) == null) { + return "unknown rule '${entity.ruleName}'" + } + return null + } } \ No newline at end of file diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/sender/SignCommandSender.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/sender/SignCommandSender.kt index 010d09e..599e895 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/sender/SignCommandSender.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/sender/SignCommandSender.kt @@ -9,4 +9,6 @@ interface SignCommandSender { suspend fun getTargetBlock(maxDistance: Int): SignLocation? + suspend fun teleport(location: SignLocation): Boolean + } \ No newline at end of file diff --git a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/utils/SignCommandMessages.kt b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/utils/SignCommandMessages.kt index 3f1e652..b7d2b41 100644 --- a/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/utils/SignCommandMessages.kt +++ b/sign-shared/src/main/kotlin/app/simplecloud/plugin/sign/shared/utils/SignCommandMessages.kt @@ -26,6 +26,8 @@ object SignCommandMessages { "$PREFIX Successfully removed sign(s) of group ." const val GENERAL_ERROR = "$PREFIX An error occurred while processing your request." + const val TP_FAILED = + "$PREFIX Unable to teleport you there." const val NO_PENDING_COMMAND = "$PREFIX You have no pending command to confirm."