Skip to content

Commit 0d4df28

Browse files
authored
Merge pull request #726 from pylonmc/balugaq/rebar-fire
Rebar fire
2 parents 09088e6 + 62e1c70 commit 0d4df28

3 files changed

Lines changed: 150 additions & 1 deletion

File tree

rebar/src/main/kotlin/io/github/pylonmc/rebar/Rebar.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ object Rebar : JavaPlugin(), RebarAddon {
202202
RebarFlowerPot.register(this, pm)
203203
RebarVanillaContainerBlock.register(this, pm)
204204
RebarHopper.register(this, pm)
205+
RebarFire.register(this, pm)
205206
RebarCargoBlock.register(this, pm)
206207
RebarCopperBlock.register(this, pm)
207208
RebarEntityChangedBlock.register(this, pm)
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package io.github.pylonmc.rebar.block.base
2+
3+
import io.github.pylonmc.rebar.Rebar
4+
import io.github.pylonmc.rebar.block.BlockListener
5+
import io.github.pylonmc.rebar.block.BlockListener.logEventHandleErr
6+
import io.github.pylonmc.rebar.block.BlockStorage
7+
import io.github.pylonmc.rebar.block.RebarBlock
8+
import io.github.pylonmc.rebar.block.context.BlockCreateContext
9+
import io.github.pylonmc.rebar.event.api.MultiListener
10+
import io.github.pylonmc.rebar.event.api.annotation.MultiHandlers
11+
import io.github.pylonmc.rebar.event.api.annotation.UniversalHandler
12+
import org.bukkit.Bukkit
13+
import org.bukkit.Material
14+
import org.bukkit.block.Block
15+
import org.bukkit.event.EventHandler
16+
import org.bukkit.event.EventPriority
17+
import org.bukkit.event.block.BlockBurnEvent
18+
import org.bukkit.event.block.BlockIgniteEvent
19+
import org.bukkit.event.block.BlockSpreadEvent
20+
import org.bukkit.event.entity.EntityDamageEvent
21+
import org.jetbrains.annotations.ApiStatus
22+
23+
@Suppress("unused")
24+
interface RebarFire {
25+
fun onDamageEntity(event: EntityDamageEvent, priority: EventPriority) {}
26+
27+
/**
28+
* Called when this fire block ignites block
29+
* Spawns copies of this fire block itself after calling, if the event is not cancelled
30+
*/
31+
fun onIgniteBlock(event: BlockIgniteEvent, priority: EventPriority) {}
32+
33+
/**
34+
* Spawns copies of this fire block itself after calling, if the event is not cancelled
35+
*/
36+
fun onFireSpread(event: BlockSpreadEvent, priority: EventPriority) {}
37+
38+
/**
39+
* Spawns copies of this fire block itself if returns true, otherwise set the block to air.
40+
*
41+
* @see Companion.onFireEatBlock
42+
*/
43+
fun onFireEatBlock(block: Block): Boolean {
44+
return true
45+
}
46+
47+
/**
48+
* Called when a fire is spawned
49+
* - after onIgniteBlock
50+
* - after onFireSpread
51+
* - fire eats block
52+
*/
53+
fun onFireSpawn(fire: Block) {}
54+
55+
@ApiStatus.Internal
56+
companion object : MultiListener {
57+
@UniversalHandler
58+
private fun onDamageEntity(event: EntityDamageEvent, priority: EventPriority) {
59+
if (event.cause != EntityDamageEvent.DamageCause.FIRE) return
60+
61+
val rebarBlock = BlockStorage.get(event.entity.location)
62+
if (rebarBlock !is RebarFire) {
63+
return
64+
}
65+
66+
try {
67+
MultiHandlers.handleEvent(rebarBlock, "onDamageEntity", event, priority)
68+
} catch (e: Exception) {
69+
BlockListener.logEventHandleErr(event, e, rebarBlock)
70+
}
71+
}
72+
73+
@UniversalHandler
74+
private fun onIgniteBlock(event: BlockIgniteEvent, priority: EventPriority) {
75+
if (event.ignitingBlock == null || event.cause != BlockIgniteEvent.IgniteCause.SPREAD) {
76+
return
77+
}
78+
79+
val rebarBlock = BlockStorage.get(event.ignitingBlock!!)
80+
if (rebarBlock !is RebarFire) return
81+
82+
try {
83+
MultiHandlers.handleEvent(rebarBlock, "onIgniteBlock", event, priority)
84+
85+
if (!event.isCancelled) {
86+
trySpawnRebarFire(rebarBlock, event.block)
87+
}
88+
} catch (e: Exception) {
89+
BlockListener.logEventHandleErr(event, e, rebarBlock)
90+
}
91+
}
92+
93+
@UniversalHandler
94+
private fun onFireSpread(event: BlockSpreadEvent, priority: EventPriority) {
95+
if (event.block.type != Material.FIRE) return
96+
97+
val rebarBlock = BlockStorage.get(event.source)
98+
if (rebarBlock !is RebarFire) return
99+
100+
try {
101+
MultiHandlers.handleEvent(rebarBlock, "onFireSpread", event, priority)
102+
103+
if (!event.isCancelled) {
104+
trySpawnRebarFire(rebarBlock, event.block)
105+
}
106+
} catch (e: Exception) {
107+
BlockListener.logEventHandleErr(event, e, rebarBlock)
108+
}
109+
}
110+
111+
/**
112+
* This is a hack to make fire spread work. After calling BlockBurnEvent,
113+
* the fire still has a chance to spawn a new fire at the block
114+
* without calling events again.
115+
*/
116+
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
117+
private fun onFireEatBlock(event: BlockBurnEvent) {
118+
val rebarBlock = BlockStorage.get(event.ignitingBlock!!)
119+
if (rebarBlock !is RebarFire) return
120+
121+
Bukkit.getScheduler().runTaskLater(Rebar, Runnable {
122+
if (event.block.type == Material.FIRE) { // SOUL_FIRE cannot spread, just ignore it.
123+
if (rebarBlock.onFireEatBlock(event.block)) {
124+
trySpawnRebarFire(rebarBlock, event.block)
125+
} else {
126+
event.block.type = Material.AIR
127+
}
128+
}
129+
}, 1)
130+
}
131+
132+
private fun <T> trySpawnRebarFire(fire: T, block: Block) where T : RebarFire, T : RebarBlock {
133+
if (BlockStorage.isRebarBlock(block)) {
134+
return
135+
}
136+
137+
// place new fire
138+
BlockStorage.placeBlock(
139+
block,
140+
fire.key,
141+
BlockCreateContext.PluginGenerate(Rebar.javaPlugin, block = block, shouldSetType = false)
142+
)
143+
fire.onFireSpawn(block)
144+
}
145+
}
146+
}

rebar/src/main/kotlin/io/github/pylonmc/rebar/block/context/BlockCreateContext.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@ interface BlockCreateContext {
6060
* ex:
6161
* - Growing of Rebar Trees
6262
* - Evolution of Rebar Sponges
63+
* - Spread of Rebar Fire
6364
*/
6465
@JvmRecord
6566
data class PluginGenerate(
6667
val plugin: Plugin,
6768
override val facing: BlockFace = BlockFace.NORTH,
6869
override val facingVertical: BlockFace = BlockFace.NORTH,
6970
override val block: Block,
70-
override val item: ItemStack,
71+
override val item: ItemStack? = null,
72+
override val shouldSetType: Boolean = true,
7173
) : BlockCreateContext
7274

7375
/**

0 commit comments

Comments
 (0)