Skip to content

Commit

Permalink
C H A I R
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Jun 30, 2024
1 parent 8c1d347 commit 90a7162
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package io.github.addoncommunity.galactifun.api.betteritem

import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
import io.github.thebusybiscuit.slimefun4.core.handlers.*
import io.github.thebusybiscuit.slimefun4.implementation.handlers.SimpleBlockBreakHandler
import org.bukkit.block.Block
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.event.block.BlockPlaceEvent
import org.bukkit.inventory.ItemStack
import java.lang.invoke.MethodHandle
import java.lang.invoke.MethodHandles
import java.lang.reflect.Method
import kotlin.reflect.KClass
import io.github.thebusybiscuit.slimefun4.api.items.ItemHandler as BaseItemHandler

open class BetterSlimefunItem : SlimefunItem {

constructor(
itemGroup: ItemGroup,
item: SlimefunItemStack,
recipeType: RecipeType,
recipe: Array<out ItemStack?>
) : super(itemGroup, item, recipeType, recipe)

constructor(
itemGroup: ItemGroup,
item: SlimefunItemStack,
recipeType: RecipeType,
recipe: Array<out ItemStack?>,
recipeOutput: ItemStack
) : super(itemGroup, item, recipeType, recipe, recipeOutput)

constructor(
itemGroup: ItemGroup,
item: ItemStack,
id: String,
recipeType: RecipeType,
recipe: Array<out ItemStack?>
) : super(itemGroup, item, id, recipeType, recipe)

companion object {

private val handlerMap =
mutableMapOf<KClass<out BaseItemHandler>, (MethodHandle) -> BaseItemHandler>()

fun <T : BaseItemHandler> registerHandler(
clazz: KClass<T>,
handler: (MethodHandle) -> BaseItemHandler
) {
handlerMap[clazz] = handler
}

init {
registerHandler(BlockBreakHandler::class) { handle ->
object : BlockBreakHandler(false, false) {
override fun onPlayerBreak(e: BlockBreakEvent, item: ItemStack, drops: MutableList<ItemStack>) {
handle.invoke(e, item, drops)
}
}
}
registerHandler(BlockDispenseHandler::class) { BlockDispenseHandler(it::invoke) }
registerHandler(BlockPlaceHandler::class) { handle ->
object : BlockPlaceHandler(false) {
override fun onPlayerPlace(e: BlockPlaceEvent) {
handle.invoke(e)
}
}
}
registerHandler(BlockUseHandler::class) { BlockUseHandler(it::invoke) }
registerHandler(BowShootHandler::class) { BowShootHandler(it::invoke) }
registerHandler(EntityInteractHandler::class) { EntityInteractHandler(it::invoke) }
registerHandler(EntityKillHandler::class) { EntityKillHandler(it::invoke) }
registerHandler(ItemConsumptionHandler::class) { ItemConsumptionHandler(it::invoke) }
registerHandler(ItemDropHandler::class) {
ItemDropHandler { e, p, i -> it.invoke(e, p, i) as Boolean }
}
registerHandler(ItemUseHandler::class) { ItemUseHandler(it::invoke) }
registerHandler(MultiBlockInteractionHandler::class) {
MultiBlockInteractionHandler { p, mb, b -> it.invoke(p, mb, b) as Boolean }
}
registerHandler(SimpleBlockBreakHandler::class) {
object : SimpleBlockBreakHandler() {
override fun onBlockBreak(b: Block) {
it.invoke(b)
}
}
}
registerHandler(ToolUseHandler::class) { ToolUseHandler(it::invoke) }
registerHandler(WeaponUseHandler::class) { WeaponUseHandler(it::invoke) }
}
}

override fun preRegister() {
for (method in javaClass.getAllMethods()) {
if (method.isAnnotationPresent(ItemHandler::class.java)) {
method.isAccessible = true
val handle = MethodHandles.lookup().unreflect(method)
val handler = method.getAnnotation(ItemHandler::class.java).handler
val handlerInstance = handlerMap[handler]?.invoke(handle.bindTo(this))
?: throw IllegalStateException("Handler $handler is not registered for BetterSlimefunItem")
addItemHandler(handlerInstance)
}
}
}
}

