From c80859d643c3f2e30501314775f4628a709e462a Mon Sep 17 00:00:00 2001 From: xtex Date: Wed, 19 Jul 2023 21:34:25 +0800 Subject: [PATCH] refactor: block entity based projection block --- common/src/main/kotlin/quaedam/Quaedam.kt | 3 +- .../projection/EntityProjectionBlock.kt | 61 ++++++------------- .../quaedam/projection/ProjectionBlock.kt | 19 +++--- .../quaedam/projection/ProjectionEffect.kt | 2 +- .../projection/SimpleProjectionEntity.kt | 51 ++++++++++++++++ .../projection/misc/NoiseProjection.kt | 18 +++--- .../projection/misc/SkylightProjection.kt | 18 +++--- .../projection/misc/SoundProjection.kt | 18 +++--- .../projection/swarm/SwarmProjection.kt | 5 ++ .../projection/swarm/SwarmProjectionBlock.kt | 13 +--- .../quaedam/projector/ProjectorBlockEntity.kt | 2 +- 11 files changed, 115 insertions(+), 95 deletions(-) create mode 100644 common/src/main/kotlin/quaedam/projection/SimpleProjectionEntity.kt diff --git a/common/src/main/kotlin/quaedam/Quaedam.kt b/common/src/main/kotlin/quaedam/Quaedam.kt index 0dcd5f6..62ee12e 100644 --- a/common/src/main/kotlin/quaedam/Quaedam.kt +++ b/common/src/main/kotlin/quaedam/Quaedam.kt @@ -9,7 +9,8 @@ import net.minecraft.resources.ResourceLocation import net.minecraft.world.item.CreativeModeTab import net.minecraft.world.item.ItemStack import org.slf4j.LoggerFactory -import quaedam.projection.* +import quaedam.projection.ProjectionCommand +import quaedam.projection.ProjectionEffectType import quaedam.projection.misc.NoiseProjection import quaedam.projection.misc.SkylightProjection import quaedam.projection.misc.SoundProjection diff --git a/common/src/main/kotlin/quaedam/projection/EntityProjectionBlock.kt b/common/src/main/kotlin/quaedam/projection/EntityProjectionBlock.kt index 6a0dbe2..93c5208 100644 --- a/common/src/main/kotlin/quaedam/projection/EntityProjectionBlock.kt +++ b/common/src/main/kotlin/quaedam/projection/EntityProjectionBlock.kt @@ -1,59 +1,32 @@ package quaedam.projection +import dev.architectury.registry.registries.DeferredSupplier import net.minecraft.core.BlockPos -import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.item.ItemStack +import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.Level -import net.minecraft.world.level.LevelAccessor -import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.EntityBlock +import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState -import net.minecraft.world.level.material.MapColor -import net.minecraft.world.level.storage.loot.LootParams -import quaedam.projector.ProjectorBlockEntity -import quaedam.utils.getChunksNearby -abstract class EntityProjectionBlock

(properties: Properties = createProperties()) : Block(properties), - ProjectionProvider

