Skip to content
This repository was archived by the owner on Nov 28, 2025. It is now read-only.

Commit e29a91a

Browse files
authored
Merge pull request #148 from DockyardMC/feature/highest-lowest-points
add way to get nearest highest, lowest points
2 parents bf93baf + d32c454 commit e29a91a

File tree

3 files changed

+154
-17
lines changed

3 files changed

+154
-17
lines changed

src/main/kotlin/Main.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import io.github.dockyardmc.events.Events
33
import io.github.dockyardmc.events.PlayerFlightToggleEvent
44
import io.github.dockyardmc.events.PlayerJoinEvent
55
import io.github.dockyardmc.events.ServerTickEvent
6+
import io.github.dockyardmc.extentions.broadcastMessage
67
import io.github.dockyardmc.maths.randomFloat
78
import io.github.dockyardmc.maths.vectors.Vector3d
89
import io.github.dockyardmc.maths.vectors.Vector3f
@@ -11,11 +12,15 @@ import io.github.dockyardmc.player.Player
1112
import io.github.dockyardmc.player.PlayerManager
1213
import io.github.dockyardmc.player.systems.GameMode
1314
import io.github.dockyardmc.protocol.packets.play.serverbound.ServerboundClientInputPacket
15+
import io.github.dockyardmc.registry.Biomes
16+
import io.github.dockyardmc.registry.DimensionTypes
1417
import io.github.dockyardmc.registry.Particles
1518
import io.github.dockyardmc.registry.Sounds
1619
import io.github.dockyardmc.registry.registries.PotionEffectRegistry
1720
import io.github.dockyardmc.sounds.playSound
1821
import io.github.dockyardmc.utils.DebugSidebar
22+
import io.github.dockyardmc.world.WorldManager
23+
import io.github.dockyardmc.world.generators.VoidWorldGenerator
1924

