Phase 3: the Mangrove Mire poisons anyone without Mire Waders
CI / build-and-smoke-test (push) Failing after 30m44s
CI / build-and-smoke-test (push) Failing after 30m44s
- Companion mod zone hazards (zone/ZoneHazards.kt, data in data/cobblesurvival/zone_hazards/): in the Mire a player without an item from #cobblesurvival:mire_protection gets Poison every 5 seconds, with a one-time warning. Potions, milk and golden apples still help. - Mire Waders: KubeJS leather boots, dropped by the Westmarch and Verdant Jungle guardians (the zones before the Mire), per Adrian's boss rule. - Self-test mire_poisons_without_waders. - Allow-list Cobblemon's misspelt jigsaw state in habitats/parched_peat_bog7.nbt, which test players now reach. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
73fe71918f
commit
d105f6757d
19 files changed
+197
-15
No files matched your search
@@ -0,0 +1,97 @@
|
||||
package dev.cobblesurvival.zone
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonElement
|
||||
import dev.cobblesurvival.CobbleSurvival
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.util.profiling.ProfilerFiller
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.item.Item
|
||||
import net.neoforged.neoforge.common.NeoForge
|
||||
import net.neoforged.neoforge.event.AddReloadListenerEvent
|
||||
import net.neoforged.neoforge.event.tick.ServerTickEvent
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Zone hazards that Cold Sweat doesn't cover (roadmap Phase 3: "a poison swamp ... as area effects"): while a player
|
||||
* is in the zone and wears nothing from the protection tag, they keep getting the effect. Potions, milk and golden
|
||||
* apples still work against it. Definitions: `data/cobblesurvival/zone_hazards/<name>.json`.
|
||||
*/
|
||||
object ZoneHazards : SimpleJsonResourceReloadListener(Gson(), "zone_hazards") {
|
||||
class Hazard(
|
||||
val zone: String,
|
||||
val effect: Holder<MobEffect>,
|
||||
val amplifier: Int,
|
||||
val durationTicks: Int,
|
||||
val everyTicks: Int,
|
||||
val protection: TagKey<Item>,
|
||||
val warning: String?,
|
||||
)
|
||||
|
||||
var hazards: List<Hazard> = emptyList()
|
||||
private set
|
||||
private val warned = HashMap<UUID, String>()
|
||||
|
||||
fun register() {
|
||||
NeoForge.EVENT_BUS.addListener<AddReloadListenerEvent> { it.addListener(this) }
|
||||
NeoForge.EVENT_BUS.addListener(::onServerTick)
|
||||
}
|
||||
|
||||
override fun apply(files: Map<ResourceLocation, JsonElement>, resources: ResourceManager, profiler: ProfilerFiller) {
|
||||
hazards = files.mapNotNull { (id, element) ->
|
||||
val json = element.asJsonObject
|
||||
val effectId = ResourceLocation.parse(json.get("effect").asString)
|
||||
val effect = BuiltInRegistries.MOB_EFFECT.getHolder(effectId).orElse(null)
|
||||
if (effect == null) {
|
||||
CobbleSurvival.LOGGER.error("Zone hazard {}: unknown effect {}", id, effectId)
|
||||
return@mapNotNull null
|
||||
}
|
||||
Hazard(
|
||||
zone = json.get("zone").asString,
|
||||
effect = effect,
|
||||
amplifier = json.get("amplifier")?.asInt ?: 0,
|
||||
durationTicks = json.get("duration_ticks").asInt,
|
||||
everyTicks = json.get("every_ticks").asInt,
|
||||
protection = TagKey.create(Registries.ITEM, ResourceLocation.parse(json.get("protection").asString)),
|
||||
warning = json.get("warning")?.asString,
|
||||
)
|
||||
}
|
||||
CobbleSurvival.LOGGER.info("Loaded {} zone hazards", hazards.size)
|
||||
}
|
||||
|
||||
private fun onServerTick(event: ServerTickEvent.Post) {
|
||||
if (hazards.isEmpty()) return
|
||||
val tick = event.server.tickCount
|
||||
for (player in event.server.playerList.players) {
|
||||
if (player.isCreative || player.isSpectator) continue
|
||||
val zone = Zones.at(player.serverLevel(), player.blockPosition())?.id
|
||||
if (zone == null || hazards.none { it.zone == zone }) {
|
||||
warned.remove(player.uuid)
|
||||
continue
|
||||
}
|
||||
for (hazard in hazards) {
|
||||
if (hazard.zone != zone || tick % hazard.everyTicks != 0 || isProtected(player, hazard)) continue
|
||||
player.addEffect(MobEffectInstance(hazard.effect, hazard.durationTicks, hazard.amplifier))
|
||||
if (hazard.warning != null && warned[player.uuid] != zone) {
|
||||
warned[player.uuid] = zone
|
||||
player.displayClientMessage(Component.translatable(hazard.warning).withStyle(ChatFormatting.DARK_GREEN), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isProtected(player: ServerPlayer, hazard: Hazard) =
|
||||
listOf(EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET)
|
||||
.any { player.getItemBySlot(it).`is`(hazard.protection) }
|
||||
}
|
||||
Reference in new issue
Block a user