diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/api/VsAPI.kt b/common/src/main/kotlin/org/valkyrienskies/mod/api/VsAPI.kt new file mode 100644 index 000000000..270bf4ebc --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/api/VsAPI.kt @@ -0,0 +1,56 @@ +package org.valkyrienskies.mod.api + +import net.minecraft.client.gui.screens.Screen +import net.minecraft.client.multiplayer.ClientLevel +import net.minecraft.core.BlockPos +import net.minecraft.world.level.ChunkPos +import net.minecraft.world.level.Level +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.entity.Entity + +import org.jetbrains.annotations.ApiStatus.* +import org.valkyrienskies.core.api.VsCoreApi +import org.valkyrienskies.core.api.event.ListenableEvent +import org.valkyrienskies.core.api.ships.* +import org.valkyrienskies.mod.api.events.PostRenderShipEvent +import org.valkyrienskies.mod.api.events.PreRenderShipEvent +import org.valkyrienskies.mod.api.events.RegisterBlockStateEvent + +@NonExtendable +interface VsApi : VsCoreApi { + + /** + * This event gets called when it's time to register physics block states for Minecraft block states. + */ + @get:Experimental + val registerBlockStateEvent: ListenableEvent + + @get:Experimental + val preRenderShipEvent: ListenableEvent + + @get:Experimental + val postRenderShipEvent: ListenableEvent + + fun isShipMountingEntity(entity: Entity): Boolean + + @Deprecated(message = "The legacy VS config system will be replaced soon. " + + "Migrate to another config library, or the new system when it's released. ") + fun createConfigScreenLegacy(parent: Screen, vararg configs: Class<*>): Screen + + /** + * Get the ship with the chunk claim that contains [pos], if it exists. + * + * If either parameter is null, this will return null. + * + * @param level The [Level] to look for the ship in. If [level] is a + * [ServerLevel], this will return a [ServerShip]. If [level] is a + * [ClientLevel], this will return a [ClientShip]. + * + * @param pos A block position in the Shipyard + */ + fun getShipManagingBlock(level: Level?, pos: BlockPos?): Ship? + + fun getShipManagingChunk(level: Level?, pos: ChunkPos?): Ship? + + fun getShipManagingChunk(level: Level?, chunkX: Int, chunkZ: Int): Ship? +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/api/events/PostRenderShipEvent.kt b/common/src/main/kotlin/org/valkyrienskies/mod/api/events/PostRenderShipEvent.kt new file mode 100644 index 000000000..33bbd6de3 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/api/events/PostRenderShipEvent.kt @@ -0,0 +1,6 @@ +package org.valkyrienskies.mod.api.events + +import org.jetbrains.annotations.ApiStatus.Experimental + +@Experimental +interface PostRenderShipEvent diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/api/events/PreRenderShipEvent.kt b/common/src/main/kotlin/org/valkyrienskies/mod/api/events/PreRenderShipEvent.kt new file mode 100644 index 000000000..2d99dbf51 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/api/events/PreRenderShipEvent.kt @@ -0,0 +1,6 @@ +package org.valkyrienskies.mod.api.events + +import org.jetbrains.annotations.ApiStatus.Experimental + +@Experimental +interface PreRenderShipEvent diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/api/events/RegisterBlockStateEvent.kt b/common/src/main/kotlin/org/valkyrienskies/mod/api/events/RegisterBlockStateEvent.kt new file mode 100644 index 000000000..12800615b --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/api/events/RegisterBlockStateEvent.kt @@ -0,0 +1,25 @@ +package org.valkyrienskies.mod.api.events + +import net.minecraft.world.level.block.state.BlockState +import org.jetbrains.annotations.ApiStatus.Experimental +import org.valkyrienskies.core.api.physics.blockstates.LiquidState +import org.valkyrienskies.core.api.physics.blockstates.SolidState + +@Experimental +interface RegisterBlockStateEvent { + + fun newLiquidStateBuilder(): LiquidState.Builder + fun buildLiquidState(block: LiquidState.Builder.() -> Unit): LiquidState + fun newSolidStateBuilder(): SolidState.Builder + fun buildSolidState(block: SolidState.Builder.() -> Unit): SolidState + + fun register(state: BlockState, solidState: SolidState) + fun register(state: BlockState, liquidState: LiquidState) + + /** + * Registers the Minecraft [state] to be represented by [LiquidState] and [SolidState] in the same block. + * This is useful for e.g., a waterlogged chest, where the [liquidState] would be water and the [solidState] would + * be the chest shape. + */ + fun register(state: BlockState, liquidState: LiquidState, solidState: SolidState) +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/api_impl/events/RegisterBlockStateEventImpl.kt b/common/src/main/kotlin/org/valkyrienskies/mod/api_impl/events/RegisterBlockStateEventImpl.kt new file mode 100644 index 000000000..683019ebe --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/api_impl/events/RegisterBlockStateEventImpl.kt @@ -0,0 +1,36 @@ +package org.valkyrienskies.mod.api_impl.events + +import net.minecraft.world.level.block.state.BlockState +import org.valkyrienskies.core.api.physics.blockstates.LiquidState +import org.valkyrienskies.core.api.physics.blockstates.SolidState +import org.valkyrienskies.core.apigame.physics.blockstates.VsBlockState +import org.valkyrienskies.mod.api.events.RegisterBlockStateEvent +import org.valkyrienskies.mod.common.ValkyrienSkiesMod.vsCore + +class RegisterBlockStateEventImpl : RegisterBlockStateEvent { + val toRegister = mutableListOf>() + + override fun newLiquidStateBuilder(): LiquidState.Builder = + vsCore.newLiquidStateBuilder() + + override fun buildLiquidState(block: LiquidState.Builder.() -> Unit): LiquidState = + vsCore.newLiquidStateBuilder().apply(block).build() + + override fun newSolidStateBuilder(): SolidState.Builder = + vsCore.newSolidStateBuilder() + + override fun buildSolidState(block: SolidState.Builder.() -> Unit): SolidState = + vsCore.newSolidStateBuilder().apply(block).build() + + override fun register(state: BlockState, solidState: SolidState) { + toRegister.add(Pair(state, VsBlockState(solidState, null))) + } + + override fun register(state: BlockState, liquidState: LiquidState) { + toRegister.add(Pair(state, VsBlockState(null, liquidState))) + } + + override fun register(state: BlockState, liquidState: LiquidState, solidState: SolidState) { + toRegister.add(Pair(state, VsBlockState(solidState, liquidState))) + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/api_impl/events/VSApiImpl.kt b/common/src/main/kotlin/org/valkyrienskies/mod/api_impl/events/VSApiImpl.kt new file mode 100644 index 000000000..3749d133e --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/api_impl/events/VSApiImpl.kt @@ -0,0 +1,44 @@ +package org.valkyrienskies.mod.api_impl.events + +import net.minecraft.client.gui.screens.Screen +import net.minecraft.core.BlockPos +import net.minecraft.world.entity.Entity +import net.minecraft.world.level.ChunkPos +import net.minecraft.world.level.Level +import org.valkyrienskies.core.api.ships.Ship +import org.valkyrienskies.core.util.events.EventEmitterImpl +import org.valkyrienskies.mod.api.VsApi +import org.valkyrienskies.mod.api.events.PostRenderShipEvent +import org.valkyrienskies.mod.api.events.PreRenderShipEvent +import org.valkyrienskies.mod.api.events.RegisterBlockStateEvent +import org.valkyrienskies.mod.common.entity.ShipMountingEntity +import org.valkyrienskies.mod.common.getShipManagingPos +import org.valkyrienskies.mod.compat.clothconfig.VSClothConfig + +class VsApiImpl : VsApi { + + override val registerBlockStateEvent = EventEmitterImpl() + override val preRenderShipEvent = EventEmitterImpl() + override val postRenderShipEvent = EventEmitterImpl() + + override fun isShipMountingEntity(entity: Entity): Boolean { + return entity is ShipMountingEntity + } + + override fun createConfigScreenLegacy(parent: Screen, vararg configs: Class<*>): Screen { + return VSClothConfig.createConfigScreenFor(parent, *configs) + } + + + override fun getShipManagingBlock(level: Level?, pos: BlockPos?): Ship? { + return pos?.let { level?.getShipManagingPos(it) } + } + + override fun getShipManagingChunk(level: Level?, pos: ChunkPos?): Ship? { + return pos?.let { level?.getShipManagingPos(it) } + } + + override fun getShipManagingChunk(level: Level?, chunkX: Int, chunkZ: Int): Ship? { + return level?.getShipManagingPos(chunkX, chunkZ) + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt b/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt index ead7d3c3b..9bbe733a6 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/compat/clothconfig/VSClothConfig.kt @@ -19,7 +19,6 @@ import org.apache.commons.lang3.StringUtils import org.valkyrienskies.core.impl.config.SidedVSConfigClass import org.valkyrienskies.core.impl.util.serialization.VSJacksonUtil import org.valkyrienskies.mod.common.vsCore - import java.util.Optional object VSClothConfig { @@ -27,6 +26,7 @@ object VSClothConfig { @JvmStatic fun createConfigScreenFor(parent: Screen, vararg configClassesJ: Class<*>): Screen { val configClasses = configClassesJ.map(vsCore::getRegisteredConfigLegacy) + return ConfigBuilder.create().apply { parentScreen = parent @@ -111,7 +111,7 @@ object VSClothConfig { val enum: ArrayNode? = schema["enum"] as? ArrayNode val type = schema["type"].asText() - val tooltip: TextComponent? = null + val tooltip: Component? = null when { type == "integer" -> { @@ -243,7 +243,7 @@ object VSClothConfig { val newValue = try { mapper.readTree(str) } catch (ex: JsonProcessingException) { - return@setErrorSupplier Optional.of(TextComponent(ex.message)) + return@setErrorSupplier Optional.of(TextComponent(ex.message ?: "")) } getValidationMessageComponent(newValue)