{ +abstract class EntityProjectionBlock

(properties: Properties = createProperties()) : + ProjectionBlock

(properties), EntityBlock { companion object { - fun createProperties(): Properties = Properties.of() - .strength(3.5f) - .requiresCorrectToolForDrops() - .mapColor(MapColor.COLOR_GRAY) - - fun findNearbyProjectors(level: Level, pos: BlockPos) = level.getChunksNearby(pos, 1) - .flatMap { - it.blockEntities.filter { (_, v) -> v is ProjectorBlockEntity } - .keys - .filterNotNull() - } - .toSet() - + fun createProperties(): Properties = ProjectionBlock.createProperties() } - @Suppress("OVERRIDE_DEPRECATION") - override fun getDrops(blockState: BlockState, builder: LootParams.Builder) = listOf(ItemStack(asItem())) + abstract val blockEntity: DeferredSupplier>> - override fun setPlacedBy( - level: Level, - pos: BlockPos, - state: BlockState, - placer: LivingEntity?, - itemStack: ItemStack - ) { - super.setPlacedBy(level, pos, state, placer, itemStack) - if (!level.isClientSide) { - findNearbyProjectors(level, pos) - .forEach { (level.getBlockEntity(it) as ProjectorBlockEntity).checkUpdate() } - } - } + override fun newBlockEntity(pos: BlockPos, state: BlockState) = blockEntity.get().create(pos, state) - override fun destroy(level: LevelAccessor, pos: BlockPos, state: BlockState) { - super.destroy(level, pos, state) - if (level is Level && !level.isClientSide) { - findNearbyProjectors(level, pos) - .forEach { (level.getBlockEntity(it) as ProjectorBlockEntity).checkUpdate() } - } + @Suppress("UNCHECKED_CAST") + fun getProjection(level: Level, pos: BlockPos) = (level.getBlockEntity(pos) as SimpleProjectionEntity

).projection + + override fun applyProjectionEffect(level: ServerLevel, state: BlockState, pos: BlockPos) = getProjection(level, pos) + + inline fun applyChange(level: Level, pos: BlockPos, func: P.() -> Unit) { + getProjection(level, pos).apply(func) + sendUpdateToProjectors(level, pos) } } diff --git a/common/src/main/kotlin/quaedam/projection/ProjectionBlock.kt b/common/src/main/kotlin/quaedam/projection/ProjectionBlock.kt index cb0762b..a3af4e4 100644 --- a/common/src/main/kotlin/quaedam/projection/ProjectionBlock.kt +++ b/common/src/main/kotlin/quaedam/projection/ProjectionBlock.kt @@ -42,18 +42,21 @@ abstract class ProjectionBlock

(properties: Properties = cr itemStack: ItemStack ) { super.setPlacedBy(level, pos, state, placer, itemStack) + sendUpdateToProjectors(level, pos) + } + + override fun destroy(level: LevelAccessor, pos: BlockPos, state: BlockState) { + super.destroy(level, pos, state) + if (level is Level) { + sendUpdateToProjectors(level, pos) + } + } + + fun sendUpdateToProjectors(level: Level, pos: BlockPos) { if (!level.isClientSide) { findNearbyProjectors(level, pos) .forEach { (level.getBlockEntity(it) as ProjectorBlockEntity).checkUpdate() } } } - override fun destroy(level: LevelAccessor, pos: BlockPos, state: BlockState) { - super.destroy(level, pos, state) - if (level is Level && !level.isClientSide) { - findNearbyProjectors(level, pos) - .forEach { (level.getBlockEntity(it) as ProjectorBlockEntity).checkUpdate() } - } - } - } diff --git a/common/src/main/kotlin/quaedam/projection/ProjectionEffect.kt b/common/src/main/kotlin/quaedam/projection/ProjectionEffect.kt index 7fa50e1..07ff993 100644 --- a/common/src/main/kotlin/quaedam/projection/ProjectionEffect.kt +++ b/common/src/main/kotlin/quaedam/projection/ProjectionEffect.kt @@ -57,5 +57,5 @@ data class ProjectionEffectType(val constructor: () -> T) } interface ProjectionProvider

{ - fun createProjectionEffect(level: ServerLevel, state: BlockState, pos: BlockPos): P? + fun applyProjectionEffect(level: ServerLevel, state: BlockState, pos: BlockPos): P? } diff --git a/common/src/main/kotlin/quaedam/projection/SimpleProjectionEntity.kt b/common/src/main/kotlin/quaedam/projection/SimpleProjectionEntity.kt new file mode 100644 index 0000000..e6a637f --- /dev/null +++ b/common/src/main/kotlin/quaedam/projection/SimpleProjectionEntity.kt @@ -0,0 +1,51 @@ +package quaedam.projection + +import dev.architectury.registry.registries.RegistrySupplier +import net.minecraft.core.BlockPos +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.ClientGamePacketListener +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.state.BlockState + +class SimpleProjectionEntity

