743d568
Branches > main > 743d568 > files
Dangit I was going to try and commit more often
Commit: 743d56824391288af266ee50b057946c9876f1e0
Parent: a347d46
22 changed files:
build.gradle.kts view file
@@ -23,7 +23,7 @@ } tasks.jar {- archiveFileName.set("Bowmap.jar")+ archiveFileName.set("Bowmap2.jar") from({ configurations.runtimeClasspath.get().map { zipTree(it) }src/main/kotlin/net/bowmap/Main.kt view file
@@ -3,40 +3,35 @@ import org.bukkit.plugin.java.JavaPlugin import net.kyori.adventure.text.Component -import net.bowmap.events.* import net.bowmap.paper.* import net.bowmap.server.setup import net.bowmap.stormbow.Listeners-import net.bowmap.handlers.MiscHandlers+import net.bowmap.handlers.* class Main : JavaPlugin() { override fun onEnable() { try { setup() server.sendMessage(Component.text("Loading Bowmap..."))- // server.pluginManager.registerEvents(Chat(), this);- server.pluginManager.registerEvents(Death(), this);- server.pluginManager.registerEvents(Durability(), this);- server.pluginManager.registerEvents(Fishing(), this);- server.pluginManager.registerEvents(Welcome(), this);- server.pluginManager.registerEvents(ZoneGuard(), this);- server.pluginManager.registerEvents(Tutorial(), this); - server.pluginManager.registerEvents(Listeners(), this);+ setupStormbow(this) MiscHandlers.register()-+ ZoneGuard.register()+ Death.register()+ Welcome.register()+ Fishing.register() } catch (t: Exception) { logger.severe("Startup Failed!") server.shutdown() } } - override fun onDisable() {- // logger.severe("Bowmap Failed!")- // server.shutdown()- }+ override fun onDisable() { } } // TODO: // Mob spawning // Disable advancements, make achievements+// Disable the nether just in case, lol+// Remove all uses of ItemStack!+src/main/kotlin/net/bowmap/events/Death.kt view file
@@ -1,64 +0,0 @@-package net.bowmap.events--import net.bowmap.paper.*-import net.bowmap.server.items.BUG-import net.kyori.adventure.text.Component-import net.kyori.adventure.text.format.NamedTextColor.*-import org.bukkit.Material-import org.bukkit.entity.Entity-import org.bukkit.entity.Player-import org.bukkit.entity.Zombie-import org.bukkit.event.EventHandler-import org.bukkit.event.Listener-import org.bukkit.event.entity.EntityDeathEvent-import org.bukkit.inventory.ItemStack--class Death : Listener {- // Doesn't use attacker but how the player died does contribute to the death event- // This should probably be the damage source?- private fun deathMessage(player: Player, attacker: Entity?): Component {- return headComponent(player)- .append(SPACE)- .append(player.displayName())- .append(Component.text(" Died.", RED))- }-- // TODO stats- private fun onPlayerDeath(e: EntityDeathEvent, player: Player, attacker: Entity?) {- e.isCancelled = true- broadcast(deathMessage(player, attacker))- }-- // There is loot table stuff now :)- private fun calculateDrops(p: Player, victim: Entity): Set<ItemStack> {- return if (victim is Zombie) {- setOf(ItemStack(Material.ROTTEN_FLESH))- } else {- setOf(BUG)- }- }-- private fun onPlayerKill(e: EntityDeathEvent, player: Player, victim: Entity) {- debug("player KILLED")- e.droppedExp = 0- // TODO Based on loot table?- player.giveExp(1)- giveOrDrop(player, calculateDrops(player, victim))- }-- @EventHandler- fun onEntityDeath(e: EntityDeathEvent) {- val victim = e.entity- val attacker = e.damageSource.causingEntity-- if (victim is Player) {- onPlayerDeath(e, victim, attacker)- }-- if (attacker is Player) {- onPlayerKill(e, attacker, victim)- }-- e.drops.clear()- }-}src/main/kotlin/net/bowmap/events/Durability.kt view file
@@ -1,12 +0,0 @@-package net.bowmap.events--import org.bukkit.event.Listener-import org.bukkit.event.EventHandler-import org.bukkit.event.player.PlayerItemDamageEvent--class Durability : Listener {- @EventHandler- fun onItemLoseDurability(e: PlayerItemDamageEvent) {- e.isCancelled = true- }-}src/main/kotlin/net/bowmap/events/Tutorial.kt view file
@@ -1,72 +0,0 @@-package net.bowmap.events--import net.bowmap.server.items.TUTORIAL_BOW--import net.bowmap.Main-import net.kyori.adventure.text.Component-import org.bukkit.Location-import org.bukkit.entity.Villager-import org.bukkit.entity.EntityType-import org.bukkit.entity.Entity-import org.bukkit.entity.Player-import org.bukkit.entity.Damageable-import org.bukkit.entity.Zombie-import org.bukkit.event.Listener-import org.bukkit.event.EventHandler-import org.bukkit.event.entity.EntityDamageByEntityEvent-import org.bukkit.event.entity.EntityDeathEvent-import org.bukkit.Bukkit-import org.bukkit.Material-import org.bukkit.inventory.ItemStack--// Give ID and kill :p-// TODO needs to be per-player-fun spawnTutorialNPC() {- val server = Bukkit.getServer()- val loc = Location(server.getWorld("world"), -1.5, 56.0, 3.5);- val tutorial = loc.getWorld().spawn(loc, Zombie::class.java);- tutorial.setAI(false)- tutorial.setShouldBurnInDay(false)- tutorial.setFireTicks(0)- tutorial.setInvulnerable(true)- tutorial.setSilent(true)- tutorial.customName(Component.text("Tutorial"));- tutorial.setCustomNameVisible(true)- // Below name says "PUNCH TO INTERACT"- // Set look at player-}--fun tutorial(e: Entity): Zombie? {- // Find a better way!- return if (e.customName() == Component.text("Tutorial")) e as? Zombie else null-}--class Tutorial : Listener {- init {- spawnTutorialNPC()- }-- @EventHandler- fun onTutorialDeath(event: EntityDeathEvent) {- if(tutorial(event.entity) != null) {- // TODO these items also need to only be pickup-able by the player?- // If they ignore the bow and don't pick it up, it shouldn't despawn...- event.drops.clear()- event.drops.add(TUTORIAL_BOW) // Tutorial Bow!- event.drops.add(ItemStack(Material.ARROW))- }- }-- // TODO can't seem to punch in survival?- @EventHandler- fun onPunchTutorial(event: EntityDamageByEntityEvent) {- tutorial(event.entity)?.let { zombie ->- // TODO remove the unsafe cast- zombie.health = 0.0;- // Give player bow!- // Drop bow- Bukkit.broadcast(Component.text("Tutorial NPC killed"))- }- }-}-src/main/kotlin/net/bowmap/events/Welcome.kt view file
@@ -1,31 +0,0 @@-package net.bowmap.events--import org.bukkit.event.*-import org.bukkit.event.player.*--import net.kyori.adventure.text.Component-import net.kyori.adventure.text.format.NamedTextColor-import net.bowmap.paper.*--class Welcome : Listener {- @EventHandler- // TODO give bow- fun onPlayerJoin(e: PlayerJoinEvent) {- e.joinMessage(null)- if (false) {- broadcast(headComponent(e.player).append(SPACE, e.player.displayName(), Component.text(" joined the server", NamedTextColor.GREEN)))- } else {- broadcast(Component.text("Welcome to Bowmap, ", NamedTextColor.GREEN)- .append(headComponent(e.player).color(NamedTextColor.WHITE),- Component.text(" "),- e.player.displayName().colorIfAbsent(NamedTextColor.WHITE),- Component.text("!", NamedTextColor.GREEN)))- }- }-- @EventHandler- fun onPlayerQuit(e: PlayerQuitEvent) {- e.quitMessage(null)- broadcast(headComponent(e.player).append(SPACE, e.player.displayName(), Component.text(" left the server", NamedTextColor.RED)))- }-}src/main/kotlin/net/bowmap/handlers/Death.kt view file
@@ -0,0 +1,40 @@+package net.bowmap.handlers++import net.bowmap.stormbow.handler+import net.bowmap.stormbow.fact.*+import net.bowmap.stormbow.effect.*++import net.bowmap.paper.*+import net.bowmap.server.item.BUG+import net.kyori.adventure.text.Component+import net.kyori.adventure.text.format.NamedTextColor.*+import org.bukkit.Material+import org.bukkit.entity.Entity+import org.bukkit.entity.Player+import org.bukkit.entity.Zombie+import org.bukkit.event.EventHandler+import org.bukkit.event.Listener+import org.bukkit.event.entity.EntityDeathEvent+import org.bukkit.inventory.ItemStack+import org.bukkit.damage.DamageSource++// Doesn't use attacker but how the player died does contribute to the death event+// This should probably be the damage source?+private fun deathMessage(player: Player, attacker: DamageSource): Component {+ return headComponent(player)+ .append(SPACE)+ .append(player.displayName())+ .append(Component.text(" Died (jk).", RED))+}++object Death {+ fun register() {+ handler<PlayerDied> {+ effects(Cancel(), Broadcast(message = deathMessage(player, cause)))+ }++ handler<PlayerKilledEntity> {+ effects(Give(player, BUG))+ }+ }+}src/main/kotlin/net/bowmap/handlers/Fishing.kt src/main/kotlin/net/bowmap/events/Fishing.kt view file
@@ -1,4 +1,8 @@-package net.bowmap.events+package net.bowmap.handlers++import net.bowmap.stormbow.handler+import net.bowmap.stormbow.fact.*+import net.bowmap.stormbow.effect.* import net.bowmap.server.loot.* import org.bukkit.Material.*@@ -10,13 +14,11 @@ import net.bowmap.paper.* -private fun calculateFishVelocity(e: PlayerFishEvent): Vector {- val hook = e.hook+private fun calculateFishVelocity(e: PlayerCaughtFish): Vector { val eye = e.player.eyeLocation+ val distance = eye.distance(e.hook.location) - val distance = eye.distance(hook.location)-- return eye.subtract(hook.location)+ return eye.subtract(e.hook.location) .toVector() .normalize() .multiply(0.2 + distance * 0.1)@@ -80,32 +82,20 @@ ) ) -private fun setWaitTime(e: PlayerFishEvent) {- e.hook.setWaitTime(20)-}+object Fishing {+ fun register() {+ handler<PlayerStartedFishing> {+ effects(SetFishTime(ticks = 20))+ } + handler<PlayerCaughtFish> {+ val loot = fishingLootTable.getLoot() -class Fishing : Listener {- @EventHandler- fun onFish(e: PlayerFishEvent) {- when (e.state) {- State.FISHING -> {- setWaitTime(e)+ for (stack in loot) {+ val item = hook.world.dropItem(hook.location, stack)+ item.setVelocity(calculateFishVelocity(this)) }-- State.CAUGHT_FISH -> {- val hook = e.hook- val loot = fishingLootTable.getLoot()-- for (stack in loot) {- val item = hook.world.dropItem(hook.location, stack)- item.setVelocity(calculateFishVelocity(e))- }-- e.caught?.remove()- e.expToDrop = 1- }- else -> {}+ effects() } } }src/main/kotlin/net/bowmap/handlers/MiscHandlers.kt view file
@@ -1,11 +1,8 @@ package net.bowmap.handlers -import net.bowmap.stormbow.register import net.bowmap.stormbow.handler-import net.bowmap.stormbow.fact.PlayerSentChatMessage-import net.bowmap.stormbow.fact.Fact-import net.bowmap.stormbow.effect.SendMessage-import net.bowmap.stormbow.effect.effects+import net.bowmap.stormbow.fact.*+import net.bowmap.stormbow.effect.* import net.kyori.adventure.text.Component import net.bowmap.perms.prefixsrc/main/kotlin/net/bowmap/handlers/Welcome.kt view file
@@ -0,0 +1,26 @@+package net.bowmap.handlers++import net.bowmap.stormbow.handler+import net.bowmap.stormbow.fact.*+import net.bowmap.stormbow.effect.*++import net.kyori.adventure.text.Component+import net.kyori.adventure.text.format.NamedTextColor+import net.bowmap.paper.*++object Welcome {+ fun register() {+ handler<PlayerJoined> {+ // broadcast(headComponent(player).append(SPACE, player.displayName(), Component.text(" joined the server", NamedTextColor.GREEN)))+ effects(Broadcast(Component.text("Welcome to Bowmap, ", NamedTextColor.GREEN)+ .append(headComponent(player).color(NamedTextColor.WHITE),+ Component.text(" "),+ player.displayName().colorIfAbsent(NamedTextColor.WHITE),+ Component.text("!", NamedTextColor.GREEN))))+ }++ handler<PlayerQuit> {+ effects(Broadcast(headComponent(player).append(SPACE, player.displayName(), Component.text(" left the server", NamedTextColor.RED))))+ }+ }+}src/main/kotlin/net/bowmap/handlers/ZoneGuard.kt src/main/kotlin/net/bowmap/events/ZoneGuard.kt view file
@@ -1,6 +1,8 @@+package net.bowmap.handlers --package net.bowmap.events+import net.bowmap.stormbow.handler+import net.bowmap.stormbow.fact.*+import net.bowmap.stormbow.effect.* import org.bukkit.event.Listener import org.bukkit.event.block.BlockBreakEvent@@ -43,11 +45,14 @@ return isInsideRegion(spawn, b.location) } -class ZoneGuard : Listener {- @EventHandler- fun onBlockBreak(e: BlockBreakEvent) {- if (isBlockInSpawn(e.block)) {- e.setCancelled(true)+object ZoneGuard {+ fun register() {+ handler<PlayerBrokeBlock> {+ if (isBlockInSpawn(block)) {+ effects(Cancel())+ } else {+ effects()+ } } } }src/main/kotlin/net/bowmap/server/Setup.kt view file
@@ -5,7 +5,8 @@ /// Sets up the world state fun setup() {- Bukkit.getWorlds().forEach { world -> + // TODO can make these into effects+ Bukkit.getWorlds().forEach { world -> world.setGameRule(GameRules.ADVANCE_TIME, false) world.setTime(18000L) world.setGameRule(GameRules.RESPAWN_RADIUS, 0)src/main/kotlin/net/bowmap/server/item/Item.kt view file
@@ -0,0 +1,53 @@+package net.bowmap.server.item++import net.kyori.adventure.text.Component+import org.bukkit.inventory.ItemStack+import org.bukkit.Material+import kotlinx.collections.immutable.*++// Bowmap's Item type++// Either a material or a custommodeldata+data class Texture(val material: Material? = null, val customModelData: Int? = null) {+ init {+ require(material != null || customModelData != null) { "Texture requires either a material or custom model data" }+ }+}++data class Item(+ val material: Material,+ val amount: Int = 1,+ val texture: Texture = Texture(material = material),+ val name: Component,+ val lore: PersistentList<Component> = persistentListOf()+)++fun toItemStack(item: Item): ItemStack {+ // TODO custommodeldata+ val itemStack = ItemStack(item.material, item.amount)+ val meta = itemStack.getItemMeta()++ // itemName is not editable via an anvil, which is the desired behavior+ // TODO make sure its not italics!+ meta.itemName(item.name)+ if (item.lore.isNotEmpty()) {+ // TODO Make sure it's not purple and italics...+ meta.lore(item.lore)+ }++ itemStack.setItemMeta(meta)+ return itemStack+}++fun toItem(itemStack: ItemStack): Item {+ // TODO custommodeldata+ // See the above itemName comment+ val meta = itemStack.getItemMeta()+ val lore = meta.lore()?.toPersistentList() ?: persistentListOf()+ return Item(+ material = itemStack.type,+ amount = itemStack.amount,+ name = meta.itemName(),+ lore = lore+ )+}src/main/kotlin/net/bowmap/server/item/Items.kt view file
@@ -0,0 +1,16 @@+package net.bowmap.server.item++import kotlinx.collections.immutable.*+import org.bukkit.Material+import net.kyori.adventure.text.Component+import net.kyori.adventure.text.format.NamedTextColor+import net.kyori.adventure.text.format.TextDecoration++val BUG = Item(+ material = Material.STONE_BUTTON,+ name = Component.text("Bug"),+ lore = persistentListOf(+ Component.text("You encountered something that hasn't been implemented yet,", NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, false),+ Component.text("so you get this instead.", NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, false)+ )+)src/main/kotlin/net/bowmap/server/items/Items.kt view file
@@ -1,52 +0,0 @@-// TODO just make an item class-package net.bowmap.server.items--import net.kyori.adventure.text.Component-import net.kyori.adventure.text.format.NamedTextColor-import net.kyori.adventure.text.format.TextDecoration-import org.bukkit.Material-import org.bukkit.inventory.ItemStack-import org.bukkit.inventory.meta.ItemMeta--val BUG: ItemStack = updateMeta(ItemStack(Material.STONE_BUTTON)) {- it.itemName(Component.text("Bug"))- it.lore(- listOf(- Component.text("You encountered something that hasn't been implemented yet,", NamedTextColor.GRAY)- .decoration(TextDecoration.ITALIC, false),- Component.text("so you get this instead.", NamedTextColor.GRAY)- .decoration(TextDecoration.ITALIC, false)- )- )-}--val TUTORIAL_BOW: ItemStack = updateMeta(ItemStack(Material.BOW)) {- it.itemName(Component.text("Tutorial Bow"))- // Rarity- // Lore:- // Less powerful than a skeleton's bow.- // You'll want to find one.-}--// TODO just use a lambda lol-fun updateMeta(item: ItemStack, f: (ItemMeta) -> Unit): ItemStack {- val newItem = item.clone()- val meta = newItem.itemMeta- f(meta)- newItem.setItemMeta(meta)- return newItem-}--// data class Texture(val material: Material, val customModelData: Int? = null)-//-// data class BowmapItem(-// val material: Material,-// val name: Component,-// val amount: Int = 1,-// val maxStackSize: Int = 1,-// val texture: Texture = Texture(material = material)-// ) {-// init {-// require(material == texture.material)-// }-// }src/main/kotlin/net/bowmap/stormbow/FactRegistry.kt view file
@@ -11,12 +11,6 @@ var registry: PersistentMap<KClass<out Fact>, PersistentList<Handler>> = persistentMapOf() -// Pretty please make these the same type :)-fun <F : Fact> register(factClass: KClass<F>, handler: Handler) {- val list = registry[factClass] ?: persistentListOf()- registry = registry.putting(factClass, list.adding(handler))-}- inline fun <reified T : Fact> handler(noinline handler: T.() -> PersistentList<Effect>) { val adapted: (Fact) -> PersistentList<Effect> = { fact -> handler(fact as T)src/main/kotlin/net/bowmap/stormbow/Listeners.kt view file
@@ -7,18 +7,22 @@ package net.bowmap.stormbow import io.papermc.paper.event.player.AsyncChatEvent-import net.bowmap.paper.headComponent+import org.bukkit.event.*+import org.bukkit.event.entity.*+import org.bukkit.event.player.*+import org.bukkit.event.block.*+import org.bukkit.entity.* import net.kyori.adventure.text.Component import net.kyori.adventure.audience.Audience +import org.bukkit.event.player.PlayerFishEvent.State import net.bowmap.paper.*-import org.bukkit.event.Listener-import org.bukkit.event.EventHandler import net.bowmap.perms.prefix -import net.bowmap.stormbow.fact.PlayerSentChatMessage-import net.bowmap.stormbow.fact.handle-import net.bowmap.stormbow.effect.execute+import net.bowmap.stormbow.fact.*+import net.bowmap.stormbow.effect.*++import org.bukkit.event.player.PlayerItemDamageEvent class Listeners : Listener { @EventHandler@@ -28,4 +32,85 @@ // Here, SendMessage effects could replace the chat message, but there's no reason to execute(handle(f)) }++ @EventHandler+ fun onItemDamage(e: PlayerItemDamageEvent) {+ // Logic leaking into this layer but oh well+ // Basically this should be controlled by a fact + effect but I can't be bothered+ e.setCancelled(true)+ }++ @EventHandler+ fun onBlockBreak(e: BlockBreakEvent) {+ // Logic leaking into this layer but oh well+ // Basically this should be controlled by a fact + effect but I can't be bothered+ val f = PlayerBrokeBlock(player = e.player, block = e.block)+ val effects = handle(f)+ if (effects.any {it is Cancel}) {+ e.setCancelled(true)+ }+ execute(effects)+ }++ @EventHandler+ fun onEntityDeath(e: EntityDeathEvent) {+ val victim = e.entity+ val attacker = e.damageSource.causingEntity++ if (victim is Player) {+ val effects = handle(PlayerDied(player = victim, cause = e.damageSource))+ if (effects.any {it is Cancel}) {+ e.setCancelled(true)+ }+ execute(effects)+ }++ if (attacker is Player) {+ val effects = handle(PlayerKilledEntity(player = attacker, entity = victim, cause = e.damageSource))+ if (effects.any {it is Cancel}) {+ e.setCancelled(true)+ }+ execute(effects)+ }++ e.drops.clear()+ e.setDroppedExp(0)+ }++ @EventHandler+ fun onPlayerJoin(e: PlayerJoinEvent) {+ e.joinMessage(null)+ execute(handle(PlayerJoined(player = e.player)))+ }++ @EventHandler+ fun onPlayerQuit(e: PlayerQuitEvent) {+ e.quitMessage(null)+ execute(handle(PlayerQuit(player = e.player)))+ }++ @EventHandler+ fun onFishEvent(e: PlayerFishEvent) {+ when (e.state) {+ State.FISHING -> {+ val effects = handle(PlayerStartedFishing(player = e.player, hook = e.hook))+ if (contains<Cancel>(effects)) {+ e.setCancelled(true)+ }++ find<SetFishTime>(effects)?.let {src/main/kotlin/net/bowmap/stormbow/Setup.kt view file
@@ -0,0 +1,6 @@++package net.bowmap.stormbow++fun setupStormbow(plugin: JavaPlugin) {+ plugin.server.pluginManager.registerEvents(Listeners(), this);+}src/main/kotlin/net/bowmap/stormbow/effect/Effect.kt view file
@@ -3,13 +3,28 @@ import kotlinx.collections.immutable.* interface Effect {+}++/// An effect that knows how to run itself.+/// Some effects are to be run by event listeners themselves+interface DefaultEffect : Effect { fun execute() } fun execute(effects: PersistentList<Effect>) { effects.forEach { effect ->- effect.execute()+ if (effect is DefaultEffect) {+ effect.execute()+ } } } fun effects(vararg e: Effect) = persistentListOf(*e)++inline fun <reified T : Effect> find(effects: PersistentList<Effect>): T? {+ return effects.filterIsInstance<T>().firstOrNull()+}++inline fun <reified T : Effect> contains(effects: PersistentList<Effect>): Boolean {+ return effects.any {it is T}+}src/main/kotlin/net/bowmap/stormbow/effect/Effects.kt view file
@@ -0,0 +1,37 @@+package net.bowmap.stormbow.effect++import net.kyori.adventure.text.Component+import net.kyori.adventure.audience.Audience+import net.bowmap.stormbow.effect.*+import org.bukkit.inventory.ItemStack+import org.bukkit.Bukkit+import org.bukkit.entity.Player+import net.bowmap.server.item.*++// TODO you can send a message to more than one audience+// I'd like audiences to just be able to be collections :/+data class SendMessage(val audience: Collection<Audience>, val message: Component) : DefaultEffect {+ override fun execute() {+ audience.forEach { a ->+ a.sendMessage(message)+ }+ }+}++data class Broadcast(val message: Component) : DefaultEffect {+ override fun execute() {+ Bukkit.broadcast(message)+ }+}++// Also make Player, mutable players are yucky+data class Give(val player: Player, val item: Item) : DefaultEffect {+ override fun execute() {+ player.give(listOf(toItemStack(item)))+ }+}++/// Cancels the current action.+/// Events will generally call .setCancelled(true), but this is a logical action, and they could do something else.+class Cancel() : Effect+data class SetFishTime(val ticks: Int) : Effectsrc/main/kotlin/net/bowmap/stormbow/effect/SendMessage.kt view file
@@ -1,15 +0,0 @@-package net.bowmap.stormbow.effect--import net.kyori.adventure.text.Component-import net.kyori.adventure.audience.Audience-import net.bowmap.stormbow.effect.Effect--// TODO you can send a message to more than one audience-// I'd like audiences to just be able to be collections :/-data class SendMessage(val audience: Collection<Audience>, val message: Component) : Effect {- override fun execute() {- audience.forEach { a ->- a.sendMessage(message)- }- }-}src/main/kotlin/net/bowmap/stormbow/fact/Facts.kt view file
@@ -1,9 +1,18 @@ package net.bowmap.stormbow.fact -import org.bukkit.entity.Player+import org.bukkit.entity.*+import org.bukkit.damage.DamageSource+import org.bukkit.block.Block import net.kyori.adventure.audience.Audience import net.kyori.adventure.text.Component // TODO a player is a game entity... // Game entities should probably be referenced by their UUID data class PlayerSentChatMessage(val player: Player, val audience: Collection<Audience>, val message: Component) : Fact+data class PlayerBrokeBlock(val player: Player, val block: Block) : Fact+data class PlayerKilledEntity(val player: Player, val entity: Entity, val cause: DamageSource) : Fact+data class PlayerDied(val player: Player, val cause: DamageSource) : Fact+data class PlayerJoined(val player: Player) : Fact+data class PlayerQuit(val player: Player) : Fact+data class PlayerStartedFishing(val player: Player, val hook: FishHook) : Fact+data class PlayerCaughtFish(val player: Player, val hook: FishHook) : Fact