2025
fun suggestPotionEffects(player: Player): List<String> {
2126
return PotionEffectRegistry.potionEffects.keys.toList()

src/main/kotlin/io/github/dockyardmc/location/Location.kt

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ package io.github.dockyardmc.location
22

33
import io.github.dockyardmc.apis.bounds.Bound
44
import io.github.dockyardmc.extentions.truncate
5-
import io.github.dockyardmc.registry.registries.RegistryBlock
65
import io.github.dockyardmc.maths.vectors.Vector2f
76
import io.github.dockyardmc.maths.vectors.Vector3
87
import io.github.dockyardmc.maths.vectors.Vector3d
98
import io.github.dockyardmc.maths.vectors.Vector3f
9+
import io.github.dockyardmc.registry.registries.RegistryBlock
1010
import io.github.dockyardmc.world.World
11+
import io.github.dockyardmc.world.block.Block
1112
import io.github.dockyardmc.world.chunk.Chunk
1213
import io.netty.buffer.ByteBuf
1314
import kotlin.math.*
@@ -21,25 +22,25 @@ class Location(
2122
var world: World,
2223
) {
2324

24-
constructor(x: Int, y: Int, z: Int, yaw: Float = 0f, pitch: Float = 0f, world: World):
25+
constructor(x: Int, y: Int, z: Int, yaw: Float = 0f, pitch: Float = 0f, world: World) :
2526
this(x.toDouble(), y.toDouble(), z.toDouble(), yaw, pitch, world)
2627

27-
constructor(x: Int, y: Int, z: Int, world: World):
28+
constructor(x: Int, y: Int, z: Int, world: World) :
2829
this(x.toDouble(), y.toDouble(), z.toDouble(), 0f, 0f, world)
2930

30-
constructor(x: Float, y: Float, z: Float, world: World):
31+
constructor(x: Float, y: Float, z: Float, world: World) :
3132
this(x.toDouble(), y.toDouble(), z.toDouble(), 0f, 0f, world)
3233

33-
constructor(x: Double, y: Double, z: Double, world: World):
34+
constructor(x: Double, y: Double, z: Double, world: World) :
3435
this(x, y, z, 0f, 0f, world)
3536

36-
constructor(vector: Vector3, yaw: Float, pitch: Float, world: World):
37+
constructor(vector: Vector3, yaw: Float, pitch: Float, world: World) :
3738
this(vector.x, vector.y, vector.z, yaw, pitch, world)
3839

39-
constructor(vector: Vector3d, yaw: Float, pitch: Float, world: World):
40+
constructor(vector: Vector3d, yaw: Float, pitch: Float, world: World) :
4041
this(vector.x, vector.y, vector.z, yaw, pitch, world)
4142

42-
constructor(vector: Vector3f, yaw: Float, pitch: Float, world: World):
43+
constructor(vector: Vector3f, yaw: Float, pitch: Float, world: World) :
4344
this(vector.x.toDouble(), vector.y.toDouble(), vector.z.toDouble(), yaw, pitch, world)
4445

4546
val blockX: Int get() = floor(x).toInt()
@@ -51,7 +52,7 @@ class Location(
5152
val fullZ: Int get() = ceil(z).toInt()
5253

5354
override fun equals(other: Any?): Boolean {
54-
if(other == null || other !is Location) return false
55+
if (other == null || other !is Location) return false
5556
return x == other.x &&
5657
y == other.y &&
5758
z == other.z &&
@@ -106,7 +107,7 @@ class Location(
106107

107108
fun getDirection(noPitch: Boolean = false): Vector3d {
108109
val rotX = yaw
109-
val rotY = if(noPitch) 0.0 else pitch
110+
val rotY = if (noPitch) 0.0 else pitch
110111
val xz = cos(Math.toRadians(rotY.toDouble()))
111112
return Vector3d(
112113
-xz * sin(Math.toRadians(rotX.toDouble())),
@@ -136,7 +137,6 @@ class Location(
136137
return this.yaw.compareTo(yaw) == 0 && this.pitch.compareTo(pitch) == 0
137138
}
138139

139-
140140
fun setDirection(vector: Vector3d): Location {
141141
val loc = this.clone()
142142
val x = vector.x
@@ -163,14 +163,14 @@ class Location(
163163
fun withNoRotation(): Location = this.clone().apply { yaw = 0f; pitch = 0f }
164164

165165
val length: Double get() = sqrt(x * x + y * y + z * z)
166-
val block: io.github.dockyardmc.world.block.Block get() = world.getBlock(this)
166+
val block: Block get() = world.getBlock(this)
167167

168168
fun toVector3(): Vector3 = Vector3(x.toInt(), y.toInt(), z.toInt())
169169
fun toVector3f(): Vector3f = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
170170
fun toVector3d(): Vector3d = Vector3d(x, y, z)
171171

172172
val blockHash: Int get() = (blockX.hashCode() + blockY.hashCode() + blockZ.hashCode() + world.name.hashCode())
173-
fun equalsBlock(location: Location): Boolean = this.blockHash == location.blockHash
173+
fun equalsBlock(location: Location): Boolean = this.blockHash == location.blockHash
174174

175175
fun sameBlock(point: Vector3): Boolean {
176176
return sameBlock(point.x, point.y, point.z)
@@ -180,7 +180,7 @@ class Location(
180180
return this.blockX == blockX && this.blockY == blockY && this.blockZ == blockZ
181181
}
182182

183-
fun setBlock(block: io.github.dockyardmc.world.block.Block) {
183+
fun setBlock(block: Block) {
184184
world.setBlock(this, block)
185185
}
186186

@@ -224,12 +224,73 @@ class Location(
224224

225225
return locations
226226
}
227+
228+
val closestNonAirBelow: Pair<Block, Location>?
229+
get() {
230+
val minY = world.dimensionType.minY
231+
val startY = this.blockY
232+
233+
for (y in startY downTo minY) {
234+
val blockLoc = world.locationAt(this.blockX, y, this.blockZ)
235+
val block = world.getBlock(blockLoc)
236+
if (!block.isAir()) {
237+
return block to blockLoc
238+
}
239+
}
240+
return null
241+
}
242+
243+
val closestSolidBelow: Pair<Block, Location>?
244+
get() {
245+
val minY = world.dimensionType.minY
246+
val startY = this.blockY
247+
248+
for (y in startY downTo minY) {
249+
val blockLoc = world.locationAt(this.blockX, y, this.blockZ)
250+
val block = world.getBlock(blockLoc)
251+
if (block.registryBlock.isSolid) {
252+
return block to blockLoc
253+
}
254+
}
255+
return null
256+
}
257+
258+
val closestNonAirAbove: Pair<Block, Location>?
259+
get() {
260+
val maxY = world.dimensionType.height - 1
261+
val startY = this.blockY
262+
263+
for (y in maxY downTo startY) {
264+
val blockLoc = world.locationAt(this.blockX, y, this.blockZ)
265+
val block = world.getBlock(blockLoc)
266+
if (!block.isAir()) {
267+
return block to blockLoc
268+
}
269+
}
270+
return null
271+
}
272+
273+
val closestSolidAbove: Pair<Block, Location>?
274+
get() {
275+
val maxY = world.dimensionType.height - 1
276+
val startY = this.blockY
277+
278+
for (y in maxY downTo startY) {
279+
val blockLoc = world.locationAt(this.blockX, y, this.blockZ)
280+
val block = world.getBlock(blockLoc)
281+
if (block.registryBlock.isSolid) {
282+
return block to blockLoc
283+
}
284+
}
285+
return null
286+
}
287+
227288
}
228289

229290
fun ByteBuf.writeRotation(location: Location, delta: Boolean) {
230-
if(delta) {
231-
this.writeByte((location.pitch * 256f / 360f).toInt())
232-
this.writeByte((location.yaw * 256f / 360f).toInt())
291+
if (delta) {
292+
this.writeByte((location.pitch * 256f / 360f).toInt())
293+
this.writeByte((location.yaw * 256f / 360f).toInt())
233294
} else {
234295
this.writeFloat(location.yaw)
235296
this.writeFloat(location.pitch)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package io.github.dockyard.tests.location
2+
3+
import io.github.dockyard.tests.TestServer
4+
import io.github.dockyardmc.location.Location
5+
import io.github.dockyardmc.registry.Blocks
6+
import io.github.dockyardmc.world.WorldManager
7+
import kotlin.test.BeforeTest
8+
import kotlin.test.Test
9+
import kotlin.test.assertEquals
10+
11+
class HighestLowestPointTest {
12+
13+
@BeforeTest
14+
fun prepare() {
15+
TestServer.getOrSetupServer()
16+
}
17+
18+
@Test
19+
fun testLowestPoint() {
20+
val world = WorldManager.mainWorld
21+
22+
world.setBlock(0, 0, 0, Blocks.STONE)
23+
val zeroZeroZero = Location(0, 0, 0, world)
24+
25+
assertEquals(zeroZeroZero, zeroZeroZero.closestNonAirBelow?.second)
26+
27+
world.setBlock(0, 0, 0, Blocks.AIR)
28+
world.setBlock(0, -1, 0, Blocks.AIR)
29+
world.setBlock(0, -30, 0, Blocks.STONE)
30+
31+
assertEquals(world.locationAt(0, -30, 0), zeroZeroZero.closestNonAirBelow?.second)
32+
33+
world.setBlock(0, -30, 0, Blocks.AIR)
34+
35+
assertEquals(null, zeroZeroZero.closestNonAirBelow)
36+
37+
world.setBlock(0, -30, 0, Blocks.SHORT_GRASS)
38+
39+
assertEquals(world.locationAt(0, -30, 0), zeroZeroZero.closestNonAirBelow?.second)
40+
assertEquals(null, zeroZeroZero.closestSolidBelow)
41+
42+
world.setBlock(0, -30, 0, Blocks.AIR)
43+
}
44+
45+
@Test
46+
fun testHighestPoint() {
47+
val world = WorldManager.mainWorld
48+
49+
world.setBlock(0, 0, 0, Blocks.STONE)
50+
world.setBlock(0, 1, 0, Blocks.AIR)
51+
val zeroZeroZero = Location(0, 0, 0, world)
52+
53+
assertEquals(zeroZeroZero, zeroZeroZero.closestNonAirAbove?.second)
54+
55+
world.setBlock(0, 0, 0, Blocks.AIR)
56+
world.setBlock(0, 30, 0, Blocks.STONE)
57+
58+
assertEquals(world.locationAt(0, 30, 0), zeroZeroZero.closestNonAirAbove?.second)
59+
60+
world.setBlock(0, 30, 0, Blocks.AIR)
61+
62+
assertEquals(null, zeroZeroZero.closestNonAirAbove)
63+
64+
world.setBlock(0, 30, 0, Blocks.SHORT_GRASS)
65+
66+
assertEquals(world.locationAt(0, 30, 0), zeroZeroZero.closestNonAirAbove?.second)
67+
assertEquals(null, zeroZeroZero.closestSolidAbove)
68+
69+
world.setBlock(0, 30, 0, Blocks.AIR)
70+
}
71+
}

0 commit comments

Comments
 (0)