Skip to content

Commit b031b8a

Browse files
authored
Merge pull request #635 from pylonmc/idra/new-drills
Multiblock utils
2 parents aa9ec05 + 0f6e714 commit b031b8a

File tree

4 files changed

+102
-3
lines changed

4 files changed

+102
-3
lines changed

rebar/src/main/kotlin/io/github/pylonmc/rebar/block/base/RebarSimpleMultiblock.kt

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import io.github.pylonmc.rebar.block.RebarBlockSchema
99
import io.github.pylonmc.rebar.datatypes.RebarSerializers
1010
import io.github.pylonmc.rebar.entity.EntityStorage
1111
import io.github.pylonmc.rebar.entity.RebarEntity
12-
import io.github.pylonmc.rebar.entity.base.RebarInteractEntity
1312
import io.github.pylonmc.rebar.entity.display.BlockDisplayBuilder
1413
import io.github.pylonmc.rebar.entity.display.ItemDisplayBuilder
1514
import io.github.pylonmc.rebar.entity.display.transform.TransformBuilder
@@ -19,10 +18,12 @@ import io.github.pylonmc.rebar.event.RebarBlockSerializeEvent
1918
import io.github.pylonmc.rebar.event.RebarBlockUnloadEvent
2019
import io.github.pylonmc.rebar.item.builder.ItemStackBuilder
2120
import io.github.pylonmc.rebar.registry.RebarRegistry
21+
import io.github.pylonmc.rebar.util.getRelative
2222
import io.github.pylonmc.rebar.util.position.ChunkPosition
2323
import io.github.pylonmc.rebar.util.position.position
2424
import io.github.pylonmc.rebar.util.rebarKey
2525
import io.github.pylonmc.rebar.util.rotateVectorToFace
26+
import io.github.pylonmc.rebar.waila.Waila
2627
import io.github.pylonmc.rebar.waila.WailaDisplay
2728
import kotlinx.coroutines.delay
2829
import net.kyori.adventure.text.Component
@@ -38,7 +39,6 @@ import org.bukkit.entity.ItemDisplay
3839
import org.bukkit.entity.Player
3940
import org.bukkit.event.EventHandler
4041
import org.bukkit.event.Listener
41-
import org.bukkit.event.player.PlayerInteractEntityEvent
4242
import org.bukkit.persistence.PersistentDataContainer
4343
import org.bukkit.util.Vector
4444
import org.jetbrains.annotations.ApiStatus
@@ -89,6 +89,14 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
8989
interface MultiblockComponent {
9090
fun matches(block: Block): Boolean
9191

92+
/**
93+
* Sets [block] to a 'default' value which matches this MultiblockComponent.
94+
*
95+
* For example, if a MultiblockComponent can be grass or dirt, this should set
96+
* the block to either grass or dirt
97+
*/
98+
fun placeDefaultBlock(block: Block)
99+
92100
companion object {
93101

94102
@JvmStatic
@@ -147,6 +155,12 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
147155

148156
override fun matches(block: Block): Boolean = !BlockStorage.isRebarBlock(block) && block.type in materials
149157

158+
override fun placeDefaultBlock(block: Block) {
159+
if (block.type.isAir && !BlockStorage.isRebarBlock(block)) {
160+
block.type = materials.first()
161+
}
162+
}
163+
150164
override fun spawnGhostBlock(block: Block): UUID {
151165
val blockDataList = blockDataList()
152166
val display = BlockDisplayBuilder()
@@ -215,6 +229,12 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
215229
return false
216230
}
217231

232+
override fun placeDefaultBlock(block: Block) {
233+
if (block.type.isAir && !BlockStorage.isRebarBlock(block)) {
234+
block.blockData = blockDatas.first()
235+
}
236+
}
237+
218238
override fun spawnGhostBlock(block: Block): UUID {
219239
val stringDatas: List<String> = blockDatas.map { it.getAsString(true) }
220240
val display = BlockDisplayBuilder()
@@ -265,6 +285,10 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
265285
return false
266286
}
267287

288+
override fun placeDefaultBlock(block: Block) {
289+
multiblockComponents.first().placeDefaultBlock(block)
290+
}
291+
268292
override fun spawnGhostBlocks(block: Block): List<UUID> {
269293
var blockDisplay: BlockDisplay? = null
270294
var itemDisplay: ItemDisplay? = null
@@ -353,6 +377,12 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
353377

354378
override fun matches(block: Block): Boolean = BlockStorage.get(block)?.schema?.key == key
355379

380+
override fun placeDefaultBlock(block: Block) {
381+
if (block.type.isAir && !BlockStorage.isRebarBlock(block)) {
382+
BlockStorage.placeBlock(block, key)
383+
}
384+
}
385+
356386
override fun spawnGhostBlock(block: Block): UUID {
357387
val schema = schema()
358388
val display = ItemDisplayBuilder()
@@ -377,6 +407,11 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
377407
*/
378408
val components: Map<Vector3i, MultiblockComponent>
379409

410+
/**
411+
* Automatically implemented by RebarBlock
412+
*/
413+
fun getWaila(player: Player): WailaDisplay?
414+
380415
/**
381416
* Sets the 'direction' we expect the multiblock to be built in. North is considered the default facing direction -
382417
* ie setFacing(BlockFace.NORTH) will preserve the original multiblock structure without rotating it.
@@ -471,6 +506,27 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
471506
val maxCorner: Vector3i
472507
get() = Vector3i(horizontalRadius, components.keys.maxOf { it.y }, horizontalRadius)
473508

509+
fun getMultiblockBlock(position: Vector3i): Block {
510+
val direction = getMultiblockDirection()
511+
return if (direction != null) {
512+
block.getRelative(rotateVectorToFace(position, direction))
513+
} else {
514+
block.getRelative(position)
515+
}
516+
}
517+
518+
fun getMultiblockComponent(position: Vector3i) =
519+
BlockStorage.get(getMultiblockBlock(position))
520+
521+
fun <T> getMultiblockComponent(clazz: Class<T>, position: Vector3i) =
522+
BlockStorage.getAs(clazz, getMultiblockBlock(position))
523+
524+
fun getMultiblockComponentOrThrow(position: Vector3i) =
525+
getMultiblockComponent(position) ?: throw IllegalStateException("There is no Rebar block at $position")
526+
527+
fun <T> getMultiblockComponentOrThrow(clazz: Class<T>, position: Vector3i) =
528+
getMultiblockComponent(clazz, position) ?: throw IllegalStateException("There is no Rebar block at $position or it is not of type $clazz")
529+
474530
override val chunksOccupied: Set<ChunkPosition>
475531
get() {
476532
val chunks = mutableSetOf<ChunkPosition>()
@@ -505,13 +561,19 @@ interface RebarSimpleMultiblock : RebarMultiblock, RebarEntityHolderBlock, Rebar
505561
EntityStorage.get(heldEntities[key]!!)!!.entity.remove()
506562
heldEntities.remove(key)
507563
}
564+
for (position in components.keys) {
565+
Waila.addWailaOverride(getMultiblockBlock(position), this::getWaila)
566+
}
508567
}
509568

510569
@MustBeInvokedByOverriders
511570
override fun onMultiblockUnformed(partUnloaded: Boolean) {
512571
if (!partUnloaded) {
513572
spawnGhostBlocks()
514573
}
574+
for (position in components.keys) {
575+
Waila.removeWailaOverride(getMultiblockBlock(position))
576+
}
515577
}
516578

517579
override fun isPartOfMultiblock(otherBlock: Block): Boolean = validStructures().any {

rebar/src/main/kotlin/io/github/pylonmc/rebar/command/RebarCommand.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import io.github.pylonmc.rebar.Rebar
1212
import io.github.pylonmc.rebar.addon.RebarAddon
1313
import io.github.pylonmc.rebar.block.BlockStorage
1414
import io.github.pylonmc.rebar.block.RebarBlockSchema
15+
import io.github.pylonmc.rebar.block.base.RebarSimpleMultiblock
1516
import io.github.pylonmc.rebar.content.debug.DebugWaxedWeatheredCutCopperStairs
1617
import io.github.pylonmc.rebar.content.guide.RebarGuide
1718
import io.github.pylonmc.rebar.entity.display.transform.Rotation
@@ -464,6 +465,36 @@ private val setphantom = buildCommand("setphantom") {
464465
}
465466
}
466467

468+
private val finishMultiblock = buildCommand("finishmultiblock") {
469+
permission("rebar.command.finishmultiblock")
470+
executesWithPlayer { player ->
471+
RebarMetrics.onCommandRun("/rb finishmultiblock")
472+
473+
val multiblock = player.getTargetBlockExact(5)?.let {
474+
BlockStorage.getAs<RebarSimpleMultiblock>(it)
475+
}
476+
if (multiblock == null) {
477+
player.sendFeedback("finishmultiblock.failed")
478+
return@executesWithPlayer
479+
}
480+
481+
for ((position, block) in multiblock.components) {
482+
block.placeDefaultBlock(multiblock.getMultiblockBlock(position))
483+
}
484+
485+
// finish sub-multiblocks (e.g. hatches)
486+
for ((position, block) in multiblock.components) {
487+
BlockStorage.getAs<RebarSimpleMultiblock>(multiblock.getMultiblockBlock(position))?.let { subMultiblock ->
488+
for ((position, block) in subMultiblock.components) {
489+
block.placeDefaultBlock(subMultiblock.getMultiblockBlock(position))
490+
}
491+
}
492+
}
493+
494+
player.sendFeedback("finishmultiblock.success")
495+
}
496+
}
497+
467498
@JvmSynthetic
468499
internal val ROOT_COMMAND = buildCommand("rebar") {
469500
permission("rebar.command.guide")
@@ -482,6 +513,7 @@ internal val ROOT_COMMAND = buildCommand("rebar") {
482513
then(research)
483514
then(exposeRecipeConfig)
484515
then(confetti)
516+
then(finishMultiblock)
485517
}
486518

487519
@JvmSynthetic

rebar/src/main/kotlin/io/github/pylonmc/rebar/util/RebarUtils.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,4 +611,6 @@ fun getBlockBreakTicks(tool: ItemStack, block: Block)
611611
/**
612612
* Schedules the entity to be removed next tick
613613
*/
614-
fun Entity.scheduleRemove() = Bukkit.getScheduler().runTask(Rebar, this::remove)
614+
fun Entity.scheduleRemove() = Bukkit.getScheduler().runTask(Rebar, this::remove)
615+
616+
fun Block.getRelative(vector: Vector3i) = this.getRelative(vector.x, vector.y, vector.z)

rebar/src/main/resources/lang/en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ message:
9898
exposerecipe:
9999
not-configurable: "<red>This recipe type is not configurable"
100100
warning: "<yellow>Warning: exposing recipe configs will keep them from updating automatically. Delete %file% to revert"
101+
finishmultiblock:
102+
failed: "<red>You are not looking at a multiblock"
103+
success: "Finished the multiblock"
101104

102105
waila:
103106
type-disabled: "<red>This server no longer permits the your previously set %type% WAILA display type, it has been reset to default"

0 commit comments

Comments
 (0)