Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/deeper world#25 #100

Merged
merged 2 commits into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions src/main/kotlin/com/mineinabyss/deeperworld/DeeperCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@ import com.mineinabyss.deeperworld.MinecraftConstants.FULL_DAY_TIME
import com.mineinabyss.deeperworld.services.WorldManager
import com.mineinabyss.deeperworld.services.canMoveSections
import com.mineinabyss.deeperworld.synchronization.sync
import com.mineinabyss.deeperworld.world.section.correspondingSection
import com.mineinabyss.deeperworld.world.section.getCorrespondingLocation
import com.mineinabyss.deeperworld.world.section.section
import com.mineinabyss.idofront.commands.brigadier.Args
import com.mineinabyss.idofront.commands.brigadier.commands
import com.mineinabyss.idofront.commands.brigadier.executes
import com.mineinabyss.idofront.commands.brigadier.playerExecutes
import com.mineinabyss.idofront.commands.execution.stopCommand
import com.mineinabyss.deeperworld.world.section.*
import com.mineinabyss.idofront.commands.brigadier.*
import com.mineinabyss.idofront.messaging.error
import com.mineinabyss.idofront.messaging.info
import com.mineinabyss.idofront.messaging.success
Expand All @@ -29,6 +23,7 @@ import com.sk89q.worldedit.regions.CuboidRegion
import com.sk89q.worldedit.session.ClipboardHolder
import com.sk89q.worldedit.world.World
import io.papermc.paper.command.brigadier.argument.ArgumentTypes
import org.bukkit.entity.Player

object DeeperCommands {
fun registerCommands() {
Expand Down Expand Up @@ -166,7 +161,8 @@ object DeeperCommands {
)

block.sync { original, corr ->
if (original.type != corr.type) corr.blockData = original.blockData.clone()
if (original.type != corr.type) corr.blockData =
original.blockData.clone()
}
}
}
Expand All @@ -179,6 +175,25 @@ object DeeperCommands {
}
}
}
"depth" {
val playerArg = ArgumentTypes.player()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am open to suggestions on how to more easily get a single player or the executor as a player if no player is specified. I'd like to avoid having to deal with a list of players in the executes logic, if possible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you have to use a list even for single players in brigadier, slightly annoying but yeah

.resolve()
.default { listOf(executor as? Player ?: fail("Receiver must be a player or pass a player as argument")) }

executes(playerArg) { players ->
val player = players.single()

WorldManager.getDepthFor(player.location)?.let{
if (sender is Player){
sender.success("Your depth is $it blocks")
}
else{
sender.success("Depth of player ${player.name} is $it blocks")
}

} ?: sender.error("${player.name} is not in a managed section")
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface WorldManager {
* Given x,y coords and a world, return the Section it is within
*
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param world The world
* @return The section or null if the location is not within a section.
Expand Down Expand Up @@ -71,6 +72,24 @@ interface WorldManager {
*/
fun unregisterSection(key: SectionKey)

/**
* Gets the depth in blocks of the given location, taking sections into account
*
* @param location The location
* @return The depth of the given location in blocks, or null if location is not in a managed section
*/
fun getDepthFor(location: Location): Int?

/**
* Gets the depth in blocks of the given position, taking sections into account
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param world The world
* @return The depth of the given position in blocks, or null if position is not in a managed section
*/
fun getDepthFor(x: Double, y: Double, z: Double, world: World): Int?

/**
* Gets an immutable copy of the currently loaded sections.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import com.mineinabyss.deeperworld.services.WorldManager
import com.mineinabyss.deeperworld.world.section.AbstractSectionKey.CustomSectionKey
import com.mineinabyss.deeperworld.world.section.Section
import com.mineinabyss.deeperworld.world.section.SectionKey
import com.mineinabyss.deeperworld.world.section.overlapWith
import com.mineinabyss.deeperworld.world.section.section
import com.mineinabyss.idofront.messaging.info
import org.bukkit.Location
import org.bukkit.World
import kotlin.math.floor

class WorldManagerImpl : WorldManager {
override val sections get() = sectionMap.values.toSet()
Expand All @@ -28,6 +32,40 @@ class WorldManagerImpl : WorldManager {

override fun unregisterSection(key: SectionKey) = TODO()

override fun getDepthFor(location: Location): Int? {
val section = WorldManager.getSectionFor(location) ?: return null

return this.internalGetDepthFor(floor(location.y).toInt(), section)
}

override fun getDepthFor(x: Double, y: Double, z: Double, world: World): Int? {
val yFloored = floor(y).toInt()
val section = WorldManager.getSectionFor(floor(x).toInt(), yFloored, floor(z).toInt(), world) ?: return null

return this.internalGetDepthFor(yFloored, section)
}

private fun internalGetDepthFor(y: Int, section: Section): Int {
var depth = (section.region.max.y - y)

var currentSection: Section = section
var aboveSection = section.aboveKey.section

if (aboveSection != null) {
depth += 1 // Account for one unit of depth missing when calculating depth with multiple sections
}

while (aboveSection != null) {
depth += aboveSection.height
depth -= aboveSection.overlapWith(currentSection) ?: 0

currentSection = aboveSection
aboveSection = currentSection.aboveKey.section
}

return depth
}

override fun getSectionFor(location: Location): Section? {
return getSectionFor(location.blockX, location.blockY, location.blockZ, location.world!!)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,8 @@ data class Section(
@Transient
internal var belowKey: SectionKey = SectionKey.TERMINAL

@Transient
val height: Int = this.region.max.y - this.region.min.y

override fun toString() = key.toString()
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ fun Location.sharedBetween(section: Section, otherSection: Section): Boolean {

fun Section.overlapWith(other: Section): Int? {
if (!isAdjacentTo(other)) return null
if(min(this.region.max.y, other.region.max.y) <= max(this.region.min.y, other.region.min.y)) return null
if (min(this.region.max.y, other.region.max.y) <= max(this.region.min.y, other.region.min.y)) return null
// We decide which two points we are translating between.
val (locA, locB) = when (isOnTopOf(other)) {
true -> referenceBottom to other.referenceTop
Expand Down