Skip to content

Commit 8d217ee

Browse files
authored
Merge pull request #31 from SLNE-Development/feat/nether-end-protections
feat: enhance protection pricing logic for Nether and The End environ…
2 parents bb5ff62 + 1e96a3e commit 8d217ee

10 files changed

Lines changed: 94 additions & 37 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
kotlin.code.style=official
22
kotlin.stdlib.default.dependency=false
33
org.gradle.parallel=true
4-
version=3.2.4
4+
version=3.2.5

src/main/kotlin/dev/slne/surf/protect/paper/config/ProtectionConfig.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package dev.slne.surf.protect.paper.config
22

3+
import dev.slne.surf.api.core.config.constraints.Range
34
import dev.slne.surf.api.paper.extensions.server
45
import dev.slne.surf.transaction.api.currency.Currency
56
import org.bukkit.Location
7+
import org.bukkit.World
68
import org.bukkit.block.BlockType
79
import org.bukkit.block.data.BlockData
810
import org.bukkit.inventory.ItemStack
@@ -30,7 +32,8 @@ data class ProtectionConfig(
3032
data class ProtectionSettings(
3133
val maxDistanceFromStart: Double = 100.0,
3234
val retailPercent: Int = 65,
33-
val renamePrice: Int = 2_500
35+
val renamePrice: Int = 2_500,
36+
val protectOnlyAboveNetherRoofInNether: Boolean = true,
3437
) {
3538
val retailModifier: Double
3639
get() = retailPercent / 100.0
@@ -73,21 +76,24 @@ data class ProtectionConfig(
7376
data class PricingSettings(
7477
val minPerBlock: Double = 4.0,
7578
val spawnProtectionPerBlock: Double = 200.0,
76-
val discountPercent: Int = 20
79+
80+
@Range(min = 0.0, max = 100.0)
81+
val discountPercent: Int = 20,
82+
83+
val environmentMultiplier: Map<World.Environment, Double> = mapOf(
84+
World.Environment.NORMAL to 1.0,
85+
World.Environment.NETHER to 2.5,
86+
)
7787
) {
7888
val discountModifier: Double
7989
get() = 1.0 - (discountPercent / 100.0)
80-
81-
init {
82-
require(discountPercent in 0..100) { "Discount percent must be between 0 and 100" }
83-
}
8490
}
8591

8692
@ConfigSerializable
8793
data class CurrencyConfig(
8894
val name: String = "CastCoin"
8995
) {
90-
val currency: Currency = Currency[name] ?: error("Currency with name '$name' not found")
96+
val currency: Currency get() = Currency[name] ?: error("Currency with name '$name' not found")
9197
}
9298

9399
@ConfigSerializable

src/main/kotlin/dev/slne/surf/protect/paper/listener/listeners/ProtectionModeListener.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ object ProtectionModeListener : Listener {
196196
.contains("SHULKER_BOX")
197197
.contains("BARREL")
198198
.contains("BEACON")
199-
.contains("BED")
199+
.contains("BED").not(Material.BEDROCK) // BEDROCK is not a bed
200200
.contains("CAULDRON")
201201
.contains("COMPARATOR")
202202
.contains("DAYLIGHT_DETECTOR")
@@ -211,5 +211,6 @@ object ProtectionModeListener : Listener {
211211
.add(Material.REPEATER)
212212
.add(Material.OBSERVER)
213213
.add(Material.CHISELED_BOOKSHELF)
214+
.add(Material.CRAFTER)
214215
.lock()
215216
}

src/main/kotlin/dev/slne/surf/protect/paper/math/Mth.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ object Mth {
4848
}
4949

5050
@JvmStatic
51-
fun calculatePricePerBlock(distance: Double): Double {
51+
fun calculatePricePerBlock(distance: Float): Double {
5252
val raw = PRICE_GRADIENT * distance + PRICE_INTERCEPT
5353
val rounded = (raw * 100.0).roundToInt() / 100.0
5454
return max(config.pricing.minPerBlock, rounded)
@@ -105,7 +105,7 @@ object Mth {
105105
data class EffectiveCostResult(
106106
val effectiveCost: Double,
107107
val pricePerBlock: Double,
108-
val spawnDistance: Double,
108+
val spawnDistance: Float,
109109
val discountFactor: Double = 1.0
110110
) {
111111
val hasDiscount: Boolean get() = discountFactor < 1.0

src/main/kotlin/dev/slne/surf/protect/paper/menu/util/view-util.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ fun createRegionItem(protection: RegionInfo, showMoreInfo: Boolean = true) =
120120
white("Id: ".toSmallCaps())
121121
variableValue(protection.region.id.toSmallCaps())
122122
}
123+
line {
124+
appendBlob()
125+
appendSpace()
126+
white("Welt: ".toSmallCaps())
127+
variableValue(protection.world?.key()?.asMinimalString()?.toSmallCaps() ?: "Unbekannt".toSmallCaps())
128+
}
123129
line {
124130
appendBlob()
125131
appendSpace()

src/main/kotlin/dev/slne/surf/protect/paper/message/Messages.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ object Messages {
197197
error("Bitte gedulde dich einen Moment.")
198198
}
199199

200+
val canOnlyProtectAboveNetherRoofInNether = buildText { // TODO: better message
201+
appendErrorPrefix()
202+
error("Du kannst nur über dem Nether-Dach schützen.")
203+
}
204+
200205
/**
201206
* Generates a message indicating how many more markers need to be placed to meet the minimum required amount.
202207
*
@@ -231,7 +236,7 @@ object Messages {
231236
effectiveCost: Double,
232237
currency: Currency,
233238
pricePerBlock: Double,
234-
distanceToSpawn: Double,
239+
distanceToSpawn: Float,
235240
discountFactor: Double = 1.0
236241
) = buildText {
237242
val distanceToSpawn = (distanceToSpawn * 100).roundToInt() / 100.0

src/main/kotlin/dev/slne/surf/protect/paper/region/ProtectionRegion.kt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import kotlinx.coroutines.withContext
4444
import org.apache.commons.lang3.RandomStringUtils
4545
import org.bukkit.Chunk
4646
import org.bukkit.ChunkSnapshot
47+
import org.bukkit.World
4748
import org.bukkit.block.data.BlockData
4849
import org.bukkit.entity.Player
4950
import org.bukkit.inventory.ItemStack
@@ -119,7 +120,15 @@ class ProtectionRegion(
119120
}
120121

121122
fun createMarker(pos: BlockPosition, previousData: BlockData, isExpanding: Boolean): Marker? {
122-
val candidate = Marker(WeakReference(player.world), this, pos, previousData)
123+
val world = player.world
124+
if (world.environment == World.Environment.NETHER && config.protection.protectOnlyAboveNetherRoofInNether) {
125+
if (pos.y() < world.logicalHeight) {
126+
player.sendMessage(Messages.Protecting.canOnlyProtectAboveNetherRoofInNether)
127+
return null
128+
}
129+
}
130+
131+
val candidate = Marker(WeakReference(world), this, pos, previousData)
123132
if (!updateHullPreview(candidate)) return null
124133

125134
// Check overlap state when not expanding
@@ -191,8 +200,8 @@ class ProtectionRegion(
191200
region = ProtectedPolygonalRegion(
192201
expandingProtection.id,
193202
vectors,
194-
world.minHeight,
195-
world.maxHeight - 1
203+
expandingProtection.minimumPoint.y(),
204+
expandingProtection.maximumPoint.y()
196205
)
197206
region.copyFrom(expandingProtection)
198207
} else {
@@ -203,7 +212,7 @@ class ProtectionRegion(
203212
region = ProtectedPolygonalRegion(
204213
name,
205214
vectors,
206-
world.minHeight,
215+
if (world.environment == World.Environment.NETHER && config.protection.protectOnlyAboveNetherRoofInNether) world.logicalHeight else world.minHeight,
207216
world.maxHeight - 1
208217
)
209218
region.owners.addPlayer(protectionUser.localPlayer)

src/main/kotlin/dev/slne/surf/protect/paper/region/info/RegionInfo.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import dev.slne.surf.protect.paper.region.flags.ProtectionFlagsRegistry
88
import dev.slne.surf.protect.paper.util.fixedVolume
99
import dev.slne.surf.protect.paper.util.getRegionManagerOrNull
1010
import dev.slne.surf.protect.paper.util.toLocalPlayer
11+
import org.bukkit.Bukkit
12+
import org.bukkit.World
1113

1214

1315
data class RegionInfo(val region: ProtectedRegion) {
@@ -21,6 +23,7 @@ data class RegionInfo(val region: ProtectedRegion) {
2123
val regionManager get() = region.getRegionManagerOrNull()
2224
val owners get() = region.owners.uniqueIds.mapTo(mutableObjectListOf()) { it.toLocalPlayer() }
2325
val members get() = region.members.uniqueIds.mapTo(mutableObjectListOf()) { it.toLocalPlayer() }
26+
val world: World? get() = regionManager?.name?.let { Bukkit.getWorld(it) }
2427

2528
init {
2629
val flagInfo = region.getFlag(ProtectionFlagsRegistry.SURF_PROTECT_FLAG)

src/main/kotlin/dev/slne/surf/protect/paper/region/utils.kt

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,61 @@ package dev.slne.surf.protect.paper.region
33
import com.sk89q.worldedit.util.Location
44
import dev.slne.surf.protect.paper.config
55
import dev.slne.surf.protect.paper.math.Mth
6-
import org.bukkit.util.Vector
7-
8-
fun Location.getProtectionPricePerBlock(): PricePerBlockResult {
9-
val spawns = listOf(
10-
Vector(0, 0, 0),
11-
Vector(0, 0, -25000),
12-
Vector(25000, 0, -25000),
13-
Vector(-25000, 0, -25000),
14-
Vector(0, 0, 25000),
15-
Vector(25000, 0, 25000),
16-
Vector(-25000, 0, 25000),
17-
Vector(25000, 0, 0),
18-
Vector(-25000, 0, 0)
6+
import dev.slne.surf.protect.paper.util.bukkitWorld
7+
import org.bukkit.World
8+
import org.spongepowered.math.vector.Vector2i
9+
10+
private val spawnPositionsByEnvironment = mapOf(
11+
World.Environment.NETHER to listOf(
12+
Vector2i(0, 0),
13+
Vector2i(0, -3125),
14+
Vector2i(3125, -3125),
15+
Vector2i(-3125, -3125),
16+
Vector2i(0, 3125),
17+
Vector2i(3125, 3125),
18+
Vector2i(-3125, 3125),
19+
Vector2i(3125, 0),
20+
Vector2i(-3125, 0)
21+
),
22+
World.Environment.THE_END to listOf(Vector2i.ZERO),
23+
World.Environment.NORMAL to listOf(
24+
Vector2i(0, 0),
25+
Vector2i(0, -25000),
26+
Vector2i(25000, -25000),
27+
Vector2i(-25000, -25000),
28+
Vector2i(0, 25000),
29+
Vector2i(25000, 25000),
30+
Vector2i(-25000, 25000),
31+
Vector2i(25000, 0),
32+
Vector2i(-25000, 0)
1933
)
34+
)
2035

21-
val pos = Vector(blockX.toDouble(), 0.0, blockZ.toDouble())
22-
23-
val nearestSpawn = spawns.minBy {
24-
pos.distance(it)
25-
}
36+
fun Location.getProtectionPricePerBlock(): PricePerBlockResult {
37+
val environment = this.bukkitWorld.environment
38+
val spawns = spawnPositionsByEnvironment[environment] ?: return PricePerBlockResult.EMPTY
39+
val pos = Vector2i(blockX, blockZ)
2640

41+
val nearestSpawn = spawns.minBy { pos.distanceSquared(it) }
2742
val distance = pos.distance(nearestSpawn)
2843

2944
if (distance < config.pricing.spawnProtectionPerBlock) {
3045
return PricePerBlockResult(Double.MAX_VALUE, distance)
3146
}
3247

33-
return PricePerBlockResult(Mth.calculatePricePerBlock(distance), distance)
48+
val multiplier = config.pricing.environmentMultiplier[environment] ?: 1.0
49+
50+
return PricePerBlockResult(
51+
Mth.calculatePricePerBlock(distance) * multiplier,
52+
distance
53+
)
3454
}
3555

3656
data class PricePerBlockResult(
3757
val pricePerBlock: Double,
38-
val spawnDistance: Double
39-
)
58+
val spawnDistance: Float
59+
) {
60+
companion object {
61+
val EMPTY = PricePerBlockResult(Double.MAX_VALUE, Float.MAX_VALUE)
62+
}
63+
}

src/main/kotlin/dev/slne/surf/protect/paper/util/util.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ fun Location.isGlobalRegion(): Boolean {
222222
val WorldEditLocation.world: WorldEditWorld
223223
get() = this.extent as? WorldEditWorld ?: error("Extent is not a World: $extent")
224224

225+
val WorldEditLocation.bukkitWorld
226+
get() = BukkitAdapter.adapt(world)!!
227+
225228
/**
226229
* Checks if the player is currently standing in the specified protected region.
227230
*

0 commit comments

Comments
 (0)