Skip to content
Merged
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Now it is possible to change Mimic config using commands in two ways:
- `/mimic config inventory-provider [value]` - set the specified inventory provider as preferred for Mimic
- `/mimic config disabled-items-registries add [item-registry]` - disable the specified item registry for Mimic
- `/mimic config disabled-items-registries remove [item-registry]` - enable the specified item registry for Mimic
- `/mimic config disabled-block-registries add [block-registry]` - disable the specified block registry for Mimic
- `/mimic config disabled-block-registries remove [block-registry]` - enable the specified block registry for Mimic
- `/mimic config reset [option]` - reset the specified option to its default value

Commands are now easier to use in general:
- `/mimic info` replaced with `/mimic`
Expand Down
1 change: 1 addition & 0 deletions mimic-api/api/mimic-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public abstract interface class ru/endlesscode/mimic/blocks/BlockRegistry : ru/e
public fun breakBlock (Ljava/lang/Object;)Z
public fun breakBlock (Ljava/lang/Object;Ljava/lang/Object;)Z
public abstract fun breakBlock (Ljava/lang/Object;Ljava/lang/Object;Lru/endlesscode/mimic/blocks/DropsConsumer;)Z
public static synthetic fun breakBlock$default (Lru/endlesscode/mimic/blocks/BlockRegistry;Ljava/lang/Object;Ljava/lang/Object;Lru/endlesscode/mimic/blocks/DropsConsumer;ILjava/lang/Object;)Z
public abstract fun getBlockId (Ljava/lang/Object;)Ljava/lang/String;
public abstract fun getBlockIdFromItem (Ljava/lang/Object;)Ljava/lang/String;
public abstract fun getKnownIds ()Ljava/util/Collection;
Expand Down
2 changes: 1 addition & 1 deletion mimic-api/src/main/kotlin/blocks/BlockRegistry.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,5 @@ public interface BlockRegistry<BlockT : Any, ItemStackT : Any> : MimicService {
*
* Returns `false` if the block can't be broken or doesn't belong to this registry.
*/
public fun breakBlock(block: BlockT, tool: ItemStackT?, dropsConsumer: DropsConsumer<ItemStackT>): Boolean
public fun breakBlock(block: BlockT, tool: ItemStackT? = null, dropsConsumer: DropsConsumer<ItemStackT>): Boolean
}
2 changes: 1 addition & 1 deletion mimic-bukkit/src/main/kotlin/MimicImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal class MimicImpl(
plugin: Plugin,
priority: ServicePriority
): BukkitBlockRegistry? = tryRegisterService<BukkitBlockRegistry>(apiLevel, plugin, priority) {
WrappedBlockRegistry(registry, plugin)
WrappedBlockRegistry(registry, config, plugin)
}

@ExperimentalMimicApi
Expand Down
9 changes: 7 additions & 2 deletions mimic-bukkit/src/main/kotlin/blocks/WrappedBlockRegistry.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ import org.bukkit.plugin.Plugin
import org.bukkit.plugin.PluginManager
import ru.endlesscode.mimic.ExperimentalMimicApi
import ru.endlesscode.mimic.WrappedMimicService
import ru.endlesscode.mimic.config.MimicConfig

