diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/PylonCore.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/PylonCore.kt index 25740d7d7..906e000a3 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/PylonCore.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/PylonCore.kt @@ -117,7 +117,7 @@ object PylonCore : JavaPlugin(), PylonAddon { Bukkit.getPluginManager().registerEvents(BlockListener, this) Bukkit.getPluginManager().registerEvents(PylonCopperBlock, this) Bukkit.getPluginManager().registerEvents(PylonItemListener, this) - Bukkit.getScheduler().runTaskTimer(this, PylonInventoryTicker(), 0, PylonConfig.inventoryTickerBaseRate) + Bukkit.getScheduler().runTaskTimer(this, PylonInventoryTicker(), 0, PylonConfig.INVENTORY_TICKER_BASE_RATE) Bukkit.getPluginManager().registerEvents(MultiblockCache, this) Bukkit.getPluginManager().registerEvents(EntityStorage, this) Bukkit.getPluginManager().registerEvents(EntityListener, this) @@ -130,6 +130,7 @@ object PylonCore : JavaPlugin(), PylonAddon { Bukkit.getPluginManager().registerEvents(PylonFluidBufferBlock, this) Bukkit.getPluginManager().registerEvents(PylonFluidTank, this) Bukkit.getPluginManager().registerEvents(PylonRecipeListener, this) + Bukkit.getPluginManager().registerEvents(PylonDirectionalBlock, this) Bukkit.getPluginManager().registerEvents(FluidPipePlacementService, this) Bukkit.getPluginManager().registerEvents(PylonTickingBlock, this) Bukkit.getPluginManager().registerEvents(PylonGuide, this) @@ -145,8 +146,8 @@ object PylonCore : JavaPlugin(), PylonAddon { PylonGuide.settingsPage.addSetting(PageButton(PlayerSettingsPage.resourcePackSettings)) - if (PylonConfig.ArmorTextureConfig.enabled) { - if (!PylonConfig.ArmorTextureConfig.forced) { + if (PylonConfig.ArmorTextureConfig.ENABLED) { + if (!PylonConfig.ArmorTextureConfig.FORCED) { PlayerSettingsPage.resourcePackSettings.addSetting(TogglePlayerSettingButton( pylonKey("toggle-armor-textures"), toggle = { player -> player.hasCustomArmorTextures = !player.hasCustomArmorTextures }, @@ -156,13 +157,13 @@ object PylonCore : JavaPlugin(), PylonAddon { packetEvents.eventManager.registerListener(ArmorTextureEngine, PacketListenerPriority.HIGHEST) } - if (PylonConfig.BlockTextureConfig.enabled) { + if (PylonConfig.BlockTextureConfig.ENABLED) { PlayerSettingsPage.resourcePackSettings.addSetting(PageButton(PlayerSettingsPage.blockTextureSettings)) Bukkit.getPluginManager().registerEvents(BlockTextureEngine, this) BlockTextureEngine.updateOccludingCacheJob.start() } - if (PylonConfig.researchesEnabled) { + if (PylonConfig.RESEARCHES_ENABLED) { PylonGuide.settingsPage.addSetting(PlayerSettingsPage.researchConfetti) PylonGuide.settingsPage.addSetting(PlayerSettingsPage.researchSounds) } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockListener.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockListener.kt index bbfbfa8cb..2ef627927 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockListener.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockListener.kt @@ -858,7 +858,7 @@ internal object BlockListener : Listener { } e.printStackTrace() blockErrMap[block] = blockErrMap[block]?.plus(1) ?: 1 - if (blockErrMap[block]!! > PylonConfig.allowedBlockErrors) { + if (blockErrMap[block]!! > PylonConfig.ALLOWED_BLOCK_ERRORS) { BlockStorage.makePhantom(block) if (block is PylonTickingBlock) { PylonTickingBlock.stopTicking(block) diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockStorage.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockStorage.kt index 414271456..106eafe8d 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockStorage.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/BlockStorage.kt @@ -465,7 +465,7 @@ object BlockStorage : Listener { chunkAutosaveTasks[event.chunk.position] = PylonCore.launch(PylonCore.minecraftDispatcher) { // Wait a random delay before starting, this is to help smooth out lag from saving - delay(Random.nextLong(PylonConfig.blockDataAutosaveIntervalSeconds * 1000)) + delay(Random.nextLong(PylonConfig.BLOCK_DATA_AUTOSAVE_INTERVAL_SECONDS * 1000)) while (true) { lockBlockRead { @@ -473,7 +473,7 @@ object BlockStorage : Listener { check(blocksInChunk != null) { "Block autosave task was not cancelled properly" } save(event.chunk, blocksInChunk) } - delay(PylonConfig.blockDataAutosaveIntervalSeconds * 1000) + delay(PylonConfig.BLOCK_DATA_AUTOSAVE_INTERVAL_SECONDS * 1000) } } } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/PylonBlock.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/PylonBlock.kt index e494332a0..8677ad4a7 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/PylonBlock.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/PylonBlock.kt @@ -90,7 +90,7 @@ open class PylonBlock internal constructor(val block: Block) { * can actually see it. */ open val blockTextureEntity: BlockTextureEntity? by lazy { - if (!PylonConfig.BlockTextureConfig.enabled || disableBlockTextureEntity) { + if (!PylonConfig.BlockTextureConfig.ENABLED || disableBlockTextureEntity) { null } else { val entity = BlockTextureEntity(this) @@ -215,10 +215,7 @@ open class PylonBlock internal constructor(val block: Block) { open fun getBlockTextureProperties(): MutableMap> { val properties = mutableMapOf>() if (this is PylonDirectionalBlock) { - val facing = getFacing() - if (facing != null) { - properties["facing"] = facing.name.lowercase() to IMMEDIATE_FACES.size - } + properties["facing"] = facing.name.lowercase() to IMMEDIATE_FACES.size } return properties } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonCargoBlock.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonCargoBlock.kt index 33de4e28d..3c43ebc55 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonCargoBlock.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonCargoBlock.kt @@ -76,7 +76,7 @@ interface PylonCargoBlock : PylonLogisticBlock, PylonEntityHolderBlock { var cargoTransferRate: Int /** - * Note that [cargoTransferRate] will be multiplied by [PylonConfig.cargoTransferRateMultiplier], + * Note that [cargoTransferRate] will be multiplied by [PylonConfig.CARGO_TRANSFER_RATE_MULTIPLIER], * and the result will be the maximum number of items that can be transferred * out of this block per cargo tick. * @@ -172,7 +172,7 @@ interface PylonCargoBlock : PylonLogisticBlock, PylonEntityHolderBlock { val toTransfer = min( min(targetMaxAmount - targetAmount, sourceAmount), - cargoBlockData.transferRate.toLong() * PylonConfig.cargoTransferRateMultiplier + cargoBlockData.transferRate.toLong() * PylonConfig.CARGO_TRANSFER_RATE_MULTIPLIER ) if (sourceAmount == toTransfer) { @@ -201,7 +201,7 @@ interface PylonCargoBlock : PylonLogisticBlock, PylonEntityHolderBlock { @JvmStatic fun cargoItemsTransferredPerSecond(cargoTransferRate: Int) - = (cargoTransferRate * PylonConfig.cargoTransferRateMultiplier).toDouble() / PylonConfig.cargoTickInterval.toDouble() + = (20 * cargoTransferRate * PylonConfig.CARGO_TRANSFER_RATE_MULTIPLIER).toDouble() / PylonConfig.CARGO_TICK_INTERVAL.toDouble() internal data class CargoBlockData( var groups: MutableMap, @@ -216,7 +216,7 @@ interface PylonCargoBlock : PylonLogisticBlock, PylonEntityHolderBlock { private fun startTicker(block: PylonCargoBlock) { cargoTickers[block] = PylonCore.launch(PylonCore.minecraftDispatcher) { while (true) { - delay(PylonConfig.cargoTickInterval.ticks) + delay(PylonConfig.CARGO_TICK_INTERVAL.ticks) block.tickCargo() } } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonDirectionalBlock.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonDirectionalBlock.kt index c5f18d08f..5039fc976 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonDirectionalBlock.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonDirectionalBlock.kt @@ -1,13 +1,61 @@ package io.github.pylonmc.pylon.core.block.base import io.github.pylonmc.pylon.core.block.PylonBlock +import io.github.pylonmc.pylon.core.datatypes.PylonSerializers +import io.github.pylonmc.pylon.core.event.PylonBlockDeserializeEvent +import io.github.pylonmc.pylon.core.event.PylonBlockSerializeEvent +import io.github.pylonmc.pylon.core.event.PylonBlockUnloadEvent +import io.github.pylonmc.pylon.core.util.pylonKey +import org.bukkit.Keyed import org.bukkit.block.BlockFace +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.jetbrains.annotations.ApiStatus +import java.util.IdentityHashMap +import kotlin.collections.set /** * Represents a block that has a specific facing direction. * * Internally only used for rotating [PylonBlock.blockTextureEntity]s. */ -interface PylonDirectionalBlock { - fun getFacing(): BlockFace? +interface PylonDirectionalBlock : Keyed { + + var facing: BlockFace + get() = directionalBlocks[this] ?: error("No direction was set for block $key") + set(value) { + directionalBlocks[this] = value + } + + @ApiStatus.Internal + companion object : Listener { + private val directionalBlockKey = pylonKey("directional_block") + + private val directionalBlocks = IdentityHashMap() + + @EventHandler + private fun onDeserialize(event: PylonBlockDeserializeEvent) { + val block = event.pylonBlock + if (block is PylonDirectionalBlock) { + directionalBlocks[block] = event.pdc.get(directionalBlockKey, PylonSerializers.BLOCK_FACE) + ?: error("Direction not found for ${block.key}") + } + } + + @EventHandler + private fun onSerialize(event: PylonBlockSerializeEvent) { + val block = event.pylonBlock + if (block is PylonDirectionalBlock) { + event.pdc.set(directionalBlockKey, PylonSerializers.BLOCK_FACE, directionalBlocks[block]!!) + } + } + + @EventHandler + private fun onUnload(event: PylonBlockUnloadEvent) { + val block = event.pylonBlock + if (block is PylonDirectionalBlock) { + directionalBlocks.remove(block) + } + } + } } \ No newline at end of file diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBlock.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBlock.kt index 992e21ca3..c94325d6d 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBlock.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBlock.kt @@ -5,11 +5,10 @@ import io.github.pylonmc.pylon.core.block.context.BlockCreateContext import io.github.pylonmc.pylon.core.content.fluid.FluidEndpointDisplay import io.github.pylonmc.pylon.core.fluid.FluidPointType import io.github.pylonmc.pylon.core.fluid.PylonFluid -import io.github.pylonmc.pylon.core.util.rotateToPlayerFacing +import io.github.pylonmc.pylon.core.util.rotateFaceToReference import org.bukkit.block.BlockFace -import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -import org.jetbrains.annotations.ApiStatus +import org.jetbrains.annotations.MustBeInvokedByOverriders /** * A block that interacts with fluids in some way. @@ -25,19 +24,11 @@ import org.jetbrains.annotations.ApiStatus * * Multiple inputs/outputs are not supported. You can have at most 1 input and 1 output. * - * PylonFLuidBlocks automatically implement [PylonDirectionalBlock]. If the block has - * an input or output point, the block direction will be towards the output or input - * point's face. Output points take precedence over input points. You can override - * this behaviour by overriding [getFacing]. * * @see PylonFluidBufferBlock * @see PylonFluidTank */ -interface PylonFluidBlock : PylonEntityHolderBlock, PylonDirectionalBlock, PylonBreakHandler { - - override fun getFacing(): BlockFace? = - getHeldPylonEntity(FluidEndpointDisplay::class.java, "fluid_point_output")?.face - ?: getHeldPylonEntity(FluidEndpointDisplay::class.java, "fluid_point_input")?.face +interface PylonFluidBlock : PylonEntityHolderBlock, PylonBreakHandler { fun getFluidPointDisplay(type: FluidPointType) = getHeldPylonEntity(FluidEndpointDisplay::class.java, getFluidPointName(type)) @@ -58,38 +49,6 @@ interface PylonFluidBlock : PylonEntityHolderBlock, PylonDirectionalBlock, Pylon */ fun createFluidPoint(type: FluidPointType, face: BlockFace) = createFluidPoint(type, face, 0.5F) - /** - * Creates a fluid input point. Call in your place constructor. Should be called at most once per block. - * - * @param player If supplied, the point will be rotated to the player's frame of reference, with NORTH - * considered 'forward' - * @param allowVerticalFaces Whether up/down should be considered when rotating to the player's frame - * of reference - * - * @see rotateToPlayerFacing - */ - fun createFluidPoint(type: FluidPointType, face: BlockFace, player: Player?, allowVerticalFaces: Boolean, radius: Float) { - var finalFace = face - if (player != null) { - finalFace = rotateToPlayerFacing(player, face, allowVerticalFaces) - } - createFluidPoint(type, finalFace, radius) - } - - /** - * Creates a fluid input point. Call in your place constructor. Should be called at most once per block. - * - * @param player If supplied, the point will be rotated to the player's frame of reference, with NORTH - * considered 'forward' - * @param allowVerticalFaces Whether up/down should be considered when rotating to the player's frame - * of reference - * - * @see rotateToPlayerFacing - */ - fun createFluidPoint(type: FluidPointType, face: BlockFace, player: Player?, allowVerticalFaces: Boolean) { - createFluidPoint(type, face, player, allowVerticalFaces, 0.5F) - } - /** * Creates a fluid input point. Call in your place constructor. Should be called at most once per block. * @@ -98,11 +57,14 @@ interface PylonFluidBlock : PylonEntityHolderBlock, PylonDirectionalBlock, Pylon * @param allowVerticalFaces Whether up/down should be considered when rotating to the player's frame * of reference * - * @see rotateToPlayerFacing + * @see rotateFaceToReference */ - fun createFluidPoint(type: FluidPointType, face: BlockFace, context: BlockCreateContext, allowVerticalFaces: Boolean) { - createFluidPoint(type, face, (context as? BlockCreateContext.PlayerPlace)?.player, allowVerticalFaces) - } + fun createFluidPoint(type: FluidPointType, face: BlockFace, context: BlockCreateContext, allowVerticalFaces: Boolean, radius: Float) + = createFluidPoint( + type, + rotateFaceToReference(if (allowVerticalFaces) context.facingVertical else context.facing, face), + radius + ) /** * Creates a fluid input point. Call in your place constructor. Should be called at most once per block. @@ -112,12 +74,12 @@ interface PylonFluidBlock : PylonEntityHolderBlock, PylonDirectionalBlock, Pylon * @param allowVerticalFaces Whether up/down should be considered when rotating to the player's frame * of reference * - * @see rotateToPlayerFacing + * @see rotateFaceToReference */ - fun createFluidPoint(type: FluidPointType, face: BlockFace, context: BlockCreateContext, allowVerticalFaces: Boolean, radius: Float) { - createFluidPoint(type, face, (context as? BlockCreateContext.PlayerPlace)?.player, allowVerticalFaces, radius) - } + fun createFluidPoint(type: FluidPointType, face: BlockFace, context: BlockCreateContext, allowVerticalFaces: Boolean) + = createFluidPoint(type, face, context, allowVerticalFaces, 0.5F) + @MustBeInvokedByOverriders override fun onBreak(drops: MutableList, context: BlockBreakContext) { val player = (context as? BlockBreakContext.PlayerBreak)?.event?.player getFluidPointDisplay(FluidPointType.INPUT)?.pipeDisplay?.delete(player, drops) @@ -125,30 +87,30 @@ interface PylonFluidBlock : PylonEntityHolderBlock, PylonDirectionalBlock, Pylon /** * Returns a map of fluid types - and their corresponding amounts - that can be supplied by - * the block for this fluid tick. deltaSeconds is the time since the last fluid tick. + * the block for this fluid tick. * * If you have a machine that can supply up to 100 fluid per second, it should supply - * 100*deltaSeconds of that fluid + * 5 * PylonConfig.fluidTickInterval of that fluid * * Any implementation of this method must NEVER call the same method for any other connection * point, otherwise you risk creating infinite loops. * * Called exactly one per fluid tick. */ - fun getSuppliedFluids(deltaSeconds: Double): Map = mapOf() + fun getSuppliedFluids(): Map = mapOf() /** * Returns the amount of the given fluid that the machine wants to receive next tick. * - * If you have a machine that consumes 100 water per second, it should request - * 100*deltaSeconds of water, and return 0 for every other fluid. + * If you have a machine that consumes 5 water per tick, it should request + * 5*PylonConfig.fluidTickInterval of water, and return 0 for every other fluid. * * Any implementation of this method must NEVER call the same method for any other connection * point, otherwise you risk creating infinite loops. * * Called at most once for any given fluid type per tick. */ - fun fluidAmountRequested(fluid: PylonFluid, deltaSeconds: Double): Double = 0.0 + fun fluidAmountRequested(fluid: PylonFluid): Double = 0.0 /** * `amount` is always at most `getRequestedFluids().get(fluid)` and will never diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBufferBlock.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBufferBlock.kt index fc6e9cb13..d17f9b133 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBufferBlock.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidBufferBlock.kt @@ -129,10 +129,10 @@ interface PylonFluidBufferBlock : PylonFluidBlock { return setFluid(fluid, fluidData(fluid).amount - amount) } - override fun fluidAmountRequested(fluid: PylonFluid, deltaSeconds: Double): Double + override fun fluidAmountRequested(fluid: PylonFluid): Double = if (hasFluid(fluid) && fluidData(fluid).input) fluidSpaceRemaining(fluid) else 0.0 - override fun getSuppliedFluids(deltaSeconds: Double): Map + override fun getSuppliedFluids(): Map = fluidBuffers.filter { it.value.output }.mapValues { it.value.amount } override fun onFluidAdded(fluid: PylonFluid, amount: Double) { diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidTank.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidTank.kt index 512de72ef..720961fdf 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidTank.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonFluidTank.kt @@ -122,7 +122,7 @@ interface PylonFluidTank : PylonFluidBlock { fun isAllowedFluid(fluid: PylonFluid): Boolean - override fun fluidAmountRequested(fluid: PylonFluid, deltaSeconds: Double): Double{ + override fun fluidAmountRequested(fluid: PylonFluid): Double{ if (!isAllowedFluid(fluid)) { return 0.0 } @@ -137,7 +137,7 @@ interface PylonFluidTank : PylonFluidBlock { } } - override fun getSuppliedFluids(deltaSeconds: Double): Map { + override fun getSuppliedFluids(): Map { val fluidData = this.fluidData // local variable to save calling fluidData getter multiple times return if (fluidData.fluid == null) { emptyMap() diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonProcessor.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonProcessor.kt index 868dae0c2..fb6f32da3 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonProcessor.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonProcessor.kt @@ -51,8 +51,7 @@ interface PylonProcessor { } /** - * Starts a new process with duration [ticks], with [ticks] being the number of server - * ticks the process will take. + * Starts a new process with duration [ticks] */ fun startProcess(ticks: Int) { processorData.processTimeTicks = ticks @@ -78,6 +77,9 @@ interface PylonProcessor { fun onProcessFinished() {} + /** + * Progresses the progress by [ticks] ticks + */ @ApiStatus.Internal fun progressProcess(ticks: Int) { val data = processorData @@ -128,10 +130,7 @@ interface PylonProcessor { private fun onSerialize(event: PylonBlockSerializeEvent) { val block = event.pylonBlock if (block is PylonProcessor) { - val data = processorBlocks[block] ?: error { - "No recipe processor data found for ${block.key}" - } - event.pdc.set(processorKey, PylonSerializers.PROCESSOR_DATA, data) + event.pdc.set(processorKey, PylonSerializers.PROCESSOR_DATA, block.processorData) } } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonSimpleMultiblock.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonSimpleMultiblock.kt index 1debcb340..7cbf2ddd0 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonSimpleMultiblock.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonSimpleMultiblock.kt @@ -24,7 +24,6 @@ import io.github.pylonmc.pylon.core.util.position.position import io.github.pylonmc.pylon.core.util.pylonKey import io.github.pylonmc.pylon.core.util.rotateVectorToFace import kotlinx.coroutines.delay -import org.bukkit.Bukkit import org.bukkit.Color import org.bukkit.Material import org.bukkit.NamespacedKey @@ -57,7 +56,7 @@ import kotlin.time.Duration.Companion.seconds * If you need something more flexible (eg: a fluid tank that can have up to 10 * fluid casings added to increase the capacity), see [PylonMultiblock]. */ -interface PylonSimpleMultiblock : PylonMultiblock, PylonEntityHolderBlock, PylonDirectionalBlock { +interface PylonSimpleMultiblock : PylonMultiblock, PylonEntityHolderBlock { /** * Implement this together with [MultiblockComponent], it is used to spawn a single entity @@ -375,23 +374,23 @@ interface PylonSimpleMultiblock : PylonMultiblock, PylonEntityHolderBlock, Pylon * * Leave this unset to accept any direction. */ - fun setFacing(facing: BlockFace?) { - simpleMultiblockData.facing = facing + fun setMultiblockDirection(direction: BlockFace?) { + simpleMultiblockData.direction = direction } /** * The 'direction' we expect the multiblock to be built in. This is not the *actual* direction that * the multiblock has been built in. */ - override fun getFacing(): BlockFace? - = simpleMultiblockData.facing + fun getMultiblockDirection(): BlockFace? + = simpleMultiblockData.direction /** * Returns all the valid configurations of the multiblock. If any of these is satisfied, the multiblock * will be considered complete. */ fun validStructures(): List> { - val facing = simpleMultiblockData.facing + val facing = simpleMultiblockData.direction return if (facing == null) { listOf( components, @@ -410,7 +409,7 @@ interface PylonSimpleMultiblock : PylonMultiblock, PylonEntityHolderBlock, Pylon @ApiStatus.Internal fun spawnGhostBlocks() { val block = (this as PylonBlock).block - val facing = simpleMultiblockData.facing + val facing = simpleMultiblockData.direction val rotatedComponents = if (facing == null) components else rotateComponentsToFace(components, facing) for ((offset, component) in rotatedComponents) { val startSection = "multiblock_ghost_block_${offset.x}_${offset.y}_${offset.z}" @@ -520,7 +519,7 @@ interface PylonSimpleMultiblock : PylonMultiblock, PylonEntityHolderBlock, Pylon } val block = (this as PylonBlock).block - val facing = simpleMultiblockData.facing + val facing = simpleMultiblockData.direction val rotatedComponents = if (facing == null) components else rotateComponentsToFace(components, facing) for ((offset, component) in rotatedComponents) { val mainKey = "multiblock_ghost_block_${offset.x}_${offset.y}_${offset.z}" @@ -558,7 +557,7 @@ interface PylonSimpleMultiblock : PylonMultiblock, PylonEntityHolderBlock, Pylon @ApiStatus.Internal companion object : Listener { - internal data class SimpleMultiblockData(var facing: BlockFace?) + internal data class SimpleMultiblockData(var direction: BlockFace?) private val simpleMultiblockKey = pylonKey("simple_multiblock_data") diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonTickingBlock.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonTickingBlock.kt index 073bc2741..cac1ac591 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonTickingBlock.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/base/PylonTickingBlock.kt @@ -19,7 +19,6 @@ import io.github.pylonmc.pylon.core.util.pylonKey import kotlinx.coroutines.Job import kotlinx.coroutines.delay import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.jetbrains.annotations.ApiStatus import java.util.IdentityHashMap @@ -31,7 +30,7 @@ interface PylonTickingBlock { private val tickingData: TickingBlockData get() = tickingBlocks.getOrPut(this) { TickingBlockData( - PylonConfig.defaultTickInterval, + PylonConfig.DEFAULT_TICK_INTERVAL, false, null )} @@ -72,7 +71,7 @@ interface PylonTickingBlock { /** * The function that should be called periodically. */ - fun tick(deltaSeconds: Double) + fun tick() @ApiStatus.Internal companion object : Listener { @@ -154,13 +153,10 @@ interface PylonTickingBlock { private fun startTicker(tickingBlock: PylonTickingBlock) { val dispatcher = if (tickingBlock.isAsync) PylonCore.asyncDispatcher else PylonCore.minecraftDispatcher tickingBlocks[tickingBlock]?.job = PylonCore.launch(dispatcher) { - var lastTickNanos = System.nanoTime() while (true) { delay(tickingBlock.tickInterval.ticks) try { - val dt = (System.nanoTime() - lastTickNanos) / 1.0e9 - lastTickNanos = System.nanoTime() - tickingBlock.tick(dt) + tickingBlock.tick() } catch (e: Exception) { PylonCore.launch(PylonCore.minecraftDispatcher) { logEventHandleErr(null, e, tickingBlock as PylonBlock) diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/context/BlockCreateContext.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/context/BlockCreateContext.kt index c833b9b55..94c5713e8 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/context/BlockCreateContext.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/block/context/BlockCreateContext.kt @@ -1,6 +1,8 @@ package io.github.pylonmc.pylon.core.block.context +import io.github.pylonmc.pylon.core.entity.display.transform.TransformUtil import org.bukkit.block.Block +import org.bukkit.block.BlockFace import org.bukkit.entity.Player import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.ItemStack @@ -11,6 +13,16 @@ import org.bukkit.plugin.Plugin */ interface BlockCreateContext { + /** + * The direction in which this block was placed. NORTH, EAST, SOUTH, WEST. + */ + val facing: BlockFace + + /** + * The direction in which this block was placed. NORTH, EAST, SOUTH, WEST, UP, DOWN + */ + val facingVertical: BlockFace + /** * The old block where the new block is about to be created. */ @@ -37,6 +49,8 @@ interface BlockCreateContext { override val item: ItemStack, val event: BlockPlaceEvent ) : BlockCreateContext { + override val facing: BlockFace = TransformUtil.yawToCardinalFace(player.yaw) + override val facingVertical: BlockFace = TransformUtil.yawAndPitchToFace(player.yaw, player.pitch) override val block = event.blockPlaced override val shouldSetType = false // The action of the placement sets the block } @@ -50,8 +64,10 @@ interface BlockCreateContext { @JvmRecord data class PluginGenerate( val plugin: Plugin, + override val facing: BlockFace = BlockFace.NORTH, + override val facingVertical: BlockFace = BlockFace.NORTH, override val block: Block, - override val item: ItemStack + override val item: ItemStack, ) : BlockCreateContext /** @@ -60,6 +76,8 @@ interface BlockCreateContext { @JvmRecord data class Default @JvmOverloads constructor( override val block: Block, + override val facing: BlockFace = BlockFace.NORTH, + override val facingVertical: BlockFace = BlockFace.NORTH, override val item: ItemStack? = null, override val shouldSetType: Boolean = true ) : BlockCreateContext diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/config/PylonConfig.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/config/PylonConfig.kt index 6548d6ccc..e17b27a1b 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/config/PylonConfig.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/config/PylonConfig.kt @@ -12,102 +12,102 @@ object PylonConfig { private val config = Config(PylonCore, "config.yml") - @JvmStatic - val pylonGuideOnFirstJoin = config.getOrThrow("pylon-guide-on-first-join", ConfigAdapter.BOOLEAN) + @JvmField + val PYLON_GUIDE_ON_FIRST_JOIN = config.getOrThrow("pylon-guide-on-first-join", ConfigAdapter.BOOLEAN) - @JvmStatic - val defaultTickInterval = config.getOrThrow("default-tick-interval", ConfigAdapter.INT) + @JvmField + val DEFAULT_TICK_INTERVAL = config.getOrThrow("default-tick-interval", ConfigAdapter.INT) - @JvmStatic - val allowedBlockErrors = config.getOrThrow("allowed-block-errors", ConfigAdapter.INT) + @JvmField + val ALLOWED_BLOCK_ERRORS = config.getOrThrow("allowed-block-errors", ConfigAdapter.INT) - @JvmStatic - val allowedEntityErrors = config.getOrThrow("allowed-entity-errors", ConfigAdapter.INT) + @JvmField + val ALLOWED_ENTITY_ERRORS = config.getOrThrow("allowed-entity-errors", ConfigAdapter.INT) - @JvmStatic - val fluidTickInterval = config.getOrThrow("fluid-tick-interval", ConfigAdapter.INT) + @JvmField + val FLUID_TICK_INTERVAL = config.getOrThrow("fluid-tick-interval", ConfigAdapter.INT) - @JvmStatic - val blockDataAutosaveIntervalSeconds = config.getOrThrow("block-data-autosave-interval-seconds", ConfigAdapter.LONG) + @JvmField + val BLOCK_DATA_AUTOSAVE_INTERVAL_SECONDS = config.getOrThrow("block-data-autosave-interval-seconds", ConfigAdapter.LONG) - @JvmStatic - val entityDataAutosaveIntervalSeconds = config.getOrThrow("entity-data-autosave-interval-seconds", ConfigAdapter.LONG) + @JvmField + val ENTITY_DATA_AUTOSAVE_INTERVAL_SECONDS = config.getOrThrow("entity-data-autosave-interval-seconds", ConfigAdapter.LONG) - @JvmStatic - val researchesEnabled = config.getOrThrow("research.enabled", ConfigAdapter.BOOLEAN) + @JvmField + val RESEARCHES_ENABLED = config.getOrThrow("research.enabled", ConfigAdapter.BOOLEAN) - @JvmStatic - val researchBaseConfettiAmount = config.get("research.confetti.base-amount", ConfigAdapter.DOUBLE, 70.0) + @JvmField + val RESEARCH_BASE_CONFETTI_AMOUNT = config.get("research.confetti.base-amount", ConfigAdapter.DOUBLE, 70.0) - @JvmStatic - val researchMultiplierConfettiAmount = config.get("research.confetti.multiplier", ConfigAdapter.DOUBLE, 0.2) + @JvmField + val RESEARCH_MULTIPLIER_CONFETTI_AMOUNT = config.get("research.confetti.multiplier", ConfigAdapter.DOUBLE, 0.2) - @JvmStatic - val researchMaxConfettiAmount = config.get("research.confetti.max-amount", ConfigAdapter.INT, 700) + @JvmField + val RESEARCH_MAX_CONFETTI_AMOUNT = config.get("research.confetti.max-amount", ConfigAdapter.INT, 700) - @JvmStatic - val researchSounds = config.getOrThrow("research.sounds", ConfigAdapter.MAP.from(ConfigAdapter.LONG, ConfigAdapter.RANDOMIZED_SOUND)) + @JvmField + val RESEARCH_SOUNDS = config.getOrThrow("research.sounds", ConfigAdapter.MAP.from(ConfigAdapter.LONG, ConfigAdapter.RANDOMIZED_SOUND)) - @JvmStatic - val pipePlacementTaskIntervalTicks = config.getOrThrow("pipe-placement.tick-interval", ConfigAdapter.LONG) + @JvmField + val PIPE_PLACEMENT_TASK_INTERVAL_TICKS = config.getOrThrow("pipe-placement.tick-interval", ConfigAdapter.LONG) - @JvmStatic - val pipePlacementMaxLength = config.getOrThrow("pipe-placement.max-length", ConfigAdapter.LONG) + @JvmField + val PIPE_PLACEMENT_MAX_LENGTH = config.getOrThrow("pipe-placement.max-length", ConfigAdapter.LONG) - @JvmStatic - val pipePlacementCancelDistance = config.getOrThrow("pipe-placement.cancel-distance", ConfigAdapter.INT) + @JvmField + val PIPE_PLACEMENT_CANCEL_DISTANCE = config.getOrThrow("pipe-placement.cancel-distance", ConfigAdapter.INT) - @JvmStatic - val translationWrapLimit = config.getOrThrow("translation-wrap-limit", ConfigAdapter.INT) + @JvmField + val TRANSLATION_WRAP_LIMIT = config.getOrThrow("translation-wrap-limit", ConfigAdapter.INT) - @JvmStatic - val metricsSaveIntervalTicks = config.getOrThrow("metrics-save-interval-ticks", ConfigAdapter.LONG) + @JvmField + val METRICS_SAVE_INTERVAL_TICKS = config.getOrThrow("metrics-save-interval-ticks", ConfigAdapter.LONG) - @JvmStatic - val disabledItems = config.getOrThrow("disabled-items", ConfigAdapter.SET.from(ConfigAdapter.NAMESPACED_KEY)) + @JvmField + val DISABLED_ITEMS = config.getOrThrow("disabled-items", ConfigAdapter.SET.from(ConfigAdapter.NAMESPACED_KEY)) - @JvmStatic - val inventoryTickerBaseRate = config.getOrThrow("inventory-ticker-base-rate", ConfigAdapter.LONG) + @JvmField + val INVENTORY_TICKER_BASE_RATE = config.getOrThrow("inventory-ticker-base-rate", ConfigAdapter.LONG) - @JvmStatic - val cargoTickInterval = config.getOrThrow("cargo-tick-interval", ConfigAdapter.INT) + @JvmField + val CARGO_TICK_INTERVAL = config.getOrThrow("cargo-tick-interval", ConfigAdapter.INT) - @JvmStatic - val cargoTransferRateMultiplier = config.getOrThrow("cargo-transfer-rate-multiplier", ConfigAdapter.INT) + @JvmField + val CARGO_TRANSFER_RATE_MULTIPLIER = config.getOrThrow("cargo-transfer-rate-multiplier", ConfigAdapter.INT) object WailaConfig { private val config = Config(PylonCore, "config.yml") @JvmStatic val enabled - get() = tickInterval > 0 && enabledTypes.isNotEmpty() + get() = TICK_INTERVAL > 0 && ENABLED_TYPES.isNotEmpty() - @JvmStatic - val tickInterval = config.getOrThrow("waila.tick-interval", ConfigAdapter.INT) + @JvmField + val TICK_INTERVAL = config.getOrThrow("waila.tick-interval", ConfigAdapter.INT) - @JvmStatic - val enabledTypes = config.getOrThrow("waila.enabled-types", ConfigAdapter.LIST.from(ConfigAdapter.ENUM.from(Waila.Type::class.java))) + @JvmField + val ENABLED_TYPES = config.getOrThrow("waila.enabled-types", ConfigAdapter.LIST.from(ConfigAdapter.ENUM.from(Waila.Type::class.java))) - @JvmStatic - val defaultType = config.getOrThrow("waila.default-type", ConfigAdapter.ENUM.from(Waila.Type::class.java)).apply { - if (!enabledTypes.contains(this)) { - throw IllegalStateException("Default Waila type $this is not in the list of enabled types: $enabledTypes") + @JvmField + val DEFAULT_TYPE = config.getOrThrow("waila.default-type", ConfigAdapter.ENUM.from(Waila.Type::class.java)).apply { + if (!ENABLED_TYPES.contains(this)) { + throw IllegalStateException("Default Waila type $this is not in the list of enabled types: $ENABLED_TYPES") } } - @JvmStatic - val allowedBossBarColors = config.getOrThrow("waila.bossbar.allowed-colors", ConfigAdapter.SET.from(ConfigAdapter.ENUM.from(BossBar.Color::class.java))) + @JvmField + val ALLOWED_BOSS_BAR_COLORS = config.getOrThrow("waila.bossbar.allowed-colors", ConfigAdapter.SET.from(ConfigAdapter.ENUM.from(BossBar.Color::class.java))) - @JvmStatic - val allowedBossBarOverlays = config.getOrThrow("waila.bossbar.allowed-overlays", ConfigAdapter.SET.from(ConfigAdapter.ENUM.from(BossBar.Overlay::class.java))) + @JvmField + val ALLOWED_BOSS_BAR_OVERLAYS = config.getOrThrow("waila.bossbar.allowed-overlays", ConfigAdapter.SET.from(ConfigAdapter.ENUM.from(BossBar.Overlay::class.java))) - @JvmStatic - val defaultDisplay = config.getOrThrow("waila.default-display.bossbar", ConfigAdapter.WAILA_DISPLAY).apply { - if (!allowedBossBarColors.contains(color)) { - throw IllegalStateException("Default bossbar color $color is not in the list of allowed colors: $allowedBossBarColors") + @JvmField + val DEFAULT_DISPLAY = config.getOrThrow("waila.default-display.bossbar", ConfigAdapter.WAILA_DISPLAY).apply { + if (!ALLOWED_BOSS_BAR_COLORS.contains(color)) { + throw IllegalStateException("Default bossbar color $color is not in the list of allowed colors: $ALLOWED_BOSS_BAR_COLORS") } - if (!allowedBossBarOverlays.contains(overlay)) { - throw IllegalStateException("Default bossbar overlay $overlay is not in the list of allowed overlays: $allowedBossBarOverlays") + if (!ALLOWED_BOSS_BAR_OVERLAYS.contains(overlay)) { + throw IllegalStateException("Default bossbar overlay $overlay is not in the list of allowed overlays: $ALLOWED_BOSS_BAR_OVERLAYS") } } } @@ -116,11 +116,11 @@ object PylonConfig { private val config = Config(PylonCore, "config.yml") - @JvmStatic - val enabled = config.getOrThrow("custom-armor-textures.enabled", ConfigAdapter.BOOLEAN) + @JvmField + val ENABLED = config.getOrThrow("custom-armor-textures.enabled", ConfigAdapter.BOOLEAN) - @JvmStatic - val forced = config.getOrThrow("custom-armor-textures.force", ConfigAdapter.BOOLEAN) + @JvmField + val FORCED = config.getOrThrow("custom-armor-textures.force", ConfigAdapter.BOOLEAN) } @@ -128,28 +128,28 @@ object PylonConfig { private val config = Config(PylonCore, "config.yml") - @JvmStatic - val enabled = config.getOrThrow("custom-block-textures.enabled", ConfigAdapter.BOOLEAN) + @JvmField + val ENABLED = config.getOrThrow("custom-block-textures.enabled", ConfigAdapter.BOOLEAN) - @JvmStatic - val default = config.getOrThrow("custom-block-textures.default", ConfigAdapter.BOOLEAN) + @JvmField + val DEFAULT = config.getOrThrow("custom-block-textures.default", ConfigAdapter.BOOLEAN) - @JvmStatic - val forced = config.getOrThrow("custom-block-textures.force", ConfigAdapter.BOOLEAN) + @JvmField + val FORCED = config.getOrThrow("custom-block-textures.force", ConfigAdapter.BOOLEAN) - @JvmStatic - val occludingCacheRefreshInterval = config.getOrThrow("custom-block-textures.culling.occluding-cache-refresh-interval", ConfigAdapter.INT) + @JvmField + val OCCLUDING_CACHE_REFRESH_INTERVAL = config.getOrThrow("custom-block-textures.culling.occluding-cache-refresh-interval", ConfigAdapter.INT) - @JvmStatic - val occludingCacheRefreshShare = config.getOrThrow("custom-block-textures.culling.occluding-cache-refresh-share", ConfigAdapter.DOUBLE) + @JvmField + val OCCLUDING_CACHE_REFRESH_SHARE = config.getOrThrow("custom-block-textures.culling.occluding-cache-refresh-share", ConfigAdapter.DOUBLE) - @JvmStatic - val cullingPresets = config.getOrThrow("custom-block-textures.culling.presets", ConfigAdapter.MAP.from(ConfigAdapter.STRING, ConfigAdapter.CULLING_PRESET)) + @JvmField + val CULLING_PRESETS = config.getOrThrow("custom-block-textures.culling.presets", ConfigAdapter.MAP.from(ConfigAdapter.STRING, ConfigAdapter.CULLING_PRESET)) - @JvmStatic - val defaultCullingPreset = run { + @JvmField + val DEFAULT_CULLING_PRESET = run { val key = config.getOrThrow("custom-block-textures.culling.default-preset", ConfigAdapter.STRING) - cullingPresets[key] ?: error("No culling preset with id '$key' found") + CULLING_PRESETS[key] ?: error("No culling preset with id '$key' found") } } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/content/guide/PylonGuide.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/content/guide/PylonGuide.kt index c69ccba7d..ee03a37dc 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/content/guide/PylonGuide.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/content/guide/PylonGuide.kt @@ -98,7 +98,7 @@ class PylonGuide(stack: ItemStack) : PylonItem(stack), PylonInteractor { */ @EventHandler(priority = EventPriority.LOWEST) private fun join(event: PlayerJoinEvent) { - if (PylonConfig.pylonGuideOnFirstJoin && !event.player.hasPlayedBefore()) { + if (PylonConfig.PYLON_GUIDE_ON_FIRST_JOIN && !event.player.hasPlayedBefore()) { event.player.give(STACK.clone()) } } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/datatypes/SimpleMultiblockDataPersistentDataType.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/datatypes/SimpleMultiblockDataPersistentDataType.kt index 60a04df00..b085edc0e 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/datatypes/SimpleMultiblockDataPersistentDataType.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/datatypes/SimpleMultiblockDataPersistentDataType.kt @@ -27,7 +27,7 @@ internal object SimpleMultiblockDataPersistentDataType : PersistentDataType PylonConfig.allowedEntityErrors) { + if (entityErrMap[entity.uuid]!! > PylonConfig.ALLOWED_ENTITY_ERRORS) { entity.entity.remove() } } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/EntityStorage.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/EntityStorage.kt index 9121096b1..54960b2ca 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/EntityStorage.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/EntityStorage.kt @@ -185,13 +185,13 @@ object EntityStorage : Listener { entityAutosaveTasks[entity.uuid] = PylonCore.launch(PylonCore.minecraftDispatcher) { // Wait a random delay before starting, this is to help smooth out lag from saving - delay(Random.nextLong(PylonConfig.entityDataAutosaveIntervalSeconds * 1000)) + delay(Random.nextLong(PylonConfig.ENTITY_DATA_AUTOSAVE_INTERVAL_SECONDS * 1000)) while (true) { lockEntityRead { entity.write(entity.entity.persistentDataContainer) } - delay(PylonConfig.entityDataAutosaveIntervalSeconds * 1000) + delay(PylonConfig.ENTITY_DATA_AUTOSAVE_INTERVAL_SECONDS * 1000) } } entity diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/display/transform/TransformUtil.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/display/transform/TransformUtil.kt index 05a505aa3..e6622c218 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/display/transform/TransformUtil.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/entity/display/transform/TransformUtil.kt @@ -22,11 +22,26 @@ object TransformUtil { = yawToCardinalDirection(yaw.toDouble()).toFloat() @JvmStatic - fun yawToFace(yaw: Double): BlockFace + fun yawToCardinalFace(yaw: Double): BlockFace = AXIS[(yaw / 90.0F).roundToInt() and 0x3] @JvmStatic - fun yawToFace(yaw: Float): BlockFace - = yawToFace(yaw.toDouble()) + fun yawToCardinalFace(yaw: Float): BlockFace + = yawToCardinalFace(yaw.toDouble()) + + @JvmStatic + fun yawAndPitchToFace(yaw: Double, pitch: Double): BlockFace { + if (pitch > 45) { + return BlockFace.UP + } + if (pitch < -45) { + return BlockFace.DOWN + } + return yawToCardinalFace(yaw) + } + + @JvmStatic + fun yawAndPitchToFace(yaw: Float, pitch: Float): BlockFace + = yawAndPitchToFace(yaw.toDouble(), pitch.toDouble()) @JvmStatic fun rotatedRadius(radius: Float, x: Float, y: Float, z: Float): Vector3f diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/event/PrePylonCraftEvent.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/event/PrePylonCraftEvent.kt deleted file mode 100644 index be505ad53..000000000 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/event/PrePylonCraftEvent.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.pylonmc.pylon.core.event - -import io.github.pylonmc.pylon.core.block.PylonBlock -import io.github.pylonmc.pylon.core.recipe.PylonRecipe -import io.github.pylonmc.pylon.core.recipe.RecipeType -import org.bukkit.entity.Player -import org.bukkit.event.Cancellable -import org.bukkit.event.Event -import org.bukkit.event.HandlerList - -/** - * Called when a crafting recipe is started. - */ -class PrePylonCraftEvent @JvmOverloads constructor( - val type: RecipeType, - val recipe: T, - val block: PylonBlock? = null, - val player: Player? = null -) : Event(), Cancellable { - - private var isCancelled = false - - override fun isCancelled(): Boolean = isCancelled - - override fun setCancelled(cancel: Boolean) { - isCancelled = cancel - } - - override fun getHandlers(): HandlerList - = handlerList - - companion object { - @JvmStatic - val handlerList: HandlerList = HandlerList() - } -} \ No newline at end of file diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/event/PylonCraftEvent.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/event/PylonCraftEvent.kt deleted file mode 100644 index cd1db3140..000000000 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/event/PylonCraftEvent.kt +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.pylonmc.pylon.core.event - -import io.github.pylonmc.pylon.core.block.PylonBlock -import io.github.pylonmc.pylon.core.recipe.PylonRecipe -import io.github.pylonmc.pylon.core.recipe.RecipeType -import org.bukkit.event.Event -import org.bukkit.event.HandlerList - -/** - * Called when a crafting recipe is started. - */ -class PylonCraftEvent @JvmOverloads constructor( - val type: RecipeType, - val recipe: T, - val block: PylonBlock? = null, -) : Event() { - - override fun getHandlers(): HandlerList - = handlerList - - companion object { - @JvmStatic - val handlerList: HandlerList = HandlerList() - } -} \ No newline at end of file diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/FluidManager.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/FluidManager.kt index 80b691d36..1ca498d74 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/FluidManager.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/FluidManager.kt @@ -280,7 +280,7 @@ internal object FluidManager { data class FluidSupplyInfo(var amount: Double, val blocks: IdentityHashMap) @JvmStatic - fun getSuppliedFluids(segment: UUID, deltaSeconds: Double): Map { + fun getSuppliedFluids(segment: UUID): Map { val suppliedFluids: MutableMap = mutableMapOf() for (point in getPoints(segment, FluidPointType.OUTPUT)) { try { @@ -289,7 +289,7 @@ internal object FluidManager { } val block = BlockStorage.getAs(point.position) ?: continue - for ((fluid, amount) in block.getSuppliedFluids(deltaSeconds)) { + for ((fluid, amount) in block.getSuppliedFluids()) { if (amount < 1.0e-6) { // prevent floating point issues supplying tiny amounts of liquid continue @@ -313,7 +313,7 @@ internal object FluidManager { * Ignore input points requesting zero or effectively zero of the fluid */ fun getRequestedFluids( - segment: UUID, fluid: PylonFluid, deltaSeconds: Double + segment: UUID, fluid: PylonFluid ): Pair, Double> { val requesters: MutableMap = mutableMapOf() var totalRequested = 0.0 @@ -324,7 +324,7 @@ internal object FluidManager { } val block = BlockStorage.getAs(point.position) ?: continue - val fluidAmountRequested = block.fluidAmountRequested(fluid, deltaSeconds) + val fluidAmountRequested = block.fluidAmountRequested(fluid) if (fluidAmountRequested < 1.0e-9) { continue } @@ -338,8 +338,8 @@ internal object FluidManager { return Pair(requesters, totalRequested) } - private fun tick(segment: UUID, deltaSeconds: Double) { - val suppliedFluids = getSuppliedFluids(segment, deltaSeconds) + private fun tick(segment: UUID) { + val suppliedFluids = getSuppliedFluids(segment) for ((fluid, info) in suppliedFluids) { @@ -349,7 +349,7 @@ internal object FluidManager { continue } - var (requesters, totalRequested) = getRequestedFluids(segment, fluid, deltaSeconds) + var (requesters, totalRequested) = getRequestedFluids(segment, fluid) // Continue if no machine is requesting the fluid if (requesters.isEmpty()) { @@ -358,7 +358,7 @@ internal object FluidManager { // Use round-robin to compute how much fluid to take from each supplier // Done in-place using the info's 'blocks' map to reduce memory operations - totalRequested = min(totalRequested, segments[segment]!!.fluidPerSecond * deltaSeconds) + totalRequested = min(totalRequested, segments[segment]!!.fluidPerSecond * PylonConfig.FLUID_TICK_INTERVAL / 20.0) val suppliers = info.blocks var remainingFluidNeeded = totalRequested var totalFluidSupplied = 0.0; @@ -428,10 +428,10 @@ internal object FluidManager { tickers[segment] = PylonCore.launch { var lastTickNanos = System.nanoTime() while (true) { - delay(PylonConfig.fluidTickInterval.ticks) + delay(PylonConfig.FLUID_TICK_INTERVAL.ticks) val dt = (System.nanoTime() - lastTickNanos) / 1.0e9 lastTickNanos = System.nanoTime() - tick(segment, dt) + tick(segment) } } } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/placement/FluidPipePlacementTask.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/placement/FluidPipePlacementTask.kt index 78b6a8062..4d01cbf3b 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/placement/FluidPipePlacementTask.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/fluid/placement/FluidPipePlacementTask.kt @@ -47,7 +47,7 @@ internal class FluidPipePlacementTask( PylonCore, Runnable { tick() }, 0, - PylonConfig.pipePlacementTaskIntervalTicks + PylonConfig.PIPE_PLACEMENT_TASK_INTERVAL_TICKS ) private fun tick() { @@ -67,7 +67,7 @@ internal class FluidPipePlacementTask( } // Check if player has moved too far away - if (player.location.distance(origin.position.location) > PylonConfig.pipePlacementCancelDistance) { + if (player.location.distance(origin.position.location) > PylonConfig.PIPE_PLACEMENT_CANCEL_DISTANCE) { FluidPipePlacementService.cancelConnection(player) return } @@ -127,7 +127,7 @@ internal class FluidPipePlacementTask( val difference = target.position.vector3i.sub(previousTargetPosition.vector3i) if (isCardinalDirection(difference)) { display.interpolationDelay = 0 - display.interpolationDuration = PylonConfig.pipePlacementTaskIntervalTicks.toInt() + display.interpolationDuration = PylonConfig.PIPE_PLACEMENT_TASK_INTERVAL_TICKS.toInt() } } @@ -268,8 +268,8 @@ internal class FluidPipePlacementTask( val solution = findClosestPointBetweenSkewLines(playerLookPosition, playerLookDirection, originPosition, Vector3f(axis)) val lambda = Math.clamp( solution.roundToLong(), - -PylonConfig.pipePlacementMaxLength, - PylonConfig.pipePlacementMaxLength + -PylonConfig.PIPE_PLACEMENT_MAX_LENGTH, + PylonConfig.PIPE_PLACEMENT_MAX_LENGTH ) return Vector3i(axis).mul(lambda.toInt()) } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/guide/pages/PlayerSettingsPage.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/guide/pages/PlayerSettingsPage.kt index d4bf1ec39..5b4291520 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/guide/pages/PlayerSettingsPage.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/guide/pages/PlayerSettingsPage.kt @@ -71,10 +71,10 @@ class PlayerSettingsPage( toggle = { player -> player.wailaConfig.vanillaWailaEnabled = !player.wailaConfig.vanillaWailaEnabled }, isEnabled = { player -> player.wailaConfig.vanillaWailaEnabled } )) - if (PylonConfig.WailaConfig.enabledTypes.size > 1) { + if (PylonConfig.WailaConfig.ENABLED_TYPES.size > 1) { addSetting(CyclePlayerSettingButton( pylonKey("cycle-waila-type"), - PylonConfig.WailaConfig.enabledTypes, + PylonConfig.WailaConfig.ENABLED_TYPES, identifier = { type -> type.name.lowercase() }, getter = { player -> player.wailaConfig.type }, setter = { player, type -> player.wailaConfig.type = type }, @@ -97,7 +97,7 @@ class PlayerSettingsPage( pylonKey("block_texture_settings"), Material.BOOKSHELF ).apply { - if (!PylonConfig.BlockTextureConfig.forced) { + if (!PylonConfig.BlockTextureConfig.FORCED) { addSetting(TogglePlayerSettingButton( pylonKey("toggle-block-textures"), toggle = { player -> player.hasCustomBlockTextures = !player.hasCustomBlockTextures }, @@ -106,7 +106,7 @@ class PlayerSettingsPage( } addSetting(CyclePlayerSettingButton( pylonKey("cycle-culling-preset"), - PylonConfig.BlockTextureConfig.cullingPresets.values.sortedBy { it.index }, + PylonConfig.BlockTextureConfig.CULLING_PRESETS.values.sortedBy { it.index }, identifier = { preset -> preset.id }, getter = { player -> player.cullingPreset }, setter = { player, preset -> player.cullingPreset = preset }, diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/i18n/PylonTranslator.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/i18n/PylonTranslator.kt index d52fa747f..363cf517f 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/i18n/PylonTranslator.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/i18n/PylonTranslator.kt @@ -25,7 +25,6 @@ import net.kyori.adventure.key.Key import net.kyori.adventure.text.Component import net.kyori.adventure.text.TextReplacementConfig import net.kyori.adventure.text.TranslatableComponent -import net.kyori.adventure.text.TranslationArgument import net.kyori.adventure.text.TranslationArgumentLike import net.kyori.adventure.text.VirtualComponent import net.kyori.adventure.text.format.NamedTextColor @@ -235,7 +234,7 @@ class PylonTranslator private constructor(private val addon: PylonAddon) : Trans if (translated.plainText.isBlank()) return@flatMap emptyList() val encoded = LineWrapEncoder.encode(translated) val wrapped = encoded.copy( - lines = encoded.lines.flatMap { wrapText(it, PylonConfig.translationWrapLimit) } + lines = encoded.lines.flatMap { wrapText(it, PylonConfig.TRANSLATION_WRAP_LIMIT) } ) wrapped.toComponentLines().map { Component.text() diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/PylonItem.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/PylonItem.kt index cd2677a5b..45ef33ecf 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/PylonItem.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/PylonItem.kt @@ -43,7 +43,7 @@ open class PylonItem(val stack: ItemStack) : Keyed { val researchBypassPermission = schema.researchBypassPermission val addon = schema.addon val pylonBlock = schema.pylonBlockKey - val isDisabled = key in PylonConfig.disabledItems + val isDisabled = key in PylonConfig.DISABLED_ITEMS val research get() = schema.research /** diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryEffectItem.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryEffectItem.kt index c7e816a32..614d30ef5 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryEffectItem.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryEffectItem.kt @@ -23,7 +23,7 @@ interface PylonInventoryEffectItem : PylonInventoryTicker { tasks[itemKey]!![player.uniqueId] = Bukkit.getScheduler().runTaskLater(PylonCore.javaPlugin, Runnable { player.persistentDataContainer.remove(itemKey) onRemovedFromInventory(player) - }, tickInterval * PylonConfig.inventoryTickerBaseRate + 1) + }, tickInterval * PylonConfig.INVENTORY_TICKER_BASE_RATE + 1) } /** diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryTicker.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryTicker.kt index d4383072d..acb771582 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryTicker.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/base/PylonInventoryTicker.kt @@ -15,6 +15,6 @@ interface PylonInventoryTicker { fun onTick(player: Player) /** Determines the rate at which the [onTick] method will be called. - * [onTick] will be called at [tickInterval] * [PylonConfig.inventoryTickerBaseRate] */ + * [onTick] will be called at [tickInterval] * [PylonConfig.INVENTORY_TICKER_BASE_RATE] */ val tickInterval: Long } \ No newline at end of file diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/research/Research.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/research/Research.kt index 29c96c4d9..c24c120a8 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/research/Research.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/item/research/Research.kt @@ -7,7 +7,6 @@ import io.github.pylonmc.pylon.core.config.ConfigSection import io.github.pylonmc.pylon.core.config.PylonConfig import io.github.pylonmc.pylon.core.config.adapter.ConfigAdapter import io.github.pylonmc.pylon.core.datatypes.PylonSerializers -import io.github.pylonmc.pylon.core.event.PrePylonCraftEvent import io.github.pylonmc.pylon.core.i18n.PylonArgument import io.github.pylonmc.pylon.core.item.PylonItem import io.github.pylonmc.pylon.core.item.research.Research.Companion.canPickUp @@ -97,14 +96,14 @@ data class Research( if (effects) { if (player.researchConfetti) { - val multiplier = (cost?.toDouble() ?: 0.0) * PylonConfig.researchMultiplierConfettiAmount - val amount = (PylonConfig.researchBaseConfettiAmount * multiplier).toInt() - val spawnedConfetti = min(amount, PylonConfig.researchMaxConfettiAmount) + val multiplier = (cost?.toDouble() ?: 0.0) * PylonConfig.RESEARCH_MULTIPLIER_CONFETTI_AMOUNT + val amount = (PylonConfig.RESEARCH_BASE_CONFETTI_AMOUNT * multiplier).toInt() + val spawnedConfetti = min(amount, PylonConfig.RESEARCH_MAX_CONFETTI_AMOUNT) ConfettiParticle.spawnMany(player.location, spawnedConfetti).run() } if (player.researchSounds) { - for ((delay, sound) in PylonConfig.researchSounds) { + for ((delay, sound) in PylonConfig.RESEARCH_SOUNDS) { Bukkit.getScheduler().runTaskLater(PylonCore, Runnable { player.playSound(sound.create(), Sound.Emitter.self()) }, delay) @@ -190,7 +189,7 @@ data class Research( @JvmOverloads @JvmName("canPlayerCraft") fun Player.canCraft(item: PylonItem, sendMessage: Boolean = false): Boolean { - if (!PylonConfig.researchesEnabled || this.hasPermission(item.researchBypassPermission)) return true + if (!PylonConfig.RESEARCHES_ENABLED || this.hasPermission(item.researchBypassPermission)) return true val research = item.research ?: return true @@ -244,7 +243,7 @@ data class Research( @JvmOverloads @JvmName("canPlayerUse") fun Player.canUse(item: PylonItem, sendMessage: Boolean = false): Boolean { - if (PylonConfig.disabledItems.contains(item.key)) { + if (PylonConfig.DISABLED_ITEMS.contains(item.key)) { if (sendMessage) { this.sendMessage( Component.translatable( @@ -270,31 +269,9 @@ data class Research( } } - @EventHandler - private fun onPrePylonCraft(event: PrePylonCraftEvent<*>) { - if (event.player == null) { - return - } - - val canCraft = event.recipe.results.all { - when (it) { - is FluidOrItem.Item -> { - val item = PylonItem.fromStack(it.item) - item == null || event.player.canCraft(item, true) - } - - else -> true - } - } - - if (!canCraft) { - event.isCancelled = true - } - } - @EventHandler private fun onJoin(e: PlayerJoinEvent) { - if (!PylonConfig.researchesEnabled) return + if (!PylonConfig.RESEARCHES_ENABLED) return val player = e.player // discover only the recipes that have no research whenever an ingredient is added to the inventory diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/metrics/PylonMetrics.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/metrics/PylonMetrics.kt index 9df68caf4..e2b6a8621 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/metrics/PylonMetrics.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/metrics/PylonMetrics.kt @@ -41,14 +41,14 @@ internal object PylonMetrics { metrics.addCustomChart(AdvancedPie("disabled_items") { val values = mutableMapOf() - for (item in PylonConfig.disabledItems) { + for (item in PylonConfig.DISABLED_ITEMS) { values.put(item.toString(), 1) } values }) metrics.addCustomChart(SimplePie("researches_enabled") { - if (PylonConfig.researchesEnabled) { "yes" } else { "no" } + if (PylonConfig.RESEARCHES_ENABLED) { "yes" } else { "no" } }) metrics.addCustomChart(AdvancedPie("researches_unlocked") { @@ -65,7 +65,7 @@ internal object PylonMetrics { commandsRun }) - Bukkit.getScheduler().runTaskTimerAsynchronously(PylonCore, Runnable { save() }, 0L, PylonConfig.metricsSaveIntervalTicks) + Bukkit.getScheduler().runTaskTimerAsynchronously(PylonCore, Runnable { save() }, 0L, PylonConfig.METRICS_SAVE_INTERVAL_TICKS) } fun save() { diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/registry/PylonRegistry.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/registry/PylonRegistry.kt index 79868a377..245d9046a 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/registry/PylonRegistry.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/registry/PylonRegistry.kt @@ -1,15 +1,24 @@ package io.github.pylonmc.pylon.core.registry import io.github.pylonmc.pylon.core.addon.PylonAddon +import io.github.pylonmc.pylon.core.block.PylonBlockSchema +import io.github.pylonmc.pylon.core.entity.PylonEntitySchema import io.github.pylonmc.pylon.core.event.PylonRegisterEvent import io.github.pylonmc.pylon.core.event.PylonUnregisterEvent +import io.github.pylonmc.pylon.core.fluid.PylonFluid +import io.github.pylonmc.pylon.core.gametest.GameTestConfig +import io.github.pylonmc.pylon.core.item.ItemTypeWrapper +import io.github.pylonmc.pylon.core.item.PylonItemSchema +import io.github.pylonmc.pylon.core.item.research.Research +import io.github.pylonmc.pylon.core.recipe.RecipeType +import io.github.pylonmc.pylon.core.util.pylonKey import org.bukkit.Keyed import org.bukkit.NamespacedKey import org.bukkit.Tag import java.util.concurrent.ConcurrentHashMap import java.util.stream.Stream -class PylonRegistry(val key: PylonRegistryKey) : Iterable { +class PylonRegistry(val key: NamespacedKey) : Iterable { private val values: MutableMap = ConcurrentHashMap() @@ -86,27 +95,39 @@ class PylonRegistry(val key: PylonRegistryKey) : Iterable { override fun toString(): String = key.toString() companion object { - private val registries: MutableMap, PylonRegistry<*>> = mutableMapOf() + private val registries: MutableMap> = mutableMapOf() // @formatter:off - @JvmField val ITEMS = PylonRegistry(PylonRegistryKey.ITEMS).also(::addRegistry) - @JvmField val BLOCKS = PylonRegistry(PylonRegistryKey.BLOCKS).also(::addRegistry) - @JvmField val ENTITIES = PylonRegistry(PylonRegistryKey.ENTITIES).also(::addRegistry) - @JvmField val FLUIDS = PylonRegistry(PylonRegistryKey.FLUIDS).also(::addRegistry) - @JvmField val ADDONS = PylonRegistry(PylonRegistryKey.ADDONS).also(::addRegistry) - @JvmField val GAMETESTS = PylonRegistry(PylonRegistryKey.GAMETESTS).also(::addRegistry) - @JvmField val RECIPE_TYPES = PylonRegistry(PylonRegistryKey.RECIPE_TYPES).also(::addRegistry) - @JvmField val RESEARCHES = PylonRegistry(PylonRegistryKey.RESEARCHES).also(::addRegistry) - @JvmField val ITEM_TAGS = PylonRegistry(PylonRegistryKey.ITEM_TAGS).also(::addRegistry) + @JvmField val ITEMS_KEY = pylonKey("items") + @JvmField val BLOCKS_KEY = pylonKey("blocks") + @JvmField val ENTITIES_KEY = pylonKey("entities") + @JvmField val FLUIDS_KEY = pylonKey("fluids") + @JvmField val GAMETESTS_KEY = pylonKey("gametests") + @JvmField val ADDONS_KEY = pylonKey("addons") + @JvmField val RECIPE_TYPES_KEY = pylonKey("recipe_types") + @JvmField val RESEARCHES_KEY = pylonKey("researches") + @JvmField val ITEM_TAGS_KEY = pylonKey("tags") + // @formatter:on + + // @formatter:off + @JvmField val ITEMS = PylonRegistry(ITEMS_KEY).also(::addRegistry) + @JvmField val BLOCKS = PylonRegistry(BLOCKS_KEY).also(::addRegistry) + @JvmField val ENTITIES = PylonRegistry(ENTITIES_KEY).also(::addRegistry) + @JvmField val FLUIDS = PylonRegistry(FLUIDS_KEY).also(::addRegistry) + @JvmField val ADDONS = PylonRegistry(ADDONS_KEY).also(::addRegistry) + @JvmField val GAMETESTS = PylonRegistry(GAMETESTS_KEY).also(::addRegistry) + @JvmField val RECIPE_TYPES = PylonRegistry>(RECIPE_TYPES_KEY).also(::addRegistry) + @JvmField val RESEARCHES = PylonRegistry(RESEARCHES_KEY).also(::addRegistry) + @JvmField val ITEM_TAGS = PylonRegistry>(ITEM_TAGS_KEY).also(::addRegistry) // @formatter:on @JvmStatic - fun getRegistry(key: PylonRegistryKey): PylonRegistry { + fun getRegistry(key: NamespacedKey): PylonRegistry { return getRegistryOrNull(key) ?: throw IllegalArgumentException("Registry $key not found") } @JvmStatic - fun getRegistryOrNull(key: PylonRegistryKey): PylonRegistry? { + fun getRegistryOrNull(key: NamespacedKey): PylonRegistry? { @Suppress("UNCHECKED_CAST") return registries[key] as? PylonRegistry } diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/registry/PylonRegistryKey.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/registry/PylonRegistryKey.kt deleted file mode 100644 index a37060db2..000000000 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/registry/PylonRegistryKey.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.github.pylonmc.pylon.core.registry - -import io.github.pylonmc.pylon.core.addon.PylonAddon -import io.github.pylonmc.pylon.core.block.PylonBlockSchema -import io.github.pylonmc.pylon.core.entity.PylonEntitySchema -import io.github.pylonmc.pylon.core.fluid.PylonFluid -import io.github.pylonmc.pylon.core.item.ItemTypeWrapper -import io.github.pylonmc.pylon.core.item.PylonItemSchema -import io.github.pylonmc.pylon.core.item.research.Research -import io.github.pylonmc.pylon.core.recipe.RecipeType -import io.github.pylonmc.pylon.core.gametest.GameTestConfig -import io.github.pylonmc.pylon.core.util.pylonKey -import net.kyori.adventure.key.Key -import org.bukkit.NamespacedKey -import org.bukkit.Tag -import org.bukkit.plugin.Plugin - -@JvmRecord -data class PylonRegistryKey(val namespace: String, val path: String) { - constructor(key: Key) : this(key.namespace(), key.value()) - constructor(plugin: Plugin, path: String) : this(NamespacedKey(plugin, path)) - - override fun toString(): String { - return "$namespace:$path" - } - - companion object { - // @formatter:off - @JvmField val ITEMS = PylonRegistryKey(pylonKey("items")) - @JvmField val BLOCKS = PylonRegistryKey(pylonKey("blocks")) - @JvmField val ENTITIES = PylonRegistryKey(pylonKey("entities")) - @JvmField val FLUIDS = PylonRegistryKey(pylonKey("fluids")) - @JvmField val GAMETESTS = PylonRegistryKey(pylonKey("gametests")) - @JvmField val ADDONS = PylonRegistryKey(pylonKey("addons")) - @JvmField val RECIPE_TYPES = PylonRegistryKey>(pylonKey("recipe_types")) - @JvmField val RESEARCHES = PylonRegistryKey(pylonKey("researches")) - @JvmField val ITEM_TAGS = PylonRegistryKey>(pylonKey("tags")) - // @formatter:on - } -} \ No newline at end of file diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/armor/ArmorTextureEngine.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/armor/ArmorTextureEngine.kt index d46cf1da1..3e840700d 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/armor/ArmorTextureEngine.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/armor/ArmorTextureEngine.kt @@ -28,8 +28,8 @@ object ArmorTextureEngine : PacketListener { @JvmStatic var Player.hasCustomArmorTextures: Boolean - get() = PylonConfig.ArmorTextureConfig.forced || this.persistentDataContainer.getOrDefault(customArmorTexturesKey, PersistentDataType.BOOLEAN, false) - set(value) = this.persistentDataContainer.set(customArmorTexturesKey, PersistentDataType.BOOLEAN, PylonConfig.ArmorTextureConfig.forced || value) + get() = PylonConfig.ArmorTextureConfig.FORCED || this.persistentDataContainer.getOrDefault(customArmorTexturesKey, PersistentDataType.BOOLEAN, false) + set(value) = this.persistentDataContainer.set(customArmorTexturesKey, PersistentDataType.BOOLEAN, PylonConfig.ArmorTextureConfig.FORCED || value) override fun onPacketSend(event: PacketSendEvent?) { if (event == null) return diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/block/BlockTextureEngine.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/block/BlockTextureEngine.kt index a79d3a4a5..706d27652 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/block/BlockTextureEngine.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/resourcepack/block/BlockTextureEngine.kt @@ -48,7 +48,7 @@ object BlockTextureEngine : Listener { /** * Periodically updates a share of the occluding cache, to ensure it stays up to date with changes in the world. - * Every [PylonConfig.BlockTextureConfig.occludingCacheRefreshInterval] ticks, it will refresh [PylonConfig.BlockTextureConfig.occludingCacheRefreshShare] + * Every [PylonConfig.BlockTextureConfig.OCCLUDING_CACHE_REFRESH_INTERVAL] ticks, it will refresh [PylonConfig.BlockTextureConfig.OCCLUDING_CACHE_REFRESH_SHARE] * percent of the cache, starting with the oldest entries. * * Normally, blocks occluding state is cached the first time its requested, and is only updated when placed or broken. @@ -57,16 +57,16 @@ object BlockTextureEngine : Listener { @JvmSynthetic internal val updateOccludingCacheJob = PylonCore.launch(start = CoroutineStart.LAZY) { while (true) { - delay(PylonConfig.BlockTextureConfig.occludingCacheRefreshInterval.ticks) + delay(PylonConfig.BlockTextureConfig.OCCLUDING_CACHE_REFRESH_INTERVAL.ticks) val now = System.currentTimeMillis() var refreshed = 0 - var toRefresh = ceil(occludingCache.size * PylonConfig.BlockTextureConfig.occludingCacheRefreshShare) + var toRefresh = ceil(occludingCache.size * PylonConfig.BlockTextureConfig.OCCLUDING_CACHE_REFRESH_SHARE) var entries = mutableListOf>() entries.addAll(occludingCache.entries) entries.sortBy { it.value.timestamp } for ((pos, data) in entries) { - if (now - data.timestamp <= PylonConfig.BlockTextureConfig.occludingCacheRefreshInterval) continue + if (now - data.timestamp <= PylonConfig.BlockTextureConfig.OCCLUDING_CACHE_REFRESH_INTERVAL) continue val world = pos.world ?: continue if (world.isChunkLoaded(pos.x, pos.z)) { @@ -86,25 +86,25 @@ object BlockTextureEngine : Listener { @JvmStatic var Player.hasCustomBlockTextures: Boolean - get() = (this.persistentDataContainer.getOrDefault(customBlockTexturesKey, PersistentDataType.BOOLEAN, PylonConfig.BlockTextureConfig.default) || PylonConfig.BlockTextureConfig.forced) - set(value) = this.persistentDataContainer.set(customBlockTexturesKey, PersistentDataType.BOOLEAN, value || PylonConfig.BlockTextureConfig.forced) + get() = (this.persistentDataContainer.getOrDefault(customBlockTexturesKey, PersistentDataType.BOOLEAN, PylonConfig.BlockTextureConfig.DEFAULT) || PylonConfig.BlockTextureConfig.FORCED) + set(value) = this.persistentDataContainer.set(customBlockTexturesKey, PersistentDataType.BOOLEAN, value || PylonConfig.BlockTextureConfig.FORCED) @JvmStatic var Player.cullingPreset: CullingPreset - get() = PylonConfig.BlockTextureConfig.cullingPresets.getOrElse(this.persistentDataContainer.getOrDefault(presetKey, PersistentDataType.STRING, PylonConfig.BlockTextureConfig.defaultCullingPreset.id)) { - PylonConfig.BlockTextureConfig.defaultCullingPreset + get() = PylonConfig.BlockTextureConfig.CULLING_PRESETS.getOrElse(this.persistentDataContainer.getOrDefault(presetKey, PersistentDataType.STRING, PylonConfig.BlockTextureConfig.DEFAULT_CULLING_PRESET.id)) { + PylonConfig.BlockTextureConfig.DEFAULT_CULLING_PRESET } set(value) = this.persistentDataContainer.set(presetKey, PersistentDataType.STRING, value.id) @JvmSynthetic internal fun insert(block: PylonBlock) { - if (!PylonConfig.BlockTextureConfig.enabled || block.disableBlockTextureEntity) return + if (!PylonConfig.BlockTextureConfig.ENABLED || block.disableBlockTextureEntity) return getOctree(block.block.world).insert(block) } @JvmSynthetic internal fun remove(block: PylonBlock) { - if (!PylonConfig.BlockTextureConfig.enabled || block.disableBlockTextureEntity) return + if (!PylonConfig.BlockTextureConfig.ENABLED || block.disableBlockTextureEntity) return getOctree(block.block.world).remove(block) block.blockTextureEntity?.let { for (viewer in it.viewers.toSet()) { @@ -115,7 +115,7 @@ object BlockTextureEngine : Listener { @JvmSynthetic internal fun getOctree(world: World): Octree { - check(PylonConfig.BlockTextureConfig.enabled) { "Tried to access BlockTextureEngine octree while custom block textures are disabled" } + check(PylonConfig.BlockTextureConfig.ENABLED) { "Tried to access BlockTextureEngine octree while custom block textures are disabled" } val border = world.worldBorder return octrees.getOrPut(world.uid) { @@ -133,7 +133,7 @@ object BlockTextureEngine : Listener { @JvmSynthetic internal fun launchBlockTextureJob(player: Player) { val uuid = player.uniqueId - if (!PylonConfig.BlockTextureConfig.enabled || !player.hasCustomBlockTextures || jobs.containsKey(uuid)) return + if (!PylonConfig.BlockTextureConfig.ENABLED || !player.hasCustomBlockTextures || jobs.containsKey(uuid)) return jobs[uuid] = PylonCore.launch(PylonCore.asyncDispatcher) { val visible = mutableSetOf() diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/util/PylonUtils.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/util/PylonUtils.kt index 3d0d1df36..9b6ac50ad 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/util/PylonUtils.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/util/PylonUtils.kt @@ -6,7 +6,6 @@ import io.github.pylonmc.pylon.core.PylonCore import io.github.pylonmc.pylon.core.addon.PylonAddon import io.github.pylonmc.pylon.core.config.Config import io.github.pylonmc.pylon.core.config.ConfigSection -import io.github.pylonmc.pylon.core.entity.display.transform.TransformUtil.yawToCardinalDirection import io.github.pylonmc.pylon.core.item.PylonItem import io.github.pylonmc.pylon.core.nms.NmsAccessor import io.github.pylonmc.pylon.core.registry.PylonRegistry @@ -86,6 +85,22 @@ fun vectorToBlockFace(vector: Vector3i): BlockFace { } } +/** + * Returns the yaw (in radians) that a face has, starting at NORTH and + * going counterclockwise. + * + * Only works for cardinal directions. + * + * @throws IllegalStateException if [face] is not a cardinal direction + */ +fun faceToYaw(face: BlockFace) = when (face) { + BlockFace.NORTH -> 0.0 + BlockFace.EAST -> -Math.PI / 2 + BlockFace.SOUTH -> Math.PI + BlockFace.WEST -> Math.PI / 2 + else -> throw IllegalArgumentException("$face is not a cardinal direction") +} + /** * Converts an orthogonal vector to a [BlockFace] * @@ -100,34 +115,23 @@ fun vectorToBlockFace(vector: Vector3f) = vectorToBlockFace(Vector3i(vector, Rou * @return The face that the vector is facing * @throws IllegalStateException if the vector is not pointing in a cardinal direction */ -// use toVector3f rather than toVector3i because toVector3i will floor components -fun vectorToBlockFace(vector: Vector) = vectorToBlockFace(vector.toVector3f()) +fun vectorToBlockFace(vector: Vector3d) = vectorToBlockFace(Vector3i(vector, RoundingMode.HALF_DOWN)) /** - * Rotates a BlockFace to the [player]'s reference frame. + * Converts an orthogonal vector to a [BlockFace] * - * @param player The player to act as the reference frame. Where the player is facing becomes NORTH. - * @param face The face to rotate - * @param allowVertical Whether we should include UP and DOWN - * @return The block face rotated to the player's reference frame + * @return The face that the vector is facing + * @throws IllegalStateException if the vector is not pointing in a cardinal direction */ -fun rotateToPlayerFacing(player: Player, face: BlockFace, allowVertical: Boolean): BlockFace { - var vector = face.direction.clone().rotateAroundY(yawToCardinalDirection(player.eyeLocation.yaw).toDouble()) - if (allowVertical) { - // never thought cross product would come in useful but here we go - val rightVector = vector.getCrossProduct(Vector(0.0, 1.0, 0.0)) - vector = - vector.rotateAroundNonUnitAxis(rightVector, -yawToCardinalDirection(player.eyeLocation.pitch).toDouble()) - } - return vectorToBlockFace(vector) -} +// use toVector3f rather than toVector3i because toVector3i will floor components +fun vectorToBlockFace(vector: Vector) = vectorToBlockFace(vector.toVector3f()) /** * Rotates [vector] to face a direction * * Assumes north to be the default direction (i.e. supplying north will result in no rotation) * - * @param face Must be a horizontal cardinal direction (north, east, south, west) + * @param face Must be a immediate direction (north, east, south, west, up, down) * @return The rotated vector */ fun rotateVectorToFace(vector: Vector3i, face: BlockFace) = when (face) { @@ -135,7 +139,9 @@ fun rotateVectorToFace(vector: Vector3i, face: BlockFace) = when (face) { BlockFace.EAST -> Vector3i(-vector.z, vector.y, vector.x) BlockFace.SOUTH -> Vector3i(-vector.x, vector.y, -vector.z) BlockFace.WEST -> Vector3i(vector.z, vector.y, -vector.x) - else -> throw IllegalArgumentException("$face is not a horizontal cardinal direction") + BlockFace.UP -> Vector3i(0, 1, 0) + BlockFace.DOWN -> Vector3i(0, -1, 0) + else -> throw IllegalArgumentException("$face is not a cardinal direction") } /** @@ -143,7 +149,7 @@ fun rotateVectorToFace(vector: Vector3i, face: BlockFace) = when (face) { * * Assumes north to be the default direction (i.e. supplying north will result in no rotation) * - * @param face Must be a horizontal cardinal direction (north, east, south, west) + * @param face Must be a immediate direction (north, east, south, west, up, down) * @return The rotated vector */ fun rotateVectorToFace(vector: Vector3d, face: BlockFace) = when (face) { @@ -151,9 +157,25 @@ fun rotateVectorToFace(vector: Vector3d, face: BlockFace) = when (face) { BlockFace.EAST -> Vector3d(-vector.z, vector.y, vector.x) BlockFace.SOUTH -> Vector3d(-vector.x, vector.y, -vector.z) BlockFace.WEST -> Vector3d(vector.z, vector.y, -vector.x) + BlockFace.UP -> Vector3d(0.0, 1.0, 0.0) + BlockFace.DOWN -> Vector3d(0.0, -1.0, 0.0) else -> throw IllegalArgumentException("$face is not a horizontal cardinal direction") } +/** + * Rotates [face] to be relative to [referenceFace]. + * + * Assumes north to be the default direction (i.e. supplying north will result in no rotation) + * + * Think of this like changing the direction of North. For example, if you change North to + * point where East would be, then suddenly East in your coordinate system becomes South. + * + * @param face Must be a horizontal cardinal direction (north, east, south, west) + * @return The rotated vector + */ +fun rotateFaceToReference(referenceFace: BlockFace, face: BlockFace) + = vectorToBlockFace(rotateVectorToFace(face.direction.toVector3d(), referenceFace)) + /** * @return Whether [vector] is a cardinal direction */ @@ -173,7 +195,7 @@ fun isCardinalDirection(vector: Vector3f) * @return The addon that [key] belongs to */ fun getAddon(key: NamespacedKey): PylonAddon = - PylonRegistry.Companion.ADDONS.find { addon -> addon.key.namespace == key.namespace } + PylonRegistry.ADDONS.find { addon -> addon.key.namespace == key.namespace } ?: error("Key does not have a corresponding addon; does your addon call registerWithPylon()?") /** diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/PlayerWailaConfig.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/PlayerWailaConfig.kt index 6446f1fa8..0f76a676c 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/PlayerWailaConfig.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/PlayerWailaConfig.kt @@ -19,7 +19,7 @@ class PlayerWailaConfig { player?.wailaConfig = this } - var type: Waila.Type = PylonConfig.WailaConfig.defaultType + var type: Waila.Type = PylonConfig.WailaConfig.DEFAULT_TYPE set(value) { field = value player?.wailaConfig = this diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/Waila.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/Waila.kt index ef5c5d488..6bacce46e 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/Waila.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/Waila.kt @@ -20,7 +20,6 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import net.kyori.adventure.bossbar.BossBar import net.kyori.adventure.text.Component -import org.bukkit.Bukkit import org.bukkit.attribute.Attribute import org.bukkit.entity.Entity import org.bukkit.entity.Player @@ -53,24 +52,24 @@ class Waila private constructor(private val player: Player, playerConfig: Player private val bossBar = BossBar.bossBar( Component.empty(), - PylonConfig.WailaConfig.defaultDisplay.progress, - PylonConfig.WailaConfig.defaultDisplay.color, - PylonConfig.WailaConfig.defaultDisplay.overlay + PylonConfig.WailaConfig.DEFAULT_DISPLAY.progress, + PylonConfig.WailaConfig.DEFAULT_DISPLAY.color, + PylonConfig.WailaConfig.DEFAULT_DISPLAY.overlay ) private fun send(display: WailaDisplay) { when (config.type) { Type.BOSSBAR -> { player.hideBossBar(bossBar) - val color = if (display.color in PylonConfig.WailaConfig.allowedBossBarColors) { + val color = if (display.color in PylonConfig.WailaConfig.ALLOWED_BOSS_BAR_COLORS) { display.color } else { - PylonConfig.WailaConfig.defaultDisplay.color + PylonConfig.WailaConfig.DEFAULT_DISPLAY.color } - val overlay = if (display.overlay in PylonConfig.WailaConfig.allowedBossBarOverlays) { + val overlay = if (display.overlay in PylonConfig.WailaConfig.ALLOWED_BOSS_BAR_OVERLAYS) { display.overlay } else { - PylonConfig.WailaConfig.defaultDisplay.overlay + PylonConfig.WailaConfig.DEFAULT_DISPLAY.overlay } bossBar.name(display.text) @@ -205,7 +204,7 @@ class Waila private constructor(private val player: Player, playerConfig: Player val waila = wailas[player.uniqueId]!! while (true) { waila.updateDisplay() - delay(PylonConfig.WailaConfig.tickInterval.ticks) + delay(PylonConfig.WailaConfig.TICK_INTERVAL.ticks) } }) } @@ -222,11 +221,11 @@ class Waila private constructor(private val player: Player, playerConfig: Player var Player.wailaConfig: PlayerWailaConfig get() = this.persistentDataContainer.getOrDefault(wailaKey, PylonSerializers.PLAYER_WAILA_CONFIG, PlayerWailaConfig()).apply { player = this@wailaConfig - if (!PylonConfig.WailaConfig.enabledTypes.contains(type)) { + if (!PylonConfig.WailaConfig.ENABLED_TYPES.contains(type)) { sendMessage(Component.translatable("pylon.pyloncore.message.waila.type-disabled").arguments( PylonArgument.of("type", type.name.lowercase()) )) - type = PylonConfig.WailaConfig.defaultType + type = PylonConfig.WailaConfig.DEFAULT_TYPE } } set(value) { diff --git a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/WailaDisplay.kt b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/WailaDisplay.kt index 66c33ba89..0526652e5 100644 --- a/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/WailaDisplay.kt +++ b/pylon-core/src/main/kotlin/io/github/pylonmc/pylon/core/waila/WailaDisplay.kt @@ -11,7 +11,7 @@ import net.kyori.adventure.text.Component @JvmRecord data class WailaDisplay @JvmOverloads constructor( val text: Component, - val color: BossBar.Color = PylonConfig.WailaConfig.defaultDisplay.color, - val overlay: BossBar.Overlay = PylonConfig.WailaConfig.defaultDisplay.overlay, - val progress: Float = PylonConfig.WailaConfig.defaultDisplay.progress + val color: BossBar.Color = PylonConfig.WailaConfig.DEFAULT_DISPLAY.color, + val overlay: BossBar.Overlay = PylonConfig.WailaConfig.DEFAULT_DISPLAY.overlay, + val progress: Float = PylonConfig.WailaConfig.DEFAULT_DISPLAY.progress ) \ No newline at end of file diff --git a/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingBlock.java b/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingBlock.java index 6e99b6e96..aa056525e 100644 --- a/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingBlock.java +++ b/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingBlock.java @@ -26,7 +26,7 @@ public TickingBlock (Block block, PersistentDataContainer pdc) { } @Override - public void tick(double deltaSeconds) { + public void tick() { ticks++; } } \ No newline at end of file diff --git a/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingErrorBlock.java b/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingErrorBlock.java index 7334687fd..268f3feb5 100644 --- a/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingErrorBlock.java +++ b/test/src/main/java/io/github/pylonmc/pylon/test/block/TickingErrorBlock.java @@ -24,7 +24,7 @@ public TickingErrorBlock(Block block, PersistentDataContainer pdc) { } @Override - public void tick(double deltaSeconds) { + public void tick() { throw new RuntimeException("This exception is thrown as part of a test"); } } \ No newline at end of file diff --git a/test/src/main/java/io/github/pylonmc/pylon/test/block/fluid/FluidProducer.java b/test/src/main/java/io/github/pylonmc/pylon/test/block/fluid/FluidProducer.java index fa237a8f3..9cf84ba58 100644 --- a/test/src/main/java/io/github/pylonmc/pylon/test/block/fluid/FluidProducer.java +++ b/test/src/main/java/io/github/pylonmc/pylon/test/block/fluid/FluidProducer.java @@ -4,6 +4,7 @@ import io.github.pylonmc.pylon.core.block.base.PylonFluidBlock; import io.github.pylonmc.pylon.core.block.base.PylonUnloadBlock; import io.github.pylonmc.pylon.core.block.context.BlockCreateContext; +import io.github.pylonmc.pylon.core.config.PylonConfig; import io.github.pylonmc.pylon.core.datatypes.PylonSerializers; import io.github.pylonmc.pylon.core.event.PylonBlockUnloadEvent; import io.github.pylonmc.pylon.core.fluid.FluidManager; @@ -56,9 +57,9 @@ public void onUnload(@NotNull PylonBlockUnloadEvent event) { } @Override - public @NotNull Map getSuppliedFluids(double deltaSeconds) { + public @NotNull Map getSuppliedFluids() { return Map.of( - getFluidType(), FLUID_PER_SECOND * deltaSeconds + getFluidType(), FLUID_PER_SECOND * PylonConfig.FLUID_TICK_INTERVAL / 20.0 ); } diff --git a/test/src/main/java/io/github/pylonmc/pylon/test/test/block/BlockEventErrorTest.java b/test/src/main/java/io/github/pylonmc/pylon/test/test/block/BlockEventErrorTest.java index eb7b3b0d5..12347a74b 100644 --- a/test/src/main/java/io/github/pylonmc/pylon/test/test/block/BlockEventErrorTest.java +++ b/test/src/main/java/io/github/pylonmc/pylon/test/test/block/BlockEventErrorTest.java @@ -21,7 +21,7 @@ public BlockEventErrorTest(){ .setUp(test -> { Block block = BlockStorage.placeBlock(test.location(), BlockEventError.KEY).getBlock(); Entity theRinger = test.location().getWorld().spawn(test.location().clone().add(1, 0, 0), Skeleton.class); - for(int i = 0; i < PylonConfig.getAllowedBlockErrors() + 1; i++){ + for(int i = 0; i < PylonConfig.ALLOWED_BLOCK_ERRORS + 1; i++){ new BellRingEvent(block, BlockFace.EAST, theRinger).callEvent(); } test.succeedWhen(() -> BlockStorage.get(block) instanceof PhantomBlock); diff --git a/test/src/main/java/io/github/pylonmc/pylon/test/test/entity/EntityEventErrorTest.java b/test/src/main/java/io/github/pylonmc/pylon/test/test/entity/EntityEventErrorTest.java index 7985580a5..0ded2598f 100644 --- a/test/src/main/java/io/github/pylonmc/pylon/test/test/entity/EntityEventErrorTest.java +++ b/test/src/main/java/io/github/pylonmc/pylon/test/test/entity/EntityEventErrorTest.java @@ -19,7 +19,7 @@ public EntityEventErrorTest(){ EntityEventError entity = new EntityEventError(test.location()); EntityStorage.add(entity); UUID entityUUID = entity.getUuid(); - for(int i = 0; i < PylonConfig.getAllowedEntityErrors() + 1; i++){ + for(int i = 0; i < PylonConfig.ALLOWED_ENTITY_ERRORS + 1; i++){ // Yes, this is cursed, yes it works. new PlayerInteractEntityEvent(null, entity.getEntity()).callEvent(); }