( + type: BlockEntityType>, + pos: BlockPos, + state: BlockState, + val projection: P +) : BlockEntity(type, pos, state) { + + companion object { + const val TAG_PROJECTION_EFFECT = "ProjectionEffect" + + fun

> createBlockEntityType( + block: RegistrySupplier, + default: () -> P, + ): BlockEntityType> { + val type = ValueContainer>>() + type.inner = BlockEntityType.Builder.of({ pos, state -> + SimpleProjectionEntity(type.inner!!, pos, state, default()) + }, block.get()).build(null) + return type.inner!! + } + } + + data class ValueContainer(var inner: E? = null) + + override fun saveAdditional(tag: CompoundTag) { + super.saveAdditional(tag) + tag.put(TAG_PROJECTION_EFFECT, projection.toNbt()) + } + + override fun load(tag: CompoundTag) { + super.load(tag) + projection.fromNbt(tag.getCompound(TAG_PROJECTION_EFFECT)) + } + + override fun getUpdateTag(): CompoundTag = saveWithoutMetadata() + + override fun getUpdatePacket(): Packet = ClientboundBlockEntityDataPacket.create(this) + +} \ No newline at end of file diff --git a/common/src/main/kotlin/quaedam/projection/misc/NoiseProjection.kt b/common/src/main/kotlin/quaedam/projection/misc/NoiseProjection.kt index de01ff1..9682356 100644 --- a/common/src/main/kotlin/quaedam/projection/misc/NoiseProjection.kt +++ b/common/src/main/kotlin/quaedam/projection/misc/NoiseProjection.kt @@ -1,15 +1,13 @@ package quaedam.projection.misc -import net.minecraft.core.BlockPos import net.minecraft.nbt.CompoundTag -import net.minecraft.server.level.ServerLevel import net.minecraft.world.item.BlockItem import net.minecraft.world.item.Item -import net.minecraft.world.level.block.state.BlockState import quaedam.Quaedam -import quaedam.projection.ProjectionBlock +import quaedam.projection.EntityProjectionBlock import quaedam.projection.ProjectionEffect import quaedam.projection.ProjectionEffectType +import quaedam.projection.SimpleProjectionEntity object NoiseProjection { @@ -29,15 +27,15 @@ object NoiseProjection { ProjectionEffectType { NoiseProjectionEffect() } }!! + val blockEntity = Quaedam.blockEntities.register(ID) { + SimpleProjectionEntity.createBlockEntityType(block, ::NoiseProjectionEffect) + }!! + } -object NoiseProjectionBlock : ProjectionBlock(createProperties().lightLevel { 3 }) { +object NoiseProjectionBlock : EntityProjectionBlock(createProperties().lightLevel { 3 }) { - override fun createProjectionEffect( - level: ServerLevel, - state: BlockState, - pos: BlockPos - ) = NoiseProjectionEffect() + override val blockEntity = NoiseProjection.blockEntity } diff --git a/common/src/main/kotlin/quaedam/projection/misc/SkylightProjection.kt b/common/src/main/kotlin/quaedam/projection/misc/SkylightProjection.kt index 3cdb562..6a8b048 100644 --- a/common/src/main/kotlin/quaedam/projection/misc/SkylightProjection.kt +++ b/common/src/main/kotlin/quaedam/projection/misc/SkylightProjection.kt @@ -1,15 +1,13 @@ package quaedam.projection.misc -import net.minecraft.core.BlockPos import net.minecraft.nbt.CompoundTag -import net.minecraft.server.level.ServerLevel import net.minecraft.world.item.BlockItem import net.minecraft.world.item.Item -import net.minecraft.world.level.block.state.BlockState import quaedam.Quaedam -import quaedam.projection.ProjectionBlock +import quaedam.projection.EntityProjectionBlock import quaedam.projection.ProjectionEffect import quaedam.projection.ProjectionEffectType +import quaedam.projection.SimpleProjectionEntity object SkylightProjection { @@ -29,15 +27,15 @@ object SkylightProjection { ProjectionEffectType { SkylightProjectionEffect() } }!! + val blockEntity = Quaedam.blockEntities.register(ID) { + SimpleProjectionEntity.createBlockEntityType(block, ::SkylightProjectionEffect) + }!! + } -object SkylightProjectionBlock : ProjectionBlock(createProperties().lightLevel { 3 }) { +object SkylightProjectionBlock : EntityProjectionBlock(createProperties().lightLevel { 3 }) { - override fun createProjectionEffect( - level: ServerLevel, - state: BlockState, - pos: BlockPos - ) = SkylightProjectionEffect() + override val blockEntity = SkylightProjection.blockEntity } diff --git a/common/src/main/kotlin/quaedam/projection/misc/SoundProjection.kt b/common/src/main/kotlin/quaedam/projection/misc/SoundProjection.kt index b0f7de7..c90e39d 100644 --- a/common/src/main/kotlin/quaedam/projection/misc/SoundProjection.kt +++ b/common/src/main/kotlin/quaedam/projection/misc/SoundProjection.kt @@ -1,15 +1,13 @@ package quaedam.projection.misc -import net.minecraft.core.BlockPos import net.minecraft.nbt.CompoundTag -import net.minecraft.server.level.ServerLevel import net.minecraft.world.item.BlockItem import net.minecraft.world.item.Item -import net.minecraft.world.level.block.state.BlockState import quaedam.Quaedam -import quaedam.projection.ProjectionBlock +import quaedam.projection.EntityProjectionBlock import quaedam.projection.ProjectionEffect import quaedam.projection.ProjectionEffectType +import quaedam.projection.SimpleProjectionEntity object SoundProjection { @@ -29,15 +27,15 @@ object SoundProjection { ProjectionEffectType { SoundProjectionEffect } }!! + val blockEntity = Quaedam.blockEntities.register(ID) { + SimpleProjectionEntity.createBlockEntityType(block) { SoundProjectionEffect } + }!! + } -object SoundProjectionBlock : ProjectionBlock(createProperties().lightLevel { 3 }) { +object SoundProjectionBlock : EntityProjectionBlock(createProperties().lightLevel { 3 }) { - override fun createProjectionEffect( - level: ServerLevel, - state: BlockState, - pos: BlockPos - ) = SoundProjectionEffect + override val blockEntity = SoundProjection.blockEntity } diff --git a/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjection.kt b/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjection.kt index bfa2192..ebec31a 100644 --- a/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjection.kt +++ b/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjection.kt @@ -4,6 +4,7 @@ import net.minecraft.world.item.BlockItem import net.minecraft.world.item.Item import quaedam.Quaedam import quaedam.projection.ProjectionEffectType +import quaedam.projection.SimpleProjectionEntity object SwarmProjection { @@ -23,6 +24,10 @@ object SwarmProjection { ProjectionEffectType { SwarmProjectionEffect() } }!! + val blockEntity = Quaedam.blockEntities.register(ID) { + SimpleProjectionEntity.createBlockEntityType(block, ::SwarmProjectionEffect) + }!! + init { ProjectedPersonEntity } diff --git a/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjectionBlock.kt b/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjectionBlock.kt index fc0fcce..c19c2a9 100644 --- a/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjectionBlock.kt +++ b/common/src/main/kotlin/quaedam/projection/swarm/SwarmProjectionBlock.kt @@ -1,16 +1,9 @@ package quaedam.projection.swarm -import net.minecraft.core.BlockPos -import net.minecraft.server.level.ServerLevel -import net.minecraft.world.level.block.state.BlockState -import quaedam.projection.ProjectionBlock +import quaedam.projection.EntityProjectionBlock -object SwarmProjectionBlock : ProjectionBlock() { +object SwarmProjectionBlock : EntityProjectionBlock() { - override fun createProjectionEffect( - level: ServerLevel, - state: BlockState, - pos: BlockPos - ) = SwarmProjectionEffect() + override val blockEntity = SwarmProjection.blockEntity } diff --git a/common/src/main/kotlin/quaedam/projector/ProjectorBlockEntity.kt b/common/src/main/kotlin/quaedam/projector/ProjectorBlockEntity.kt index db3b1e8..34e04a5 100644 --- a/common/src/main/kotlin/quaedam/projector/ProjectorBlockEntity.kt +++ b/common/src/main/kotlin/quaedam/projector/ProjectorBlockEntity.kt @@ -132,7 +132,7 @@ class ProjectorBlockEntity(pos: BlockPos, state: BlockState) : val blockState = level.getBlockState(pos) val block = blockState.block if (block is ProjectionProvider<*>) { - val projection = block.createProjectionEffect(level, blockState, pos) + val projection = block.applyProjectionEffect(level, blockState, pos) if (projection != null) { effects[projection.type] = projection }