@ExperimentalMimicApi
internal class WrappedBlockRegistry(
internal val delegate: BukkitBlockRegistry,
private val config: MimicConfig,
pluginName: String,
pluginManager: PluginManager,
) : WrappedMimicService(delegate, pluginName, pluginManager), BukkitBlockRegistry {

constructor(delegate: BukkitBlockRegistry, plugin: Plugin)
: this(delegate, plugin.name, plugin.server.pluginManager)
constructor(delegate: BukkitBlockRegistry, config: MimicConfig, plugin: Plugin)
: this(delegate, config, plugin.name, plugin.server.pluginManager)

override val isEnabled: Boolean
get() = super<WrappedMimicService>.isEnabled && id !in config.disabledBlockRegistries

override val knownIds: Collection<String> by delegate::knownIds

Expand Down
4 changes: 2 additions & 2 deletions mimic-bukkit/src/main/kotlin/command/BlocksSubcommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import ru.endlesscode.mimic.ExperimentalMimicApi
import ru.endlesscode.mimic.blocks.BukkitBlockRegistry
import ru.endlesscode.mimic.blocks.DropsConsumer
import ru.endlesscode.mimic.blocks.DropsConsumer.Companion.disappear
import ru.endlesscode.mimic.blocks.unwrap
import ru.endlesscode.mimic.impl.mimic.MimicBlockRegistry
import ru.endlesscode.mimic.impl.mimic.registry
Expand Down Expand Up @@ -157,7 +157,7 @@ private fun setExecutor(blockRegistry: BukkitBlockRegistry): CommandAction<Comma
val position = location.toPosition()
if (!blockRegistry.setBlock(target, block, payload)) {
// Replace existing block like vanilla /setblock does: break it without drops and set the new one
if (target.isEmpty || !blockRegistry.breakBlock(target, tool = null, DropsConsumer.disappear())) {
if (target.isEmpty || !blockRegistry.breakBlock(target, dropsConsumer = disappear())) {
throw commandError("Failed to set '$block' at $position.")
}
if (!blockRegistry.setBlock(target, block, payload)) {
Expand Down
36 changes: 36 additions & 0 deletions mimic-bukkit/src/main/kotlin/command/ConfigCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ru.endlesscode.mimic.config.MimicConfig
* /mimic config
* /mimic config [single-property] [value]
* /mimic config [collection-property] add|remove [value]
* /mimic config reset [property]
* ```
*/
internal fun CommandBuilder.configSubcommand(
Expand Down Expand Up @@ -71,6 +72,39 @@ internal fun CommandBuilder.configSubcommand(
}
}
}

// Enable/Disable a block registry in Mimic
@OptIn(ExperimentalMimicApi::class)
literal("disabled-block-registries") {
literal(ACTION_ADD) {
stringSetArgument(
BLOCK_REGISTRY,
"block registry",
{ mimic.getAllBlockRegistries().keys - MimicConfig.DEFAULT_BLOCK_REGISTRIES },
) { sender, blockRegistry ->
config.disabledBlockRegistries += blockRegistry
showConfig(sender)
}
}
literal(ACTION_REMOVE) {
stringSetArgument(BLOCK_REGISTRY, "disabled block registry", { config.disabledBlockRegistries }) { sender, blockRegistry ->
config.disabledBlockRegistries -= blockRegistry
showConfig(sender)
}
}
}

// Reset a property to its default value
literal(ACTION_RESET) {
for (property in MimicConfig.properties) {
literal(property.path) {
executesAny { sender, _ ->
config.reset(property)
showConfig(sender)
}
}
}
}
}

private fun CommandBuilder.stringSetArgument(
Expand All @@ -89,5 +123,7 @@ private fun CommandBuilder.stringSetArgument(

private const val VALUE = "value"
private const val ITEMS_REGISTRY = "items-registry"
private const val BLOCK_REGISTRY = "block-registry"
private const val ACTION_ADD = "add"
private const val ACTION_REMOVE = "remove"
internal const val ACTION_RESET = "reset"
26 changes: 25 additions & 1 deletion mimic-bukkit/src/main/kotlin/command/ConfigMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@ internal fun buildConfigMessage(mimic: Mimic, config: MimicConfig): TextComponen
appendHeader("Mimic Config")
appendSelectablePropertyConfig(
property = MimicConfig.LEVEL_SYSTEM,
configuredValue = config.levelSystem,
selectedOption = mimic.getLevelSystemProvider().id,
options = mimic.getAllLevelSystemProviders().keys,
)
appendSelectablePropertyConfig(
property = MimicConfig.CLASS_SYSTEM,
configuredValue = config.classSystem,
selectedOption = mimic.getClassSystemProvider().id,
options = mimic.getAllClassSystemProviders().keys,
)
appendSelectablePropertyConfig(
property = MimicConfig.INVENTORY_PROVIDER,
configuredValue = config.inventoryProvider,
selectedOption = mimic.getPlayerInventoryProvider().id,
options = mimic.getAllPlayerInventoryProviders().keys,
)
Expand All @@ -38,14 +41,22 @@ internal fun buildConfigMessage(mimic: Mimic, config: MimicConfig): TextComponen
options = mimic.getAllItemsRegistries().keys,
permanentOptions = MimicConfig.DEFAULT_ITEMS_REGISTRIES,
)
appendSetPropertyConfig(
property = MimicConfig.DISABLED_BLOCK_REGISTRIES,
values = config.disabledBlockRegistries,
options = mimic.getAllBlockRegistries().keys,
permanentOptions = MimicConfig.DEFAULT_BLOCK_REGISTRIES,
)
}

private fun TextComponent.Builder.appendSelectablePropertyConfig(
property: StringConfigProperty,
configuredValue: String,
selectedOption: String,
options: Set<String>,
) = appendProperty(property) {
val availableOptions = options - selectedOption
val isAutomatic = configuredValue.isEmpty()
val availableOptions = if (isAutomatic) options else options - selectedOption
if (availableOptions.isNotEmpty()) {
appendLine()
appendComment("Options: ")
Expand All @@ -60,6 +71,19 @@ private fun TextComponent.Builder.appendSelectablePropertyConfig(
appendLine()
appendPropertyPath(property)
append(selectedOption)
if (isAutomatic) {
append(" (auto)", NamedTextColor.GRAY)
} else {
append(" ")
append(text {
color(NamedTextColor.GRAY)
appendClickable(
ACTION_RESET,
hint = "Click to use the implementation with the highest priority",
command = "/$COMMAND_NAME config $ACTION_RESET ${property.path}",
)
})
}
}

private fun TextComponent.Builder.appendSetPropertyConfig(
Expand Down
31 changes: 29 additions & 2 deletions mimic-bukkit/src/main/kotlin/config/MimicConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class MimicConfig(
var classSystem: String by configuration.property(CLASS_SYSTEM)
var inventoryProvider: String by configuration.property(INVENTORY_PROVIDER)
var disabledItemsRegistries: Set<String> by configuration.property(DISABLED_ITEMS_REGISTRIES)
var disabledBlockRegistries: Set<String> by configuration.property(DISABLED_BLOCK_REGISTRIES)

constructor(plugin: Plugin) : this(plugin.toString(), File(plugin.dataFolder, "config.yml"))

Expand All @@ -29,7 +30,7 @@ internal class MimicConfig(
pluginName,
"",
"Here you can configure Mimic APIs.",
"Use command '/mimic info' to list available implementations.",
"Use command '/mimic' to list available implementations.",
)
properties.forEach(::addDefault)
}
Expand Down Expand Up @@ -58,6 +59,20 @@ internal class MimicConfig(
if (notDisabledRegistries.isNotEmpty()) {
Log.w("Config: Items registries $notDisabledRegistries can not be disabled. It will be removed from config.")
}

val configuredDisabledBlockRegistries = disabledBlockRegistries
disabledBlockRegistries = configuredDisabledBlockRegistries - DEFAULT_BLOCK_REGISTRIES

val notDisabledBlockRegistries = configuredDisabledBlockRegistries - disabledBlockRegistries
if (notDisabledBlockRegistries.isNotEmpty()) {
Log.w("Config: Block registries $notDisabledBlockRegistries can not be disabled. It will be removed from config.")
}
}

/** Resets the given [property] to its default value. */
fun reset(property: ConfigProperty<*>) {
configuration.set(property.path, property.defaultValue)
save()
}

fun save() {
Expand Down Expand Up @@ -87,6 +102,7 @@ internal class MimicConfig(
"If the value is empty, will be used implementation with the highest priority."

val DEFAULT_ITEMS_REGISTRIES = setOf("mimic", "minecraft")
val DEFAULT_BLOCK_REGISTRIES = DEFAULT_ITEMS_REGISTRIES

val LEVEL_SYSTEM = StringConfigProperty(
path = "level-system",
Expand Down Expand Up @@ -122,11 +138,22 @@ internal class MimicConfig(
),
)

private val properties = listOf(
val DISABLED_BLOCK_REGISTRIES = StringSetConfigProperty(
path = "disabled-block-registries",
title = "BlockRegistry API",
comments = arrayOf(
"List here disabled block registry implementations.",
"You can't disable 'mimic' and 'minecraft' block registries.",
"By default, all implementations are enabled.",
),
)

val properties = listOf(
LEVEL_SYSTEM,
CLASS_SYSTEM,
INVENTORY_PROVIDER,
DISABLED_ITEMS_REGISTRIES,
DISABLED_BLOCK_REGISTRIES,
)
}
}
48 changes: 48 additions & 0 deletions mimic-bukkit/src/test/kotlin/config/MimicConfigTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ru.endlesscode.mimic.config

import io.kotest.matchers.collections.shouldBeEmpty
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldBeEmpty
import org.junit.jupiter.api.io.TempDir
import ru.endlesscode.mimic.BukkitTestBase
import java.io.File
import kotlin.test.Test

internal class MimicConfigTest : BukkitTestBase() {

@TempDir
lateinit var directory: File

private val file: File get() = File(directory, "config.yml")

private fun loadConfig() = MimicConfig("Mimic", file)

@Test
fun `when load disabled block registries - should remove default registries`() {
file.writeText("disabled-block-registries: [custom, minecraft, mimic]\n")

loadConfig().disabledBlockRegistries shouldBe setOf("custom")
}

@Test
fun `when reset string property - should save empty value`() {
val config = loadConfig()
config.levelSystem = "custom"

config.reset(MimicConfig.LEVEL_SYSTEM)

config.levelSystem.shouldBeEmpty()
loadConfig().levelSystem.shouldBeEmpty()
}

@Test
fun `when reset set property - should save empty set`() {
val config = loadConfig()
config.disabledBlockRegistries = setOf("custom")

config.reset(MimicConfig.DISABLED_BLOCK_REGISTRIES)

config.disabledBlockRegistries.shouldBeEmpty()
loadConfig().disabledBlockRegistries.shouldBeEmpty()
}
}
27 changes: 25 additions & 2 deletions mimic-bukkit/src/test/kotlin/impl/mimic/MimicBlockRegistryTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import ru.endlesscode.mimic.ExperimentalMimicApi
import ru.endlesscode.mimic.blocks.BukkitBlockRegistry
import ru.endlesscode.mimic.blocks.DropsConsumer
import ru.endlesscode.mimic.blocks.WrappedBlockRegistry
import ru.endlesscode.mimic.config.MimicConfig
import ru.endlesscode.mimic.internal.parseKey
import kotlin.test.Test

Expand Down Expand Up @@ -203,6 +204,22 @@ internal class MimicBlockRegistryTest : BukkitTestBase() {
}
}

@Test
fun `when registry is disabled in config - should ignore it`() {
servicesManager.unregister(customRegistry)
servicesManager.register(
BukkitBlockRegistry::class.java,
wrap(customRegistry, disabledRegistries = setOf(customRegistry.id)),
plugin,
Normal,
)

assertSoftly {
blockRegistry.isBlockExists("custom:ruby_block").shouldBeFalse()
blockRegistry.getBlockId(mockBlock(Material.NOTE_BLOCK)) shouldBe "minecraft:note_block"
}
}

@Test
fun `when break block with disappearing drops - should not drop items`() {
blockRegistry.breakBlock(mockBlock(Material.STONE), tool = null, DropsConsumer.disappear()).shouldBeTrue()
Expand Down Expand Up @@ -259,11 +276,17 @@ internal class MimicBlockRegistryTest : BukkitTestBase() {
every { isEmpty } returns (material == Material.AIR)
}

private fun wrap(registry: BukkitBlockRegistry): BukkitBlockRegistry {
private fun wrap(
registry: BukkitBlockRegistry,
disabledRegistries: Set<String> = emptySet(),
): BukkitBlockRegistry {
val pluginManager = mockk<PluginManager> {
every { isPluginEnabled(any<String>()) } returns true
}
return WrappedBlockRegistry(registry, "Mimic", pluginManager)
val config = mockk<MimicConfig> {
every { disabledBlockRegistries } returns disabledRegistries
}
return WrappedBlockRegistry(registry, config, "Mimic", pluginManager)
}
}

Expand Down
Loading