diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/Rebar.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/Rebar.kt index 31fc213dc..ccfd9b429 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/Rebar.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/Rebar.kt @@ -54,6 +54,7 @@ import kotlinx.coroutines.launch import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.NamespacedKey +import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.entity.BlockDisplay import org.bukkit.entity.FallingBlock import org.bukkit.entity.Interaction @@ -95,10 +96,21 @@ object Rebar : JavaPlugin(), RebarAddon { logger.severe("!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!") logger.severe("You are running Rebar on Minecraft version $actualVersion") logger.severe("This build of Rebar expects Minecraft version $expectedVersion") - logger.severe("Rebar may run fine, but you may encounter bugs ranging from mild to catastrophic") - logger.severe("Please update your Rebar version accordingly") logger.severe("Please see https://github.com/pylonmc/rebar/releases for available Rebar versions") + try { + if (RebarConfig.BYPASS_VERSION_CHECK) { + logger.severe("Bypass version set to true in config; proceeding anyway") + } else { + logger.severe("Rebar will refuse to start") + logger.severe("You can attempt to start anyway by setting bypass-version-check to true in the config") + } + } catch (e: Exception){ + throw RuntimeException("Error while getting value of bypass-version-check", e) + } logger.severe("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + if (!RebarConfig.BYPASS_VERSION_CHECK) { + throw RuntimeException("The server is running $actualVersion but Rebar expected $expectedVersion") + } } InvUI.getInstance().setPlugin(this) @@ -274,10 +286,6 @@ object Rebar : JavaPlugin(), RebarAddon { ) addDefaultPermission("rebar.command.guide") - addDefaultPermission("rebar.command.waila") - addDefaultPermission("rebar.command.research.list.self") - addDefaultPermission("rebar.command.research.discover") - addDefaultPermission("rebar.command.research.points.query.self") lifecycleManager.registerEventHandler(LifecycleEvents.COMMANDS) { it.registrar().register(ROOT_COMMAND) it.registrar().register(ROOT_COMMAND_RE_ALIAS) @@ -404,10 +412,7 @@ object Rebar : JavaPlugin(), RebarAddon { override val material = Material.BEDROCK - override val languages: Set = setOf( - Locale.ENGLISH, - Locale.of("enws") - ) + override val defaultLanguage: Locale = RebarConfig.DEFAULT_LANGUAGE } private fun addDefaultPermission(permission: String) { diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/addon/RebarAddon.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/addon/RebarAddon.kt index acbcc0ba0..321a1be73 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/addon/RebarAddon.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/addon/RebarAddon.kt @@ -18,7 +18,9 @@ import org.bukkit.event.Listener import org.bukkit.event.server.PluginDisableEvent import org.bukkit.plugin.java.JavaPlugin import org.jetbrains.annotations.ApiStatus +import java.io.File import java.util.Locale +import java.util.jar.JarFile /** * Welcome to the place where it all begins: the Rebar addon! @@ -31,14 +33,16 @@ interface RebarAddon : Keyed { val javaPlugin: JavaPlugin /** - * The set of [Locale]s this addon has translations for. + * The material to represent this addon in menus. */ - val languages: Set + val material: Material /** - * The material to represent this addon in menus. + * The language to fall back to if a language entry is not found for the user's language. + * + * It is recommended to make this configurable in your addon's config.yml */ - val material: Material + val defaultLanguage: Locale /** * The name used to represent this addon in the guide and other places. @@ -77,7 +81,7 @@ interface RebarAddon : Keyed { RebarRegistry.ADDONS.register(this) if (!suppressAddonNameWarning) { - for (locale in languages) { + for (locale in translator.languages) { if (!translator.canTranslate("${key.namespace}.addon", locale)) { Rebar.logger.warning("${key.namespace} is missing the 'addon' translation key for ${locale.displayName}") } diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidBufferRebarBlock.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidBufferRebarBlock.kt index 52b9bba59..f1154e554 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidBufferRebarBlock.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidBufferRebarBlock.kt @@ -45,6 +45,7 @@ interface FluidBufferRebarBlock : FluidRebarBlock { * @param output whether this buffer can be taken from by fluid output points */ fun createFluidBuffer(fluid: RebarFluid, capacity: Double, input: Boolean, output: Boolean) { + check(fluid !in fluidBuffers) { "Fluid $fluid already has a buffer" } fluidBuffers[fluid] = FluidBufferData(0.0, capacity, input, output) } diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidTankRebarBlock.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidTankRebarBlock.kt index d8cee9941..30f246778 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidTankRebarBlock.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/FluidTankRebarBlock.kt @@ -62,7 +62,7 @@ interface FluidTankRebarBlock : FluidRebarBlock { get() = fluidData.capacity - fluidData.amount /** - * Sets the type of fluid in the fluid tank + * Sets the type of fluid in the fluid tank. */ fun setFluidType(fluid: RebarFluid?) { fluidData.fluid = fluid diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/GuiRebarBlock.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/GuiRebarBlock.kt index 9284e07fc..09f42846d 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/GuiRebarBlock.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/GuiRebarBlock.kt @@ -7,6 +7,7 @@ import io.github.pylonmc.rebar.event.RebarBlockLoadEvent import io.github.pylonmc.rebar.event.RebarBlockPlaceEvent import io.github.pylonmc.rebar.event.RebarBlockUnloadEvent import net.kyori.adventure.text.Component +import org.bukkit.entity.Player import org.bukkit.event.Event import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority @@ -31,16 +32,44 @@ import java.util.IdentityHashMap */ interface GuiRebarBlock : NoVanillaInventoryRebarBlock { + /** + * The title of the GUI + */ + val guiTitle: Component + get() = (this as RebarBlock).nameTranslationKey + /** * Returns the block's GUI. Called when a block is created. */ fun createGui(): Gui /** - * The title of the GUI + * Refreshes the stores GUI by calling [createGui] again. + * + * If players have the GUI already open, it will be closed and then re-opened with the + * new GUI manually. + * + * Strongly consider [updating individual items](https://docs.xenondevs.xyz/invui/item/) + * before you use this method, to prevent having to constantly close and re-open windows. */ - val guiTitle: Component - get() = (this as RebarBlock).nameTranslationKey + fun refreshGui() { + val oldGui = guiBlocks[this] + val players = oldGui?.windows?.map { it.viewer } ?: emptyList() + oldGui?.windows?.forEach { it.close() } + guiBlocks[this] = createGui() + for (player in players) { + open(player) + } + } + + fun open(player: Player) { + Window.builder() + .setUpperGui(guiBlocks[this]!!) + .setTitle(guiTitle) + .setViewer(player) + .build() + .open() + } companion object : Listener { private val guiBlocks = IdentityHashMap() @@ -74,12 +103,7 @@ interface GuiRebarBlock : NoVanillaInventoryRebarBlock { event.setUseInteractedBlock(Event.Result.DENY) event.setUseItemInHand(Event.Result.DENY) - Window.builder() - .setUpperGui(guiBlocks[guiBlock]!!) - .setTitle(guiBlock.guiTitle) - .setViewer(event.player) - .build() - .open() + guiBlock.open(event.player) } @EventHandler diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/command/RebarCommand.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/command/RebarCommand.kt index bb602bd82..2d3627f78 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/command/RebarCommand.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/command/RebarCommand.kt @@ -18,6 +18,7 @@ import io.github.pylonmc.rebar.content.guide.RebarGuide import io.github.pylonmc.rebar.entity.display.transform.Rotation import io.github.pylonmc.rebar.gametest.GameTestConfig import io.github.pylonmc.rebar.i18n.RebarArgument +import io.github.pylonmc.rebar.i18n.RebarTranslator.Companion.translator import io.github.pylonmc.rebar.i18n.customMiniMessage import io.github.pylonmc.rebar.item.ItemTypeWrapper import io.github.pylonmc.rebar.item.RebarItem @@ -647,6 +648,7 @@ private val fillMultiblock = buildCommand("fillmultiblock") { } private val versions = buildCommand("versions") { + permission("rebar.command.versions") executes { sender -> RebarMetrics.onCommandRun("/rb versions") val serverImplementation = Bukkit.getName() @@ -678,6 +680,17 @@ private val versions = buildCommand("versions") { } } +private val reloadlang = buildCommand("reloadlang") { + permission("rebar.command.reloadlang") + executes { sender -> + RebarMetrics.onCommandRun("/rb reloadlang") + for (addon in RebarRegistry.ADDONS) { + addon.translator.reload() + } + sender.sendFeedback("reloadlang.success") + } +} + @JvmSynthetic internal val ROOT_COMMAND = buildCommand("rebar") { permission("rebar.command.guide") @@ -699,6 +712,7 @@ internal val ROOT_COMMAND = buildCommand("rebar") { then(confetti) then(fillMultiblock) then(versions) + then(reloadlang) } @JvmSynthetic diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/RebarConfig.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/RebarConfig.kt index d1d336472..a0e942398 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/RebarConfig.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/RebarConfig.kt @@ -12,6 +12,12 @@ object RebarConfig { private val config = ConfigSection.copyResource(Rebar, "config.yml") + @JvmField + val BYPASS_VERSION_CHECK = config.getOrThrow("bypass-version-check", ConfigAdapter.BOOLEAN) + + @JvmField + val DEFAULT_LANGUAGE = config.getOrThrow("default-language", ConfigAdapter.LOCALE) + @JvmField val DEFAULT_TICK_INTERVAL = config.getOrThrow("default-tick-interval", ConfigAdapter.INTEGER) diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/adapter/ConfigAdapter.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/adapter/ConfigAdapter.kt index 88e9a115b..a0d8f255b 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/adapter/ConfigAdapter.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/config/adapter/ConfigAdapter.kt @@ -15,6 +15,7 @@ import org.joml.Vector3d import org.joml.Vector3f import org.joml.Vector3i import java.lang.reflect.Type +import java.util.Locale interface ConfigAdapter { @@ -53,6 +54,7 @@ interface ConfigAdapter { @JvmField val ITEM_TYPE_WRAPPER = KEYED.fromGetter { ItemTypeWrapper(it) } @JvmField val ITEM_STACK = ItemStackConfigAdapter @JvmField val BLOCK_DATA = ConfigAdapter { Bukkit.createBlockData(STRING.convert(it)) } + @JvmField val LOCALE = ConfigAdapter { Locale.of(STRING.convert(it)) } @JvmField val VECTOR_2I = ConfigAdapter { val list = (it as List<*>).filterIsInstance() diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/fluid/RebarFluid.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/fluid/RebarFluid.kt index 0fd188b30..45af0fe28 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/fluid/RebarFluid.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/fluid/RebarFluid.kt @@ -62,7 +62,7 @@ open class RebarFluid( init { if (key !in nameWarningsSuppressed) { - for (locale in addon.languages) { + for (locale in addon.translator.languages) { val translationKey = "${key.namespace}.fluid.${key.key}" if (!addon.translator.canTranslate(translationKey, locale)) { Rebar.logger.warning("${key.namespace} is missing a translation key for fluid ${key.key} (locale: ${locale.displayName} | expected translation key: $translationKey)") diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/guide/button/ItemButton.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/guide/button/ItemButton.kt index f144b2d07..f140780e4 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/guide/button/ItemButton.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/guide/button/ItemButton.kt @@ -67,7 +67,7 @@ class ItemButton private constructor( builder.set(DataComponentTypes.ITEM_MODEL, Material.STRUCTURE_VOID.key) } - if (!player.canCraft(itemSchema, respectBypass = false)) { + if (!player.canCraft(itemSchema)) { builder.set(DataComponentTypes.ITEM_MODEL, Material.BARRIER.key) .set(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, false) @@ -99,7 +99,7 @@ class ItemButton private constructor( } if (player.guideHints) { - if (!player.canCraft(itemSchema, respectBypass = false)) { + if (!player.canCraft(itemSchema)) { builder.lore(Component.translatable("rebar.guide.button.item.hints.unresearched")) } } diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarMiniMessage.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarMiniMessage.kt index 604b07188..4d9c4add9 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarMiniMessage.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarMiniMessage.kt @@ -28,10 +28,11 @@ import org.bukkit.NamespacedKey * * ### Custom Tags * - ``|`` - Inserts a right arrow (→) with the specified color (default: 0x666666) - * - ` - Shorthand for `` + * - ` - Shorthand for `` * - ``|`` - Inserts a diamond (◆) with the specified color (default: 0x666666) * - ``|`` - Inserts a star (★) with the specified color (default: [NamedTextColor.BLUE]) * - `` - Applies a yellow styling (0xf9d104), used for instructions + * - `` - Applies a light purple styling (0xeac5f4), used for guide hints * - `` - Applies a purple styling (0xc907f4), used for guide instructions * - `` - Applies a cyan styling (0xa9d9e8), used for attributes * - `` - Formats a **constant** number as a unit, with an optional metric prefix @@ -55,10 +56,11 @@ val customMiniMessage = MiniMessage.builder() it.tag("diamond", ::diamond) it.tag("star", ::star) it.tag("insn") { _, _ -> Tag.styling(TextColor.color(0xf9d104)) } + it.tag("guidehint") { _, _ -> Tag.styling(TextColor.color(0xeac5f4), TextDecoration.ITALIC) } it.tag("guideinsn") { _, _ -> Tag.styling(TextColor.color(0xc907f4)) } it.tag("story") { _, _ -> Tag.styling { builder -> - builder.color(TextColor.color(0xcc9bf2)).decorate(TextDecoration.ITALIC) + builder.color(TextColor.color(0xde76e0)).decorate(TextDecoration.ITALIC) } } it.tag("attr") { _, _ -> Tag.styling(TextColor.color(0xa9d9e8)) } @@ -79,7 +81,7 @@ private fun arrow(args: ArgumentQueue, @Suppress("unused") ctx: Context): Tag { } private fun guidearrow(args: ArgumentQueue, @Suppress("unused") ctx: Context): Tag { - val color = TextColor.color(0x3a293) + val color = TextColor.color(0x653d6d) return Tag.selfClosingInserting(Component.text("\u2192").color(color)) } diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarTranslator.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarTranslator.kt index 50b8ee9eb..8c5e97d17 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarTranslator.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/i18n/RebarTranslator.kt @@ -26,6 +26,7 @@ import net.kyori.adventure.text.format.Style import net.kyori.adventure.translation.GlobalTranslator import net.kyori.adventure.translation.Translator import org.apache.commons.lang3.LocaleUtils +import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.NamespacedKey import org.bukkit.event.EventHandler @@ -35,8 +36,10 @@ import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerLocaleChangeEvent import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.inventory.ItemStack +import java.io.File import java.text.MessageFormat import java.util.* +import java.util.jar.JarFile import kotlin.io.path.exists import kotlin.io.path.listDirectoryEntries import kotlin.io.path.nameWithoutExtension @@ -52,7 +55,7 @@ class RebarTranslator private constructor(private val addon: RebarAddon) : Trans private val addonNamespace = addon.key.namespace - private val translations: Map + private val translations: MutableMap = mutableMapOf() val languages: Set get() = translations.keys @@ -60,24 +63,41 @@ class RebarTranslator private constructor(private val addon: RebarAddon) : Trans private val translationCache = mutableMapOf, Component>() init { - for (lang in addon.languages) { - mergeResource(addon, "lang/$lang.yml", "lang/$addonNamespace/$lang.yml") - } + // Copy builtin language files + val jarFile = JarFile(File(addon.javaClass.protectionDomain.codeSource.location.toURI())) + jarFile.stream() + .filter { it.name.startsWith("lang/") && it.name.endsWith(".yml") } + .map { it.name.removePrefix("lang/") } + .forEach { file -> mergeResource(addon, "lang/$file", "lang/$addonNamespace/$file") } + + loadTranslations() + } + + private fun loadTranslations() { val langsDir = Rebar.dataPath.resolve("lang").resolve(addonNamespace) - translations = if (!langsDir.exists()) { - emptyMap() - } else { - langsDir.listDirectoryEntries("*.yml").associate { + if (langsDir.exists()) { + langsDir.listDirectoryEntries("*.yml").forEach { val split = it.nameWithoutExtension.split('_', limit = 3) - Locale.of( + val locale = Locale.of( split.first(), split.getOrNull(1).orEmpty(), split.getOrNull(2).orEmpty() - ) to ConfigSection.fromOrThrow(it) + ) + val config = ConfigSection.fromOrThrow(it) + translations[locale] = config } } } + fun reload() { + translationCache.clear() + translations.clear() + loadTranslations() + for (player in Bukkit.getOnlinePlayers()) { + NmsAccessor.instance.resendInventory(player) + } + } + override fun canTranslate(key: String, locale: Locale): Boolean { return getRawTranslation(key, locale) != null } @@ -114,7 +134,7 @@ class RebarTranslator private constructor(private val addon: RebarAddon) : Trans if (parts.size < 2) return null val (addon, key) = parts if (addon != addonNamespace) return null - val translations = findTranslations(locale) ?: return null + val translations = findTranslations(locale) ?: findTranslations(this.addon.defaultLanguage) ?: return null val translation = translations.get(key, ConfigAdapter.STRING) ?: return null customMiniMessage.deserialize(translation) } @@ -130,7 +150,6 @@ class RebarTranslator private constructor(private val addon: RebarAddon) : Trans .sortedByDescending { it.weight } } return Locale.lookup(languageRange, this.translations.keys)?.let(translations::get) - ?: findTranslations(addon.languages.first()) } override fun name(): Key = addon.key @@ -151,7 +170,7 @@ class RebarTranslator private constructor(private val addon: RebarAddon) : Trans @get:JvmName("getTranslatorForAddon") val RebarAddon.translator: RebarTranslator get() = translators[this.key] - ?: error("Addon does not have a translator; did you forget to call registerWithRebar()?") + ?: error("Addon ${this.key} does not have a translator; did you forget to call registerWithRebar()?") /** * Modifies the [ItemStack] to translate its name and lore into the specified [locale]. diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItem.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItem.kt index a0648d625..a310e2d2d 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItem.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItem.kt @@ -4,7 +4,6 @@ import io.github.pylonmc.rebar.Rebar import io.github.pylonmc.rebar.block.RebarBlock import io.github.pylonmc.rebar.block.context.BlockCreateContext import io.github.pylonmc.rebar.config.ConfigSection -import io.github.pylonmc.rebar.config.RebarConfig import io.github.pylonmc.rebar.config.adapter.ConfigAdapter import io.github.pylonmc.rebar.datatypes.RebarSerializers import io.github.pylonmc.rebar.entity.RebarEntity @@ -40,7 +39,6 @@ open class RebarItem(val stack: ItemStack) : Keyed { */ val schema = RebarRegistry.ITEMS.getOrThrow(key) - val researchBypassPermission = schema.researchBypassPermission val addon = schema.addon val rebarBlock = schema.rebarBlockKey val isDisabled = schema.isDisabled @@ -117,7 +115,7 @@ open class RebarItem(val stack: ItemStack) : Keyed { if (isNameValid) { val translator = schema.addon.translator - for (locale in schema.addon.languages) { + for (locale in schema.addon.translator.languages) { if (!translator.canTranslate(name!!.key(), locale)) { Rebar.logger.warning( "${schema.key.namespace} is missing a name translation key for item ${schema.key} (locale: ${locale.displayName} | expected translation key: ${ diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItemSchema.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItemSchema.kt index ebc901f7b..5ddd26730 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItemSchema.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/RebarItemSchema.kt @@ -13,7 +13,6 @@ import io.github.pylonmc.rebar.util.findConstructorMatching import io.github.pylonmc.rebar.util.getAddon import io.github.pylonmc.rebar.util.position.position import io.github.pylonmc.rebar.util.rebarKey -import io.papermc.paper.command.brigadier.argument.ArgumentTypes.blockPosition import org.bukkit.Keyed import org.bukkit.NamespacedKey import org.bukkit.inventory.ItemStack @@ -64,8 +63,6 @@ class RebarItemSchema @JvmOverloads internal constructor( val research: Research? get() = RebarRegistry.RESEARCHES.find { key in it.unlocks } - val researchBypassPermission = "rebar.item.${key.namespace}.${key.key}" - @JvmSynthetic internal val loadConstructor: MethodHandle = itemClass.findConstructorMatching(ItemStack::class.java) ?: throw NoSuchMethodException("Item '$key' (${itemClass.simpleName}) is missing a load constructor (ItemStack)") diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/research/Research.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/research/Research.kt index 6c4e87ddb..65ec692a9 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/research/Research.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/item/research/Research.kt @@ -193,14 +193,14 @@ class Research( @JvmStatic @JvmOverloads @JvmName("canPlayerCraft") - fun Player.canCraft(item: RebarItem, sendMessage: Boolean = false, respectBypass: Boolean = true): Boolean - = canCraft(item.schema, sendMessage, respectBypass) + fun Player.canCraft(item: RebarItem, sendMessage: Boolean = false): Boolean + = canCraft(item.schema, sendMessage) @JvmStatic @JvmOverloads @JvmName("canPlayerCraft") - fun Player.canCraft(key: NamespacedKey, sendMessage: Boolean = false, respectBypass: Boolean = true): Boolean - = RebarRegistry.ITEMS[key]?.let { canCraft(it, sendMessage, respectBypass) } ?: false + fun Player.canCraft(key: NamespacedKey, sendMessage: Boolean = false): Boolean + = RebarRegistry.ITEMS[key]?.let { canCraft(it, sendMessage) } ?: false /** * Checks whether a player can craft an item (ie has the associated research, or @@ -212,8 +212,8 @@ class Research( @JvmStatic @JvmOverloads @JvmName("canPlayerCraft") - fun Player.canCraft(schema: RebarItemSchema, sendMessage: Boolean = false, respectBypass: Boolean = true): Boolean { - if (!RebarConfig.ResearchConfig.ENABLED || (respectBypass && this.hasPermission(schema.researchBypassPermission))) return true + fun Player.canCraft(schema: RebarItemSchema, sendMessage: Boolean = false): Boolean { + if (!RebarConfig.ResearchConfig.ENABLED) return true val research = schema.research ?: return true diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/util/RebarUtils.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/util/RebarUtils.kt index a737b2f74..1a860b44a 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/util/RebarUtils.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/util/RebarUtils.kt @@ -473,10 +473,10 @@ val Player.pdc: PersistentDataContainer @JvmSynthetic internal fun mergeResource(fromAddon: RebarAddon, from: String, to: String, warnMissing: Boolean = true): ConfigSection { require(from.endsWith(".yml") || from.endsWith(".yaml")) { - "Config file must be a YAML file (addon: ${fromAddon.javaClass.simpleName}, path: $from" + "Config file must be a YAML file (addon: ${fromAddon.javaClass.simpleName}, path: $from)" } require(to.endsWith(".yml") || to.endsWith(".yaml")) { - "Config file must be a YAML file (addon: ${fromAddon.javaClass.simpleName}, path: $to" + "Config file must be a YAML file (addon: ${fromAddon.javaClass.simpleName}, path: $to)" } val cached = globalConfigCache[from to to] diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/waila/Waila.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/waila/Waila.kt index e8cafb9be..e578d0992 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/waila/Waila.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/waila/Waila.kt @@ -167,8 +167,16 @@ class Waila private constructor( this.targetEntity = null this.targetBlock = null - rayTraceResult?.hitEntity?.let { entity -> this.targetEntity = entity.uniqueId } - rayTraceResult?.hitBlock?.let { block -> this.targetBlock = block.position } + rayTraceResult?.hitEntity?.let { entity -> + if (entity.isValid) { + this.targetEntity = entity.uniqueId + } + } + rayTraceResult?.hitBlock?.let { block -> + if (!block.isEmpty) { // Not sure this is possible, but just in case + this.targetBlock = block.position + } + } updateContents() } diff --git a/rebar/src/main/resources/config.yml b/rebar/src/main/resources/config.yml index 92380e9a6..e37625a60 100644 --- a/rebar/src/main/resources/config.yml +++ b/rebar/src/main/resources/config.yml @@ -1,3 +1,10 @@ +# If set to true, Rebar will attempt to start even if the server is not running the expected Minecraft version +# It is recommended to take a backup before enabling this, just in case +bypass-version-check: false + +# The language to fall back to if a language entry is not found for the user's language +default-language: en + rebar-guide: # Should players be given the Rebar guide book when they first join? give-on-first-join: true diff --git a/rebar/src/main/resources/lang/en.yml b/rebar/src/main/resources/lang/en.yml index 2760fe67a..b102df4cb 100644 --- a/rebar/src/main/resources/lang/en.yml +++ b/rebar/src/main/resources/lang/en.yml @@ -63,6 +63,9 @@ message: unlocked: "You have discovered %research%" click_to_research: "Click to research (%points% points)" + waila: + type-disabled: "This server no longer permits the your previously set %type% WAILA display type, it has been reset to default" + command: error: no_permission: "You do not have permission to use this command" @@ -109,8 +112,8 @@ message: Installed Addons: (%addon_count%) %addon_list% - waila: - type-disabled: "This server no longer permits the your previously set %type% WAILA display type, it has been reset to default" + reloadlang: + success: "Language entries reloaded" gui: scroll: @@ -133,9 +136,7 @@ guide: back: name: "Back" hints: |- - - Hints - Shift left click to go to the main menu + Shift left click to go to the main menu watermelon item-recipes: "Recipe" machine-recipes: "Recipes made with this machine" search-specifiers: @@ -155,13 +156,11 @@ guide: hints: researched: |- - Hints - Right click to see unlocked items + Right click to see unlocked items unresearched: |- - Hints - Left click to research - Right click to see unlocked items + Left click to research + Right click to see unlocked items unlocks-title: |- Unlocks @@ -180,8 +179,7 @@ guide: hints: unresearched: |- - Hints - Shift left click to research + Shift left click to research error: "Item failed to load" amount: "%name%: %amount%%breakdown%" amount-breakdown: " (%stacks%x%stack-size% + %remainder%)" @@ -363,11 +361,11 @@ guide: enabled: name: "Guide Hints: Enabled (Click to toggle)" lore: |- - Whether to show hints in the guide + Whether to show guide hints disabled: name: "Guide Hints: Disabled (Click to toggle)" lore: |- - Whether to show hints in the guide + Whether to show hints toggle-guide-sounds: enabled: name: "Guide Sounds: Enabled (Click to toggle)" diff --git a/test/src/main/java/io/github/pylonmc/rebar/test/RebarTest.java b/test/src/main/java/io/github/pylonmc/rebar/test/RebarTest.java index 81aa9caa1..45a221d7c 100644 --- a/test/src/main/java/io/github/pylonmc/rebar/test/RebarTest.java +++ b/test/src/main/java/io/github/pylonmc/rebar/test/RebarTest.java @@ -199,11 +199,6 @@ public void onEnable() { return this; } - @Override - public @NotNull Set<@NotNull Locale> getLanguages() { - return Set.of(); - } - public static @NotNull NamespacedKey key(String key) { return new NamespacedKey(instance, key); } @@ -212,4 +207,9 @@ public void onEnable() { public @NotNull Material getMaterial() { return Material.WAXED_WEATHERED_CUT_COPPER_STAIRS; } + + @Override + public @NotNull Locale getDefaultLanguage() { + return Locale.of("none"); + } }