diff --git a/nms/src/main/kotlin/io/github/pylonmc/rebar/nms/entity/BlockTextureEntityImpl.kt b/nms/src/main/kotlin/io/github/pylonmc/rebar/nms/entity/BlockTextureEntityImpl.kt index f96fe58de..beed9e6c2 100644 --- a/nms/src/main/kotlin/io/github/pylonmc/rebar/nms/entity/BlockTextureEntityImpl.kt +++ b/nms/src/main/kotlin/io/github/pylonmc/rebar/nms/entity/BlockTextureEntityImpl.kt @@ -11,6 +11,7 @@ import io.github.pylonmc.rebar.entity.packet.BlockTextureEntity.Companion.SCALE_ import io.github.pylonmc.rebar.entity.packet.BlockTextureEntity.Companion.SCALE_DISTANCE_THRESHOLD import io.github.pylonmc.rebar.util.IMMEDIATE_FACES import io.github.pylonmc.rebar.util.delayTicks +import io.github.pylonmc.rebar.util.isChunkLoaded import io.github.pylonmc.rebar.util.position.BlockPosition import kotlinx.coroutines.launch import net.minecraft.network.protocol.Packet @@ -376,7 +377,7 @@ class BlockTextureEntityImpl : BlockTextureEntity, SyncedDataHolder { var brightestLight = 0.toByte() if (brightest !== ZERO_VECTOR) { val delegateBlock = block.block.getRelative(brightest.x.toInt(), brightest.y.toInt(), brightest.z.toInt()) as? CraftBlock - if (delegateBlock?.blockState?.hasLightingData ?: false) { + if (delegateBlock != null && delegateBlock.isChunkLoaded && delegateBlock.blockState.hasLightingData) { brightestLight = delegateBlock.lightLevel if (brightestLight >= 15) return brightest brightestFace = IMMEDIATE_FACES.firstOrNull { it.modX == brightest.x.toInt() && it.modY == brightest.y.toInt() && it.modZ == brightest.z.toInt() } @@ -386,7 +387,7 @@ class BlockTextureEntityImpl : BlockTextureEntity, SyncedDataHolder { for (face in IMMEDIATE_FACES) { if (brightestFace == face) continue val delegateBlock = block.block.getRelative(face) as? CraftBlock ?: continue - if (delegateBlock.blockState.hasLightingData) { + if (delegateBlock.isChunkLoaded && delegateBlock.blockState.hasLightingData) { val light = delegateBlock.lightLevel if (light > brightestLight) { brightestLight = light diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/BlockStorage.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/BlockStorage.kt index 7ffbc27dd..b056c056d 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/BlockStorage.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/BlockStorage.kt @@ -607,7 +607,7 @@ object BlockStorage : Listener { } else if (block.schema.key.isFromAddon(addon)) { RebarBlockSchema.schemaCache[block.block.position] = PhantomBlock.schema RebarBlock.serialize(block, block.block.chunk.persistentDataContainer.adapterContext)?.let { pdc -> - PhantomBlock(pdc, block.schema.key, block.block) + PhantomBlock(pdc, block.schema.key, block.block, true) } } else { null diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/PhantomBlock.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/PhantomBlock.kt index 98d38d366..8718a5892 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/PhantomBlock.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/PhantomBlock.kt @@ -41,7 +41,8 @@ import java.util.UUID class PhantomBlock( val pdc: PersistentDataContainer, val erroredBlockKey: NamespacedKey, - block: Block + block: Block, + val preventErrorEntity: Boolean = false ) : RebarBlock(block, pdc), BlockBreakRebarBlockHandler { override var disableBlockTextureEntity: Boolean = true @@ -62,20 +63,23 @@ class PhantomBlock( } init { - errorOutlineEntityId = block.world.spawn(block.location.toCenterLocation(), ItemDisplay::class.java) { display -> - display.setItemStack(ItemStackBuilder.of(Material.BARRIER).set(DataComponentTypes.ITEM_MODEL, PhantomBlock.key).build()) - display.glowColorOverride = Color.RED - display.isGlowing = true - display.isPersistent = false - display.brightness = Display.Brightness(15, 15) - display.setTransformationMatrix(TransformBuilder().scale(1.001f).buildForItemDisplay()) - }.uniqueId + if (!preventErrorEntity) { + errorOutlineEntityId = block.world.spawn(block.location.toCenterLocation(), ItemDisplay::class.java) { display -> + display.setItemStack(ItemStackBuilder.of(Material.BARRIER).set(DataComponentTypes.ITEM_MODEL, PhantomBlock.key).build()) + display.glowColorOverride = Color.RED + display.isGlowing = true + display.isPersistent = false + display.brightness = Display.Brightness(15, 15) + display.setTransformationMatrix(TransformBuilder().scale(1.001f).buildForItemDisplay()) + }.uniqueId + } } override fun onPostBlockBreak(context: BlockBreakContext) { errorOutlineEntityId?.let { uuid -> block.world.getEntity(uuid)?.remove() } + errorOutlineEntityId = null } override fun getWaila(player: Player): WailaDisplay? { diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/RebarBlock.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/RebarBlock.kt index b72095707..8e1e59022 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/RebarBlock.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/RebarBlock.kt @@ -189,8 +189,9 @@ open class RebarBlock private constructor(val block: Block) : Keyed { /** * Returns the item that should be used to display the block's texture. * - * By default, returns the item with the same key as the block, marked with the - * [rebarBlockTextureEntityKey]. The item will also have custom model data with + * By default, returns the rebar item with the same key as the block, marked with the + * [rebarBlockTextureEntityKey], or if there is no matching rebar item, an item with + * the block material & key. The item will also have custom model data with * the vanilla block state properties of the block, merged with any custom * properties provided by the block. (see [getBlockTextureProperties]) * This allows resource packs to provide different models/textures for different @@ -201,14 +202,23 @@ open class RebarBlock private constructor(val block: Block) : Keyed { * * @return the item that should be used to display the block's texture */ - open fun getBlockTextureItem() = defaultItem?.getItemStack()?.let { ItemStackBuilder(it) }?.apply { - editPdc { it.set(rebarBlockTextureEntityKey, RebarSerializers.BOOLEAN, true) } - val properties = NmsAccessor.instance.getStateProperties(block, getBlockTextureProperties()) - for ((property, value) in properties) { - addCustomModelDataString("$property=$value") + open fun getBlockTextureItem(): ItemStack? { + val builder = if (defaultItem != null) { + ItemStackBuilder.of(defaultItem.getItemStack()) + } else { + ItemStackBuilder.of(schema.material) + .addCustomModelDataString(key.toString()) } - set(DataComponentTypes.ITEM_MODEL, Key.key("air")) - }?.build() + + return builder.apply { + editPdc { it.set(rebarBlockTextureEntityKey, RebarSerializers.BOOLEAN, true) } + val properties = NmsAccessor.instance.getStateProperties(block, getBlockTextureProperties()) + for ((property, value) in properties) { + addCustomModelDataString("$property=$value") + } + set(DataComponentTypes.ITEM_MODEL, Key.key("air")) + }.build() + } /** * WAILA is the text that shows up when looking at a block to tell you what the block is. diff --git a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/TickingRebarBlock.kt b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/TickingRebarBlock.kt index 68ec45468..d5e4ad9a2 100644 --- a/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/TickingRebarBlock.kt +++ b/rebar/src/main/kotlin/io/github/pylonmc/rebar/block/interfaces/TickingRebarBlock.kt @@ -156,13 +156,17 @@ interface TickingRebarBlock { private val dispatchers = mutableMapOf() private fun startTicker(tickingBlock: TickingRebarBlock) { + if (tickingBlock.tickingData.job != null) { + tickingBlock.tickingData.job!!.cancel() + } + val rebarBlock = tickingBlock as RebarBlock val dispatcher = dispatchers.getOrPut(rebarBlock.schema) { if (tickingBlock.isAsync) Dispatchers.Default else Rebar.mainThreadDispatcher } val scope = ChunkScope(Rebar.scope.coroutineContext.createChildContext(), rebarBlock.block.chunk.position) - tickingBlocks[tickingBlock]?.job = scope.launch(dispatcher) { + tickingBlock.tickingData.job = scope.launch(dispatcher) { while (true) { delayTicks(tickingBlock.tickInterval.toLong()) try {