package dev.cobblesurvival import com.cobblemon.mod.common.Cobblemon import com.cobblemon.mod.common.api.pokemon.PokemonSpecies import com.mojang.logging.LogUtils import dev.cobblesurvival.catching.Catching import dev.cobblesurvival.dev.BiomePreview import dev.cobblesurvival.dev.OreVeins import dev.cobblesurvival.ore.BaseLoot import dev.cobblesurvival.ore.OreNodes import dev.cobblesurvival.permadeath.Permadeath import dev.cobblesurvival.boss.BossCommands import dev.cobblesurvival.boss.BossFights import dev.cobblesurvival.boss.BossToughness import dev.cobblesurvival.boss.EndBoss import dev.cobblesurvival.machine.MachineShowcase import dev.cobblesurvival.machine.Machines import dev.cobblesurvival.party.ShoulderPassives import dev.cobblesurvival.progress.Gates import dev.cobblesurvival.selftest.SelfTest import dev.cobblesurvival.world.OnlyPokemon import dev.cobblesurvival.world.SharedLoot import dev.cobblesurvival.world.SpecialPokemon import dev.cobblesurvival.zone.Guardians import dev.cobblesurvival.zone.InZoneCondition import dev.cobblesurvival.zone.LevelPressure import dev.cobblesurvival.zone.Wanderers import dev.cobblesurvival.zone.ZoneCondition import dev.cobblesurvival.zone.ZoneHazards import dev.cobblesurvival.zone.Zones import net.minecraft.commands.Commands import net.minecraft.core.BlockPos import net.minecraft.network.chat.Component import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerLevel import net.minecraft.server.packs.PackType import net.minecraft.server.packs.repository.Pack import net.minecraft.server.packs.repository.PackSource import net.minecraft.world.level.Level import net.neoforged.fml.ModList import net.neoforged.fml.common.Mod import net.neoforged.neoforge.common.NeoForge import net.neoforged.neoforge.event.AddPackFindersEvent import net.neoforged.neoforge.event.RegisterCommandsEvent import net.neoforged.neoforge.event.level.BlockEvent import net.neoforged.neoforge.event.server.ServerStartedEvent import org.slf4j.Logger import thedarkcolour.kotlinforforge.neoforge.forge.MOD_BUS @Mod(CobbleSurvival.MOD_ID) class CobbleSurvival { companion object { const val MOD_ID = "cobblesurvival" val LOGGER: Logger = LogUtils.getLogger() val version: String get() = ModList.get().getModContainerById(MOD_ID) .map { it.modInfo.version.toString() } .orElse("unknown") /** One line the server smoke test reads over RCON to confirm the mod is live. */ fun statusLine() = "$MOD_ID $version ok; cobblemon ${Cobblemon.VERSION}; species ${PokemonSpecies.count()}" } init { LOGGER.info("Cobblemon Survival companion {} loaded (Cobblemon {})", version, Cobblemon.VERSION) MOD_BUS.addListener(::onAddPackFinders) InZoneCondition.register(MOD_BUS) Machines.register(MOD_BUS) NeoForge.EVENT_BUS.addListener(::onRegisterCommands) NeoForge.EVENT_BUS.addListener(::onServerStarted) NeoForge.EVENT_BUS.addListener(::onPortalSpawn) NeoForge.EVENT_BUS.addListener(OnlyPokemon::onChunkLoad) NeoForge.EVENT_BUS.addListener(OnlyPokemon::onEntityJoin) NeoForge.EVENT_BUS.addListener(OnlyPokemon::onServerTick) Permadeath.register() ZoneCondition.register() NeoForge.EVENT_BUS.addListener(Zones::onAddReloadListeners) Guardians.register() BossFights.register() BossToughness.register() EndBoss.register() Gates.register() ShoulderPassives.register() OreNodes.register() BaseLoot.register() Catching.register() Wanderers.register() SharedLoot.register() SpecialPokemon.register() ZoneHazards.register() LevelPressure.register() SelfTest.register() } /** The island world type has no Nether, so a lit obsidian frame must not turn into a dead portal. */ private fun onPortalSpawn(event: BlockEvent.PortalSpawnEvent) { val level = event.level as? ServerLevel ?: return if (level.server.getLevel(Level.NETHER) == null) { event.isCanceled = true } } /** Ships datapacks/core from the repo as a built-in data pack that is always on, in every world. */ private fun onAddPackFinders(event: AddPackFindersEvent) { event.addPackFinders( ResourceLocation.fromNamespaceAndPath(MOD_ID, "datapacks/core"), PackType.SERVER_DATA, Component.literal("Cobblemon Survival core data"), PackSource.BUILT_IN, true, Pack.Position.TOP, ) } private fun onRegisterCommands(event: RegisterCommandsEvent) { val root = Commands.literal(MOD_ID) .requires { it.hasPermission(2) } .then(Commands.literal("status").executes { context -> context.source.sendSuccess({ Component.literal(statusLine()) }, false) 1 }) .then(BiomePreview.command()) .then(OreVeins.command()) .then(MachineShowcase.command()) .then(Commands.literal("zone").executes { context -> val source = context.source val zone = Zones.at(source.level, BlockPos.containing(source.position)) val text = zone?.let { "${it.name} (${it.id}), Lv ${it.minLevel}-${it.maxLevel}" } ?: "no zone" source.sendSuccess({ Component.literal(text) }, false) 1 }) .then(Commands.literal("guardians").executes { context -> val lines = Guardians.status(context.source.server.overworld()) context.source.sendSuccess({ Component.literal(lines.joinToString("\n").ifEmpty { "no guardians loaded" }) }, false) 1 }.then(BossCommands.guardianReset())) .then(BossCommands.practice()) if (SelfTest.enabled) root.then(SelfTest.command()) event.dispatcher.register(root) } private fun onServerStarted(event: ServerStartedEvent) { LOGGER.info("Cobblemon Survival companion ready: {}", statusLine()) } }