private fun Class<*>.getAllMethods(): List<Method> {
val methods = mutableListOf<Method>()
var currentClass: Class<*>? = this
while (currentClass != null) {
methods.addAll(currentClass.declaredMethods)
currentClass = currentClass.superclass
}
return methods
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.addoncommunity.galactifun.api.betteritem

import io.github.thebusybiscuit.slimefun4.api.items.ItemHandler
import kotlin.reflect.KClass

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class ItemHandler(val handler: KClass<out ItemHandler>)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.addoncommunity.galactifun.impl

import io.github.addoncommunity.galactifun.api.objects.properties.atmosphere.Gas
import io.github.addoncommunity.galactifun.impl.items.CaptainsChair
import io.github.addoncommunity.galactifun.impl.items.CommandComputer
import io.github.addoncommunity.galactifun.impl.items.FuelTank
import io.github.addoncommunity.galactifun.impl.items.RocketEngine
Expand All @@ -24,7 +25,18 @@ object GalactifunItems {
recipeType = RecipeType.NULL
recipe = emptyArray()

+"&7The core for any rocket"
+"<gray>The core for any rocket"
}

val CAPTAINS_CHAIR = buildSlimefunItem<CaptainsChair> {
category = GalactifunCategories.ROCKET_COMPONENTS
id = "CAPTAINS_CHAIR"
name = "<white>Captain's Chair"
material = MaterialType.Material(Material.OAK_STAIRS)
recipeType = RecipeType.NULL
recipe = emptyArray()

+"<gray>The Captain's Chair"
}

val FUEL_TANK_I = buildSlimefunItem<FuelTank>(1000.liters) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.github.addoncommunity.galactifun.impl.items

import io.github.addoncommunity.galactifun.impl.items.abstract.Seat
import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
import org.bukkit.block.Block
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack

class CaptainsChair(
itemGroup: ItemGroup,
item: SlimefunItemStack,
recipeType: RecipeType,
recipe: Array<out ItemStack?>
) : Seat(itemGroup, item, recipeType, recipe) {

override fun onSit(p: Player, b: Block) {
p.sendMessage("You are now sitting in the Captain's Chair")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package io.github.addoncommunity.galactifun.impl.items.abstract

import io.github.addoncommunity.galactifun.api.betteritem.BetterSlimefunItem
import io.github.addoncommunity.galactifun.api.betteritem.ItemHandler
import io.github.addoncommunity.galactifun.units.Angle.Companion.radians
import io.github.addoncommunity.galactifun.util.key
import io.github.addoncommunity.galactifun.util.nearbyEntitiesByType
import io.github.addoncommunity.galactifun.util.summon
import io.github.seggan.sf4k.serial.pdc.set
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent
import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack
import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler
import io.github.thebusybiscuit.slimefun4.implementation.handlers.SimpleBlockBreakHandler
import org.bukkit.Location
import org.bukkit.block.Block
import org.bukkit.block.data.Directional
import org.bukkit.entity.ArmorStand
import org.bukkit.entity.Player
import org.bukkit.event.block.BlockPlaceEvent
import org.bukkit.inventory.ItemStack
import kotlin.math.atan2

open class Seat(
itemGroup: ItemGroup,
item: SlimefunItemStack,
recipeType: RecipeType,
recipe: Array<out ItemStack?>
) : BetterSlimefunItem(itemGroup, item, recipeType, recipe) {

private val armorStandKey = "seat".key()

@ItemHandler(BlockPlaceHandler::class)
private fun onPlace(e: BlockPlaceEvent) {
val b = e.block
val armorStand = b.world.summon<ArmorStand>(b.location.toStandLocation())
armorStand.isInvisible = true
armorStand.isInvulnerable = true
armorStand.isSmall = true
armorStand.setGravity(false)
armorStand.setAI(false)
armorStand.isMarker = true
armorStand.persistentDataContainer.set(armorStandKey, true)
val data = b.blockData
if (data is Directional) {
val facing = data.facing
val location = armorStand.location
location.yaw = atan2(facing.modZ.toDouble(), facing.modX.toDouble()).radians
.degrees.toFloat() + 90
armorStand.teleportAsync(location)
}
}

@ItemHandler(SimpleBlockBreakHandler::class)
private fun onBreak(b: Block) {
val armorStand = b.world.nearbyEntitiesByType<ArmorStand>(b.location.toStandLocation(), 0.5) {
it.persistentDataContainer.has(armorStandKey)
}.firstOrNull() ?: return
armorStand.remove()
}

@ItemHandler(BlockUseHandler::class)
private fun onUse(e: PlayerRightClickEvent) {
val block = e.clickedBlock.get()
val armorStand = block.world.nearbyEntitiesByType<ArmorStand>(block.location.toStandLocation(), 0.5) {
it.persistentDataContainer.has(armorStandKey)
}.firstOrNull() ?: return
armorStand.addPassenger(e.player)
onSit(e.player, block)
}

protected open fun onSit(p: Player, b: Block) {}
}

private fun Location.toStandLocation() = add(0.5, 0.4, 0.5)
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import io.github.addoncommunity.galactifun.api.objects.properties.atmosphere.Atm
import io.github.addoncommunity.galactifun.impl.Permissions
import io.github.addoncommunity.galactifun.impl.space.SpaceGenerator
import io.github.addoncommunity.galactifun.pluginInstance
import io.github.addoncommunity.galactifun.util.getNearbyEntitiesByType
import io.github.addoncommunity.galactifun.util.key
import io.github.addoncommunity.galactifun.util.locationZero
import io.github.addoncommunity.galactifun.util.spawn
import io.github.addoncommunity.galactifun.util.nearbyEntitiesByType
import io.github.addoncommunity.galactifun.util.summon
import io.papermc.paper.event.entity.EntityMoveEvent
import org.bukkit.Bukkit
import org.bukkit.GameRule
Expand Down Expand Up @@ -65,10 +65,10 @@ object PlanetManager : Listener {
Atmosphere.NONE.applyEffects(spaceWorld)
spaceWorld.setGameRule(GameRule.DO_MOB_SPAWNING, false)

spaceWorldMarker = spaceWorld.getNearbyEntitiesByType<Marker>(
spaceWorldMarker = spaceWorld.nearbyEntitiesByType<Marker>(
locationZero(spaceWorld),
0.1
).firstOrNull() ?: spaceWorld.spawn<Marker>(locationZero(spaceWorld))
).firstOrNull() ?: spaceWorld.summon<Marker>(locationZero(spaceWorld))

orbits = spaceWorldMarker.persistentDataContainer.getOrDefault(orbitsKey, orbitsPdt, mutableMapOf())

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.addoncommunity.galactifun.util

import io.github.addoncommunity.galactifun.pluginInstance
import org.bukkit.metadata.MetadataValueAdapter

object DummyMetadataValue : MetadataValueAdapter(pluginInstance) {
override fun value() = Unit
override fun invalidate() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import org.bukkit.*
import org.bukkit.entity.Entity
import org.bukkit.event.*
import org.bukkit.event.player.PlayerTeleportEvent
import org.bukkit.metadata.FixedMetadataValue
import java.util.*
import java.util.concurrent.CompletableFuture
import kotlin.coroutines.resume

fun String.key(): NamespacedKey = NamespacedKey(pluginInstance, this)

fun Location.withWorld(world: World): Location = Location(world, x, y, z, yaw, pitch)

inline fun <reified T : Entity> World.getNearbyEntitiesByType(
inline fun <reified T : Entity> World.nearbyEntitiesByType(
location: Location,
radius: Double,
crossinline predicate: (T) -> Boolean = { true }
Expand All @@ -32,7 +32,7 @@ inline fun <reified T : Entity> World.getNearbyEntitiesByType(
}
}

inline fun <reified T : Entity> World.spawn(location: Location): T = spawn(location, T::class.java)
inline fun <reified T : Entity> World.summon(location: Location): T = spawn(location, T::class.java)

operator fun RegionAccessor.get(x: Int, y: Int, z: Int): Material = getType(x, y, z)
operator fun RegionAccessor.get(location: Location): Material = getType(location)
Expand All @@ -47,7 +47,7 @@ fun Entity.galactifunTeleport(
dest: Location,
reason: PlayerTeleportEvent.TeleportCause = PlayerTeleportEvent.TeleportCause.PLUGIN
): CompletableFuture<Boolean> {
setMetadata("galactifun.teleporting", FixedMetadataValue(pluginInstance, Unit))
setMetadata("galactifun.teleporting", DummyMetadataValue)
return teleportAsync(dest, reason).thenApply {
removeMetadata("galactifun.teleporting", pluginInstance)
it
Expand All @@ -56,18 +56,16 @@ fun Entity.galactifunTeleport(

operator fun TextColor.plus(s: String): TextComponent = Component.text()
.color(this)
.decoration(TextDecoration.ITALIC, false)
.decorations(EnumSet.allOf(TextDecoration::class.java), false)
.content(s)
.build()

operator fun <T : Keyed> Tag<T>.contains(item: T): Boolean = isTagged(item)

fun String.miniMessageToLegacy(): String =
LegacyComponentSerializer.legacyAmpersand().serialize(MiniMessage.miniMessage().deserialize(this))
fun String.miniMessageToLegacy(): String = LegacyComponentSerializer.legacyAmpersand()
.serialize(MiniMessage.miniMessage().deserialize(this))

fun locationZero(world: World?): Location {
return Location(world, 0.0, 0.0, 0.0)
}
fun locationZero(world: World?): Location = Location(world, 0.0, 0.0, 0.0)

suspend inline fun <reified E : Event> waitForEvent(
priority: EventPriority = EventPriority.NORMAL,
Expand Down

0 comments on commit 90a7162

Please sign in to comment.