diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index e4d49fa..df99e6f 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -11,9 +11,10 @@ plugins { repositories { mavenCentral() - maven(url = "https://jitpack.io/") - maven(url = "https://repo.papermc.io/repository/maven-public/") - maven(url = "https://repo.aikar.co/content/groups/aikar/") + maven("https://jitpack.io/") + maven("https://repo.papermc.io/repository/maven-public/") + maven("https://repo.aikar.co/content/groups/aikar/") + maven("https://repo.metamechanists.org/releases/") } dependencies { @@ -43,6 +44,8 @@ dependencies { implementation("org.bstats:bstats-bukkit:3.0.2") implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT") + implementation("org.metamechanists:DisplayModelLib:34") + implementation("io.github.seggan:sf4k:0.6.0") testImplementation(kotlin("test")) @@ -89,6 +92,7 @@ tasks.shadowJar { doRelocate("io.github.seggan.kfun") doRelocate("co.aikar.commands") doRelocate("co.aikar.locales") + doRelocate("org.metamechanists.displaymodellib") } else { archiveClassifier = "unrelocated" } diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt index 5325931..fcc848e 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/Galactifun2.kt @@ -40,6 +40,7 @@ import org.bukkit.plugin.java.JavaPlugin import java.nio.file.Path import java.util.logging.Level import kotlin.coroutines.CoroutineContext +import kotlin.io.path.createDirectories import kotlin.script.experimental.api.ResultValue import kotlin.script.experimental.api.ScriptDiagnostic import kotlin.script.experimental.api.valueOrThrow @@ -116,6 +117,7 @@ open class Galactifun2 : AbstractAddon() { launchMessages = config.getStringList("rockets.launch-msgs") structuresFolder = dataFolder.toPath().resolve("structures") + structuresFolder.createDirectories() BaseUniverse.init() diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/betteritem/BetterSlimefunItem.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/betteritem/BetterSlimefunItem.kt index f3e7469..8e27030 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/betteritem/BetterSlimefunItem.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/betteritem/BetterSlimefunItem.kt @@ -96,7 +96,7 @@ open class BetterSlimefunItem : SlimefunItem { } } - override fun preRegister() { + final override fun preRegister() { for (method in javaClass.getAllMethods()) { if (method.isAnnotationPresent(ItemHandler::class.java)) { method.isAccessible = true @@ -120,8 +120,11 @@ open class BetterSlimefunItem : SlimefunItem { }) } } + beforeRegister() } + protected open fun beforeRegister() {} + protected fun itemSetting(key: String, default: T): ItemSetting { val setting = ItemSetting(this, key, default) addItemSetting(setting) diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/rockets/RocketInfo.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/rockets/RocketInfo.kt index 51a191a..60f759c 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/rockets/RocketInfo.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/api/rockets/RocketInfo.kt @@ -47,7 +47,7 @@ class RocketInfo( val dryMass = wetMass - stages.unitSumOf { it.fuelMass } val info = buildString { - val planet = PlanetManager.getByWorld(commandComputer.world) ?: error("Planet not found") + val planet = PlanetManager.getByWorld(commandComputer.world) appendLine("Stages:") var stageNum = 1 for (stage in stages) { @@ -66,7 +66,9 @@ class RocketInfo( appendLine("Thrust: %,.2f kilonewtons".format(thrust.kilonewtons)) appendLine("Wet mass: %.2s".format(wetMass)) appendLine("Dry mass: %.2s".format(dryMass)) - appendLine("TWR: %.2f".format(twr(planet.gravity))) + if (planet != null) { + appendLine("TWR: %.2f".format(twr(planet.gravity))) + } appendLine("Delta-V: %.2s".format(deltaV(engines, wetMass, dryMass))) } diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/Gf2Command.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/Gf2Command.kt index b41cd8b..c70437f 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/Gf2Command.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/Gf2Command.kt @@ -12,7 +12,7 @@ import io.github.addoncommunity.galactifun.util.menu.PlanetMenu import io.github.seggan.sf4k.extensions.plusAssign import kotlinx.datetime.Clock import org.bukkit.Location -import org.bukkit.entity.BlockDisplay +import org.bukkit.entity.FallingBlock import org.bukkit.entity.Player @Suppress("unused") @@ -66,7 +66,7 @@ object Gf2Command : BaseCommand() { fun undiplayentityify(player: Player) { var count = 0 for (entity in player.world.entities) { - if (entity is BlockDisplay) { + if (entity is FallingBlock) { if (entity.toBlock()) { count++ } diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/CommandComputer.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/CommandComputer.kt index 7b8631a..35a94ec 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/CommandComputer.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/CommandComputer.kt @@ -1,5 +1,6 @@ package io.github.addoncommunity.galactifun.impl.items +import com.destroystokyo.paper.ParticleBuilder import com.github.shynixn.mccoroutine.bukkit.launch import io.github.addoncommunity.galactifun.api.betteritem.BetterSlimefunItem import io.github.addoncommunity.galactifun.api.betteritem.ItemHandler @@ -9,19 +10,14 @@ import io.github.addoncommunity.galactifun.impl.items.abstract.Seat import io.github.addoncommunity.galactifun.impl.managers.PlanetManager import io.github.addoncommunity.galactifun.impl.managers.RocketManager import io.github.addoncommunity.galactifun.pluginInstance -import io.github.addoncommunity.galactifun.units.Acceleration.Companion.metersPerSecondSquared -import io.github.addoncommunity.galactifun.units.Velocity.Companion.metersPerSecond import io.github.addoncommunity.galactifun.units.abs -import io.github.addoncommunity.galactifun.units.times -import io.github.addoncommunity.galactifun.units.unitSumOf import io.github.addoncommunity.galactifun.util.* import io.github.addoncommunity.galactifun.util.bukkit.* +import io.github.seggan.sf4k.extensions.minus import io.github.seggan.sf4k.extensions.plus import io.github.seggan.sf4k.extensions.position import io.github.seggan.sf4k.serial.blockstorage.getBlockStorage import io.github.seggan.sf4k.serial.blockstorage.setBlockStorage -import io.github.seggan.sf4k.serial.pdc.getData -import io.github.seggan.sf4k.serial.pdc.setData import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack @@ -29,27 +25,31 @@ 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.libraries.dough.blocks.BlockPosition +import io.papermc.paper.event.entity.EntityMoveEvent import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap -import kotlinx.coroutines.future.await import me.mrCookieSlime.Slimefun.api.BlockStorage +import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.title.Title +import net.kyori.adventure.util.Ticks +import org.bukkit.Bukkit import org.bukkit.Location +import org.bukkit.Material import org.bukkit.Particle import org.bukkit.block.Block import org.bukkit.block.BlockFace -import org.bukkit.entity.BlockDisplay import org.bukkit.entity.Entity -import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener import org.bukkit.event.block.BlockPlaceEvent +import org.bukkit.event.player.PlayerMoveEvent +import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.inventory.ItemStack import org.bukkit.util.BoundingBox import java.util.* import kotlin.collections.ArrayDeque import kotlin.jvm.optionals.getOrNull -import kotlin.math.max -import kotlin.random.Random -import kotlin.time.Duration.Companion.seconds class CommandComputer( itemGroup: ItemGroup, @@ -60,8 +60,35 @@ class CommandComputer( private val counters = Object2IntOpenHashMap() - companion object { + companion object : Listener { val SERIALIZED_BLOCK_KEY = "serialized_block".key() + + private val frozenEntities = mutableSetOf() + + init { + Bukkit.getPluginManager().registerEvents(this, pluginInstance) + } + + @EventHandler + private fun onPlayerMove(e: PlayerMoveEvent) { + val player = e.player + if (player in frozenEntities && e.hasChangedPosition()) { + e.isCancelled = true + } + } + + @EventHandler + private fun onEntityMove(e: EntityMoveEvent) { + val entity = e.entity + if (entity in frozenEntities && e.hasChangedPosition()) { + e.isCancelled = true + } + } + + @EventHandler + private fun onPlayerLeave(e: PlayerQuitEvent) { + frozenEntities.remove(e.player) + } } @Ticker @@ -151,7 +178,7 @@ class CommandComputer( return } - p.sendMessage("Enter the destination's x, y, z coordinates separated by commas") + p.sendMessage("Enter the destination's x y z coordinates separated by spaces") val coords = p.awaitChatInput() if (Seat.getSitting(p) != seat) return val match = coordinateRegex.matchEntire(coords) @@ -162,124 +189,137 @@ class CommandComputer( val (x, y, z) = match.destructured val dest = space.offset(x.toDouble(), y.toDouble(), z.toDouble()) - val entities = mutableSetOf(p) - rocket.blocks.consumeSpreadOut(200) { b -> + val entities = mutableSetOf() + val players = mutableSetOf() + val blocks = rocket.blocks + rocket.blocks.map { it.getFace(BlockFace.UP) } + blocks.toSet().consumeSpreadOut(200) { b -> val block = b.block - val foundEntities = world.getNearbyEntities(BoundingBox.of(block)) - foundEntities.addAll( - world.getNearbyEntities(BoundingBox.of(block.getRelative(BlockFace.UP))) - .filter { it.isOnGround } - ) - val display = block.toDisplay() - entities.add(display) - entities.addAll(foundEntities.filter { it.vehicle == null }.flatMap(::freezeEntity)) - } - - // Random launch messages - var launched = false - pluginInstance.launch { - val launchMessages = ArrayDeque(pluginInstance.launchMessages) - launchMessages.shuffle() - while (true) { - delayTicks(Random.nextInt(15, 30)) - if (launched) break - for (player in entities.filterIsInstance()) { - player.sendMessage(launchMessages.removeFirst() + "...") + for (entity in world.getNearbyEntities(BoundingBox.of(block))) { + if (entity is Player) { + players.add(entity) + entities.add(entity) + } else { + entity.remove() } } } + var launched = false + // Engine smoke pluginInstance.launch { while (!launched) { for ((_, engine) in firstStage.engines) { - world.spawnParticle( - Particle.CAMPFIRE_SIGNAL_SMOKE, - engine.location.add(0.0, -1.0, 0.0), - Random.nextInt(1, 3), - 0.5, - 0.0, - 0.5 - ) + ParticleBuilder(Particle.CAMPFIRE_SIGNAL_SMOKE) + .location(engine.location) + .offset(0.5, 0.5, 0.5) + .count(1) + .spawn() } delayTicks(2) } } // Countdown + val launchMessages = ArrayDeque(pluginInstance.launchMessages) + launchMessages.shuffle() repeat(10) { - for (player in entities.filterIsInstance()) { - player.sendMessage(NamedTextColor.GOLD + "Launching in ${10 - it}...") + val message = NamedTextColor.GOLD + "${launchMessages.removeFirst()}..." + for (player in players) { + player.sendMessage(message) + player.showTitle( + Title.title( + "T-${10 - it}".miniComponent(), + Component.empty(), + Title.Times.times( + Ticks.duration(5), + Ticks.duration(10), + Ticks.duration(5) + ) + ) + ) } delayTicks(20) } launched = true - val offsets = entities.associateWith { it.location.subtract(pos.toLocation()) } + val blockOffsets = blocks.associateWith { it.location - pos.toLocation() } + val entityOffsets = entities.associateWith { it.location - pos.toLocation() } + val destMinHeight = PlanetManager.spaceWorld.minHeight + val globalOffset = (destMinHeight - blockOffsets.minOf { (_, offset) -> offset.y }) + .coerceAtLeast(0.0) + + val explosionLocations = mutableSetOf() + for (blockPos in blocks) { + val oldBlock = blockPos.block + val newLoc = dest + blockOffsets[blockPos]!!.copy(world = PlanetManager.spaceWorld) + newLoc.y += globalOffset + val newBlock = newLoc.block + if (!newBlock.type.isAir && !newBlock.isReplaceable) { + explosionLocations.add(newLoc) + } + newBlock.type = oldBlock.type + newBlock.blockData = oldBlock.blockData + @Suppress("UnstableApiUsage") + oldBlock.state.copy(newLoc) + + if (BlockStorage.hasBlockInfo(oldBlock)) { + val oldBs = BlockStorage.getBlockInfoAsJson(oldBlock) + BlockStorage.clearBlockInfo(oldBlock) + BlockStorage.setBlockInfo(newBlock, oldBs, true) + } + + oldBlock.type = Material.AIR + } + + for (entity in entities) { + val end = dest + entityOffsets[entity]!!.copy(world = PlanetManager.spaceWorld) + end.y += globalOffset + entity.galactifunTeleport(end) + } + + delayTicks(1) + + for (loc in explosionLocations) { + loc.world.createExplosion(loc, 3f, false, true) + } + + /* + TODO make rockets move + val maxHeight = world.maxHeight var position = pos.y.toDouble() + val offsets = entities.associateWith { it.location - pos.toLocation() } val weight = rocket.wetMass * currentPlanet.gravity val netForce = firstStage.engines.unitSumOf { it.first.thrust } - weight - val acceleration = 0.5.metersPerSecondSquared + val acceleration = netForce divToAcceleration rocket.wetMass val marginalAcceleration = acceleration * 0.05.seconds - var speed = 0.0.metersPerSecond + val marginalAccelerationVector = UnitVector.Y * marginalAcceleration.metersPerSecond while (position < maxHeight) { for (entity in entities) { - entity.galactifunTeleport( - entity.location.add(0.0, (speed / 20).metersPerSecond, 0.0) - ).await() + entity.velocity += marginalAccelerationVector position = max(position, entity.location.y) } - speed += marginalAcceleration delayTicks(1) } for (entity in entities) { - entity.galactifunTeleport( - dest + offsets[entity]!!.copy(world = PlanetManager.spaceWorld) - ).await() - unfreezeEntity(entity) - } - } -} - -private val coordinateRegex = """\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*(-?\d+)\s*""".toRegex() -private val GRAVITY_KEY = "has_gravity".key() -private val AI_KEY = "has_ai".key() -private val FLIGHT_KEY = "is_flight".key() - -fun freezeEntity(entity: Entity): List { - val pdc = entity.persistentDataContainer - pdc.setData(GRAVITY_KEY, entity.hasGravity()) - entity.setGravity(false) - if (entity is LivingEntity) { - if (entity is Player) { - pdc.setData(FLIGHT_KEY, entity.allowFlight) - entity.allowFlight = false - } else { - pdc.setData(AI_KEY, entity.hasAI()) - entity.setAI(false) + pluginInstance.launch { + if (!entity.galactifunTeleport( + dest + offsets[entity]!!.copy(world = PlanetManager.spaceWorld) + ).await()) { + error("Failed to teleport entity") + } + delayTicks(1) + when (entity) { + is FallingBlock -> entity.toBlock() + is Player -> frozenPlayers.remove(entity) + } + } } + */ } - return entity.passengers.flatMap(::freezeEntity) + entity } -fun unfreezeEntity(entity: Entity) { - val pdc = entity.persistentDataContainer - when (entity) { - is Player -> { - entity.sendMessage("You have arrived at your destination") - entity.allowFlight = pdc.getData(FLIGHT_KEY) ?: false - } - - is BlockDisplay -> entity.toBlock() - - else -> { - entity.setGravity(pdc.getData(GRAVITY_KEY) ?: true) - if (entity is LivingEntity) { - entity.setAI(pdc.getData(AI_KEY) ?: true) - } - } - } -} \ No newline at end of file +private val coordinateRegex = """\s*(-?\d+)\s+(-?\d+)\s+(-?\d+)\s*""".toRegex() \ No newline at end of file diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/FuelTank.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/FuelTank.kt index 358c1cc..a5bb22e 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/FuelTank.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/FuelTank.kt @@ -127,7 +127,7 @@ class FuelTank( return getMass(block) + fuelMass } - override fun preRegister() { + override fun beforeRegister() { menu.apply(this) } } \ No newline at end of file diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/SlimefunStructureBlock.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/SlimefunStructureBlock.kt index 63ad54f..869893c 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/SlimefunStructureBlock.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/SlimefunStructureBlock.kt @@ -38,9 +38,7 @@ import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.ItemStack import org.bukkit.util.BlockVector import org.bukkit.util.Vector -import kotlin.io.path.exists -import kotlin.io.path.inputStream -import kotlin.io.path.outputStream +import kotlin.io.path.* class SlimefunStructureBlock( itemGroup: ItemGroup, @@ -92,7 +90,10 @@ class SlimefunStructureBlock( return@onClick } pluginInstance.structuresFolder.resolve("$name.nbt") - .outputStream().use(structure::saveToStream) + .apply { deleteIfExists() } + .createFile() + .outputStream() + .use(structure::saveToStream) p.sendMessage(NamedTextColor.GREEN + "Saved structure $name") } @@ -111,25 +112,20 @@ class SlimefunStructureBlock( val offset = getOffset(block) val offsetLocation = block.location + offset - val keyName = block.getBlockStorage(KEY_NAME) - if (keyName.isNullOrBlank()) { + val name = block.getBlockStorage(KEY_NAME) + if (name.isNullOrBlank()) { p.sendMessage(NamedTextColor.RED + "Please set a name first") return@onClick } - val key = keyName.key() - val structureFile = pluginInstance.structuresFolder.resolve("$key.nbt") - val structure = if (structureFile.exists()) { - structureFile.inputStream().use(SlimefunStructure::loadFromStream) - } else { - null - } - if (structure == null) { - p.sendMessage(NamedTextColor.RED + "No structure found with key $key") + val structureFile = pluginInstance.structuresFolder.resolve("$name.nbt") + if (!structureFile.exists()) { + p.sendMessage(NamedTextColor.RED + "No structure found with name $name") return@onClick } + val structure = structureFile.inputStream().use(SlimefunStructure::loadFromStream) structure.placeDefault(offsetLocation) - p.sendMessage(NamedTextColor.GREEN + "Loaded structure with key $key") + p.sendMessage(NamedTextColor.GREEN + "Loaded structure with key $name") } } @@ -340,22 +336,30 @@ class SlimefunStructureBlock( val start = block.location + offset val steps = size * particlesPerBlock - for ((axis, opposite) in AXES) { + for ((axes, color) in AXES) { + val (axis, axis1, axis2) = axes val stepVector = axis / particlesPerBlock - val (axis1, axis2) = opposite val startPoints = listOf( start, start + (size * axis1), start + (size * axis2), start + size * (axis1 + axis2), ) + var colored = false for (startPoint in startPoints) { - generateParticles(startPoint, stepVector * axis, (steps * axis).length().toInt()) + val lineColor = if (colored) Color.WHITE else color + generateParticles( + startPoint, + stepVector * axis, + (steps * axis).length().toInt(), + lineColor + ) + colored = true } } } - private fun generateParticles(start: Location, step: Vector, steps: Int) { + private fun generateParticles(start: Location, step: Vector, steps: Int, color: Color) { val locations = mutableListOf() val current = start.clone() repeat(steps) { @@ -366,7 +370,7 @@ class SlimefunStructureBlock( ParticleBuilder(Particle.DUST) .count(1) .location(location) - .color(Color.WHITE) + .color(color) .spawn() } } @@ -378,7 +382,7 @@ class SlimefunStructureBlock( } private val AXES = listOf( - UnitVector.X to (UnitVector.Y to UnitVector.Z), - UnitVector.Y to (UnitVector.X to UnitVector.Z), - UnitVector.Z to (UnitVector.X to UnitVector.Y), + listOf(UnitVector.X, UnitVector.Y, UnitVector.Z) to Color.RED, + listOf(UnitVector.Y, UnitVector.X, UnitVector.Z) to Color.GREEN, + listOf(UnitVector.Z, UnitVector.X, UnitVector.Y) to Color.BLUE, ) \ No newline at end of file diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/abstract/Seat.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/abstract/Seat.kt index d722816..6542ab3 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/abstract/Seat.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/impl/items/abstract/Seat.kt @@ -14,7 +14,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.handlers.SimpleBlockBre import org.bukkit.Location import org.bukkit.block.Block import org.bukkit.block.data.Directional -import org.bukkit.entity.ArmorStand +import org.bukkit.entity.Arrow import org.bukkit.entity.Player import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.ItemStack @@ -31,47 +31,44 @@ open class Seat( private val armorStandKey = "seat".key() fun getSitting(player: Player): Location? { - val armorStand = player.vehicle as? ArmorStand ?: return null - return armorStand.getPdc(armorStandKey) + val entity = player.vehicle as? Arrow ?: return null + return entity.getPdc(armorStandKey) } } @ItemHandler(BlockPlaceHandler::class) private fun onPlace(e: BlockPlaceEvent) { val b = e.block - val armorStand = b.world.summon(b.location.toStandLocation()) - armorStand.isInvisible = true - armorStand.isInvulnerable = true - armorStand.isSmall = true - armorStand.setGravity(false) - armorStand.setAI(false) - armorStand.isMarker = true - armorStand.setPdc(armorStandKey, b.location) + val entity = b.world.summon(b.location.toStandLocation()) + entity.isInvisible = true + entity.isInvulnerable = true + entity.setGravity(false) + entity.setPdc(armorStandKey, b.location) val data = b.blockData if (data is Directional) { val facing = data.facing - val location = armorStand.location + val location = entity.location location.yaw = atan2(facing.modZ.toDouble(), facing.modX.toDouble()).radians .degrees.toFloat() + 90 - armorStand.teleportAsync(location) + entity.teleportAsync(location) } } @ItemHandler(SimpleBlockBreakHandler::class) private fun onBreak(b: Block) { - val armorStand = b.world.nearbyEntitiesByType(b.location.toStandLocation(), 0.5) { + val entity = b.world.nearbyEntitiesByType(b.location.toStandLocation(), 0.5) { it.persistentDataContainer.has(armorStandKey) }.firstOrNull() ?: return - armorStand.remove() + entity.remove() } @ItemHandler(BlockUseHandler::class) private fun onUse(e: PlayerRightClickEvent) { val block = e.clickedBlock.get() - val armorStand = block.world.nearbyEntitiesByType(block.location.toStandLocation(), 0.5) { + val entity = block.world.nearbyEntitiesByType(block.location.toStandLocation(), 0.5) { it.persistentDataContainer.has(armorStandKey) }.firstOrNull() ?: return - armorStand.addPassenger(e.player) + entity.addPassenger(e.player) onSit(e.player, block) } diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/McUtils.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/McUtils.kt index ac875e2..fcfdfb7 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/McUtils.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/McUtils.kt @@ -1,7 +1,6 @@ package io.github.addoncommunity.galactifun.util.bukkit import io.github.addoncommunity.galactifun.pluginInstance -import io.papermc.paper.entity.TeleportFlag.EntityState import net.kyori.adventure.text.Component import org.bukkit.* import org.bukkit.block.structure.Mirror @@ -58,9 +57,7 @@ fun Entity.galactifunTeleport( setMetadata("galactifun.teleporting", DummyMetadataValue) return teleportAsync( dest, - reason, - EntityState.RETAIN_VEHICLE, - EntityState.RETAIN_PASSENGERS + reason ).thenApply { removeMetadata("galactifun.teleporting", pluginInstance) it diff --git a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/SerUtils.kt b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/SerUtils.kt index 6d90ec8..8335026 100644 --- a/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/SerUtils.kt +++ b/plugin/src/main/kotlin/io/github/addoncommunity/galactifun/util/bukkit/SerUtils.kt @@ -2,13 +2,14 @@ package io.github.addoncommunity.galactifun.util.bukkit import io.github.addoncommunity.galactifun.impl.items.CommandComputer import io.github.addoncommunity.galactifun.util.SlimefunStructure +import io.github.seggan.sf4k.extensions.minus +import io.github.seggan.sf4k.extensions.plus import io.github.seggan.sf4k.serial.pdc.getData import io.github.seggan.sf4k.serial.pdc.setData -import org.bukkit.Location import org.bukkit.Material import org.bukkit.NamespacedKey import org.bukkit.block.Block -import org.bukkit.entity.BlockDisplay +import org.bukkit.entity.FallingBlock import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataHolder import org.bukkit.util.BlockVector @@ -24,9 +25,15 @@ inline fun PersistentDataHolder.setPdc(key: NamespacedKey, value: T) persistentDataContainer.setData(key, value) } -fun Block.toDisplay(spawnLocation: Location = location): BlockDisplay { - val display = world.summon(spawnLocation) - display.block = blockData +fun Block.toEntity(): FallingBlock { + val display = world.summon(location + (UnitVector.X + UnitVector.Z)) + display.blockData = blockData + display.cancelDrop = true + display.isInvulnerable = true + display.isSilent = true + display.setGravity(false) + display.setHurtEntities(false) + val structure = SlimefunStructure() structure.fill(location, BlockVector(1, 1, 1), false) val bytes = ByteArrayOutputStream().apply(structure::saveToStream).toByteArray() @@ -35,10 +42,10 @@ fun Block.toDisplay(spawnLocation: Location = location): BlockDisplay { return display } -fun BlockDisplay.toBlock(placeLocation: Location = location): Boolean { +fun FallingBlock.toBlock(): Boolean { val bytes = persistentDataContainer.getData(CommandComputer.SERIALIZED_BLOCK_KEY) ?: return false val block = SlimefunStructure.loadFromStream(bytes.inputStream()) - block.placeDefault(placeLocation) + block.placeDefault(location - (UnitVector.X + UnitVector.Z)) remove() return true } \ No newline at end of file