mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-27 04:26:27 -04:00
Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89c2b5cef3 | ||
|
|
bd4a6fc48c | ||
|
|
c7bca0ba19 | ||
|
|
9b2d032c6a | ||
|
|
be76f8a180 | ||
|
|
2af0324ee5 | ||
|
|
8aa4f57a33 | ||
|
|
3599dc97cc | ||
|
|
8a5d895f03 | ||
|
|
36169db388 | ||
|
|
1900999a74 | ||
|
|
ab16814cd2 | ||
|
|
9f622fcd74 | ||
|
|
956e2c43b8 | ||
|
|
130f87c9f7 | ||
|
|
22b4e8c75f | ||
|
|
c19a3ca444 | ||
|
|
a006eb5dcc | ||
|
|
ed419e7e53 | ||
|
|
bff2387b4d | ||
|
|
41544efeba | ||
|
|
e6e6c9f7f6 | ||
|
|
22d8e39db3 | ||
|
|
bfdf1e9e6c | ||
|
|
c3fccfde09 | ||
|
|
4bb8d43a6e | ||
|
|
fda4b67776 | ||
|
|
f1ee9d45de | ||
|
|
01f7d13e3f | ||
|
|
d85e30f3a6 | ||
|
|
4074aa50ce |
+42
-1
@@ -1,4 +1,29 @@
|
||||
# Changelog
|
||||
## [1.7.0 (Month xth, 2025)](#1-7-0)
|
||||
|
||||
### Additions
|
||||
- Added an in-game configuration screen, allowing all settings from `main.json` to be edited directly in-game.
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
|
||||
### Changes
|
||||
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
|
||||
|
||||
### Fixes
|
||||
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
|
||||
- Fixed PCs always opening at box 2 instead of box 1.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
- Dialogues are correctly removed from memory when they are stopped.
|
||||
- Dialogues with variably-set initial pages now properly start timeout tracking.
|
||||
- Added `EvGainedEvent.Pre` and `EvGainedEvent.Post`.
|
||||
- Deprecated `EVs#add(Stat, Int)`, you will not be able to compile against this code please migrate to the `EVs#add(Stat, Int, EvSource)` you most likely want to use `SidemodEvSource` but please check other implementations or make your own.
|
||||
|
||||
### Additions
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
- Added the Model Appendages system, allowing for resolver-based bedrock model attachments to Pokémon models based on Locators.
|
||||
- View the `egg` examples in `assets/cobblemon/bedrock/appendage` for an example of how to use this system.
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
### Additions
|
||||
@@ -12,6 +37,22 @@
|
||||
- Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex.
|
||||
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true.
|
||||
- Added debug renderer for posable entity locators.
|
||||
- Added crossover paintings from Close Combat, Premonition, Altar, Slumber, and Nomad.
|
||||
- Added optional box argument to the /pc command
|
||||
|
||||
### Changes
|
||||
- Pokémon will now be dynamically revealed to the Pokédex as they're seen instead of revealing entire parties at the end of battle regardless.
|
||||
- Unseen wild Pokémon will update their name from '???' to their real name as soon as a battle starts to reflect the battle UI showing the actual species name.
|
||||
- Pokémon under the illusion effect will reveal their disguise to the Pokédex first and then the base Pokémon once the disguise is broken.
|
||||
- Added more support for a variety of Fabric/NeoForge Convention tags.
|
||||
- Reformatted some tags to be more consistent.
|
||||
- Edited some recipes to utilize tags instead of direct item ids, for greater mod compatibility.
|
||||
- Berries will drop if broken at age 0
|
||||
- Improved Fortune drops on Mint Seeds
|
||||
- New Slowpoke shiny texture.
|
||||
- Updated drops for many Pokémon.
|
||||
- Completely resynced Pokémon move and stat data based on later games. Learnsets have changed considerably to maximise available moves.
|
||||
- Cobblemon save data now saves .old files where applicable as a means to recover from file corruption due to crashes or similar abrupt stops
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
@@ -175,7 +216,7 @@
|
||||
- Added `hideNameTag` field and `HideNPCNameTag` nbt tag to `NPCEntity` to allow hiding the name tag of the NPC.
|
||||
- Added the player to `PokerodReelEvent` so you know who is doing the reeling.
|
||||
|
||||
### MoLang & Datapacks
|
||||
### MoLang & Datapacks
|
||||
- Added flows for:
|
||||
- `forme_change`: Triggered when a Pokémon changes form in battle.
|
||||
- `mega_evolution`: Triggered when a Pokémon mega evolves in battle. (Note: Third-party mods are required for this feature currently)
|
||||
|
||||
@@ -41,7 +41,7 @@ dependencies {
|
||||
|
||||
// Integrations
|
||||
compileOnlyApi(libs.jei.api)
|
||||
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
|
||||
isTransitive = false
|
||||
}
|
||||
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
|
||||
|
||||
@@ -62,11 +62,7 @@ import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBacken
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.client.CobblemonPack
|
||||
@@ -89,22 +85,11 @@ import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.*
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifDedicatedServer
|
||||
import com.cobblemon.mod.common.util.isLaterVersion
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
@@ -112,25 +97,26 @@ import com.mongodb.ConnectionString
|
||||
import com.mongodb.MongoClientSettings
|
||||
import com.mongodb.client.MongoClient
|
||||
import com.mongodb.client.MongoClients
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.item.NameTagItem
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
object Cobblemon {
|
||||
const val MODID = CobblemonBuildDetails.MOD_ID
|
||||
@@ -220,7 +206,7 @@ object Cobblemon {
|
||||
storage.onPlayerDataSync(it)
|
||||
playerDataManager.syncAllToPlayer(it)
|
||||
starterHandler.handleJoin(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel, this.config.maxPokemonLevel, this.config.maxPokemonFriendship, this.config.maxDynamaxLevel).sendToPlayer(it)
|
||||
sendServerSettingsPacketToPlayer(it)
|
||||
}
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
@@ -268,8 +254,17 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
}
|
||||
|
||||
|
||||
fun sendServerSettingsPacketToPlayer(player: ServerPlayer) {
|
||||
ServerSettingsPacket(
|
||||
this.config.preventCompletePartyDeposit,
|
||||
this.config.displayEntityLevelLabel,
|
||||
this.config.displayEntityNameLabel,
|
||||
this.config.maxPokemonLevel,
|
||||
this.config.maxPokemonFriendship,
|
||||
this.config.maxDynamaxLevel,
|
||||
).sendToPlayer(player)
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
@@ -429,7 +424,23 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeConfig() {
|
||||
loadCobblemonConfig()
|
||||
saveConfig(this.config)
|
||||
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
|
||||
}
|
||||
|
||||
fun loadConfig() {
|
||||
initializeConfig()
|
||||
bestSpawner.init()
|
||||
}
|
||||
|
||||
fun reloadConfig() {
|
||||
initializeConfig()
|
||||
bestSpawner.reloadConfig()
|
||||
}
|
||||
|
||||
private fun loadCobblemonConfig() {
|
||||
val configFile = File(CONFIG_PATH)
|
||||
configFile.parentFile.mkdirs()
|
||||
|
||||
@@ -472,12 +483,6 @@ object Cobblemon {
|
||||
} else {
|
||||
this.config = CobblemonConfig()
|
||||
}
|
||||
|
||||
config.lastSavedVersion = VERSION
|
||||
this.saveConfig()
|
||||
|
||||
bestSpawner.loadConfig()
|
||||
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
|
||||
}
|
||||
|
||||
fun loadStarterConfig(): StarterConfig {
|
||||
@@ -500,12 +505,14 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
fun saveConfig() {
|
||||
fun saveConfig(config: CobblemonConfig) {
|
||||
config.lastSavedVersion = VERSION
|
||||
|
||||
try {
|
||||
val configFile = File(CONFIG_PATH)
|
||||
val fileWriter = FileWriter(configFile)
|
||||
// Put the config to json then flush the writer to commence writing.
|
||||
CobblemonConfig.GSON.toJson(this.config, fileWriter)
|
||||
CobblemonConfig.GSON.toJson(config, fileWriter)
|
||||
fileWriter.flush()
|
||||
fileWriter.close()
|
||||
} catch (exception: Exception) {
|
||||
@@ -527,4 +534,4 @@ object Cobblemon {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ object CobblemonCommands {
|
||||
FreezePokemonCommand.register(dispatcher)
|
||||
ApplyPlayerTextureCommand.register(dispatcher)
|
||||
RunMolangScriptCommand.register(dispatcher)
|
||||
CobblemonConfigCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.OpenCobblemonConfigEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.spawn.SpawnExtraDataEntityHandler
|
||||
@@ -80,6 +81,7 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
|
||||
@@ -284,6 +286,7 @@ object CobblemonNetwork {
|
||||
|
||||
// Settings packets
|
||||
list.add(PacketRegisterInfo(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler))
|
||||
list.add(PacketRegisterInfo(OpenCobblemonConfigScreenPacket.ID, OpenCobblemonConfigScreenPacket::decode, OpenCobblemonConfigEditorHandler))
|
||||
|
||||
// Data registries
|
||||
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
@@ -43,7 +43,8 @@ interface SleepDepth {
|
||||
"comatose" to comatose,
|
||||
"normal" to normal
|
||||
)
|
||||
val adapter = StringIdentifiedObjectAdapter { depths[it] ?: throw IllegalArgumentException("Unknown sleep depth: $it") }
|
||||
|
||||
val adapter = StringIdentifiedObjectAdapter({ depths[it] ?: throw IllegalArgumentException("Unknown sleep depth: $it") })
|
||||
}
|
||||
|
||||
fun canSleep(pokemonEntity: PokemonEntity): Boolean
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.BattleEvSource
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
@@ -272,7 +273,7 @@ open class PokemonBattle(
|
||||
opponent.awardExperience(opponentPokemon, experience)
|
||||
}
|
||||
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
|
||||
pokemon.evs.add(stat, amount)
|
||||
pokemon.evs.add(stat, amount, BattleEvSource(this, opponentPokemon.facedOpponents.toList(), pokemon))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ class ActiveDialogue(var playerEntity: ServerPlayer, var dialogueReference: Dial
|
||||
)
|
||||
|
||||
dialogueReference.initializationAction.invoke(this)
|
||||
setPage(currentPage)
|
||||
|
||||
if (!completion.isDone) {
|
||||
val packet = DialogueOpenedPacket(this, true)
|
||||
|
||||
@@ -52,6 +52,6 @@ object DialogueManager {
|
||||
fun stopDialogue(playerEntity: ServerPlayer) {
|
||||
val activeDialogue = playerEntity.activeDialogue ?: return
|
||||
DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity)
|
||||
activeDialogues.remove(activeDialogue.dialogueId)
|
||||
activeDialogues.remove(playerEntity.uuid)
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.drop
|
||||
|
||||
import com.cobblemon.mod.common.api.serialization.StringIdentifiedObjectAdapter
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
/**
|
||||
* The way an item will be dropped.
|
||||
@@ -28,6 +29,9 @@ enum class ItemDropMethod(val methodName: String) {
|
||||
TO_INVENTORY("to-inventory");
|
||||
|
||||
companion object {
|
||||
val adapter = StringIdentifiedObjectAdapter { str -> values().firstOrNull { it.methodName == str } }
|
||||
val adapter = StringIdentifiedObjectAdapter(
|
||||
{ str -> ItemDropMethod.entries.firstOrNull { it.methodName == str } },
|
||||
{ value -> (value ?: ON_ENTITY).methodName },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -158,6 +158,11 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDY_USE_POST = EventObservable<ExperienceCandyUseEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val EV_GAINED_EVENT_PRE = CancelableObservable<EvGainedEvent.Pre>()
|
||||
@JvmField
|
||||
val EV_GAINED_EVENT_POST = EventObservable<EvGainedEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_RELEASED_EVENT_PRE = CancelableObservable<ReleasePokemonEvent.Pre>()
|
||||
@JvmField
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.EvSource
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
|
||||
/**
|
||||
* Fired during EV mutation.
|
||||
*
|
||||
* @see [Pre]
|
||||
* @see [Post]
|
||||
*/
|
||||
interface EvGainedEvent {
|
||||
|
||||
/**
|
||||
* The [Stat] having EVs added to itself.
|
||||
*/
|
||||
val stat: Stat
|
||||
|
||||
/**
|
||||
* The [EvSource] that fired this event.
|
||||
*/
|
||||
val source: EvSource
|
||||
|
||||
/**
|
||||
* Fired before EV mutation occurs, cancelling will cause the mutation to be flagged as not successful (returns 0).
|
||||
*
|
||||
* @property stat See [EvGainedEvent.stat].
|
||||
* @property amount The amount of EVs that will be gained.
|
||||
* @property source See [EvGainedEvent.source].
|
||||
*/
|
||||
class Pre(override val stat: Stat, var amount: Int, override val source: EvSource) : EvGainedEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Fired after EV mutation occurs, this is purely for notification purposes.
|
||||
*
|
||||
* @property stat See [EvGainedEvent.stat].
|
||||
* @property amount The final amount of EVs gained.
|
||||
* @property source See [EvGainedEvent.source].
|
||||
*/
|
||||
class Post(override val stat: Stat, val amount: Int, override val source: EvSource) : EvGainedEvent
|
||||
|
||||
}
|
||||
+2
-2
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.permission
|
||||
|
||||
import com.cobblemon.mod.common.command.AbandonMultiTeam
|
||||
|
||||
object CobblemonPermissions {
|
||||
|
||||
private const val COMMAND_PREFIX = "command."
|
||||
@@ -84,6 +82,8 @@ object CobblemonPermissions {
|
||||
|
||||
val RUN_MOLANG_SCRIPT = this.create("${COMMAND_PREFIX}runmolangscript", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val COBBLEMON_CONFIG_RELOAD = this.create("${COMMAND_PREFIX}cobblemonconfig.reload", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
fun all(): Iterable<Permission> = this.permissions
|
||||
|
||||
private fun create(node: String, level: PermissionLevel): Permission {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.cobblemon.mod.common.api.pokemon.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
interface EvSource {
|
||||
|
||||
/**
|
||||
* The [Pokemon] being affected.
|
||||
*/
|
||||
val pokemon: Pokemon
|
||||
|
||||
/**
|
||||
* Utility function that checks if the source is an implementation of [BattleEvSource].
|
||||
*/
|
||||
fun isBattle() = this is BattleEvSource
|
||||
|
||||
/**
|
||||
* Utility function that checks if the source is an implementation of [ItemEvSource].
|
||||
*/
|
||||
fun isInteraction() = this is ItemEvSource
|
||||
|
||||
/**
|
||||
* Utility function that checks if the source is an implementation of [SidemodEvSource].
|
||||
*/
|
||||
fun isSidemod() = this is SidemodEvSource
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered by sidemods.
|
||||
*
|
||||
* @property sidemodId The mod ID of the sidemod triggering this source.
|
||||
* @property pokemon See [EvSource.pokemon].
|
||||
*/
|
||||
open class SidemodEvSource(
|
||||
val sidemodId: String,
|
||||
override val pokemon: Pokemon
|
||||
) : EvSource
|
||||
|
||||
/**
|
||||
* An Ev source fired when using Ev mutating items.
|
||||
*
|
||||
* @property player The [ServerPlayer] using the item.
|
||||
* @property stack The [ItemStack] being consumed.
|
||||
* @property pokemon See [EvSource.pokemon].
|
||||
*/
|
||||
open class ItemEvSource(
|
||||
val player: ServerPlayer,
|
||||
val stack: ItemStack,
|
||||
override val pokemon: Pokemon
|
||||
) : EvSource
|
||||
|
||||
/**
|
||||
* An Ev source fired in battles.
|
||||
*
|
||||
* @property battle The associated [PokemonBattle].
|
||||
* @property facedPokemon The [BattlePokemon]s that the [pokemon] faced.
|
||||
* @property pokemon See [EvSource.pokemon], comes from the original [BattlePokemon.effectedPokemon].
|
||||
*/
|
||||
open class BattleEvSource(
|
||||
val battle: PokemonBattle,
|
||||
val facedPokemon: List<BattlePokemon>,
|
||||
override val pokemon: Pokemon
|
||||
) : EvSource
|
||||
+11
-1
@@ -11,6 +11,9 @@ package com.cobblemon.mod.common.api.serialization
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
@@ -19,6 +22,13 @@ import java.lang.reflect.Type
|
||||
* @author Hiroku
|
||||
* @since July 18th, 2022
|
||||
*/
|
||||
class StringIdentifiedObjectAdapter<T>(val fromString: (String) -> T) : JsonDeserializer<T> {
|
||||
class StringIdentifiedObjectAdapter<T>(
|
||||
val fromString: (String) -> T,
|
||||
val toString: ((T) -> String)? = null,
|
||||
) : JsonDeserializer<T>, JsonSerializer<T> {
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext) = fromString(json.asString)
|
||||
override fun serialize(src: T, type: Type?, ctx: JsonSerializationContext?): JsonElement? {
|
||||
val stringValue = toString?.invoke(src) ?: throw IllegalStateException("No toString function provided for serialization.")
|
||||
return JsonPrimitive(stringValue)
|
||||
}
|
||||
}
|
||||
@@ -498,7 +498,7 @@ class LookAtDirection : ParticleCameraMode {
|
||||
rotation.hamiltonProduct(Axis.ZP.rotationDegrees(particleAngle))
|
||||
|
||||
// Minecraft in 1.21 or 1.20.4 or something fucked with vertex draw order, and it flipped everything.
|
||||
rotation.hamiltonProduct(Axis.YP.rotationDegrees(180F))
|
||||
rotation.hamiltonProduct(Axis.XP.rotationDegrees(180F))
|
||||
|
||||
return rotation
|
||||
}
|
||||
|
||||
@@ -83,8 +83,9 @@ object BestSpawner {
|
||||
var defaultPokemonDespawner: Despawner<PokemonEntity> = CobblemonAgingDespawner(getAgeTicks = { it.ticksLived })
|
||||
lateinit var fishingSpawner: FishingSpawner
|
||||
|
||||
fun loadConfig() {
|
||||
fun init() {
|
||||
LOGGER.info("Starting the Best Spawner...")
|
||||
|
||||
SpawningCondition.register(BasicSpawningCondition.NAME, BasicSpawningCondition::class.java)
|
||||
SpawningCondition.register(AreaSpawningCondition.NAME, AreaSpawningCondition::class.java)
|
||||
SpawningCondition.register(SubmergedSpawningCondition.NAME, SubmergedSpawningCondition::class.java)
|
||||
@@ -94,6 +95,7 @@ object BestSpawner {
|
||||
SpawningCondition.register(FishingSpawningCondition.NAME, FishingSpawningCondition::class.java)
|
||||
|
||||
LOGGER.info("Loaded ${SpawningCondition.conditionTypes.size} spawning condition types.")
|
||||
|
||||
SpawningContextCalculator.register(GroundedSpawningContextCalculator)
|
||||
SpawningContextCalculator.register(SeafloorSpawningContextCalculator)
|
||||
SpawningContextCalculator.register(LavafloorSpawningContextCalculator)
|
||||
@@ -113,14 +115,23 @@ object BestSpawner {
|
||||
SpawnDetail.registerSpawnType(name = NPCSpawnDetail.TYPE, NPCSpawnDetail::class.java)
|
||||
LOGGER.info("Loaded ${SpawnDetail.spawnDetailTypes.size} spawn detail types.")
|
||||
|
||||
config = BestSpawnerConfig.load()
|
||||
loadConfig()
|
||||
|
||||
SpawnDetailPresets.registerPresetType(BasicSpawnDetailPreset.NAME, BasicSpawnDetailPreset::class.java)
|
||||
SpawnDetailPresets.registerPresetType(PokemonSpawnDetailPreset.NAME, PokemonSpawnDetailPreset::class.java)
|
||||
}
|
||||
|
||||
fun loadConfig() {
|
||||
config = BestSpawnerConfig.load()
|
||||
}
|
||||
|
||||
fun reloadConfig() {
|
||||
loadConfig()
|
||||
spawnerManagers.forEach(SpawnerManager::onConfigReload)
|
||||
}
|
||||
|
||||
fun onServerStarted() {
|
||||
spawnerManagers.forEach(SpawnerManager::onServerStarted)
|
||||
fishingSpawner = FishingSpawner()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,4 +96,4 @@ object SpawnDetailPresets : JsonDataRegistry<SpawnDetailPreset> {
|
||||
this.presets = data.toMutableMap()
|
||||
Cobblemon.LOGGER.info("Loaded ${presets.size} spawn detail presets.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.spawning
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.TickingSpawner
|
||||
import com.cobblemon.mod.common.util.server
|
||||
@@ -58,6 +59,12 @@ open class SpawnerManager {
|
||||
}
|
||||
}
|
||||
|
||||
open fun onConfigReload() {
|
||||
spawners.filterIsInstance<PlayerSpawner>().forEach {
|
||||
it.ticksBetweenSpawns = Cobblemon.config.ticksBetweenSpawnAttempts
|
||||
}
|
||||
}
|
||||
|
||||
open fun onServerStarted() {
|
||||
spawners.clear()
|
||||
}
|
||||
|
||||
+1
-1
@@ -161,4 +161,4 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -221,4 +221,4 @@ abstract class SpawningContext {
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,4 +64,4 @@ open class SpawningContextInput(
|
||||
val cause: SpawnCause,
|
||||
/** The [Level] the spawning context exists in. */
|
||||
val world: ServerLevel
|
||||
)
|
||||
)
|
||||
|
||||
@@ -103,4 +103,4 @@ abstract class SpawnDetail : ModDependant {
|
||||
}
|
||||
|
||||
abstract fun doSpawn(ctx: SpawningContext): SpawnAction<*>
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -46,16 +46,16 @@ open class JSONStoreAdapter(
|
||||
|
||||
override fun <E, T : PokemonStore<E>> load(file: File, storeClass: Class<out T>, uuid: UUID, registryAccess: RegistryAccess): T? {
|
||||
return try {
|
||||
val br = BufferedReader(FileReader(file))
|
||||
val json = gson.fromJson<JsonObject>(br)
|
||||
br.close()
|
||||
val store = try {
|
||||
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
|
||||
} catch (exception: NoSuchMethodException) {
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
file.reader().use {
|
||||
val json = gson.fromJson<JsonObject>(it)
|
||||
val store = try {
|
||||
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
|
||||
} catch (exception: NoSuchMethodException) {
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
}
|
||||
store.loadFromJSON(json, registryAccess)
|
||||
store
|
||||
}
|
||||
store.loadFromJSON(json, registryAccess)
|
||||
store
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
+36
-15
@@ -42,6 +42,7 @@ abstract class OneToOneFileStoreAdapter<S>(
|
||||
) : FileStoreAdapter<S>, CobblemonAdapterParent<S>() {
|
||||
abstract fun save(file: File, serialized: S)
|
||||
abstract fun <E, T : PokemonStore<E>> load(file: File, storeClass: Class<out T>, uuid: UUID, registryAccess: RegistryAccess): T?
|
||||
|
||||
fun getFile(storeClass: Class<out PokemonStore<*>>, uuid: UUID): File {
|
||||
val className = storeClass.simpleName.lowercase()
|
||||
val subfolder1 = if (folderPerClass) "$className/" else ""
|
||||
@@ -56,34 +57,54 @@ abstract class OneToOneFileStoreAdapter<S>(
|
||||
override fun save(storeClass: Class<out PokemonStore<*>>, uuid: UUID, serialized: S) {
|
||||
val file = getFile(storeClass, uuid)
|
||||
val tempFile = File(file.absolutePath + ".temp")
|
||||
val oldFile = File(file.absolutePath + ".old")
|
||||
tempFile.createNewFile()
|
||||
save(tempFile, serialized)
|
||||
if (file.exists()) {
|
||||
file.copyTo(oldFile, overwrite = true)
|
||||
}
|
||||
tempFile.copyTo(file, overwrite = true)
|
||||
tempFile.delete()
|
||||
}
|
||||
|
||||
override fun <E : StorePosition, T : PokemonStore<E>> provide(storeClass: Class<T>, uuid: UUID, registryAccess: RegistryAccess): T? {
|
||||
val file = getFile(storeClass, uuid)
|
||||
val tempFile = File(file.absolutePath + ".temp")
|
||||
if (tempFile.exists()) {
|
||||
try {
|
||||
val tempLoaded = load(tempFile, storeClass, uuid, registryAccess)
|
||||
if (tempLoaded != null) {
|
||||
save(file, serialize(tempLoaded, registryAccess))
|
||||
return tempLoaded
|
||||
}
|
||||
} finally {
|
||||
tempFile.delete()
|
||||
}
|
||||
}
|
||||
val oldFile = File(file.absolutePath + ".old")
|
||||
|
||||
return if (file.exists()) {
|
||||
return if (file.exists() && file.length() > 0L) {
|
||||
load(file, storeClass, uuid, registryAccess)
|
||||
?: let {
|
||||
LOGGER.error("Pokémon save file for ${storeClass.simpleName} ($uuid) was corrupted. A fresh file will be created.")
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
file.delete()
|
||||
if (oldFile.exists() && oldFile.length() > 0L) {
|
||||
var result = load(oldFile, storeClass, uuid, registryAccess) ?: let {
|
||||
LOGGER.error("Pokémon save file for ${storeClass.simpleName} ($uuid) was corrupted. A fresh file will be created.")
|
||||
var result = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
save(storeClass, uuid, serialize(result, registryAccess))
|
||||
oldFile.delete()
|
||||
return result
|
||||
}
|
||||
LOGGER.warn("Loading old Pokémon save file for ${storeClass.simpleName} ($uuid) due to corruption of current file.")
|
||||
oldFile.copyTo(file, overwrite = true)
|
||||
result
|
||||
}
|
||||
else {
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
var result = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
save(storeClass, uuid, serialize(result, registryAccess))
|
||||
oldFile.delete()
|
||||
result
|
||||
}
|
||||
}
|
||||
} else {
|
||||
file.delete()
|
||||
if (oldFile.exists() && oldFile.length() > 0L) {
|
||||
var result = load(oldFile, storeClass, uuid, registryAccess) ?: let {
|
||||
oldFile.delete()
|
||||
return null
|
||||
}
|
||||
oldFile.copyTo(file, overwrite = true)
|
||||
result
|
||||
}
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
+63
-6
@@ -8,10 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.storage.player.adapter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.storage.player.InstancedPlayerData
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreType
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.UUID
|
||||
|
||||
@@ -35,15 +37,70 @@ abstract class FileBasedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
savePath = server.getWorldPath(LevelResource.PLAYER_DATA_DIR).parent
|
||||
}
|
||||
|
||||
//TODO: Set file extension to be a field
|
||||
fun getSubFile(uuid: UUID): String {
|
||||
return if (useNestedStructure) {
|
||||
"${uuid.toString().substring(0, 2)}/$uuid.$fileExt"
|
||||
protected fun postSaveFileMoving(playerData: T) {
|
||||
val tempFile = filePath(playerData.uuid, TEMPORARY_FILE_EXTENSION)
|
||||
val oldFile = filePath(playerData.uuid, OLD_FILE_EXTENSION)
|
||||
val file = filePath(playerData.uuid)
|
||||
if (file.exists()) {
|
||||
file.copyTo(oldFile, overwrite = true)
|
||||
}
|
||||
tempFile.copyTo(file, overwrite = true)
|
||||
tempFile.delete()
|
||||
}
|
||||
|
||||
protected fun loadWithFallback(uuid: UUID, loadFunction: (File) -> T): T {
|
||||
val playerFile = filePath(uuid)
|
||||
val playerFileOld = filePath(uuid, OLD_FILE_EXTENSION)
|
||||
playerFile.parentFile.mkdirs()
|
||||
val loadFallback: () -> T = {
|
||||
playerFile.delete()
|
||||
if (playerFileOld.exists() && playerFileOld.length() > 0L) {
|
||||
try {
|
||||
var result = loadFunction(playerFileOld)
|
||||
playerFileOld.copyTo(playerFile)
|
||||
Cobblemon.LOGGER.debug("Loaded .old {} for {}", subfolder, uuid)
|
||||
result
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Failed to load .old $subfolder for $uuid due to ${e.message}. Data is lost")
|
||||
Cobblemon.LOGGER.error(e)
|
||||
playerFileOld.delete()
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Cobblemon.LOGGER.error(".old File $subfolder for $uuid is corrupt or missing. Data is lost")
|
||||
playerFileOld.delete()
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}
|
||||
}
|
||||
return if (playerFile.exists() && playerFile.length() > 0L) {
|
||||
try {
|
||||
loadFunction(playerFile)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
Cobblemon.LOGGER.warn("Failed to load $subfolder for $uuid due to ${e.message}")
|
||||
Cobblemon.LOGGER.warn(e)
|
||||
loadFallback()
|
||||
}
|
||||
} else {
|
||||
"$uuid.$fileExt"
|
||||
loadFallback()
|
||||
}.also { it.initialize() }
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun getSubFile(uuid: UUID, extension: String? = null): String {
|
||||
return if (useNestedStructure) {
|
||||
"${uuid.toString().substring(0, 2)}/$uuid.$fileExt${if (extension != null) ".$extension" else ""}"
|
||||
} else {
|
||||
"$uuid.$fileExt.${if (extension != null) ".$extension" else ""}"
|
||||
}
|
||||
}
|
||||
|
||||
fun filePath(uuid: UUID) = savePath.resolve("$subfolder/${getSubFile(uuid)}").toFile()
|
||||
@JvmOverloads
|
||||
fun filePath(uuid: UUID, extension: String? = null): File = savePath.resolve("$subfolder/${getSubFile(uuid, extension)}").toFile()
|
||||
|
||||
companion object {
|
||||
const val OLD_FILE_EXTENSION = "old"
|
||||
const val TEMPORARY_FILE_EXTENSION = "tmp"
|
||||
}
|
||||
}
|
||||
+16
-19
@@ -28,29 +28,26 @@ abstract class JsonBackedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
abstract val classToken: TypeToken<T>
|
||||
|
||||
override fun save(playerData: T) {
|
||||
val file = filePath(playerData.uuid)
|
||||
file.parentFile.mkdirs()
|
||||
val pw = PrintWriter(filePath(playerData.uuid))
|
||||
pw.write(gson.toJson(playerData))
|
||||
pw.flush()
|
||||
pw.close()
|
||||
val fileTmp = filePath(playerData.uuid, TEMPORARY_FILE_EXTENSION)
|
||||
fileTmp.parentFile.mkdirs()
|
||||
fileTmp.printWriter().use { pw ->
|
||||
pw.write(gson.toJson(playerData))
|
||||
}
|
||||
postSaveFileMoving(playerData)
|
||||
}
|
||||
|
||||
override fun load(uuid: UUID): T {
|
||||
val playerFile = filePath(uuid)
|
||||
playerFile.parentFile.mkdirs()
|
||||
return if (playerFile.exists() && playerFile.length() > 0L) {
|
||||
gson.fromJson(BufferedReader(FileReader(playerFile)), classToken).also {
|
||||
// Resolves old data that's missing new properties
|
||||
val newProps = it::class.memberProperties.filterIsInstance<KMutableProperty<*>>().filter { member -> member.getter.call(it) == null }
|
||||
if (newProps.isNotEmpty()) {
|
||||
val defaultData = defaultData(uuid)
|
||||
newProps.forEach { member -> member.setter.call(it, member.getter.call(defaultData)) }
|
||||
return loadWithFallback(uuid) {
|
||||
it.reader().use { reader ->
|
||||
gson.fromJson(reader, classToken).also {
|
||||
// Resolves old data that's missing new properties
|
||||
val newProps = it::class.memberProperties.filterIsInstance<KMutableProperty<*>>().filter { member -> member.getter.call(it) == null }
|
||||
if (newProps.isNotEmpty()) {
|
||||
val defaultData = defaultData(uuid)
|
||||
newProps.forEach { member -> member.setter.call(it, member.getter.call(defaultData)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}.also { it.initialize() }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+11
-16
@@ -24,29 +24,24 @@ abstract class NbtBackedPlayerData<T : InstancedPlayerData>(
|
||||
type: PlayerInstancedDataStoreType
|
||||
) : FileBasedPlayerDataStoreBackend<T>(subfolder, type, "nbt") {
|
||||
abstract val codec: Codec<T>
|
||||
|
||||
override fun save(playerData: T) {
|
||||
val file = filePath(playerData.uuid)
|
||||
file.parentFile.mkdirs()
|
||||
val os = DataOutputStream(FileOutputStream(filePath(playerData.uuid)))
|
||||
val encodeResult = NbtOps.INSTANCE.withEncoder(codec).apply(playerData)
|
||||
NbtIo.write(encodeResult.result().get() as CompoundTag, os)
|
||||
os.flush()
|
||||
os.close()
|
||||
val fileTmp = filePath(playerData.uuid, TEMPORARY_FILE_EXTENSION)
|
||||
fileTmp.parentFile.mkdirs()
|
||||
val encodeResult = codec.encodeStart(NbtOps.INSTANCE, playerData)
|
||||
NbtIo.write(encodeResult.result().get() as CompoundTag, fileTmp.toPath())
|
||||
postSaveFileMoving(playerData)
|
||||
}
|
||||
|
||||
override fun load(uuid: UUID): T {
|
||||
val playerFile = filePath(uuid)
|
||||
playerFile.parentFile.mkdirs()
|
||||
return if (playerFile.exists() && playerFile.length() > 0L) {
|
||||
val input = NbtIo.read(playerFile.toPath())
|
||||
val decodeResult = NbtOps.INSTANCE.withDecoder(codec).apply(input)
|
||||
decodeResult.getPartialOrThrow {
|
||||
return loadWithFallback(uuid) {
|
||||
val input = NbtIo.read(it.toPath())
|
||||
val decodeResult = codec.decode(NbtOps.INSTANCE, input)
|
||||
decodeResult.getOrThrow {
|
||||
Cobblemon.LOGGER.error("Error decoding $subfolder for player uuid $uuid")
|
||||
Cobblemon.LOGGER.error(it)
|
||||
throw UnsupportedOperationException()
|
||||
}.first
|
||||
} else {
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}.also { it.initialize() }
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -68,6 +68,8 @@ class WinInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
}
|
||||
}
|
||||
battle.dispatchGo {
|
||||
battle.winners = winners
|
||||
battle.losers = losers
|
||||
battle.end()
|
||||
CobblemonEvents.BATTLE_VICTORY.post(BattleVictoryEvent(battle, winners, losers, wasCaught))
|
||||
ShowdownInterpreter.lastCauser.remove(battle.battleId)
|
||||
|
||||
+5
-2
@@ -308,9 +308,12 @@ class HealingMachineBlockEntity(
|
||||
} else {
|
||||
// Recharging
|
||||
if (blockEntity.healingCharge < blockEntity.maxCharge) {
|
||||
val chargePerTick = (Cobblemon.config.chargeGainedPerTick).coerceAtLeast(0F)
|
||||
val secondsToChargeHealingMachine = (Cobblemon.config.secondsToChargeHealingMachine).coerceAtLeast(0.0)
|
||||
val totalTicks = secondsToChargeHealingMachine * 20
|
||||
val chargePerTick = if (totalTicks > 0) blockEntity.maxCharge / totalTicks else 0.0
|
||||
|
||||
blockEntity.healingCharge =
|
||||
(blockEntity.healingCharge + chargePerTick).coerceIn(0F..blockEntity.maxCharge)
|
||||
(blockEntity.healingCharge + chargePerTick.toFloat()).coerceIn(0F..blockEntity.maxCharge)
|
||||
blockEntity.updateBlockChargeLevel()
|
||||
blockEntity.updateRedstoneSignal()
|
||||
blockEntity.markUpdated()
|
||||
|
||||
@@ -21,12 +21,10 @@ import com.cobblemon.mod.common.client.render.models.blockbench.ExcludedLabels
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.*
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.appendage.ModelAppendageModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.sineFunction
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import java.util.function.Function
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
@@ -53,7 +51,7 @@ object ClientMoLangFunctions {
|
||||
"say" to java.util.function.Function { params -> Minecraft.getInstance().player?.sendSystemMessage(params.getString(0).text()) ?: Unit },
|
||||
)
|
||||
|
||||
val animationFunctions = hashMapOf<String, Function<PosableModel, Function<MoParams, Any>>>(
|
||||
val posableModelFunctions = hashMapOf<String, Function<PosableModel, Function<MoParams, Any>>>(
|
||||
"exclude_labels" to Function { model -> Function { params ->
|
||||
val labels = params.params.map { it.asString() }
|
||||
ObjectValue(ExcludedLabels(labels))
|
||||
@@ -244,6 +242,18 @@ object ClientMoLangFunctions {
|
||||
)
|
||||
}
|
||||
},
|
||||
"appendage_model" to Function {
|
||||
model -> Function { params ->
|
||||
val name = params.getString(0)
|
||||
ObjectValue((ModelAppendageModelRepository to name.asResource()))
|
||||
}
|
||||
},
|
||||
"vanilla_model" to Function {
|
||||
model -> Function { params ->
|
||||
val id = params.getString(0).asResource()
|
||||
ObjectValue(id)
|
||||
}
|
||||
},
|
||||
"primary_animation" to Function { model ->
|
||||
Function { params ->
|
||||
val animation = params.get<ObjectValue<ActiveAnimation>>(0)?.obj ?: return@Function DoubleValue.ZERO
|
||||
@@ -344,7 +354,7 @@ object ClientMoLangFunctions {
|
||||
}
|
||||
)
|
||||
|
||||
fun PosableModel.animationFunctions(): HashMap<String, Function<MoParams, Any>> = animationFunctions.map { (k, v) -> k to v.apply(this) }.toHashMap()
|
||||
fun PosableModel.animationFunctions(): HashMap<String, Function<MoParams, Any>> = posableModelFunctions.map { (k, v) -> k to v.apply(this) }.toHashMap()
|
||||
|
||||
fun MoLangRuntime.setupClient(): MoLangRuntime {
|
||||
environment.query.addFunctions(clientFunctions)
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscM
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.appendage.ModelAppendageModelRepository
|
||||
import com.cobblemon.mod.common.client.render.npc.NPCRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokeball.PokeBallRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer
|
||||
@@ -100,7 +101,8 @@ object CobblemonClient {
|
||||
NPCModelRepository,
|
||||
FossilModelRepository,
|
||||
BlockEntityModelRepository,
|
||||
GenericBedrockEntityModelRepository
|
||||
GenericBedrockEntityModelRepository,
|
||||
ModelAppendageModelRepository
|
||||
)
|
||||
|
||||
val overlay: PartyOverlay by lazy { PartyOverlay() }
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.config
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.client.gui.components.StringWidget
|
||||
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout
|
||||
import net.minecraft.client.gui.layouts.LinearLayout
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.CommonComponents
|
||||
|
||||
class CobblemonConfigScreen(
|
||||
private val previousScreen: Screen?,
|
||||
) : Screen("gui.cobblemon_config.title".asTranslated()), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val HEIGHT = 240
|
||||
const val HEADER_HEIGHT = 45
|
||||
const val FOOTER_HEIGHT = 33
|
||||
const val PADDING = 4
|
||||
const val SLOT_WIDTH = 340
|
||||
const val SLOT_HEIGHT = 22
|
||||
const val HALF_SLOT_WIDTH = SLOT_WIDTH / 2
|
||||
const val RESET_SLOT_WIDTH = 40
|
||||
const val WIDGET_WIDTH = 110 - RESET_SLOT_WIDTH - PADDING
|
||||
const val WIDGET_HEIGHT = SLOT_HEIGHT - PADDING
|
||||
const val LABEL_Y_OFFSET = 4
|
||||
const val WIDGET_Y_OFFSET = 0
|
||||
}
|
||||
|
||||
val clonedConfig = Cobblemon.config.clone()
|
||||
val defaultConfig = CobblemonConfig()
|
||||
|
||||
private lateinit var layout: HeaderAndFooterLayout
|
||||
private lateinit var searchEdit: EditBox
|
||||
private lateinit var variableList: CobblemonConfigVariableList
|
||||
private lateinit var doneButton: Button
|
||||
|
||||
private var searchString: String = ""
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
|
||||
if (::layout.isInitialized) layout.visitWidgets { removeWidget(it) }
|
||||
layout = HeaderAndFooterLayout(this, HEADER_HEIGHT, FOOTER_HEIGHT)
|
||||
|
||||
if (::variableList.isInitialized) removeWidget(variableList)
|
||||
variableList = CobblemonConfigVariableList(this)
|
||||
variableList.filterConfigurations(searchString)
|
||||
addRenderableWidget(variableList)
|
||||
|
||||
searchEdit = EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
width / 2 - HALF_SLOT_WIDTH / 2,
|
||||
variableList.y,
|
||||
HALF_SLOT_WIDTH,
|
||||
SLOT_HEIGHT,
|
||||
lang("config.ui.search_configurations"),
|
||||
).also {
|
||||
it.height = WIDGET_HEIGHT
|
||||
it.setMaxLength(250)
|
||||
|
||||
it.value = searchString
|
||||
it.setResponder { text ->
|
||||
variableList.filterConfigurations(text)
|
||||
searchString = text
|
||||
}
|
||||
}
|
||||
|
||||
val linearLayout = layout.addToHeader(LinearLayout.vertical())
|
||||
linearLayout.addChild(StringWidget(lang("config.ui.search_configurations"), this.font))
|
||||
linearLayout.addChild(searchEdit)
|
||||
layout.addToHeader(linearLayout)
|
||||
|
||||
doneButton = Button.builder(CommonComponents.GUI_DONE) { doneButtonClick() }
|
||||
.pos(width / 2 - HALF_SLOT_WIDTH / 2, variableList.y + variableList.height + PADDING)
|
||||
.width(HALF_SLOT_WIDTH).build()
|
||||
layout.addToFooter(doneButton)
|
||||
|
||||
layout.visitWidgets { widget ->
|
||||
addRenderableWidget(widget)
|
||||
}
|
||||
arrangeLayoutElements()
|
||||
}
|
||||
|
||||
private fun arrangeLayoutElements() {
|
||||
layout.arrangeElements()
|
||||
variableList.updateSize(this.width, this.layout)
|
||||
}
|
||||
|
||||
private fun doneButtonClick() {
|
||||
Cobblemon.saveConfig(clonedConfig)
|
||||
Cobblemon.reloadConfig()
|
||||
onClose()
|
||||
}
|
||||
|
||||
override fun onClose() {
|
||||
minecraft?.setScreen(previousScreen)
|
||||
}
|
||||
}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.config
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.LABEL_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.PADDING
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList.CobblemonConfigVariableListEntry
|
||||
import com.cobblemon.mod.common.client.gui.config.variable.*
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.Category
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.CobblemonConfigField
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.SharedConstants
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.ContainerObjectSelectionList
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.gui.narration.NarratableEntry
|
||||
import kotlin.math.min
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
class CobblemonConfigVariableList(
|
||||
val parent: CobblemonConfigScreen,
|
||||
) : ContainerObjectSelectionList<CobblemonConfigVariableListEntry>(
|
||||
Minecraft.getInstance(),
|
||||
Minecraft.getInstance().window.guiScaledWidth,
|
||||
HEIGHT,
|
||||
0,
|
||||
SLOT_HEIGHT
|
||||
) {
|
||||
|
||||
val entries = mutableListOf<CobblemonConfigCategory>()
|
||||
|
||||
init {
|
||||
this.x = 0
|
||||
this.y = minecraft.window.guiScaledHeight / 2 - HEIGHT / 2
|
||||
|
||||
setRenderHeader(false, 0)
|
||||
addEntries()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun addEntries() {
|
||||
parent.clonedConfig::class.memberProperties.map { property ->
|
||||
if (!property.javaField!!.isAnnotationPresent(CobblemonConfigField::class.java)) {
|
||||
return@map null
|
||||
}
|
||||
|
||||
val entry: CobblemonConfigVariable? =
|
||||
when (val classifier = property.returnType.classifier) {
|
||||
String::class -> CobblemonConfigStringVariable(this, property as KMutableProperty1<out CobblemonConfig, String>)
|
||||
Int::class -> CobblemonConfigIntVariable(this, property as KMutableProperty1<out CobblemonConfig, Int>)
|
||||
Float::class -> CobblemonConfigFloatVariable(this, property as KMutableProperty1<out CobblemonConfig, Float>)
|
||||
Double::class -> CobblemonConfigDoubleVariable(this, property as KMutableProperty1<out CobblemonConfig, Double>)
|
||||
Boolean::class -> CobblemonConfigBooleanVariable(this, property as KMutableProperty1<out CobblemonConfig, Boolean>)
|
||||
is KClass<*> -> if (classifier.java.isEnum) {
|
||||
CobblemonConfigEnumVariable(this, property as KMutableProperty1<out CobblemonConfig, Enum<*>>)
|
||||
} else null
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
if (SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
Cobblemon.LOGGER.warn("Widget for variable type: ${property.returnType.classifier} not registered: ${property.name}")
|
||||
}
|
||||
|
||||
return@map null
|
||||
}
|
||||
|
||||
return@map entry
|
||||
}
|
||||
.filterNotNull()
|
||||
.groupBy { it.cobblemonConfigFieldAnnotation.category }
|
||||
.toSortedMap(compareBy { it.ordinal })
|
||||
.forEach { category, variables ->
|
||||
val categoryEntry = CobblemonConfigCategory(this, category, variables)
|
||||
entries.add(categoryEntry)
|
||||
}
|
||||
|
||||
entries.forEach { entry -> entry.add() }
|
||||
}
|
||||
|
||||
override fun renderWidget(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
super.renderWidget(guiGraphics, mouseX, mouseY, partialTick)
|
||||
|
||||
val hoveredVariableTooltip = this.hovered?.tooltip
|
||||
if (isMouseInsideScrollList(mouseX, mouseY) && hoveredVariableTooltip != null) {
|
||||
guiGraphics.renderTooltip(minecraft.font, hoveredVariableTooltip.toCharSequence(minecraft), mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
|
||||
fun isMouseInsideScrollList(mouseX: Int, mouseY: Int): Boolean {
|
||||
val bottomX = parent.width / 2 - SLOT_WIDTH / 2
|
||||
val upperX = parent.width / 2 + SLOT_WIDTH / 2
|
||||
|
||||
return mouseX >= bottomX && mouseX <= upperX && mouseY >= y && mouseY <= bottom
|
||||
}
|
||||
|
||||
override fun getRowWidth(): Int = width
|
||||
override fun getScrollbarPosition(): Int = width / 2 - SLOT_WIDTH / 2 + SLOT_WIDTH + PADDING
|
||||
|
||||
fun filterConfigurations(text: String) {
|
||||
for (entry in entries) {
|
||||
entry.remove()
|
||||
}
|
||||
|
||||
for (entry in entries) {
|
||||
if (text.isBlank() || entry.filter(text)) {
|
||||
entry.add(text)
|
||||
}
|
||||
}
|
||||
|
||||
scrollAmount = min(maxScroll.toDouble(), scrollAmount)
|
||||
}
|
||||
|
||||
abstract class CobblemonConfigVariableListEntry(
|
||||
val parent: CobblemonConfigVariableList,
|
||||
) : Entry<CobblemonConfigVariableListEntry>() {
|
||||
val children = mutableListOf<GuiEventListener>()
|
||||
var tooltip: Tooltip? = null
|
||||
|
||||
fun getX(left: Int) = parent.width / 2 - SLOT_WIDTH / 2
|
||||
fun getY(top: Int) = top
|
||||
|
||||
abstract fun filter(text: String): Boolean
|
||||
|
||||
override fun children(): MutableList<out GuiEventListener> = children
|
||||
override fun narratables(): MutableList<out NarratableEntry> = children.filterIsInstance<NarratableEntry>().toMutableList()
|
||||
}
|
||||
|
||||
class CobblemonConfigCategory(
|
||||
parent: CobblemonConfigVariableList,
|
||||
val category: Category,
|
||||
val configVariables: List<CobblemonConfigVariable>
|
||||
) : CobblemonConfigVariableListEntry(parent) {
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = "cobblemon.config.ui.category.${category.lang}".asTranslated().yellow(),
|
||||
x = parent.width / 2,
|
||||
y = getY(top) + LABEL_Y_OFFSET,
|
||||
shadow = true,
|
||||
centered = true,
|
||||
)
|
||||
}
|
||||
|
||||
fun add(filter: String? = null) {
|
||||
parent.addEntry(this)
|
||||
configVariables.forEach { variable ->
|
||||
if (filter == null || variable.filter(filter)) {
|
||||
parent.addEntry(variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun remove() {
|
||||
parent.removeEntry(this)
|
||||
configVariables.forEach { variable -> parent.removeEntry(variable) }
|
||||
}
|
||||
|
||||
override fun filter(text: String): Boolean = configVariables.any { it.filter(text) }
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.config.variable
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.PADDING
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList
|
||||
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.network.chat.CommonComponents
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
|
||||
abstract class CobblemonConfigButtonVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, *>,
|
||||
) : CobblemonConfigVariable(parent, config) {
|
||||
val button: Button =
|
||||
Button.builder(labelLang) { onButtonClick() }
|
||||
.size(WIDGET_WIDTH, WIDGET_HEIGHT)
|
||||
.build()
|
||||
|
||||
init {
|
||||
children.addFirst(button)
|
||||
}
|
||||
|
||||
abstract fun onButtonClick()
|
||||
|
||||
override fun updateConfigValueDisplay() {
|
||||
button.message = Component.literal(getConfigValueAsString())
|
||||
}
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
super.render(context, index, top, left, width, height, mouseX, mouseY, hovering, partialTick)
|
||||
|
||||
button.x = resetButton.x - button.width - PADDING
|
||||
button.y = getY(top) + WIDGET_Y_OFFSET
|
||||
button.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigBooleanVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Boolean>,
|
||||
) : CobblemonConfigButtonVariable(parent, config) {
|
||||
|
||||
init {
|
||||
updateConfigValueDisplay()
|
||||
}
|
||||
|
||||
override fun getConfigValueAsString(): String = (if (isSelected()) CommonComponents.GUI_YES else CommonComponents.GUI_NO).string
|
||||
override fun onButtonClick() = setConfigValue(!isSelected())
|
||||
|
||||
private fun isSelected() = (config.getter.call(parent.parent.clonedConfig) as Boolean?) ?: false
|
||||
}
|
||||
|
||||
class CobblemonConfigEnumVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Enum<*>>,
|
||||
) : CobblemonConfigButtonVariable(parent, config) {
|
||||
|
||||
private var enumIndex = 0
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private val enumValues: Array<Enum<*>> = config.returnType.classifier
|
||||
.let { it as? KClass<Enum<*>> }
|
||||
?.java?.enumConstants ?: emptyArray()
|
||||
|
||||
init {
|
||||
val currentEnumValue = getCurrentEnumValue()
|
||||
enumValues.firstOrNull { it.name == currentEnumValue?.name }?.let {
|
||||
enumIndex = it.ordinal
|
||||
}
|
||||
updateConfigValueDisplay()
|
||||
}
|
||||
|
||||
override fun getConfigValueAsString(): String {
|
||||
return getCurrentEnumValue()?.name?.let {
|
||||
lang("$labelEntry.${it.lowercase()}").string
|
||||
} ?: ""
|
||||
}
|
||||
|
||||
private fun getConfigValueTooltipString(): String {
|
||||
return getCurrentEnumValue()?.name?.let {
|
||||
lang("$labelEntry.${it.lowercase()}.tooltip").string
|
||||
} ?: ""
|
||||
}
|
||||
|
||||
override fun onButtonClick() {
|
||||
enumIndex = (enumIndex + 1) % enumValues.size
|
||||
val newEnumValue = enumValues[enumIndex]
|
||||
|
||||
setConfigValue(newEnumValue)
|
||||
}
|
||||
|
||||
override fun updateConfigValueDisplay() {
|
||||
super.updateConfigValueDisplay()
|
||||
tooltip = Tooltip.create(Component.literal(getConfigValueTooltipString()))
|
||||
}
|
||||
|
||||
private fun getCurrentEnumValue(): Enum<*>? = (config.getter.call(parent.parent.clonedConfig) as Enum<*>?)
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.config.variable
|
||||
|
||||
import com.cobblemon.mod.common.api.text.add
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.PADDING
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.client.gui.components.EditBox.DEFAULT_TEXT_COLOR
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
abstract class CobblemonConfigEditBoxVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, *>,
|
||||
) : CobblemonConfigVariable(parent, config) {
|
||||
val editBox = EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
parent.x,
|
||||
parent.y,
|
||||
WIDGET_WIDTH,
|
||||
SLOT_HEIGHT,
|
||||
labelLang,
|
||||
).also {
|
||||
it.height = WIDGET_HEIGHT
|
||||
it.setMaxLength(250)
|
||||
|
||||
it.value = getConfigValueAsString()
|
||||
}
|
||||
|
||||
init {
|
||||
children.addFirst(editBox)
|
||||
}
|
||||
|
||||
override fun updateConfigValueDisplay() {
|
||||
editBox.value = getConfigValueAsString()
|
||||
}
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
super.render(context, index, top, left, width, height, mouseX, mouseY, hovering, partialTick)
|
||||
|
||||
editBox.x = resetButton.x - editBox.width - PADDING
|
||||
editBox.y = getY(top) + WIDGET_Y_OFFSET
|
||||
editBox.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigStringVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, String>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as String?) ?: ""
|
||||
|
||||
init {
|
||||
editBox.setResponder { value ->
|
||||
setConfigValue(value, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigIntVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Int>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
private val intConstraintAnnotation: IntConstraint? =
|
||||
config.javaField!!.annotations.firstOrNull{ it is IntConstraint } as IntConstraint?
|
||||
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as Int?).toString()
|
||||
|
||||
init {
|
||||
editBox.setFilter { value -> value.toIntOrNull() != null || value.isBlank() }
|
||||
editBox.setResponder { value ->
|
||||
if (value.isBlank()) {
|
||||
return@setResponder
|
||||
}
|
||||
|
||||
val intValue = value.toInt()
|
||||
setConfigValue(intValue, false)
|
||||
|
||||
if (intConstraintAnnotation != null) {
|
||||
val isBetweenIntConstraint = intValue >= intConstraintAnnotation.min && intValue <= intConstraintAnnotation.max
|
||||
if (isBetweenIntConstraint) {
|
||||
tooltip = originalTooltip
|
||||
editBox.setTextColor(DEFAULT_TEXT_COLOR)
|
||||
} else {
|
||||
val errorLang = lang("config.ui.error.int_constraint", intConstraintAnnotation.min, intConstraintAnnotation.max).red()
|
||||
tooltip = Tooltip.create(tooltipLang.plainCopy().add(Component.literal("\n")).add(errorLang))
|
||||
ChatFormatting.RED.color?.let { editBox.setTextColor(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigFloatVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Float>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as Float?).toString()
|
||||
|
||||
init {
|
||||
editBox.setFilter { value -> value.toFloatOrNull() != null || value.isBlank() }
|
||||
editBox.setResponder { value ->
|
||||
if (value.toFloatOrNull() != null) {
|
||||
setConfigValue(value.toFloat(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CobblemonConfigDoubleVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
config: KMutableProperty1<out CobblemonConfig, Double>,
|
||||
) : CobblemonConfigEditBoxVariable(parent, config) {
|
||||
override fun getConfigValueAsString(): String = (config.getter.call(parent.parent.clonedConfig) as Double?).toString()
|
||||
|
||||
init {
|
||||
editBox.setFilter { value -> value.toDoubleOrNull() != null || value.isBlank() }
|
||||
editBox.setResponder { value ->
|
||||
if (value.toDoubleOrNull() != null) {
|
||||
setConfigValue(value.toDouble(), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.config.variable
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.LABEL_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.RESET_SLOT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.SLOT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen.Companion.WIDGET_Y_OFFSET
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigVariableList.CobblemonConfigVariableListEntry
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.CobblemonConfigField
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import java.text.Normalizer
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
import kotlin.reflect.jvm.javaField
|
||||
|
||||
abstract class CobblemonConfigVariable(
|
||||
parent: CobblemonConfigVariableList,
|
||||
val config: KMutableProperty1<out CobblemonConfig, *>,
|
||||
) : CobblemonConfigVariableListEntry(parent) {
|
||||
val cobblemonConfigFieldAnnotation: CobblemonConfigField =
|
||||
config.javaField!!.annotations.firstOrNull{ it is CobblemonConfigField } as CobblemonConfigField
|
||||
|
||||
val labelEntry = "config.ui.${cobblemonConfigFieldAnnotation.lang}"
|
||||
val tooltipEntry = "$labelEntry.tooltip"
|
||||
val labelLang: MutableComponent = lang(labelEntry)
|
||||
val tooltipLang: MutableComponent = lang(tooltipEntry)
|
||||
val originalTooltip: Tooltip? = if (!tooltipLang.string.endsWith(tooltipEntry)) Tooltip.create(tooltipLang) else null
|
||||
|
||||
val resetButton: Button =
|
||||
Button.builder(lang("config.ui.reset")) {
|
||||
val defaultValue = config.getter.call(parent.parent.defaultConfig)
|
||||
setConfigValue(defaultValue)
|
||||
}
|
||||
.size(RESET_SLOT_WIDTH, WIDGET_HEIGHT)
|
||||
.build()
|
||||
|
||||
init {
|
||||
tooltip = originalTooltip
|
||||
children.add(resetButton)
|
||||
updateResetButton()
|
||||
}
|
||||
|
||||
abstract fun getConfigValueAsString(): String
|
||||
abstract fun updateConfigValueDisplay()
|
||||
|
||||
fun setConfigValue(value: Any?, updateConfigValueDisplay: Boolean = true) {
|
||||
config.setter.call(parent.parent.clonedConfig, value)
|
||||
|
||||
if (updateConfigValueDisplay) {
|
||||
updateConfigValueDisplay()
|
||||
}
|
||||
|
||||
updateResetButton()
|
||||
}
|
||||
|
||||
private fun updateResetButton() {
|
||||
resetButton.active = config.getter.call(parent.parent.clonedConfig) != config.getter.call(parent.parent.defaultConfig)
|
||||
}
|
||||
|
||||
override fun filter(text: String): Boolean {
|
||||
val normalizedLabel = Normalizer.normalize(labelLang.string, Normalizer.Form.NFD).replace("\\p{M}+".toRegex(), "")
|
||||
return normalizedLabel.contains(text, ignoreCase = true)
|
||||
}
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
top: Int,
|
||||
left: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
hovering: Boolean,
|
||||
partialTick: Float
|
||||
) {
|
||||
val x = getX(left)
|
||||
val y = getY(top)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = labelLang,
|
||||
x = getX(left),
|
||||
y = getY(top) + LABEL_Y_OFFSET,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
resetButton.x = x + SLOT_WIDTH - RESET_SLOT_WIDTH
|
||||
resetButton.y = y + WIDGET_Y_OFFSET
|
||||
resetButton.render(context, mouseX, mouseY, partialTick)
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class GrabbedStorageSlot(
|
||||
) : StorageSlot(x, y, parent, {}) {
|
||||
|
||||
init {
|
||||
isSelected = true
|
||||
isSlotSelected = true
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
|
||||
@@ -46,7 +46,7 @@ open class StorageSlot(
|
||||
private val slotOverlayMoveIconResource = cobblemonResource("textures/gui/pasture/pc_slot_icon_move.png")
|
||||
}
|
||||
|
||||
protected var isSelected = false;
|
||||
protected var isSlotSelected = false;
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
}
|
||||
@@ -84,7 +84,7 @@ open class StorageSlot(
|
||||
|
||||
context.disableScissor()
|
||||
|
||||
if (!isSelected) {
|
||||
if (!isSlotSelected) {
|
||||
// Ensure elements are not hidden behind Pokémon render
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, 0.0, 100.0)
|
||||
@@ -129,7 +129,7 @@ open class StorageSlot(
|
||||
matrices.translate(0.0, 0.0, 500.0)
|
||||
|
||||
val config = parent.pcGui.configuration
|
||||
if (pokemon.tetheringId != null && !isSelected) {
|
||||
if (pokemon.tetheringId != null && !isSlotSelected) {
|
||||
if (isStationary()) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.settings
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object OpenCobblemonConfigEditorHandler : ClientNetworkPacketHandler<OpenCobblemonConfigScreenPacket> {
|
||||
override fun handle(packet: OpenCobblemonConfigScreenPacket, client: Minecraft) {
|
||||
client.setScreen(CobblemonConfigScreen(Minecraft.getInstance().screen))
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.render
|
||||
|
||||
import com.cobblemon.mod.common.util.math.geometry.getOrigin
|
||||
import com.cobblemon.mod.common.util.math.geometry.transformPosition
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.fabricmc.loader.impl.lib.sat4j.core.Vec
|
||||
import org.joml.Matrix4f
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
@@ -204,8 +204,8 @@ class SnowstormParticle(
|
||||
val spriteURange = sprite.u1 - sprite.u0
|
||||
val spriteVRange = sprite.v1 - sprite.v0
|
||||
|
||||
val maxU = uvs.startU * spriteURange + sprite.u0
|
||||
val minU = uvs.endU * spriteURange + sprite.u0
|
||||
val minU = uvs.startU * spriteURange + sprite.u0
|
||||
val maxU = uvs.endU * spriteURange + sprite.u0
|
||||
val minV = uvs.startV * spriteVRange + sprite.v0
|
||||
val maxV = uvs.endV * spriteVRange + sprite.v0
|
||||
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ import com.cobblemon.mod.common.api.mulch.MulchVariant
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides
|
||||
import com.cobblemon.mod.common.client.render.layer.CobblemonRenderLayers
|
||||
import com.cobblemon.mod.common.client.render.layer.CobblemonRenderTypes
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.setPosition
|
||||
import com.cobblemon.mod.common.util.math.geometry.Axis
|
||||
@@ -54,7 +54,7 @@ class BerryBlockRenderer(private val context: BlockEntityRendererProvider.Contex
|
||||
if (entity.renderState == null) {
|
||||
entity.renderState = BerryBlockEntityRenderState()
|
||||
}
|
||||
val bf = vertexConsumers.getBuffer(CobblemonRenderLayers.BERRY_LAYER)
|
||||
val bf = vertexConsumers.getBuffer(CobblemonRenderTypes.BERRY_LAYER)
|
||||
val renderState = entity.renderState as BerryBlockEntityRenderState
|
||||
// if (renderState.needsRebuild || renderState.vboLightLevel != light) {
|
||||
renderToBuffer(entity, matrices, light, overlay, renderState, bf)
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ import net.minecraft.Util
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderStateShard.*
|
||||
|
||||
object CobblemonRenderLayers {
|
||||
object CobblemonRenderTypes {
|
||||
val BERRY_LAYER = run {
|
||||
val multiPhaseParameters = RenderType.CompositeState.builder()
|
||||
.setLightmapState(LIGHTMAP)
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package com.cobblemon.mod.common.client.render.layer
|
||||
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.appendage.ModelAppendageModelRepository
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemDisplayContext
|
||||
import org.joml.Vector3f
|
||||
|
||||
object ModelAppendageRenderer {
|
||||
|
||||
fun <T> render(
|
||||
poseStack: PoseStack,
|
||||
bufferSource: MultiBufferSource,
|
||||
packedLight: Int,
|
||||
livingEntity: T,
|
||||
limbSwing: Float,
|
||||
limbSwingAmount: Float,
|
||||
ageInTicks: Float,
|
||||
netHeadYaw: Float,
|
||||
headPitch: Float,
|
||||
locator: String,
|
||||
context: RenderContext,
|
||||
parentModel: ResourceLocation
|
||||
) where T : PokemonEntity {
|
||||
val clientDelegate = livingEntity.delegate as PokemonClientDelegate
|
||||
val appendages = ModelAppendageModelRepository.getAppendagesForModelAndTarget(parentModel, locator) ?: return
|
||||
// avoid editing the original context
|
||||
val clonedContext = context.clone()
|
||||
appendages.forEach { appendage ->
|
||||
val modelObj = appendage.model.resolveObject(clientDelegate.runtime).obj
|
||||
if (modelObj is ResourceLocation) {
|
||||
poseStack.pushPose()
|
||||
clientDelegate.locatorStates[locator]?.let { bone ->
|
||||
val stack = if(modelObj.toString() == "cobblemon:held_item") livingEntity.pokemon.heldItemNoCopy() else BuiltInRegistries.ITEM.get(modelObj).defaultInstance
|
||||
val pos = bone.getOrigin().subtract(livingEntity.position())
|
||||
val scale = Vector3f()
|
||||
bone.matrix.getScale(scale)
|
||||
poseStack.scale(scale.x(), scale.y(), scale.z())
|
||||
poseStack.translate(pos.x, pos.y, pos.z)
|
||||
poseStack.mulPose(bone.clone().matrix.setTranslation(0.0f, 0.0f, 0.0f))
|
||||
poseStack.scale(
|
||||
appendage.scale.x().toFloat(), appendage.scale.y().toFloat(),
|
||||
appendage.scale.z().toFloat()
|
||||
)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(appendage.rotation.x().toFloat()))
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(appendage.rotation.y().toFloat()))
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(appendage.rotation.z().toFloat()))
|
||||
poseStack.translate(appendage.offset.x(), appendage.offset.y(), appendage.offset.z())
|
||||
Minecraft.getInstance().itemRenderer.renderStatic(stack, ItemDisplayContext.THIRD_PERSON_RIGHT_HAND, packedLight, OverlayTexture.NO_OVERLAY, poseStack, bufferSource, livingEntity.level(), 0)
|
||||
}
|
||||
poseStack.popPose()
|
||||
} else if (modelObj is Pair<*, *>) {
|
||||
val repo = modelObj.first as ModelAppendageModelRepository
|
||||
val resLoc = modelObj.second as ResourceLocation
|
||||
val model =
|
||||
repo.getPoserNullable(resLoc, clientDelegate) ?: return
|
||||
model.context = clonedContext
|
||||
model.setLayerContext(
|
||||
bufferSource,
|
||||
clientDelegate,
|
||||
ModelAppendageModelRepository.getLayers(resLoc, clientDelegate)
|
||||
)
|
||||
poseStack.pushPose()
|
||||
clientDelegate.locatorStates[locator]?.let { bone ->
|
||||
val pos = bone.getOrigin().subtract(livingEntity.position())
|
||||
val scale = Vector3f()
|
||||
bone.matrix.getScale(scale)
|
||||
poseStack.scale(scale.x(), scale.y(), scale.z())
|
||||
poseStack.translate(pos.x, pos.y, pos.z)
|
||||
poseStack.mulPose(bone.clone().matrix.setTranslation(0.0f, 0.0f, 0.0f))
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(180f))
|
||||
poseStack.translate(0.0, -1.75, 0.0)
|
||||
poseStack.scale(
|
||||
appendage.scale.x().toFloat(), appendage.scale.y().toFloat(),
|
||||
appendage.scale.z().toFloat()
|
||||
)
|
||||
poseStack.mulPose(Axis.XP.rotationDegrees(appendage.rotation.x().toFloat()))
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(appendage.rotation.y().toFloat()))
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(appendage.rotation.z().toFloat()))
|
||||
poseStack.translate(appendage.offset.x(), appendage.offset.y(), appendage.offset.z())
|
||||
model.applyAnimations(
|
||||
livingEntity,
|
||||
clientDelegate,
|
||||
limbSwing,
|
||||
limbSwingAmount,
|
||||
ageInTicks,
|
||||
netHeadYaw,
|
||||
headPitch
|
||||
)
|
||||
val buffer = bufferSource.getBuffer(
|
||||
RenderType.entityCutout(
|
||||
ModelAppendageModelRepository.getTexture(
|
||||
resLoc,
|
||||
clientDelegate
|
||||
)
|
||||
)
|
||||
)
|
||||
model.withLayerContext(
|
||||
bufferSource,
|
||||
clientDelegate,
|
||||
ModelAppendageModelRepository.getLayers(resLoc, clientDelegate)
|
||||
) {
|
||||
model.render(clonedContext, poseStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
|
||||
}
|
||||
model.green = 1F
|
||||
model.blue = 1F
|
||||
model.red = 1F
|
||||
|
||||
model.resetLayerContext()
|
||||
poseStack.popPose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.cobblemon.mod.common.client.render.layer.appendage
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
data class ModelAppendage(
|
||||
@SerializedName("target_model") val targetModel: ResourceLocation?,
|
||||
@SerializedName("model") val model: ExpressionLike,
|
||||
@SerializedName("target_locator") val targetLocator: String,
|
||||
@SerializedName("scale") val scale: Vec3 = Vec3(1.0, 1.0, 1.0),
|
||||
@SerializedName("rotation") val rotation: Vec3 = Vec3(0.0, 0.0, 0.0),
|
||||
@SerializedName("offset") val offset: Vec3 = Vec3(0.0, 0.0, 0.0)
|
||||
)
|
||||
+6
@@ -80,6 +80,12 @@ class RenderContext {
|
||||
this.context.remove(key)
|
||||
}
|
||||
|
||||
fun clone(): RenderContext {
|
||||
val newContext = RenderContext()
|
||||
newContext.context.putAll(this.context)
|
||||
return newContext
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a key used for accessing values in the context.
|
||||
*
|
||||
|
||||
+4
-2
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.repository.Varyi
|
||||
import com.cobblemon.mod.common.client.util.exists
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.Vec3dAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.endsWith
|
||||
@@ -72,6 +73,7 @@ abstract class VaryingModelRepository<T : PosableModel> {
|
||||
GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(Vec3::class.java, Vec3dAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
@@ -213,7 +215,7 @@ abstract class VaryingModelRepository<T : PosableModel> {
|
||||
Cobblemon.LOGGER.info("Loaded $models $title models.")
|
||||
}
|
||||
|
||||
fun reload(resourceManager: ResourceManager) {
|
||||
open fun reload(resourceManager: ResourceManager) {
|
||||
Cobblemon.LOGGER.info("Loading $title assets...")
|
||||
this.variations.clear()
|
||||
this.posers.clear()
|
||||
@@ -222,7 +224,7 @@ abstract class VaryingModelRepository<T : PosableModel> {
|
||||
registerVariations(resourceManager)
|
||||
}
|
||||
|
||||
fun getPoser(name: ResourceLocation, state: PosableState): T {
|
||||
open fun getPoser(name: ResourceLocation, state: PosableState): T {
|
||||
try {
|
||||
val poser = this.variations[name]?.getPoser(state)
|
||||
if (poser != null) {
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.repository.appendage
|
||||
|
||||
import com.cobblemon.mod.common.client.render.layer.appendage.ModelAppendage
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.endsWith
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import java.io.File
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
object ModelAppendageModelRepository : VaryingModelRepository<PosableModel>() {
|
||||
override val poserClass: Class<PosableModel>
|
||||
get() = PosableModel::class.java
|
||||
override val title: String
|
||||
get() = "Model Appendage"
|
||||
override val type: String
|
||||
get() = "appendage"
|
||||
override val variationDirectories: List<String>
|
||||
get() = listOf("bedrock/$type/variations")
|
||||
override val poserDirectories: List<String>
|
||||
get() = listOf("bedrock/$type/posers")
|
||||
override val modelDirectories: List<String>
|
||||
get() = listOf("bedrock/$type/models")
|
||||
override val animationDirectories: List<String>
|
||||
get() = listOf("bedrock/$type/animations")
|
||||
val appendageDirectories: List<String>
|
||||
get() = listOf("bedrock/$type/appendages")
|
||||
val appendages = mutableMapOf<ResourceLocation, ModelAppendage>()
|
||||
override val fallback: ResourceLocation = cobblemonResource("substitute")
|
||||
override val isForLivingEntityRenderer: Boolean
|
||||
get() = true
|
||||
|
||||
override fun registerInBuiltPosers() {}
|
||||
|
||||
override fun reload(resourceManager: ResourceManager) {
|
||||
super.reload(resourceManager)
|
||||
this.appendages.clear()
|
||||
registerJsonAppendages(resourceManager)
|
||||
}
|
||||
|
||||
private fun registerJsonAppendages(resourceManager: ResourceManager) {
|
||||
for (directory in appendageDirectories) {
|
||||
resourceManager
|
||||
.listResources(directory) { path -> path.endsWith(".json") }
|
||||
.forEach { (identifier, resource) ->
|
||||
resource.open().use { stream ->
|
||||
val json = String(stream.readAllBytes(), StandardCharsets.UTF_8)
|
||||
val resolvedIdentifier = ResourceLocation.fromNamespaceAndPath(identifier.namespace, File(identifier.path).nameWithoutExtension)
|
||||
appendages[resolvedIdentifier] = gson.fromJson(json, ModelAppendage::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getAppendagesForModelAndTarget(model: ResourceLocation, target: String): List<ModelAppendage> {
|
||||
return appendages.entries.filter { (it.value.targetModel == model || it.value.targetModel == null) && it.value.targetLocator == target }.map { it.value }
|
||||
}
|
||||
|
||||
fun getPoserNullable(name: ResourceLocation, state: PosableState): PosableModel? {
|
||||
try {
|
||||
val poser = this.variations[name]?.getPoser(state)
|
||||
if (poser != null) {
|
||||
return poser
|
||||
}
|
||||
} catch(e: IllegalStateException) {
|
||||
// e.printStackTrace()
|
||||
}
|
||||
return this.variations[fallback]?.getPoser(state)
|
||||
}
|
||||
}
|
||||
+118
-34
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.client.entity.PokemonClientDelegate.Companion.BE
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate.Companion.BEAM_SHRINK_TIME
|
||||
import com.cobblemon.mod.common.client.keybind.boundKey
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding
|
||||
import com.cobblemon.mod.common.client.render.layer.ModelAppendageRenderer
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PosablePokemonEntityModel
|
||||
@@ -41,7 +42,6 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.math.remap
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import kotlin.math.*
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.Font.DisplayMode
|
||||
@@ -61,15 +61,17 @@ import org.joml.Math
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import org.joml.Vector4f
|
||||
import kotlin.math.*
|
||||
|
||||
class PokemonRenderer(
|
||||
context: EntityRendererProvider.Context
|
||||
var context: EntityRendererProvider.Context
|
||||
) : MobRenderer<PokemonEntity, PosablePokemonEntityModel>(context, PosablePokemonEntityModel(), 0.5f) {
|
||||
companion object {
|
||||
val recallBeamColour = Vector4f(1F, 0.1F, 0.1F, 1F)
|
||||
fun ease(x: Double): Double {
|
||||
return 1 - (1 - x).pow(3)
|
||||
}
|
||||
|
||||
private val LEVEL_LABEL_STYLE = Style.EMPTY.withColor(ChatFormatting.WHITE)
|
||||
.withBold(false)
|
||||
.withItalic(false)
|
||||
@@ -88,7 +90,10 @@ class PokemonRenderer(
|
||||
}
|
||||
|
||||
override fun getTextureLocation(entity: PokemonEntity): ResourceLocation {
|
||||
return PokemonModelRepository.getTexture(entity.pokemon.species.resourceIdentifier, entity.delegate as PokemonClientDelegate)
|
||||
return PokemonModelRepository.getTexture(
|
||||
entity.pokemon.species.resourceIdentifier,
|
||||
entity.delegate as PokemonClientDelegate
|
||||
)
|
||||
}
|
||||
|
||||
override fun render(
|
||||
@@ -100,7 +105,10 @@ class PokemonRenderer(
|
||||
packedLight: Int
|
||||
) {
|
||||
val clientDelegate = entity.delegate as PokemonClientDelegate
|
||||
shadowRadius = min((entity.boundingBox.maxX - entity.boundingBox.minX), (entity.boundingBox.maxZ) - (entity.boundingBox.minZ)).toFloat() / 1.5F * (entity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
shadowRadius = min(
|
||||
(entity.boundingBox.maxX - entity.boundingBox.minX),
|
||||
(entity.boundingBox.maxZ) - (entity.boundingBox.minZ)
|
||||
).toFloat() / 1.5F * (entity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
model.posableModel = PokemonModelRepository.getPoser(entity.pokemon.species.resourceIdentifier, clientDelegate)
|
||||
model.posableModel.context = model.context
|
||||
model.setupEntityTypeContext(entity)
|
||||
@@ -126,7 +134,7 @@ class PokemonRenderer(
|
||||
clientDelegate
|
||||
)
|
||||
}
|
||||
if(entity.platform != PlatformType.NONE) {
|
||||
if (entity.platform != PlatformType.NONE) {
|
||||
drawPlatform(
|
||||
poseMatrix,
|
||||
entity,
|
||||
@@ -138,10 +146,34 @@ class PokemonRenderer(
|
||||
poseMatrix.translate(0.0, 0.25 * (entity.delegate as PokemonClientDelegate).entityScaleModifier, 0.0)
|
||||
}
|
||||
|
||||
modelNow.setLayerContext(buffer, clientDelegate, PokemonModelRepository.getLayers(entity.pokemon.species.resourceIdentifier, clientDelegate))
|
||||
modelNow.setLayerContext(
|
||||
buffer,
|
||||
clientDelegate,
|
||||
PokemonModelRepository.getLayers(entity.pokemon.species.resourceIdentifier, clientDelegate)
|
||||
)
|
||||
|
||||
|
||||
super.render(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
|
||||
PokemonModelRepository.variations[entity.pokemon.species.resourceIdentifier]?.getResolvedModel(clientDelegate).let { parentModel ->
|
||||
clientDelegate.locatorStates.keys.forEach { locatorKey ->
|
||||
if (parentModel != null) {
|
||||
ModelAppendageRenderer.render(
|
||||
poseMatrix,
|
||||
buffer,
|
||||
packedLight,
|
||||
entity,
|
||||
0f,
|
||||
0f,
|
||||
entity.age.toFloat() + partialTicks,
|
||||
entityYaw,
|
||||
entity.lookAngle.x.toFloat(),
|
||||
locatorKey,
|
||||
model.context,
|
||||
parentModel
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modelNow.green = 1F
|
||||
modelNow.blue = 1F
|
||||
@@ -165,7 +197,7 @@ class PokemonRenderer(
|
||||
val s = clientDelegate.secondsSinceBeamEffectStarted
|
||||
if (beamMode == 3) {
|
||||
if (s > BEAM_EXTEND_TIME) {
|
||||
val value = (s - BEAM_EXTEND_TIME) / BEAM_SHRINK_TIME
|
||||
val value = (s - BEAM_EXTEND_TIME) / BEAM_SHRINK_TIME
|
||||
val colourValue = 1F - min(0.6F, value)
|
||||
modelNow.green = colourValue
|
||||
modelNow.blue = colourValue
|
||||
@@ -181,7 +213,9 @@ class PokemonRenderer(
|
||||
val lookVec = phaseTarget.lookAngle.yRot((PI / 2).toFloat()).multiply(1.0, 0.0, 1.0).normalize()
|
||||
phaseTarget.getEyePosition(partialTicks).subtract(0.0, 0.4, 0.0).subtract(lookVec.scale(0.3))
|
||||
} else {
|
||||
val lookVec = phaseTarget.lookAngle.yRot((PI / 2 - (phaseTarget.visualRotationYInDegrees - phaseTarget.xRot).toRadians()).toFloat()).multiply(1.0, 0.0, 1.0).normalize()
|
||||
val lookVec =
|
||||
phaseTarget.lookAngle.yRot((PI / 2 - (phaseTarget.visualRotationYInDegrees - phaseTarget.xRot).toRadians()).toFloat())
|
||||
.multiply(1.0, 0.0, 1.0).normalize()
|
||||
phaseTarget.getEyePosition(partialTicks).subtract(0.0, 0.7, 0.0).subtract(lookVec.scale(0.4))
|
||||
}
|
||||
}
|
||||
@@ -192,7 +226,8 @@ class PokemonRenderer(
|
||||
clientDelegate.sendOutPosition = clientDelegate.sendOutPosition!!.add(0.0, 0.04, 0.0)
|
||||
beamSourcePosition = clientDelegate.sendOutPosition!!
|
||||
}
|
||||
val offsetDirection = beamSourcePosition.subtract(entity.position()).normalize().scale(-clientDelegate.ballOffset.toDouble())
|
||||
val offsetDirection =
|
||||
beamSourcePosition.subtract(entity.position()).normalize().scale(-clientDelegate.ballOffset.toDouble())
|
||||
val facingDir: Vec3
|
||||
with(beamSourcePosition.subtract(entity.position())) {
|
||||
var newOffset = offsetDirection.scale(2.0)
|
||||
@@ -200,16 +235,17 @@ class PokemonRenderer(
|
||||
newOffset = newOffset.scale((distance / 10.0) * 5)
|
||||
facingDir = newOffset.normalize()
|
||||
clientDelegate.sendOutOffset = newOffset
|
||||
poseMatrix.translate(x+newOffset.x, y+newOffset.y, z+newOffset.z)
|
||||
poseMatrix.translate(x + newOffset.x, y + newOffset.y, z + newOffset.z)
|
||||
}
|
||||
val dir = beamSourcePosition.subtract(entity.position()).normalize()
|
||||
val angle = Mth.atan2(dir.z, dir.x) - PI / 2
|
||||
poseMatrix.mulPose(Axis.YP.rotation(-angle.toFloat() + (180 * Math.PI / 180).toFloat()))
|
||||
|
||||
if (beamMode == 1 && !clientDelegate.ballDone){
|
||||
if(entity.pokemon.caughtBall.name.toString().contains("beast")){
|
||||
if (beamMode == 1 && !clientDelegate.ballDone) {
|
||||
if (entity.pokemon.caughtBall.name.toString().contains("beast")) {
|
||||
// get rotation angle on x-axis for facingDir
|
||||
val xAngleFacingDir = Mth.atan2(facingDir.y, sqrt(facingDir.x * facingDir.x + facingDir.z * facingDir.z))
|
||||
val xAngleFacingDir =
|
||||
Mth.atan2(facingDir.y, sqrt(facingDir.x * facingDir.x + facingDir.z * facingDir.z))
|
||||
poseMatrix.mulPose(Axis.XP.rotation(-xAngleFacingDir.toFloat()))
|
||||
}
|
||||
drawPokeBall(
|
||||
@@ -221,7 +257,7 @@ class PokemonRenderer(
|
||||
packedLight = packedLight,
|
||||
ball = CobblemonClient.storage.myParty.firstOrNull { it?.uuid == entity.pokemon.uuid }?.caughtBall
|
||||
?: clientDelegate.currentEntity.pokemon.caughtBall,
|
||||
distance = ceil(beamSourcePosition.distanceTo(entity.position())/4f).toInt()
|
||||
distance = ceil(beamSourcePosition.distanceTo(entity.position()) / 4f).toInt()
|
||||
)
|
||||
}
|
||||
poseMatrix.popPose()
|
||||
@@ -231,7 +267,8 @@ class PokemonRenderer(
|
||||
}
|
||||
|
||||
override fun scale(pEntity: PokemonEntity, pPoseStack: PoseStack, pPartialTickTime: Float) {
|
||||
val scale = pEntity.pokemon.form.baseScale * pEntity.pokemon.scaleModifier * (pEntity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
val scale =
|
||||
pEntity.pokemon.form.baseScale * pEntity.pokemon.scaleModifier * (pEntity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
pPoseStack.scale(scale, scale, scale)
|
||||
}
|
||||
|
||||
@@ -245,9 +282,17 @@ class PokemonRenderer(
|
||||
* @param colour The colour of the beam.
|
||||
* @param buffer The vertex consumer provider.
|
||||
*/
|
||||
fun renderBeam(matrixStack: PoseStack, partialTicks: Float, entity: PokemonEntity, beamTarget: Entity, buffer: MultiBufferSource, offset: Vec3) {
|
||||
fun renderBeam(
|
||||
matrixStack: PoseStack,
|
||||
partialTicks: Float,
|
||||
entity: PokemonEntity,
|
||||
beamTarget: Entity,
|
||||
buffer: MultiBufferSource,
|
||||
offset: Vec3
|
||||
) {
|
||||
val clientDelegate = entity.delegate as PokemonClientDelegate
|
||||
val pokemonPosition = entity.position().add(0.0, entity.bbHeight / 2.0 * clientDelegate.entityScaleModifier.toDouble(), 0.0)
|
||||
val pokemonPosition =
|
||||
entity.position().add(0.0, entity.bbHeight / 2.0 * clientDelegate.entityScaleModifier.toDouble(), 0.0)
|
||||
var beamSourcePosition = if (beamTarget is EmptyPokeBallEntity) {
|
||||
(beamTarget.delegate as PokeBallPosableState).locatorStates["beam"]?.getOrigin() ?: beamTarget.position()
|
||||
} else {
|
||||
@@ -257,7 +302,9 @@ class PokemonRenderer(
|
||||
} else if (beamTarget is NPCEntity) {
|
||||
(beamTarget.delegate as NPCClientDelegate).locatorStates["beam"]?.getOrigin() ?: beamTarget.position()
|
||||
} else {
|
||||
val lookVec = beamTarget.lookAngle.yRot((PI / 2 - (beamTarget.visualRotationYInDegrees - beamTarget.xRot).toRadians()).toFloat()).multiply(1.0, 0.0, 1.0).normalize()
|
||||
val lookVec =
|
||||
beamTarget.lookAngle.yRot((PI / 2 - (beamTarget.visualRotationYInDegrees - beamTarget.xRot).toRadians()).toFloat())
|
||||
.multiply(1.0, 0.0, 1.0).normalize()
|
||||
beamTarget.getEyePosition(partialTicks).subtract(0.0, 0.7, 0.0).subtract(lookVec.scale(0.4))
|
||||
}
|
||||
}
|
||||
@@ -272,8 +319,9 @@ class PokemonRenderer(
|
||||
// the further away the source position is, the smaller the newOffset should be. Max distance is 20 blocks
|
||||
val distance = beamSourcePosition.distanceTo(entity.position())
|
||||
newOffset = newOffset.scale((distance / 10.0) * 5)
|
||||
newOffset = newOffset.multiply(0.0, 1+ease(clientDelegate.ballOffset.toDouble()), 0.0)
|
||||
val direction = pokemonPosition.subtract(beamSourcePosition.add(newOffset)).let { Vector3f(it.x.toFloat(), it.y.toFloat(), it.z.toFloat()) }
|
||||
newOffset = newOffset.multiply(0.0, 1 + ease(clientDelegate.ballOffset.toDouble()), 0.0)
|
||||
val direction = pokemonPosition.subtract(beamSourcePosition.add(newOffset))
|
||||
.let { Vector3f(it.x.toFloat(), it.y.toFloat(), it.z.toFloat()) }
|
||||
|
||||
matrixStack.pushPose()
|
||||
with(beamSourcePosition.subtract(entity.position())) {
|
||||
@@ -349,10 +397,10 @@ class PokemonRenderer(
|
||||
}
|
||||
val player = Minecraft.getInstance().player ?: return
|
||||
val d = this.entityRenderDispatcher.distanceToSqr(entity)
|
||||
if (d <= 4096.0){
|
||||
if (d <= 4096.0) {
|
||||
val scale = min(1.5, max(0.65, d.remap(DoubleRange(-16.0, 96.0), DoubleRange(0.0, 1.0))))
|
||||
val sizeScale = Mth.lerp(scale.remap(DoubleRange(0.65, 1.5), DoubleRange(0.0,1.0)), 0.5, 1.0)
|
||||
val offsetScale = Mth.lerp(scale.remap(DoubleRange(0.65, 1.5), DoubleRange(0.0,1.0)), 0.0,1.0)
|
||||
val sizeScale = Mth.lerp(scale.remap(DoubleRange(0.65, 1.5), DoubleRange(0.0, 1.0)), 0.5, 1.0)
|
||||
val offsetScale = Mth.lerp(scale.remap(DoubleRange(0.65, 1.5), DoubleRange(0.0, 1.0)), 0.0, 1.0)
|
||||
val entityHeight = entity.boundingBox.ysize + 0.5f
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, entityHeight, 0.0)
|
||||
@@ -374,15 +422,48 @@ class PokemonRenderer(
|
||||
var h = (-this.font.width(label) / 2).toFloat()
|
||||
val y = 0F
|
||||
val packedLight = LightTexture.pack(15, 15)
|
||||
this.font.drawInBatch(label, h, y, 0x20FFFFFF, false, matrix4f, vertexConsumers, DisplayMode.SEE_THROUGH, opacity, packedLight)
|
||||
this.font.drawInBatch(
|
||||
label,
|
||||
h,
|
||||
y,
|
||||
0x20FFFFFF,
|
||||
false,
|
||||
matrix4f,
|
||||
vertexConsumers,
|
||||
DisplayMode.SEE_THROUGH,
|
||||
opacity,
|
||||
packedLight
|
||||
)
|
||||
this.font.drawInBatch(label, h, y, -1, false, matrix4f, vertexConsumers, DisplayMode.NORMAL, 0, packedLight)
|
||||
|
||||
if (CobblemonClient.clientPlayerData.showChallengeLabel && entity.canBattle(player)) {
|
||||
val sendOutBinding = PartySendBinding.boundKey().displayName
|
||||
val battlePrompt = lang("challenge_label", sendOutBinding)
|
||||
h = (-this.font.width(battlePrompt) / 2).toFloat()
|
||||
this.font.drawInBatch(battlePrompt, h, y + 10, 0x20FFFFFF, false, matrix4f, vertexConsumers, DisplayMode.SEE_THROUGH, opacity, packedLight)
|
||||
this.font.drawInBatch(battlePrompt, h, y + 10, -1, false, matrix4f, vertexConsumers, DisplayMode.NORMAL, 0, packedLight)
|
||||
this.font.drawInBatch(
|
||||
battlePrompt,
|
||||
h,
|
||||
y + 10,
|
||||
0x20FFFFFF,
|
||||
false,
|
||||
matrix4f,
|
||||
vertexConsumers,
|
||||
DisplayMode.SEE_THROUGH,
|
||||
opacity,
|
||||
packedLight
|
||||
)
|
||||
this.font.drawInBatch(
|
||||
battlePrompt,
|
||||
h,
|
||||
y + 10,
|
||||
-1,
|
||||
false,
|
||||
matrix4f,
|
||||
vertexConsumers,
|
||||
DisplayMode.NORMAL,
|
||||
0,
|
||||
packedLight
|
||||
)
|
||||
}
|
||||
matrices.popPose()
|
||||
}
|
||||
@@ -391,7 +472,10 @@ class PokemonRenderer(
|
||||
private fun resolveBaseLabel(entity: PokemonEntity): MutableComponent {
|
||||
return when {
|
||||
!ServerSettings.displayEntityNameLabel -> Component.empty()
|
||||
Cobblemon.config.displayNameForUnknownPokemon || CobblemonClient.clientPokedexData.getKnowledgeForSpecies(entity.pokemon.species.resourceIdentifier) != PokedexEntryProgress.NONE -> entity.name.copy()
|
||||
Cobblemon.config.displayNameForUnknownPokemon || CobblemonClient.clientPokedexData.getKnowledgeForSpecies(
|
||||
entity.pokemon.species.resourceIdentifier
|
||||
) != PokedexEntryProgress.NONE -> entity.name.copy()
|
||||
|
||||
else -> Component.literal(HIDDEN_NAME)
|
||||
}
|
||||
}
|
||||
@@ -416,7 +500,7 @@ class PokemonRenderer(
|
||||
} else {
|
||||
matrixStack.translate(0.0, -0.2, 0.0)
|
||||
val rot = 360F * distance
|
||||
if(ball.name.toString().contains("beast")){
|
||||
if (ball.name.toString().contains("beast")) {
|
||||
matrixStack.mulPose(Axis.ZN.rotationDegrees(Math.lerp(0F, rot, scale)))
|
||||
} else {
|
||||
matrixStack.mulPose(Axis.XN.rotationDegrees(Math.lerp(0F, rot, scale)))
|
||||
@@ -440,12 +524,12 @@ class PokemonRenderer(
|
||||
}
|
||||
|
||||
private fun drawPlatform(
|
||||
matrixStack: PoseStack,
|
||||
entity: PokemonEntity,
|
||||
scale: Float = 1F,
|
||||
buff: MultiBufferSource,
|
||||
packedLight: Int,
|
||||
) {
|
||||
matrixStack: PoseStack,
|
||||
entity: PokemonEntity,
|
||||
scale: Float = 1F,
|
||||
buff: MultiBufferSource,
|
||||
packedLight: Int,
|
||||
) {
|
||||
val (modelResource, textureResource) = PlatformType.getModelWithTexture(entity.platform)
|
||||
val model = MiscModelRepository.modelOf(modelResource) ?: return
|
||||
matrixStack.pushPose()
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.OpenCobblemonConfigScreenPacket
|
||||
import com.cobblemon.mod.common.util.commandLang
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object CobblemonConfigCommand {
|
||||
fun register(dispatcher: CommandDispatcher<CommandSourceStack>) {
|
||||
dispatcher.register(
|
||||
Commands.literal("cobblemonconfig")
|
||||
.executes {
|
||||
it.source.playerOrException.sendPacket(OpenCobblemonConfigScreenPacket())
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
.then(
|
||||
Commands.literal("reload")
|
||||
.permission(CobblemonPermissions.COBBLEMON_CONFIG_RELOAD)
|
||||
.executes {
|
||||
Cobblemon.reloadConfig()
|
||||
it.source.server.playerList.players.forEach { player ->
|
||||
if (player is ServerPlayer) {
|
||||
Cobblemon.sendServerSettingsPacketToPlayer(player)
|
||||
}
|
||||
}
|
||||
|
||||
it.source.sendSuccess({ commandLang("cobblemon_config.reload") }, true)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.config
|
||||
|
||||
enum class Category {
|
||||
Starter,
|
||||
Pokedex,
|
||||
Pokemon,
|
||||
Spawning,
|
||||
Battles,
|
||||
PassiveStatus,
|
||||
Healing,
|
||||
Storage,
|
||||
World,
|
||||
Debug
|
||||
enum class Category(val lang: String) {
|
||||
Pokemon("pokemon"),
|
||||
Spawning("spawning"),
|
||||
Battles("battles"),
|
||||
PassiveStatus("passive_status"),
|
||||
Healing("healing"),
|
||||
World("world"),
|
||||
Pokedex("pokedex"),
|
||||
Storage("storage"),
|
||||
Starter("starter"),
|
||||
Debug("debug"),
|
||||
}
|
||||
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.pokeball.catching.calculators.CobblemonCaptureCa
|
||||
import com.cobblemon.mod.common.util.adapters.CaptureCalculatorAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
|
||||
import com.google.gson.GsonBuilder
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
class CobblemonConfig {
|
||||
@@ -31,114 +33,112 @@ class CobblemonConfig {
|
||||
|
||||
var lastSavedVersion: String = "0.0.1"
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "max_pokemon_level")
|
||||
@IntConstraint(min = 1, max = 1000)
|
||||
var maxPokemonLevel = 100
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "max_pokemon_friendship")
|
||||
@IntConstraint(min = 0, max = 1000)
|
||||
var maxPokemonFriendship = 255
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "announce_drop_items")
|
||||
var announceDropItems = true
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "default_drop_item_method")
|
||||
var defaultDropItemMethod = ItemDropMethod.ON_ENTITY
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "ambient_pokemon_cry_ticks")
|
||||
@LastChangedVersion("1.4.0")
|
||||
var ambientPokemonCryTicks = 1080
|
||||
|
||||
@NodeCategory(Category.Storage)
|
||||
@CobblemonConfigField(Category.Storage, lang = "default_box_count")
|
||||
@IntConstraint(min = 1, max = 1000)
|
||||
var defaultBoxCount = 30
|
||||
@NodeCategory(Category.Storage)
|
||||
@CobblemonConfigField(Category.Storage, lang = "pokemon_save_interval_seconds")
|
||||
@IntConstraint(min = 1, max = 120)
|
||||
var pokemonSaveIntervalSeconds = 30
|
||||
|
||||
@NodeCategory(Category.Storage)
|
||||
@CobblemonConfigField(Category.Storage, lang = "storage_format")
|
||||
var storageFormat = "nbt"
|
||||
|
||||
@NodeCategory(Category.Storage)
|
||||
@CobblemonConfigField(Category.Storage, lang = "prevent_complete_party_deposit")
|
||||
var preventCompletePartyDeposit = false
|
||||
|
||||
@NodeCategory(Category.Storage)
|
||||
@CobblemonConfigField(Category.Storage, lang = "mongo_db_connection_string")
|
||||
var mongoDBConnectionString = "mongodb://localhost:27017"
|
||||
@NodeCategory(Category.Storage)
|
||||
@CobblemonConfigField(Category.Storage, lang = "mongo_db_database_name")
|
||||
var mongoDBDatabaseName = "cobblemon"
|
||||
|
||||
// TODO new types of constraint
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "max_vertical_correction_blocks")
|
||||
@IntConstraint(min = 1, max = 200)
|
||||
var maxVerticalCorrectionBlocks = 64
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "minimum_level_range_max")
|
||||
@IntConstraint(min = 1, max = 1000)
|
||||
var minimumLevelRangeMax = 10
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "enable_spawning")
|
||||
var enableSpawning = true
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "minimum_distance_between_entities")
|
||||
var minimumDistanceBetweenEntities = 8.0
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "max_nearby_blocks_horizontal_range")
|
||||
var maxNearbyBlocksHorizontalRange = 4
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "max_nearby_blocks_vertical_range")
|
||||
var maxNearbyBlocksVerticalRange = 2
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "max_vertical_space")
|
||||
var maxVerticalSpace = 8
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "world_slice_diameter")
|
||||
var worldSliceDiameter = 8
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "world_slice_height")
|
||||
var worldSliceHeight = 16
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "ticks_between_spawn_attempts")
|
||||
var ticksBetweenSpawnAttempts = 20F
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "minimum_slice_distance_from_player")
|
||||
var minimumSliceDistanceFromPlayer = 16F
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "maximum_slice_distance_from_player")
|
||||
var maximumSliceDistanceFromPlayer = 16 * 4F
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "export_spawn_config")
|
||||
var exportSpawnConfig = false
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "save_pokemon_to_world")
|
||||
var savePokemonToWorld = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
@CobblemonConfigField(Category.Starter, lang = "export_starter_config")
|
||||
var exportStarterConfig = false
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "auto_update_showdown")
|
||||
var autoUpdateShowdown = true
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "default_flee_distance")
|
||||
var defaultFleeDistance = 16F * 2
|
||||
|
||||
@NodeCategory(category = Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "allow_experience_from_pvp")
|
||||
var allowExperienceFromPvP = true
|
||||
|
||||
@NodeCategory(category = Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "experience_share_multiplier")
|
||||
var experienceShareMultiplier = .5
|
||||
|
||||
@NodeCategory(category = Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "lucky_egg_multiplier")
|
||||
var luckyEggMultiplier = 1.5
|
||||
|
||||
@NodeCategory(category = Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "allow_spectating")
|
||||
var allowSpectating = true
|
||||
|
||||
@NodeCategory(category = Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "experience_multiplier")
|
||||
var experienceMultiplier = 2F
|
||||
|
||||
@NodeCategory(category = Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "pokemon_per_chunk")
|
||||
var pokemonPerChunk = 1F
|
||||
|
||||
@NodeCategory(Category.PassiveStatus)
|
||||
@CobblemonConfigField(Category.PassiveStatus, lang = "passive_statuses")
|
||||
var passiveStatuses = mutableMapOf(
|
||||
Statuses.POISON.configEntry(),
|
||||
Statuses.POISON_BADLY.configEntry(),
|
||||
@@ -148,110 +148,124 @@ class CobblemonConfig {
|
||||
Statuses.BURN.configEntry()
|
||||
)
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
@CobblemonConfigField(Category.Healing, lang = "infinite_healer_charge")
|
||||
var infiniteHealerCharge = false
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
@CobblemonConfigField(Category.Healing, lang = "max_healer_charge")
|
||||
var maxHealerCharge = 6.0f
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
var chargeGainedPerTick = 0.000333333f
|
||||
@CobblemonConfigField(Category.Healing, lang = "seconds_to_charge_healing_machine")
|
||||
var secondsToChargeHealingMachine = 900.0
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
@CobblemonConfigField(Category.Healing, lang = "default_faint_timer")
|
||||
var defaultFaintTimer = 300
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
@CobblemonConfigField(Category.Healing, lang = "faint_awaken_health_percent")
|
||||
var faintAwakenHealthPercent = 0.2f
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
@CobblemonConfigField(Category.Healing, lang = "heal_percent")
|
||||
var healPercent = 0.05
|
||||
|
||||
@NodeCategory(Category.Healing)
|
||||
@CobblemonConfigField(Category.Healing, lang = "heal_timer")
|
||||
var healTimer = 60
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "base_apricorn_tree_generation_chance")
|
||||
var baseApricornTreeGenerationChance = 0.1F
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "display_entity_level_label")
|
||||
var displayEntityLevelLabel = true
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "display_entity_name_label")
|
||||
var displayEntityNameLabel = true
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "display_name_for_unknown_pokemon")
|
||||
var displayNameForUnknownPokemon = false
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
var displayEntityLabelsWhenCrouchingOnly = false
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "display_entity_labels_when_crouching_only")
|
||||
var displayEntityLabelsWhenCrouchingOnly = true
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "shiny_rate")
|
||||
var shinyRate = 8192F
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
val shinyNoticeParticlesDistance = 24F
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "shiny_notice_particles_distance")
|
||||
var shinyNoticeParticlesDistance = 24F
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "capture_calculator")
|
||||
var captureCalculator: CaptureCalculator = CobblemonCaptureCalculator
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "player_damage_pokemon")
|
||||
var playerDamagePokemon = true
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "apple_leftovers_chance")
|
||||
var appleLeftoversChance = 0.025
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "max_roots_in_area")
|
||||
var maxRootsInArea = 5
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "big_root_propagation_chance")
|
||||
var bigRootPropagationChance = 0.1
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "energy_root_chance")
|
||||
var energyRootChance = 0.25
|
||||
|
||||
@NodeCategory(Category.Pokemon)
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "max_dynamax_level")
|
||||
@IntConstraint(min = 0, max = 10)
|
||||
var maxDynamaxLevel = 10
|
||||
|
||||
@NodeCategory(Category.Spawning)
|
||||
@CobblemonConfigField(Category.Spawning, lang = "tera_type_rate")
|
||||
var teraTypeRate = 20F
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "default_pastured_pokemon_limit")
|
||||
var defaultPasturedPokemonLimit = 16
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "pasture_block_update_ticks")
|
||||
var pastureBlockUpdateTicks = 40
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "pasture_max_wander_distance")
|
||||
var pastureMaxWanderDistance = 64
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "pasture_max_per_chunk")
|
||||
var pastureMaxPerChunk = 4F
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "max_inserted_fossil_items")
|
||||
var maxInsertedFossilItems = 2
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "walking_in_battle_animations")
|
||||
var walkingInBattleAnimations = false
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "battle_wild_max_distance")
|
||||
var battleWildMaxDistance = 12F
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
@CobblemonConfigField(Category.World, lang = "trade_max_distance")
|
||||
var tradeMaxDistance = 12F
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "battle_pvp_max_distance")
|
||||
@SerializedName("battlePvPMaxDistance", alternate = ["BattlePvPMaxDistance"])
|
||||
var battlePvPMaxDistance = 32F
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
@CobblemonConfigField(Category.Battles, lang = "battle_spectate_max_distance")
|
||||
var battleSpectateMaxDistance = 64F
|
||||
|
||||
@NodeCategory(Category.Pokedex)
|
||||
@CobblemonConfigField(Category.Pokedex, lang = "max_pokedex_scanning_detection_range")
|
||||
var maxPokedexScanningDetectionRange = 10.0
|
||||
|
||||
@NodeCategory(Category.Pokedex)
|
||||
@CobblemonConfigField(Category.Pokedex, lang = "hide_unimplemented_pokemon_in_the_pokedex")
|
||||
var hideUnimplementedPokemonInThePokedex = false
|
||||
|
||||
@NodeCategory(Category.Debug)
|
||||
@CobblemonConfigField(Category.Debug, lang = "enable_debug_keys")
|
||||
var enableDebugKeys = false
|
||||
|
||||
fun clone(): CobblemonConfig {
|
||||
val newConfig = CobblemonConfig()
|
||||
CobblemonConfig::class.memberProperties.forEach { property ->
|
||||
if (property is kotlin.reflect.KMutableProperty<*>) {
|
||||
property.isAccessible = true
|
||||
val value = property.getter.call(this)
|
||||
if (value != null) {
|
||||
property.setter.call(newConfig, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return newConfig
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.config
|
||||
|
||||
@Target(AnnotationTarget.FIELD)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class NodeCategory(
|
||||
val category: Category
|
||||
annotation class CobblemonConfigField(
|
||||
val category: Category,
|
||||
val lang: String,
|
||||
)
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.config.constraint
|
||||
|
||||
@Target(AnnotationTarget.FIELD)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class IntConstraint(
|
||||
val min : Int,
|
||||
val max : Int
|
||||
|
||||
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.config.starter
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.config.Category
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.NodeCategory
|
||||
import com.cobblemon.mod.common.config.CobblemonConfigField
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.google.gson.GsonBuilder
|
||||
|
||||
@@ -24,14 +24,14 @@ class StarterConfig {
|
||||
.create()
|
||||
}
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
@CobblemonConfigField(Category.Starter, lang = "allow_starter_on_join")
|
||||
var allowStarterOnJoin = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
@CobblemonConfigField(Category.Starter, lang = "prompt_starter_once_only")
|
||||
@LastChangedVersion("1.5.0")
|
||||
var promptStarterOnceOnly = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
@CobblemonConfigField(Category.Starter, lang = "starters")
|
||||
var starters = mutableListOf(
|
||||
StarterCategory(
|
||||
name = "Kanto",
|
||||
|
||||
+3
-4
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMechanics
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.ItemEvSource
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -44,10 +45,8 @@ class FriendshipRaisingBerryItem(block: BerryBlock, val stat: Stat) : BerryItem(
|
||||
|
||||
val increasedFriendship = pokemon.incrementFriendship(friendshipRaiseAmount)
|
||||
|
||||
val currentStat = pokemon.evs.getOrDefault(stat)
|
||||
val newEV = max(currentStat - genericRuntime.resolveInt(CobblemonMechanics.berries.evLowerAmount), 0)
|
||||
pokemon.setEV(stat, newEV)
|
||||
val decreasedEVs = currentStat != pokemon.evs.getOrDefault(stat)
|
||||
val evLowerAmount = max(genericRuntime.resolveInt(CobblemonMechanics.berries.evLowerAmount), 0)
|
||||
val decreasedEVs = pokemon.evs.add(stat, evLowerAmount, ItemEvSource(player, stack, pokemon)) != 0
|
||||
|
||||
return if (increasedFriendship || decreasedEVs) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.item.interactive
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.ItemEvSource
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.pokemon.EVs
|
||||
@@ -35,7 +36,7 @@ class FeatherItem(val stat: Stat) : CobblemonItem(Properties()), PokemonSelectin
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack> {
|
||||
val evsGained = pokemon.evs.add(stat, EV_YIELD)
|
||||
val evsGained = pokemon.evs.add(stat, EV_YIELD, ItemEvSource(player, stack, pokemon))
|
||||
return if (evsGained > 0) {
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_FEATHER_USE, 1F, 1F)
|
||||
if (!player.isCreative) {
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.item.interactive
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.ItemEvSource
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.pokemon.EVs
|
||||
@@ -35,7 +36,7 @@ class VitaminItem(val stat: Stat) : CobblemonItem(Properties()), PokemonSelectin
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack> {
|
||||
val evsGained = pokemon.evs.add(stat, EV_YIELD)
|
||||
val evsGained = pokemon.evs.add(stat, EV_YIELD, ItemEvSource(player, stack, pokemon))
|
||||
return if (evsGained > 0) {
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_PILLS_USE, 1F, 1F)
|
||||
if (!player.isCreative) {
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.settings
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class OpenCobblemonConfigScreenPacket: NetworkPacket<OpenCobblemonConfigScreenPacket> {
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("open_cobblemon_config_screen")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = OpenCobblemonConfigScreenPacket()
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@ import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
* @author Hiroku
|
||||
* @since June 20th, 2022
|
||||
*/
|
||||
class OpenPCPacket(val storeID: UUID, val box: Int = 1) : NetworkPacket<OpenPCPacket> {
|
||||
class OpenPCPacket(val storeID: UUID, val box: Int = 0) : NetworkPacket<OpenPCPacket> {
|
||||
|
||||
override val id = ID
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
package com.cobblemon.mod.common.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.EvGainedEvent
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.EvSource
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
@@ -35,19 +38,50 @@ class EVs : PokemonStats() {
|
||||
* @param value The amount to attempt to add, this wil safely be coerced to the highest possible value.
|
||||
* @return The amount added or 0 if the addition was impossible.
|
||||
*/
|
||||
@Deprecated(
|
||||
message = "Please update to modern API",
|
||||
replaceWith = ReplaceWith("add(key, value, source)", "com.cobblemon.mod.common.api.pokemon.stats.Stat", "com.cobblemon.mod.common.api.pokemon.stats.EvSource"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
fun add(key: Stat, value: Int): Int {
|
||||
return this.performAdd(key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely adds the given amount of EVs to this store.
|
||||
*
|
||||
* @param key The [Stat] being mutated.
|
||||
* @param value The amount to attempt to add, this wil safely be coerced to the highest possible value.
|
||||
* @param source The [EvSource] of this addition.
|
||||
* @return The amount added or 0 if the addition was impossible.
|
||||
*/
|
||||
fun add(key: Stat, value: Int, source: EvSource): Int {
|
||||
CobblemonEvents.EV_GAINED_EVENT_PRE.postThen(
|
||||
event = EvGainedEvent.Pre(key, value, source),
|
||||
ifCanceled = { return 0 },
|
||||
ifSucceeded = { event ->
|
||||
val result = this.performAdd(event.stat, event.amount)
|
||||
CobblemonEvents.EV_GAINED_EVENT_POST.post(EvGainedEvent.Post(key, result, source))
|
||||
return result
|
||||
}
|
||||
)
|
||||
// This never runs, just the impl of the observables doesn't allow us to infer the actual return
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun performAdd(stat: Stat, value: Int): Int {
|
||||
val currentTotal = this.sumOf { it.value }
|
||||
if (currentTotal == MAX_TOTAL_VALUE && value > 0) {
|
||||
return 0
|
||||
}
|
||||
val currentStat = this.getOrDefault(key)
|
||||
val currentStat = this.getOrDefault(stat)
|
||||
val possibleForStat = MAX_STAT_VALUE - currentStat
|
||||
val possibleForTotal = MAX_TOTAL_VALUE - currentTotal
|
||||
val coercedValue = value.coerceIn(-currentStat, min(possibleForStat, possibleForTotal))
|
||||
val newValue = currentStat + coercedValue
|
||||
// avoid unnecessary updates
|
||||
if (newValue != currentStat) {
|
||||
this[key] = newValue
|
||||
this[stat] = newValue
|
||||
return coercedValue
|
||||
}
|
||||
return 0
|
||||
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.egg.idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"egg": {
|
||||
"rotation": [0, 0, 0],
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"body": {
|
||||
"rotation": [0, 0, 0],
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"egg_shell1": {
|
||||
"position": [0, "math.sin(q.anim_time*90+1)", 0]
|
||||
},
|
||||
"egg_shell2": {
|
||||
"position": [0, "math.sin(q.anim_time*90+2)", 0]
|
||||
},
|
||||
"egg_shell3": {
|
||||
"position": [0, "math.sin(q.anim_time*90+3)", 0]
|
||||
},
|
||||
"egg_shell4": {
|
||||
"position": [0, "math.sin(q.anim_time*90+4)", 0]
|
||||
},
|
||||
"egg_shell5": {
|
||||
"position": [0, "math.sin(q.anim_time*90+5)", 0]
|
||||
},
|
||||
"egg_shell6": {
|
||||
"position": [0, "math.sin(q.anim_time*90+6)", 0]
|
||||
},
|
||||
"egg_shell7": {
|
||||
"position": [0, "math.sin(q.anim_time*90+7)", 0]
|
||||
},
|
||||
"egg_shell8": {
|
||||
"position": [0, "math.sin(q.anim_time*90+8)", 0]
|
||||
},
|
||||
"egg_shell9": {
|
||||
"position": [0, "math.sin(q.anim_time*90+9)", 0]
|
||||
},
|
||||
"egg_shell10": {
|
||||
"position": [0, "math.sin(q.anim_time*90+10)", 0]
|
||||
},
|
||||
"egg_shell11": {
|
||||
"position": [0, "math.sin(q.anim_time*90+11)", 0]
|
||||
},
|
||||
"egg_shell12": {
|
||||
"position": [0, "math.sin(q.anim_time*90+12)", 0]
|
||||
},
|
||||
"egg_shell13": {
|
||||
"position": [0, "math.sin(q.anim_time*90+13)", 0]
|
||||
},
|
||||
"egg_shell14": {
|
||||
"position": [0, "math.sin(q.anim_time*90+14)", 0]
|
||||
},
|
||||
"egg_shell15": {
|
||||
"position": [0, "math.sin(q.anim_time*90+15)", 0]
|
||||
},
|
||||
"egg_shell16": {
|
||||
"position": [0, "math.sin(q.anim_time*90+16)", 0]
|
||||
},
|
||||
"egg_shell17": {
|
||||
"position": [0, "math.sin(q.anim_time*90+17)", 0]
|
||||
},
|
||||
"egg_shell18": {
|
||||
"position": [0, "math.sin(q.anim_time*90+18)", 0]
|
||||
},
|
||||
"egg_shell19": {
|
||||
"position": [0, "math.sin(q.anim_time*90+19)", 0]
|
||||
},
|
||||
"egg_shell20": {
|
||||
"position": [0, "math.sin(q.anim_time*90+20)", 0]
|
||||
},
|
||||
"egg_shell21": {
|
||||
"position": [0, "math.sin(q.anim_time*90+21)", 0]
|
||||
},
|
||||
"egg_shell22": {
|
||||
"position": [0, "math.sin(q.anim_time*90+22)", 0]
|
||||
},
|
||||
"egg_shell23": {
|
||||
"position": [0, "math.sin(q.anim_time*90+23)", 0]
|
||||
},
|
||||
"egg_shell24": {
|
||||
"position": [0, "math.sin(q.anim_time*90+24)", 0]
|
||||
},
|
||||
"egg_shell25": {
|
||||
"position": [0, "math.sin(q.anim_time*90+25)", 0]
|
||||
},
|
||||
"egg_shell26": {
|
||||
"position": [0, "math.sin(q.anim_time*90+26)", 0]
|
||||
},
|
||||
"egg_shell27": {
|
||||
"position": [0, "math.sin(q.anim_time*90+27)", 0]
|
||||
},
|
||||
"egg_shell28": {
|
||||
"position": [0, "math.sin(q.anim_time*90+28)", 0]
|
||||
},
|
||||
"egg_shell29": {
|
||||
"position": [0, "math.sin(q.anim_time*90+29)", 0]
|
||||
},
|
||||
"egg_shell30": {
|
||||
"position": [0, "math.sin(q.anim_time*90+30)", 0]
|
||||
},
|
||||
"egg_shell31": {
|
||||
"position": [0, "math.sin(q.anim_time*90+31)", 0]
|
||||
},
|
||||
"egg_shell32": {
|
||||
"position": [0, "math.sin(q.anim_time*90+32)", 0]
|
||||
},
|
||||
"egg_shell33": {
|
||||
"position": [0, "math.sin(q.anim_time*90+33)", 0]
|
||||
},
|
||||
"egg_shell34": {
|
||||
"position": [0, "math.sin(q.anim_time*90+34)", 0]
|
||||
},
|
||||
"egg_shell35": {
|
||||
"position": [0, "math.sin(q.anim_time*90+35)", 0]
|
||||
},
|
||||
"egg_shell36": {
|
||||
"position": [0, "math.sin(q.anim_time*90+36)", 0]
|
||||
},
|
||||
"egg_shell37": {
|
||||
"position": [0, "math.sin(q.anim_time*90+37)", 0]
|
||||
},
|
||||
"egg_shell38": {
|
||||
"position": [0, "math.sin(q.anim_time*90+38)", 0]
|
||||
},
|
||||
"egg_shell39": {
|
||||
"position": [0, "math.sin(q.anim_time*90+39)", 0]
|
||||
},
|
||||
"egg_shell40": {
|
||||
"position": [0, "math.sin(q.anim_time*90+40)", 0]
|
||||
},
|
||||
"egg_shell41": {
|
||||
"position": [0, "math.sin(q.anim_time*90+41)", 0]
|
||||
},
|
||||
"egg_shell42": {
|
||||
"position": [0, "math.sin(q.anim_time*90+42)", 0]
|
||||
},
|
||||
"egg_shell43": {
|
||||
"position": [0, "math.sin(q.anim_time*90+43)", 0]
|
||||
},
|
||||
"egg_shell44": {
|
||||
"position": [0, "math.sin(q.anim_time*90+44)", 0]
|
||||
},
|
||||
"egg_shell45": {
|
||||
"position": [0, "math.sin(q.anim_time*90+45)", 0]
|
||||
},
|
||||
"egg_shell46": {
|
||||
"position": [0, "math.sin(q.anim_time*90+46)", 0]
|
||||
},
|
||||
"egg_shell47": {
|
||||
"position": [0, "math.sin(q.anim_time*90+47)", 0]
|
||||
},
|
||||
"egg_shell48": {
|
||||
"position": [0, "math.sin(q.anim_time*90+48)", 0]
|
||||
},
|
||||
"egg_shell49": {
|
||||
"position": [0, "math.sin(q.anim_time*90+49)", 0]
|
||||
},
|
||||
"egg_shell50": {
|
||||
"position": [0, "math.sin(q.anim_time*90+50)", 0]
|
||||
},
|
||||
"egg_shell51": {
|
||||
"position": [0, "math.sin(q.anim_time*90+51)", 0]
|
||||
},
|
||||
"egg_shell52": {
|
||||
"position": [0, "math.sin(q.anim_time*90+52)", 0]
|
||||
},
|
||||
"egg_shell53": {
|
||||
"position": [0, "math.sin(q.anim_time*90+53)", 0]
|
||||
},
|
||||
"egg_shell54": {
|
||||
"position": [0, "math.sin(q.anim_time*90+54)", 0]
|
||||
},
|
||||
"egg_shell55": {
|
||||
"position": [0, "math.sin(q.anim_time*90+55)", 0]
|
||||
},
|
||||
"egg_shell56": {
|
||||
"position": [0, "math.sin(q.anim_time*90+56)", 0]
|
||||
},
|
||||
"egg_shell57": {
|
||||
"position": [0, "math.sin(q.anim_time*90+57)", 0]
|
||||
},
|
||||
"egg_shell58": {
|
||||
"position": [0, "math.sin(q.anim_time*90+58)", 0]
|
||||
},
|
||||
"egg_shell59": {
|
||||
"position": [0, "math.sin(q.anim_time*90+59)", 0]
|
||||
},
|
||||
"egg_shell60": {
|
||||
"position": [0, "math.sin(q.anim_time*90+60)", 0]
|
||||
},
|
||||
"egg_shell61": {
|
||||
"position": [0, "math.sin(q.anim_time*90+61)", 0]
|
||||
},
|
||||
"egg_shell62": {
|
||||
"position": [0, "math.sin(q.anim_time*90+62)", 0]
|
||||
},
|
||||
"egg_shell63": {
|
||||
"position": [0, "math.sin(q.anim_time*90+63)", 0]
|
||||
},
|
||||
"egg_shell64": {
|
||||
"position": [0, "math.sin(q.anim_time*90+64)", 0]
|
||||
},
|
||||
"egg_shell65": {
|
||||
"position": [0, "math.sin(q.anim_time*90+65)", 0]
|
||||
},
|
||||
"egg_shell66": {
|
||||
"position": [0, "math.sin(q.anim_time*90+66)", 0]
|
||||
},
|
||||
"egg_shell67": {
|
||||
"position": [0, "math.sin(q.anim_time*90+67)", 0]
|
||||
},
|
||||
"egg_shell68": {
|
||||
"position": [0, "math.sin(q.anim_time*90+68)", 0]
|
||||
},
|
||||
"egg_shell69": {
|
||||
"position": [0, "math.sin(q.anim_time*90+69)", 0]
|
||||
},
|
||||
"egg_shell70": {
|
||||
"position": [0, "math.sin(q.anim_time*90+70)", 0]
|
||||
},
|
||||
"egg_shell71": {
|
||||
"position": [0, "math.sin(q.anim_time*90+71)", 0]
|
||||
},
|
||||
"egg_shell72": {
|
||||
"position": [0, "math.sin(q.anim_time*90+72)", 0]
|
||||
},
|
||||
"egg_shell73": {
|
||||
"position": [0, "math.sin(q.anim_time*90+73)", 0]
|
||||
},
|
||||
"egg_shell74": {
|
||||
"position": [0, "math.sin(q.anim_time*90+74)", 0]
|
||||
},
|
||||
"egg_shell75": {
|
||||
"position": [0, "math.sin(q.anim_time*90+75)", 0]
|
||||
},
|
||||
"egg_shell76": {
|
||||
"position": [0, "math.sin(q.anim_time*90+76)", 0]
|
||||
},
|
||||
"egg_shell77": {
|
||||
"position": [0, "math.sin(q.anim_time*90+77)", 0]
|
||||
},
|
||||
"egg_shell78": {
|
||||
"position": [0, "math.sin(q.anim_time*90+78)", 0]
|
||||
},
|
||||
"egg_shell79": {
|
||||
"position": [0, "math.sin(q.anim_time*90+79)", 0]
|
||||
},
|
||||
"egg_shell80": {
|
||||
"position": [0, "math.sin(q.anim_time*90+80)", 0]
|
||||
},
|
||||
"egg_shell81": {
|
||||
"position": [0, "math.sin(q.anim_time*90+81)", 0]
|
||||
},
|
||||
"egg_shell82": {
|
||||
"position": [0, "math.sin(q.anim_time*90+82)", 0]
|
||||
},
|
||||
"egg_shell83": {
|
||||
"position": [0, "math.sin(q.anim_time*90+83)", 0]
|
||||
},
|
||||
"egg_shell84": {
|
||||
"position": [0, "math.sin(q.anim_time*90+84)", 0]
|
||||
},
|
||||
"egg_shell85": {
|
||||
"position": [0, "math.sin(q.anim_time*90+85)", 0]
|
||||
},
|
||||
"egg_shell86": {
|
||||
"position": [0, "math.sin(q.anim_time*90+86)", 0]
|
||||
},
|
||||
"egg_shell87": {
|
||||
"position": [0, "math.sin(q.anim_time*90+87)", 0]
|
||||
},
|
||||
"egg_shell88": {
|
||||
"position": [0, "math.sin(q.anim_time*90+88)", 0]
|
||||
},
|
||||
"egg_shell89": {
|
||||
"position": [0, "math.sin(q.anim_time*90+89)", 0]
|
||||
},
|
||||
"egg_shell90": {
|
||||
"position": [0, "math.sin(q.anim_time*90+90)", 0]
|
||||
},
|
||||
"egg_shell91": {
|
||||
"position": [0, "math.sin(q.anim_time*90+91)", 0]
|
||||
},
|
||||
"egg_shell92": {
|
||||
"position": [0, "math.sin(q.anim_time*90+92)", 0]
|
||||
},
|
||||
"egg_shell93": {
|
||||
"position": [0, "math.sin(q.anim_time*90+93)", 0]
|
||||
},
|
||||
"egg_shell94": {
|
||||
"position": [0, "math.sin(q.anim_time*90+94)", 0]
|
||||
},
|
||||
"egg_shell95": {
|
||||
"position": [0, "math.sin(q.anim_time*90+95)", 0]
|
||||
},
|
||||
"egg_shell96": {
|
||||
"position": [0, "math.sin(q.anim_time*90+96)", 0]
|
||||
},
|
||||
"egg_shell97": {
|
||||
"position": [0, "math.sin(q.anim_time*90+97)", 0]
|
||||
},
|
||||
"egg_shell98": {
|
||||
"position": [0, "math.sin(q.anim_time*90+98)", 0]
|
||||
},
|
||||
"egg_shell99": {
|
||||
"position": [0, "math.sin(q.anim_time*90+99)", 0]
|
||||
},
|
||||
"egg_shell100": {
|
||||
"position": [0, "math.sin(q.anim_time*90+100)", 0]
|
||||
},
|
||||
"egg_shell105": {
|
||||
"position": [0, "math.sin(q.anim_time*90+105+1)", 0]
|
||||
},
|
||||
"egg_shell106": {
|
||||
"position": [0, "math.sin(q.anim_time*90+106+1)", 0]
|
||||
},
|
||||
"egg_shell107": {
|
||||
"position": [0, "math.sin(q.anim_time*90+107+1)", 0]
|
||||
},
|
||||
"egg_shell108": {
|
||||
"position": [0, "math.sin(q.anim_time*90+108+1)", 0]
|
||||
},
|
||||
"egg_shell109": {
|
||||
"position": [0, "math.sin(q.anim_time*90+109+1)", 0]
|
||||
},
|
||||
"egg_shell110": {
|
||||
"position": [0, "math.sin(q.anim_time*90+110+1)", 0]
|
||||
},
|
||||
"egg_shell111": {
|
||||
"position": [0, "math.sin(q.anim_time*90+111+1)", 0]
|
||||
},
|
||||
"egg_shell112": {
|
||||
"position": [0, "math.sin(q.anim_time*90+112+1)", 0]
|
||||
},
|
||||
"egg_shell113": {
|
||||
"position": [0, "math.sin(q.anim_time*90+113+1)", 0]
|
||||
},
|
||||
"egg_shell114": {
|
||||
"position": [0, "math.sin(q.anim_time*90+114+1)", 0]
|
||||
},
|
||||
"egg_shell115": {
|
||||
"position": [0, "math.sin(q.anim_time*90+115+1)", 0]
|
||||
},
|
||||
"egg_shell116": {
|
||||
"position": [0, "math.sin(q.anim_time*90+116+1)", 0]
|
||||
},
|
||||
"egg_shell117": {
|
||||
"position": [0, "math.sin(q.anim_time*90+117+1)", 0]
|
||||
},
|
||||
"egg_shell118": {
|
||||
"position": [0, "math.sin(q.anim_time*90+118+1)", 0]
|
||||
},
|
||||
"egg_shell119": {
|
||||
"position": [0, "math.sin(q.anim_time*90+119+1)", 0]
|
||||
},
|
||||
"egg_shell120": {
|
||||
"position": [0, "math.sin(q.anim_time*90+120+1)", 0]
|
||||
},
|
||||
"egg_shell121": {
|
||||
"position": [0, "math.sin(q.anim_time*90+121+1)", 0]
|
||||
},
|
||||
"egg_shell123": {
|
||||
"position": [0, "math.sin(q.anim_time*90+123+1)", 0]
|
||||
},
|
||||
"egg_shell124": {
|
||||
"position": [0, "math.sin(q.anim_time*90+124+1)", 0]
|
||||
},
|
||||
"egg_shell125": {
|
||||
"position": [0, "math.sin(q.anim_time*90+125+1)", 0]
|
||||
},
|
||||
"egg_shell126": {
|
||||
"position": [0, "math.sin(q.anim_time*90+126+1)", 0]
|
||||
},
|
||||
"egg_shell127": {
|
||||
"position": [0, "math.sin(q.anim_time*90+127+1)", 0]
|
||||
},
|
||||
"egg_shell128": {
|
||||
"position": [0, "math.sin(q.anim_time*90+128+1)", 0]
|
||||
},
|
||||
"egg_shell129": {
|
||||
"position": [0, "math.sin(q.anim_time*90+129+1)", 0]
|
||||
},
|
||||
"egg_shell130": {
|
||||
"position": [0, "math.sin(q.anim_time*90+130+1)", 0]
|
||||
},
|
||||
"egg_shell131": {
|
||||
"position": [0, "math.sin(q.anim_time*90+131+1)", 0]
|
||||
},
|
||||
"egg_shell132": {
|
||||
"position": [0, "math.sin(q.anim_time*90+132+1)", 0]
|
||||
},
|
||||
"egg_shell133": {
|
||||
"position": [0, "math.sin(q.anim_time*90+133+1)", 0]
|
||||
},
|
||||
"egg_shell134": {
|
||||
"position": [0, "math.sin(q.anim_time*90+134+1)", 0]
|
||||
},
|
||||
"egg_shell135": {
|
||||
"position": [0, "math.sin(q.anim_time*90+135+1)", 0]
|
||||
},
|
||||
"egg_shell136": {
|
||||
"position": [0, "math.sin(q.anim_time*90+136+1)", 0]
|
||||
},
|
||||
"egg_shell137": {
|
||||
"position": [0, "math.sin(q.anim_time*90+137+1)", 0]
|
||||
},
|
||||
"egg_shell138": {
|
||||
"position": [0, "math.sin(q.anim_time*90+138+1)", 0]
|
||||
},
|
||||
"egg_shell139": {
|
||||
"position": [0, "math.sin(q.anim_time*90+139+1)", 0]
|
||||
},
|
||||
"egg_shell140": {
|
||||
"position": [0, "math.sin(q.anim_time*90+140+1)", 0]
|
||||
},
|
||||
"egg_shell141": {
|
||||
"position": [0, "math.sin(q.anim_time*90+141+1)", 0]
|
||||
},
|
||||
"egg_shell142": {
|
||||
"position": [0, "math.sin(q.anim_time*90+142+1)", 0]
|
||||
},
|
||||
"egg_shell143": {
|
||||
"position": [0, "math.sin(q.anim_time*90+143+1)", 0]
|
||||
},
|
||||
"egg_shell144": {
|
||||
"position": [0, "math.sin(q.anim_time*90+144+1)", 0]
|
||||
},
|
||||
"egg_shell145": {
|
||||
"position": [0, "math.sin(q.anim_time*90+145+1)", 0]
|
||||
},
|
||||
"egg_shell146": {
|
||||
"position": [0, "math.sin(q.anim_time*90+146+1)", 0]
|
||||
},
|
||||
"egg_shell147": {
|
||||
"position": [0, "math.sin(q.anim_time*90+147+1)", 0]
|
||||
},
|
||||
"egg_shell148": {
|
||||
"position": [0, "math.sin(q.anim_time*90+148+1)", 0]
|
||||
},
|
||||
"egg_shell149": {
|
||||
"position": [0, "math.sin(q.anim_time*90+149+1)", 0]
|
||||
},
|
||||
"egg_shell150": {
|
||||
"position": [0, "math.sin(q.anim_time*90+150+1)", 0]
|
||||
},
|
||||
"egg_shell151": {
|
||||
"position": [0, "math.sin(q.anim_time*90+151+1)", 0]
|
||||
},
|
||||
"egg_shell152": {
|
||||
"position": [0, "math.sin(q.anim_time*90+152+1)", 0]
|
||||
},
|
||||
"egg_shell153": {
|
||||
"position": [0, "math.sin(q.anim_time*90+153+1)", 0]
|
||||
},
|
||||
"egg_shell154": {
|
||||
"position": [0, "math.sin(q.anim_time*90+154+1)", 0]
|
||||
},
|
||||
"egg_shell155": {
|
||||
"position": [0, "math.sin(q.anim_time*90+155+1)", 0]
|
||||
},
|
||||
"egg_shell156": {
|
||||
"position": [0, "math.sin(q.anim_time*90+156+1)", 0]
|
||||
},
|
||||
"egg_shell157": {
|
||||
"position": [0, "math.sin(q.anim_time*90+157+1)", 0]
|
||||
},
|
||||
"egg_shell158": {
|
||||
"position": [0, "math.sin(q.anim_time*90+158+1)", 0]
|
||||
},
|
||||
"egg_shell159": {
|
||||
"position": [0, "math.sin(q.anim_time*90+159+1)", 0]
|
||||
},
|
||||
"egg_shell160": {
|
||||
"position": [0, "math.sin(q.anim_time*90+160+1)", 0]
|
||||
},
|
||||
"egg_shell161": {
|
||||
"position": [0, "math.sin(q.anim_time*90+161+1)", 0]
|
||||
},
|
||||
"egg_shell162": {
|
||||
"position": [0, "math.sin(q.anim_time*90+162+1)", 0]
|
||||
},
|
||||
"egg_shell163": {
|
||||
"position": [0, "math.sin(q.anim_time*90+163+1)", 0]
|
||||
},
|
||||
"egg_shell164": {
|
||||
"position": [0, "math.sin(q.anim_time*90+164+1)", 0]
|
||||
},
|
||||
"egg_shell165": {
|
||||
"position": [0, "math.sin(q.anim_time*90+165+1)", 0]
|
||||
},
|
||||
"egg_shell166": {
|
||||
"position": [0, "math.sin(q.anim_time*90+166+1)", 0]
|
||||
},
|
||||
"egg_shell167": {
|
||||
"position": [0, "math.sin(q.anim_time*90+167+1)", 0]
|
||||
},
|
||||
"egg_shell168": {
|
||||
"position": [0, "math.sin(q.anim_time*90+168+1)", 0]
|
||||
},
|
||||
"egg_shell169": {
|
||||
"position": [0, "math.sin(q.anim_time*90+169+1)", 0]
|
||||
},
|
||||
"egg_shell170": {
|
||||
"position": [0, "math.sin(q.anim_time*90+170+1)", 0]
|
||||
},
|
||||
"egg_shell171": {
|
||||
"position": [0, "math.sin(q.anim_time*90+171+1)", 0]
|
||||
},
|
||||
"egg_shell172": {
|
||||
"position": [0, "math.sin(q.anim_time*90+172+1)", 0]
|
||||
},
|
||||
"egg_shell173": {
|
||||
"position": [0, "math.sin(q.anim_time*90+173+1)", 0]
|
||||
},
|
||||
"egg_shell174": {
|
||||
"position": [0, "math.sin(q.anim_time*90+174+1)", 0]
|
||||
},
|
||||
"egg_shell175": {
|
||||
"position": [0, "math.sin(q.anim_time*90+175+1)", 0]
|
||||
},
|
||||
"egg_shell176": {
|
||||
"position": [0, "math.sin(q.anim_time*90+176+1)", 0]
|
||||
},
|
||||
"egg_shell177": {
|
||||
"position": [0, "math.sin(q.anim_time*90+177+1)", 0]
|
||||
},
|
||||
"egg_shell178": {
|
||||
"position": [0, "math.sin(q.anim_time*90+178+1)", 0]
|
||||
},
|
||||
"egg_shell179": {
|
||||
"position": [0, "math.sin(q.anim_time*90+179+1)", 0]
|
||||
},
|
||||
"egg_shell180": {
|
||||
"position": [0, "math.sin(q.anim_time*90+180+1)", 0]
|
||||
},
|
||||
"egg_shell181": {
|
||||
"position": [0, "math.sin(q.anim_time*90+181+1)", 0]
|
||||
},
|
||||
"egg_shell182": {
|
||||
"position": [0, "math.sin(q.anim_time*90+182+1)", 0]
|
||||
},
|
||||
"egg_shell183": {
|
||||
"position": [0, "math.sin(q.anim_time*90+183+1)", 0]
|
||||
},
|
||||
"egg_shell184": {
|
||||
"position": [0, "math.sin(q.anim_time*90+184+1)", 0]
|
||||
},
|
||||
"egg_shell185": {
|
||||
"position": [0, "math.sin(q.anim_time*90+185+1)", 0]
|
||||
},
|
||||
"egg_body": {
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"egg_body185": {
|
||||
"position": [0, 0, 5]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"model": "q.appendage_model('cobblemon:egg');",
|
||||
"target_locator": "head",
|
||||
"scale": [1.0, 1.0, 1.0],
|
||||
"offset": [0.0, 0, 0.0],
|
||||
"rotation": [0.0, 45.0, 0.0]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"poses": {
|
||||
"standing": {
|
||||
"poseName": "standing",
|
||||
"transformTicks": 0,
|
||||
"poseTypes": ["STAND", "WALK", "SLEEP", "HOVER", "FLY", "FLOAT", "SWIM", "PORTRAIT", "PROFILE"],
|
||||
"animations": [
|
||||
"q.bedrock('egg', 'idle')"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "cobblemon:egg",
|
||||
"order": 0,
|
||||
"variations": [
|
||||
{
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"poser": "cobblemon:egg",
|
||||
"model": "cobblemon:egg.geo",
|
||||
"texture": "cobblemon:textures/appendage/egg.png",
|
||||
"layers": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1528,6 +1528,173 @@
|
||||
"cobblemon.command.pokemonrestart": "Cleared %1$s's party and PC.",
|
||||
"cobblemon.command.freezepokemon.non_pokemon": "You are not looking at a Pokémon.",
|
||||
"cobblemon.command.npcedit.non_npc": "You are not looking at a NPC.",
|
||||
"cobblemon.command.cobblemon_config.reload": "Reloading Cobblemon settings.",
|
||||
|
||||
"cobblemon.config.ui.search_configurations": "Search Configurations",
|
||||
"cobblemon.config.ui.reset": "Reset",
|
||||
"cobblemon.config.ui.error.int_constraint": "The value must be between %1$s and %2$s.",
|
||||
|
||||
"cobblemon.config.ui.category.starter": "Starter",
|
||||
"cobblemon.config.ui.category.pokedex": "Pokédex",
|
||||
"cobblemon.config.ui.category.pokemon": "Pokémon",
|
||||
"cobblemon.config.ui.category.spawning": "Spawning",
|
||||
"cobblemon.config.ui.category.battles": "Battles",
|
||||
"cobblemon.config.ui.category.passive_status": "Passive Status",
|
||||
"cobblemon.config.ui.category.healing": "Healing",
|
||||
"cobblemon.config.ui.category.storage": "Storage",
|
||||
"cobblemon.config.ui.category.world": "World",
|
||||
"cobblemon.config.ui.category.debug": "Debug",
|
||||
|
||||
"cobblemon.config.ui.max_pokemon_level": "Max Pokémon Level",
|
||||
"cobblemon.config.ui.max_pokemon_level.tooltip": "The maximum level Pokémon can get to.",
|
||||
"cobblemon.config.ui.max_pokemon_friendship": "Max Pokémon Friendship",
|
||||
"cobblemon.config.ui.max_pokemon_friendship.tooltip": "The maximum friendship value.",
|
||||
"cobblemon.config.ui.announce_drop_items": "Announce Drop Items",
|
||||
"cobblemon.config.ui.announce_drop_items.tooltip": "Whether to notify the Player of dropped items from defeating wild Pokémon.",
|
||||
"cobblemon.config.ui.default_drop_item_method": "Default Drop Item Method",
|
||||
"cobblemon.config.ui.default_drop_item_method.tooltip": "Defines how items are dropped (entity, player, or inventory).",
|
||||
"cobblemon.config.ui.default_drop_item_method.on_entity": "On Entity",
|
||||
"cobblemon.config.ui.default_drop_item_method.on_entity.tooltip": "Drops the item on the entity that is dying, if it exists. If not, drops at the position parsed into drops.",
|
||||
"cobblemon.config.ui.default_drop_item_method.on_player": "On Player",
|
||||
"cobblemon.config.ui.default_drop_item_method.on_player.tooltip": "Drops the item on the player that caused the drop, if they exist. If not, drops at the position parsed into drops.",
|
||||
"cobblemon.config.ui.default_drop_item_method.to_inventory": "To Inventory",
|
||||
"cobblemon.config.ui.default_drop_item_method.to_inventory.tooltip": "Puts the item in the player's inventory or drops it on the ground if the inventory is full. If the player that caused the drop doesn't exist, it drops at the position parsed into drops.",
|
||||
"cobblemon.config.ui.ambient_pokemon_cry_ticks": "Ambient Pokémon Cry Ticks",
|
||||
"cobblemon.config.ui.ambient_pokemon_cry_ticks.tooltip": "Ticks between Pokémon cries. (Currently unused)",
|
||||
"cobblemon.config.ui.default_box_count": "Default Box Count",
|
||||
"cobblemon.config.ui.default_box_count.tooltip": "The number of boxes available in the PC.",
|
||||
"cobblemon.config.ui.pokemon_save_interval_seconds": "Pokémon Save Interval Seconds",
|
||||
"cobblemon.config.ui.pokemon_save_interval_seconds.tooltip": "Seconds between saving storage data to file. eg Party & PC data.",
|
||||
"cobblemon.config.ui.storage_format": "Storage Format",
|
||||
"cobblemon.config.ui.storage_format.tooltip": "The storage format used for storing Cobblemon data. (nbt/json/mongodb)",
|
||||
"cobblemon.config.ui.prevent_complete_party_deposit": "Prevent Complete Party Deposit",
|
||||
"cobblemon.config.ui.prevent_complete_party_deposit.tooltip": "Whether to prevent Players from depositing their last Party Pokémon into the PC.",
|
||||
"cobblemon.config.ui.mongo_db_connection_string": "MongoDB Connection String",
|
||||
"cobblemon.config.ui.mongodb_connection_string.tooltip": "The database connection string for your MongoDB database for Cobblemon data storage.",
|
||||
"cobblemon.config.ui.mongo_db_database_name": "MongoDB Database Name",
|
||||
"cobblemon.config.ui.mongodb_database_name.tooltip": "The name of the MongoDB for Cobblemon data storage.",
|
||||
"cobblemon.config.ui.max_vertical_correction_blocks": "Max Vertical Correction Blocks",
|
||||
"cobblemon.config.ui.max_vertical_correction_blocks.tooltip": "The maximum number of blocks that can be corrected when choosing a spawning area. The larger this value, the more reliably spawning will work in vertically bumpy terrain such as mountains. Raising this value only has a very small, negative impact on performance.",
|
||||
"cobblemon.config.ui.minimum_level_range_max": "Minimum Level Range Max",
|
||||
"cobblemon.config.ui.minimum_level_range_max.tooltip": "The value considered to be the highest party Pokémon level when a player's party is empty or extremely low level. The higher this value, the higher the levels of Pokémon can be around players with no or very weak Pokémon.",
|
||||
"cobblemon.config.ui.enable_spawning": "Enable Spawning",
|
||||
"cobblemon.config.ui.enable_spawning.tooltip": "Whether to allow Pokémon to spawn.",
|
||||
"cobblemon.config.ui.minimum_distance_between_entities": "Minimum Distance Between Entities",
|
||||
"cobblemon.config.ui.minimum_distance_between_entities.tooltip": "The minimum block distance between spawning Pokémon and existing Entities in the World. This prevents clustered Pokémon spawning.",
|
||||
"cobblemon.config.ui.max_nearby_blocks_horizontal_range": "Max Nearby Blocks Horizontal Range",
|
||||
"cobblemon.config.ui.max_nearby_blocks_horizontal_range.tooltip": "The maximum number of horizontal blocks away that a block can be for it to still be considered 'nearby' in a spawn condition. Lowering this value can slightly improve performance.",
|
||||
"cobblemon.config.ui.max_nearby_blocks_vertical_range": "Max Nearby Blocks Vertical Range",
|
||||
"cobblemon.config.ui.max_nearby_blocks_vertical_range.tooltip": "The maximum number of vertical blocks away that a block can be for it to still be considered 'nearby' in a spawn condition. Lowering this value can slightly improve performance.",
|
||||
"cobblemon.config.ui.max_vertical_space": "Max Vertical Space",
|
||||
"cobblemon.config.ui.max_vertical_space.tooltip": "How far to check above a spawn location to investigate head room. This value exists for performance reasons but should never be less than the largest 'height'/'depth' condition in a spawn file.",
|
||||
"cobblemon.config.ui.world_slice_diameter": "World Slice Diameter",
|
||||
"cobblemon.config.ui.world_slice_diameter.tooltip": "The diameter of the world slices that a spawn action can occur in. When this value is large, there is more reliably frequent spawning at the cost of performance.",
|
||||
"cobblemon.config.ui.world_slice_height": "World Slice Height",
|
||||
"cobblemon.config.ui.world_slice_height.tooltip": "The height of the world slices that a spawn action can occur in. When this value is large, there is more reliably frequent spawning at the cost of performance.",
|
||||
"cobblemon.config.ui.ticks_between_spawn_attempts": "Ticks Between Spawn Attempts",
|
||||
"cobblemon.config.ui.ticks_between_spawn_attempts.tooltip": "The amount of ticks (~20/second) between spawn attempts.",
|
||||
"cobblemon.config.ui.minimum_slice_distance_from_player": "Minimum Slice Distance From Player",
|
||||
"cobblemon.config.ui.minimum_slice_distance_from_player.tooltip": "Minimum amount of blocks from the Player that Pokémon can spawn.",
|
||||
"cobblemon.config.ui.maximum_slice_distance_from_player": "Maximum Slice Distance From Player",
|
||||
"cobblemon.config.ui.maximum_slice_distance_from_player.tooltip": "Maximum amount of blocks from the Player that Pokémon can spawn.",
|
||||
"cobblemon.config.ui.export_spawn_config": "Export Spawn Config",
|
||||
"cobblemon.config.ui.export_spawn_config.tooltip": "Whether to generate the spawn config for more specific spawning settings.",
|
||||
"cobblemon.config.ui.save_pokemon_to_world": "Save Pokémon to World",
|
||||
"cobblemon.config.ui.save_pokemon_to_world.tooltip": "Whether to save Pokémon to the World so they exist after a Chunk/World is reloaded.",
|
||||
"cobblemon.config.ui.export_starter_config": "Export Starter Config",
|
||||
"cobblemon.config.ui.export_starter_config.tooltip": "Whether to generate starter.json for editing the starter list.",
|
||||
"cobblemon.config.ui.auto_update_showdown": "Auto Update Showdown",
|
||||
"cobblemon.config.ui.auto_update_showdown.tooltip": "Whether to automatically update Showdown to the version shipped in the current Cobblemon version.",
|
||||
"cobblemon.config.ui.default_flee_distance": "Default Flee Distance",
|
||||
"cobblemon.config.ui.default_flee_distance.tooltip": "How far away a Player must get to flee a battle (non-PvP). If the value is -1, battles cannot be fled.",
|
||||
"cobblemon.config.ui.allow_experience_from_pvp": "Allow Experience from PvP",
|
||||
"cobblemon.config.ui.allow_experience_from_pvp.tooltip": "Whether to allow Exp. gain from PvP battles.",
|
||||
"cobblemon.config.ui.experience_share_multiplier": "Experience Share Multiplier",
|
||||
"cobblemon.config.ui.experience_share_multiplier.tooltip": "Multiplier of how much of the total Exp is given to a Pokémon holding an Exp. Share.",
|
||||
"cobblemon.config.ui.lucky_egg_multiplier": "Lucky Egg Multiplier",
|
||||
"cobblemon.config.ui.lucky_egg_multiplier.tooltip": "Multiplier of how much of the total Exp is given to a Pokémon holding a Lucky Egg.",
|
||||
"cobblemon.config.ui.allow_spectating": "Allow Spectating",
|
||||
"cobblemon.config.ui.allow_spectating.tooltip": "Whether to allow battles to be spectated.",
|
||||
"cobblemon.config.ui.experience_multiplier": "Experience Multiplier",
|
||||
"cobblemon.config.ui.experience_multiplier.tooltip": "Additional Exp. multiplier for Exp. calculation.",
|
||||
"cobblemon.config.ui.pokemon_per_chunk": "Pokémon per Chunk",
|
||||
"cobblemon.config.ui.pokemon_per_chunk.tooltip": "The amount of Pokémon allowed within a Chunk when spawning.",
|
||||
"cobblemon.config.ui.passive_statuses": "Passive Statuses",
|
||||
"cobblemon.config.ui.passive_statuses.tooltip": "Range of seconds before clearing the status effect. The value is selected randomly from the range each time an effect is applied.",
|
||||
"cobblemon.config.ui.infinite_healer_charge": "Infinite Healer Charge",
|
||||
"cobblemon.config.ui.infinite_healer_charge.tooltip": "Whether Healing Machines have infinite charges to heal Pokémon.",
|
||||
"cobblemon.config.ui.max_healer_charge": "Max Healer Charge",
|
||||
"cobblemon.config.ui.max_healer_charge.tooltip": "The maximum amount of full HP restoration Healing Machines can have. 1 charge is equivalent to a Max Revive, plus PP restoration.",
|
||||
"cobblemon.config.ui.seconds_to_charge_healing_machine": "Seconds to Fully Charge a Healing Machine",
|
||||
"cobblemon.config.ui.seconds_to_charge_healing_machine.tooltip": "The amount of seconds that takes for a Healing Machine to fully charge.",
|
||||
"cobblemon.config.ui.default_faint_timer": "Default Faint Timer",
|
||||
"cobblemon.config.ui.default_faint_timer.tooltip": "How many seconds before reviving a fainted Pokémon.",
|
||||
"cobblemon.config.ui.faint_awaken_health_percent": "Faint Awaken Health Percent",
|
||||
"cobblemon.config.ui.faint_awaken_health_percent.tooltip": "How much HP to restore when defaultFaintTimer is up.",
|
||||
"cobblemon.config.ui.heal_percent": "Heal Percent",
|
||||
"cobblemon.config.ui.heal_percent.tooltip": "How much HP to restore when healTimer is up.",
|
||||
"cobblemon.config.ui.heal_timer": "Heal Timer",
|
||||
"cobblemon.config.ui.heal_timer.tooltip": "How many seconds between HP naturally restoring.",
|
||||
"cobblemon.config.ui.base_apricorn_tree_generation_chance": "Base Apricorn Tree Generation Chance",
|
||||
"cobblemon.config.ui.base_apricorn_tree_generation_chance.tooltip": "Multiplier on biome-based chance for Apricorn trees to spawn during world generation.",
|
||||
"cobblemon.config.ui.display_entity_level_label": "Display Entity Level Label",
|
||||
"cobblemon.config.ui.display_entity_level_label.tooltip": "Whether to display the level above a Pokémon.",
|
||||
"cobblemon.config.ui.display_entity_name_label": "Display Entity Name Label",
|
||||
"cobblemon.config.ui.display_entity_name_label.tooltip": "Whether to display the name above a Pokémon.",
|
||||
"cobblemon.config.ui.display_name_for_unknown_pokemon": "Display Name for Unknown Pokémon",
|
||||
"cobblemon.config.ui.display_name_for_unknown_pokemon.tooltip": "Whether to display the name above a Pokémon if it has not been scanned with the Pokédex yet.",
|
||||
"cobblemon.config.ui.display_entity_labels_when_crouching_only": "Display Entity Labels When Crouching Only",
|
||||
"cobblemon.config.ui.display_entity_labels_when_crouching_only.tooltip": "Whether to display the name above a Pokémon only when crouching or at all times.",
|
||||
"cobblemon.config.ui.shiny_rate": "Shiny Rate",
|
||||
"cobblemon.config.ui.shiny_rate.tooltip": "The chance for a spawned Pokémon to be shiny. If 0 no spawned Pokémon will be shiny. Calculated as 1/x.",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance": "Shiny Notice Particles Distance",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance.tooltip": "The distance at which shiny particles for Pokémon will start appearing.",
|
||||
"cobblemon.config.ui.capture_calculator": "Capture Calculator",
|
||||
"cobblemon.config.ui.capture_calculator.tooltip": "The ID of the capture calculator. Can be added by another mod. If the ID doesn't exist it uses the default capture calculator.",
|
||||
"cobblemon.config.ui.player_damage_pokemon": "Player Damage Pokémon",
|
||||
"cobblemon.config.ui.player_damage_pokemon.tooltip": "Whether Players can attack Pokémon like normal Minecraft entities.",
|
||||
"cobblemon.config.ui.apple_leftovers_chance": "Apple Leftovers Chance",
|
||||
"cobblemon.config.ui.apple_leftovers_chance.tooltip": "The chance to drop Leftovers when a Player eats an item that has #cobblemon:held/leaves_leftovers.",
|
||||
"cobblemon.config.ui.max_roots_in_area": "Max Roots in Area",
|
||||
"cobblemon.config.ui.max_roots_in_area.tooltip": "The maximum number of #cobblemon:roots that can generate within a 8x2x8 sphere.",
|
||||
"cobblemon.config.ui.big_root_propagation_chance": "Big Root Propagation Chance",
|
||||
"cobblemon.config.ui.big_root_propagation_chance.tooltip": "The chance that Big Roots will grow more roots where possible.",
|
||||
"cobblemon.config.ui.energy_root_chance": "Energy Root Chance",
|
||||
"cobblemon.config.ui.energy_root_chance.tooltip": "The chance that a Big Root will grow an Energy Root.",
|
||||
"cobblemon.config.ui.max_dynamax_level": "Max Dynamax Level",
|
||||
"cobblemon.config.ui.max_dynamax_level.tooltip": "The maximum Dynamax level Pokémon can be upgraded to.",
|
||||
"cobblemon.config.ui.tera_type_rate": "Tera Type Rate",
|
||||
"cobblemon.config.ui.tera_type_rate.tooltip": "The chance for a spawned Pokémon to have a Tera type that doesn't match it's typing. Calculated as 1/x.",
|
||||
"cobblemon.config.ui.default_pastured_pokemon_limit": "Default Pastured Pokémon Limit",
|
||||
"cobblemon.config.ui.default_pastured_pokemon_limit.tooltip": "The maximum Pokémon that can be placed in a Pasture block.",
|
||||
"cobblemon.config.ui.pasture_block_update_ticks": "Pasture Block Update Ticks",
|
||||
"cobblemon.config.ui.pasture_block_update_ticks.tooltip": "The number of server ticks between Pasture block updates.",
|
||||
"cobblemon.config.ui.pasture_max_wander_distance": "Pasture Max Wander Distance",
|
||||
"cobblemon.config.ui.pasture_max_wander_distance.tooltip": "The maximum amount of blocks a Pokémon can move from the Pasture block.",
|
||||
"cobblemon.config.ui.pasture_max_per_chunk": "Pasture Max per Chunk",
|
||||
"cobblemon.config.ui.pasture_max_per_chunk.tooltip": "The maximum number of pastured Pokémon that can be sent out in a chunk.",
|
||||
"cobblemon.config.ui.max_inserted_fossil_items": "Max Inserted Fossil Items",
|
||||
"cobblemon.config.ui.max_inserted_fossil_items.tooltip": "The maximum amount of fossils that can be added to the FossilAnalyzer.",
|
||||
"cobblemon.config.ui.walking_in_battle_animations": "Walking in Battle Animations",
|
||||
"cobblemon.config.ui.walking_in_battle_animations.tooltip": "Whether to allow walking animations to play during battle animations.",
|
||||
"cobblemon.config.ui.battle_wild_max_distance": "Battle Wild Max Distance",
|
||||
"cobblemon.config.ui.battle_wild_max_distance.tooltip": "The maximum distance at which wild battles can occur.",
|
||||
"cobblemon.config.ui.trade_max_distance": "Trade Max Distance",
|
||||
"cobblemon.config.ui.trade_max_distance.tooltip": "The maximum distance at which trades are allowed.",
|
||||
"cobblemon.config.ui.battle_pvp_max_distance": "Battle PvP Max Distance",
|
||||
"cobblemon.config.ui.battle_pvp_max_distance.tooltip": "The maximum distance at which PvP battles can occur.",
|
||||
"cobblemon.config.ui.battle_spectate_max_distance": "Battle Spectate Max Distance",
|
||||
"cobblemon.config.ui.battle_spectate_max_distance.tooltip": "The maximum distance at which players can spectate battles.",
|
||||
"cobblemon.config.ui.max_pokedex_scanning_detection_range": "Max Pokédex Scanning Detection Range",
|
||||
"cobblemon.config.ui.max_pokedex_scanning_detection_range.tooltip": "The maximum distance at which the Pokédex can detect and scan Pokémon.",
|
||||
"cobblemon.config.ui.hide_unimplemented_pokemon_in_the_pokedex": "Hide Unimplemented Pokémon in the Pokédex",
|
||||
"cobblemon.config.ui.hide_unimplemented_pokemon_in_the_pokedex.tooltip": "Whether to hide unimplemented Pokémon from the Pokédex.",
|
||||
"cobblemon.config.ui.enable_debug_keys": "Enable Debug Keys",
|
||||
"cobblemon.config.ui.enable_debug_keys.tooltip": "Enables additional commands and chat logging to assist with implementing Pokémon (see the wiki for a list of commands).",
|
||||
|
||||
"cobblemon.config.ui.allow_starter_on_join": "Allow Starter on Join",
|
||||
"cobblemon.config.ui.prompt_starter_once_only": "Prompt Starter Once Only",
|
||||
"cobblemon.config.ui.starters": "Starters",
|
||||
|
||||
"advancements.cobblemon.root": "The World of Cobblemon!",
|
||||
"advancements.cobblemon.root.description": "Choose a starter Pokémon and set out on a new adventure",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 395 B |
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 3.0 KiB |
@@ -8,11 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.SidemodEvSource
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.junit.BootstrapMinecraft
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
@BootstrapMinecraft
|
||||
@@ -34,11 +36,12 @@ internal class EVsKtTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Requires GameTest due to need to access Pokemon")
|
||||
fun `attempt to add an illegal amount of evs`() {
|
||||
val evs = EVs.createEmpty()
|
||||
evs[Stats.HP] = EVs.MAX_STAT_VALUE
|
||||
evs[Stats.ATTACK] = EVs.MAX_STAT_VALUE
|
||||
val added = evs.add(Stats.DEFENCE, 7)
|
||||
val added = evs.add(Stats.DEFENCE, 7, SidemodEvSource("test", Pokemon()))
|
||||
assert(added == 6)
|
||||
}
|
||||
|
||||
@@ -49,9 +52,11 @@ internal class EVsKtTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Requires GameTest due to need to access Pokemon")
|
||||
fun `decrement EVs`() {
|
||||
val evs = EVs.createEmpty()
|
||||
evs[Stats.HP] = EVs.MAX_STAT_VALUE
|
||||
assert(evs.add(Stats.HP, -(EVs.MAX_STAT_VALUE + 1)) == -EVs.MAX_STAT_VALUE)
|
||||
assert(evs.add(Stats.HP, -(EVs.MAX_STAT_VALUE + 1), SidemodEvSource("test", Pokemon())) == -EVs.MAX_STAT_VALUE)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,8 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
<details>
|
||||
<summary><b>Tag:</b> #biome:is_arid</summary>
|
||||
|
||||
- #cobblemon:is_sandy
|
||||
- #cobblemon:is_badlands
|
||||
- #cobblemon:is_desert
|
||||
- #cobblemon:is_savanna
|
||||
|
||||
</details>
|
||||
@@ -1039,15 +1040,164 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:alolan</summary>
|
||||
<summary><b>Tag:</b> #regional:bergmite_hisuibiome</summary>
|
||||
|
||||
- #cobblemon:is_tropical_island
|
||||
- #minecraft:is_beach
|
||||
- #cobblemon:is_freezing
|
||||
- #cobblemon:is_hills
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:cyndaquil_quilava_hisui_bias</summary>
|
||||
<summary><b>Tag:</b> #regional:bergmite_kalosbiome</summary>
|
||||
|
||||
- #cobblemon:is_frozen_ocean
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:cubone_alolabiome</summary>
|
||||
|
||||
- #cobblemon:is_beach
|
||||
- #cobblemon:is_volcanic
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:cubone_kantobiome</summary>
|
||||
|
||||
- #cobblemon:is_arid
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:dartrix_alolabiome</summary>
|
||||
|
||||
- #cobblemon:is_beach
|
||||
- #cobblemon:is_ocean
|
||||
- #cobblemon:is_tropical_island
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:dartrix_hisuibiome</summary>
|
||||
|
||||
- #cobblemon:is_freezing
|
||||
- #cobblemon:is_hills
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:dewott_hisuibiome</summary>
|
||||
|
||||
- #cobblemon:is_coast
|
||||
- #cobblemon:is_cold_ocean
|
||||
- minecraft:snowy_beach
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:dewott_unovabiome</summary>
|
||||
|
||||
- #cobblemon:is_beach
|
||||
- #cobblemon:is_ocean
|
||||
- #cobblemon:is_tropical_island
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:exeggcute_alolabiome</summary>
|
||||
|
||||
- #cobblemon:is_beach
|
||||
- #cobblemon:is_tropical_island
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:exeggcute_kantobiome</summary>
|
||||
|
||||
- #cobblemon:is_jungle
|
||||
- #cobblemon:is_savanna
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:goomy_hisuibiome</summary>
|
||||
|
||||
- #cobblemon:is_dripstone
|
||||
- #cobblemon:is_lush
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:goomy_kalosbiome</summary>
|
||||
|
||||
- #cobblemon:is_overworld
|
||||
- #cobblemon:is_swamp
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:koffing_galarbiome</summary>
|
||||
|
||||
- #cobblemon:is_mushroom
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:koffing_kantobiome</summary>
|
||||
|
||||
- #cobblemon:nether/is_toxic
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:mimejr_galarbiome</summary>
|
||||
|
||||
- #cobblemon:is_freezing
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:mimejr_sinnohbiome</summary>
|
||||
|
||||
- #cobblemon:is_temperate
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:petilil_hisuibiome</summary>
|
||||
|
||||
- #cobblemon:is_freezing
|
||||
- #cobblemon:is_hills
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:petilil_unovabiome</summary>
|
||||
|
||||
- #cobblemon:is_floral
|
||||
- #cobblemon:is_forest
|
||||
- #cobblemon:is_tropical_island
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:pikachu_alolabiome</summary>
|
||||
|
||||
- #cobblemon:is_beach
|
||||
- #cobblemon:is_tropical_island
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:pikachu_kantobiome</summary>
|
||||
|
||||
- #cobblemon:is_forest
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:quilava_hisuibiome</summary>
|
||||
|
||||
- #cobblemon:is_taiga
|
||||
- #cobblemon:nether/is_crimson
|
||||
@@ -1057,60 +1207,62 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:lilligant_unovan</summary>
|
||||
<summary><b>Tag:</b> #regional:quilava_johtobiome</summary>
|
||||
|
||||
- #cobblemon:is_temperate
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:rufflet_hisuibiome</summary>
|
||||
|
||||
- #cobblemon:is_freezing
|
||||
- #cobblemon:is_hills
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional:rufflet_unovabiome</summary>
|
||||
|
||||
- #cobblemon:is_temperate
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:archipelago</summary>
|
||||
|
||||
- #cobblemon:is_mushroom
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:archipelago_anti</summary>
|
||||
|
||||
- #cobblemon:is_magical
|
||||
- #cobblemon:is_spooky
|
||||
- #cobblemon:is_swamp
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:continental</summary>
|
||||
|
||||
- #cobblemon:is_plains
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:continental_anti</summary>
|
||||
|
||||
- #cobblemon:is_floral
|
||||
- #cobblemon:is_forest
|
||||
- #cobblemon:is_tropical_island
|
||||
- #cobblemon:is_mushroom
|
||||
- #cobblemon:is_savanna
|
||||
- minecraft:sunflower_plains
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:oshawott_dewott_hisui_bias</summary>
|
||||
|
||||
- #c:stony_shores
|
||||
- minecraft:snowy_beach
|
||||
- minecraft:stony_shore
|
||||
- terralith:basalt_cliffs
|
||||
- terralith:granite_cliffs
|
||||
- terralith:white_cliffs
|
||||
- wythers:calcite_coast
|
||||
- wythers:cold_island
|
||||
- wythers:cold_stony_shore
|
||||
- wythers:deepslate_shore
|
||||
- wythers:frigid_island
|
||||
- wythers:frozen_island
|
||||
- wythers:gravelly_beach
|
||||
- wythers:icy_shore
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:rowlet_dartrix_alolan</summary>
|
||||
|
||||
- #cobblemon:is_forest
|
||||
- #cobblemon:is_taiga
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:rowlet_dartrix_hisui_bias</summary>
|
||||
|
||||
- #cobblemon:is_snowy_forest
|
||||
- #cobblemon:is_snowy_taiga
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:sliggoo_hisuian</summary>
|
||||
|
||||
- #cobblemon:is_dripstone
|
||||
- #cobblemon:is_lush
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:vivillon_elegant</summary>
|
||||
<summary><b>Tag:</b> #vivillon:elegant</summary>
|
||||
|
||||
- #cobblemon:is_magical
|
||||
- #cobblemon:is_spooky
|
||||
@@ -1118,7 +1270,123 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:vivillon_monsoon</summary>
|
||||
<summary><b>Tag:</b> #vivillon:elegant_anti</summary>
|
||||
|
||||
- #cobblemon:is_mountain
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:fancy</summary>
|
||||
|
||||
- #cobblemon:is_cherry_blossom
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:forsaken</summary>
|
||||
|
||||
- #cobblemon:is_deep_dark
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:garden</summary>
|
||||
|
||||
- #cobblemon:is_forest
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:garden_anti</summary>
|
||||
|
||||
- #cobblemon:is_cherry_blossom
|
||||
- #cobblemon:is_floral
|
||||
- #cobblemon:is_jungle
|
||||
- #cobblemon:is_magical
|
||||
- #cobblemon:is_mountain
|
||||
- #cobblemon:is_mushroom
|
||||
- #cobblemon:is_plains
|
||||
- #cobblemon:is_spooky
|
||||
- #cobblemon:is_swamp
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:high_plains</summary>
|
||||
|
||||
- #cobblemon:is_badlands
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:icy_snow</summary>
|
||||
|
||||
- #cobblemon:is_taiga
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:icy_snow_anti</summary>
|
||||
|
||||
- #cobblemon:is_mountain
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:inferno</summary>
|
||||
|
||||
- #minecraft:is_nether
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:jungle</summary>
|
||||
|
||||
- #cobblemon:is_jungle
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:jungle_anti</summary>
|
||||
|
||||
- #cobblemon:is_mountain
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:marine</summary>
|
||||
|
||||
- #cobblemon:is_ocean
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:marine_anti</summary>
|
||||
|
||||
- #cobblemon:is_frozen_ocean
|
||||
- #cobblemon:is_warm_ocean
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:meadow</summary>
|
||||
|
||||
- #cobblemon:is_floral
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:meadow_anti</summary>
|
||||
|
||||
- #cobblemon:is_cherry_blossom
|
||||
- #cobblemon:is_magical
|
||||
- minecraft:sunflower_plains
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:monsoon</summary>
|
||||
|
||||
- #cobblemon:is_mountain
|
||||
- #cobblemon:is_peak
|
||||
@@ -1126,7 +1394,18 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:vivillon_ocean</summary>
|
||||
<summary><b>Tag:</b> #vivillon:monsoon_anti</summary>
|
||||
|
||||
- #cobblemon:is_badlands
|
||||
- #cobblemon:is_desert
|
||||
- #cobblemon:is_floral
|
||||
- #cobblemon:is_mushroom
|
||||
- #cobblemon:is_tropical_island
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:ocean</summary>
|
||||
|
||||
- #cobblemon:is_coast
|
||||
- #cobblemon:is_warm_ocean
|
||||
@@ -1134,7 +1413,24 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:vivillon_river</summary>
|
||||
<summary><b>Tag:</b> #vivillon:ocean_anti</summary>
|
||||
|
||||
- #cobblemon:is_cold_ocean
|
||||
- #cobblemon:is_frozen_ocean
|
||||
- #cobblemon:is_lukewarm_ocean
|
||||
- #cobblemon:is_temperate_ocean
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:polar</summary>
|
||||
|
||||
- #cobblemon:is_frozen_ocean
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:river</summary>
|
||||
|
||||
- #cobblemon:is_river
|
||||
- #cobblemon:is_swamp
|
||||
@@ -1142,7 +1438,48 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:vivillon_sun</summary>
|
||||
<summary><b>Tag:</b> #vivillon:river_anti</summary>
|
||||
|
||||
- #cobblemon:is_forest
|
||||
- #cobblemon:is_jungle
|
||||
- #cobblemon:is_magical
|
||||
- #cobblemon:is_spooky
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:sandstorm</summary>
|
||||
|
||||
- #cobblemon:is_desert
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:sandstorm_anti</summary>
|
||||
|
||||
- #cobblemon:is_badlands
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:savanna</summary>
|
||||
|
||||
- #cobblemon:is_savanna
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:savanna_anti</summary>
|
||||
|
||||
- #cobblemon:is_badlands
|
||||
- #cobblemon:is_desert
|
||||
- #cobblemon:is_floral
|
||||
- #cobblemon:is_mountain
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:sun</summary>
|
||||
|
||||
- #cobblemon:is_sky
|
||||
- #cobblemon:is_volcanic
|
||||
@@ -1151,7 +1488,7 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #evolution:vivillon_tundra</summary>
|
||||
<summary><b>Tag:</b> #vivillon:tundra</summary>
|
||||
|
||||
- #cobblemon:is_glacial
|
||||
- #cobblemon:is_snowy_forest
|
||||
@@ -1159,6 +1496,20 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:tundra_anti</summary>
|
||||
|
||||
- #cobblemon:is_mountain
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #vivillon:void</summary>
|
||||
|
||||
- #minecraft:is_end
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #has_density:dense</summary>
|
||||
|
||||
@@ -1439,6 +1790,7 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
<details>
|
||||
<summary><b>Tag:</b> #has_season:spring</summary>
|
||||
|
||||
- #aether:is_aether
|
||||
- #cobblemon:is_floral
|
||||
- #cobblemon:is_lukewarm_ocean
|
||||
- #cobblemon:is_magical
|
||||
@@ -1666,60 +2018,109 @@ This file contains tags related to different biomes in cobblemon, as well as som
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional_bias_evolutions:alolan</summary>
|
||||
<summary><b>Tag:</b> #space:is_fiery</summary>
|
||||
|
||||
- #cobblemon:is_tropical_island
|
||||
- #minecraft:is_beach
|
||||
- #stellaris:mercury_biomes
|
||||
- space:mercury_hotspot
|
||||
- space:mercury_plains
|
||||
- space:venus_highlands
|
||||
- space:venus_lava_caves
|
||||
- space:venus_lowlands
|
||||
- space:venus_midlands
|
||||
- space:venus_volcanic_plains
|
||||
- stellaris:infernal_venus_barrens
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional_bias_evolutions:cyndaquil_quilava_hisui_bias</summary>
|
||||
<summary><b>Tag:</b> #space:is_icy</summary>
|
||||
|
||||
- #cobblemon:is_taiga
|
||||
- #cobblemon:nether/is_crimson
|
||||
- #cobblemon:nether/is_forest
|
||||
- #cobblemon:nether/is_overgrowth
|
||||
- #space:ice_craters
|
||||
- stellaris:mars_ice_spikes
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional_bias_evolutions:oshawott_dewott_hisui_bias</summary>
|
||||
<summary><b>Tag:</b> #space:is_mars</summary>
|
||||
|
||||
- #c:stony_shores
|
||||
- minecraft:snowy_beach
|
||||
- minecraft:stony_shore
|
||||
- terralith:basalt_cliffs
|
||||
- terralith:granite_cliffs
|
||||
- terralith:white_cliffs
|
||||
- wythers:calcite_coast
|
||||
- wythers:coastal_mangroves
|
||||
- wythers:cold_island
|
||||
- wythers:cold_stony_shore
|
||||
- wythers:deepslate_shore
|
||||
- wythers:frigid_island
|
||||
- wythers:frozen_island
|
||||
- wythers:gravelly_beach
|
||||
- wythers:icy_shore
|
||||
- wythers:mediterranean_island
|
||||
- wythers:temperate_island
|
||||
- wythers:tropical_island
|
||||
- wythers:warm_stony_shore
|
||||
- #stellaris:mars_biomes
|
||||
- #stellaris:mars_biomes
|
||||
- #stellaris:mars_biomes
|
||||
- space:mars_dripstone
|
||||
- space:mars_highlands
|
||||
- space:mars_ice
|
||||
- space:mars_lowlands
|
||||
- space:mars_lush_caves
|
||||
- space:mars_midlands
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional_bias_evolutions:rowlet_dartrix_alolan</summary>
|
||||
<summary><b>Tag:</b> #space:is_mercury</summary>
|
||||
|
||||
- #cobblemon:is_forest
|
||||
- #cobblemon:is_taiga
|
||||
- #stellaris:mercury_biomes
|
||||
- space:mercury_hotspot
|
||||
- space:mercury_ice
|
||||
- space:mercury_plains
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #regional_bias_evolutions:rowlet_dartrix_hisui_bias</summary>
|
||||
<summary><b>Tag:</b> #space:is_moon</summary>
|
||||
|
||||
- #cobblemon:is_snowy_forest
|
||||
- #cobblemon:is_snowy_taiga
|
||||
- #stellaris:moon_biomes
|
||||
- space:moon_highlands
|
||||
- space:moon_ice
|
||||
- space:moon_lowlands
|
||||
- space:moon_midlands
|
||||
- space:moon_rocks
|
||||
- swe:moon
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #space:is_space</summary>
|
||||
|
||||
- #stellaris:mars_biomes
|
||||
- #stellaris:mercury_biomes
|
||||
- #stellaris:moon_biomes
|
||||
- #stellaris:venus_biomes
|
||||
- space:mars_dripstone
|
||||
- space:mars_highlands
|
||||
- space:mars_ice
|
||||
- space:mars_lowlands
|
||||
- space:mars_lush_caves
|
||||
- space:mars_midlands
|
||||
- space:mercury_hotspot
|
||||
- space:mercury_ice
|
||||
- space:mercury_plains
|
||||
- space:moon_highlands
|
||||
- space:moon_ice
|
||||
- space:moon_lowlands
|
||||
- space:moon_midlands
|
||||
- space:moon_rocks
|
||||
- space:space
|
||||
- space:venus_highlands
|
||||
- space:venus_lava_caves
|
||||
- space:venus_lowlands
|
||||
- space:venus_midlands
|
||||
- space:venus_plankton_bloom
|
||||
- space:venus_sky
|
||||
- space:venus_volcanic_plains
|
||||
- swe:moon
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #space:is_venus</summary>
|
||||
|
||||
- #stellaris:venus_biomes
|
||||
- space:venus_highlands
|
||||
- space:venus_lava_caves
|
||||
- space:venus_lowlands
|
||||
- space:venus_midlands
|
||||
- space:venus_plankton_bloom
|
||||
- space:venus_sky
|
||||
- space:venus_volcanic_plains
|
||||
|
||||
</details>
|
||||
@@ -186,6 +186,7 @@ This file contains tags related to block in cobblemon.
|
||||
|
||||
- #c:farmland
|
||||
- #c:farmlands
|
||||
- aether:aether_farmland
|
||||
- minecraft:farmland
|
||||
|
||||
</details>
|
||||
@@ -465,6 +466,19 @@ This file contains tags related to block in cobblemon.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #block:gilded_chests</summary>
|
||||
|
||||
- cobblemon:black_gilded_chest
|
||||
- cobblemon:blue_gilded_chest
|
||||
- cobblemon:gilded_chest
|
||||
- cobblemon:green_gilded_chest
|
||||
- cobblemon:pink_gilded_chest
|
||||
- cobblemon:white_gilded_chest
|
||||
- cobblemon:yellow_gilded_chest
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #block:glazed_terracotta_blocks</summary>
|
||||
|
||||
@@ -1172,6 +1186,7 @@ This file contains tags related to block in cobblemon.
|
||||
- botania:white_floating_flower
|
||||
- botania:white_mystical_flower
|
||||
- botania:white_shiny_flower
|
||||
- cobblemon:pep_up_flower
|
||||
- deep_aether:enchanted_blossom
|
||||
- farmersdelight:wild_carrots
|
||||
- minecraft:azure_bluet
|
||||
@@ -1863,10 +1878,7 @@ This file contains tags related to block in cobblemon.
|
||||
<details>
|
||||
<summary><b>Tag:</b> #block:logs</summary>
|
||||
|
||||
- cobblemon:apricorn_log
|
||||
- cobblemon:apricorn_wood
|
||||
- cobblemon:stripped_apricorn_log
|
||||
- cobblemon:stripped_apricorn_wood
|
||||
- #cobblemon:apricorn_logs
|
||||
|
||||
</details>
|
||||
|
||||
@@ -229,14 +229,6 @@ This file contains tags related to items in cobblemon.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:cobblemon_seeds</summary>
|
||||
|
||||
- #cobblemon:mint_seeds
|
||||
- cobblemon:vivichoke_seeds
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:cooked_meat</summary>
|
||||
|
||||
@@ -329,6 +321,7 @@ This file contains tags related to items in cobblemon.
|
||||
- cobblemon:reaper_cloth
|
||||
- cobblemon:ribbon_sweet
|
||||
- cobblemon:sachet
|
||||
- cobblemon:shell_helmet
|
||||
- cobblemon:star_sweet
|
||||
- cobblemon:strawberry_sweet
|
||||
- cobblemon:sweet_apple
|
||||
@@ -433,6 +426,19 @@ This file contains tags related to items in cobblemon.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:gilded_chests</summary>
|
||||
|
||||
- cobblemon:black_gilded_chest
|
||||
- cobblemon:blue_gilded_chest
|
||||
- cobblemon:gilded_chest
|
||||
- cobblemon:green_gilded_chest
|
||||
- cobblemon:pink_gilded_chest
|
||||
- cobblemon:white_gilded_chest
|
||||
- cobblemon:yellow_gilded_chest
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:hanging_signs</summary>
|
||||
|
||||
@@ -590,9 +596,9 @@ This file contains tags related to items in cobblemon.
|
||||
- #cobblemon:apricorn_sprouts
|
||||
- #cobblemon:apricorns
|
||||
- #cobblemon:berries
|
||||
- #cobblemon:cobblemon_seeds
|
||||
- #cobblemon:herbs
|
||||
- #cobblemon:mint_leaf
|
||||
- #cobblemon:seeds
|
||||
- cobblemon:big_root
|
||||
- cobblemon:energy_root
|
||||
- cobblemon:medicinal_leek
|
||||
@@ -820,12 +826,9 @@ This file contains tags related to items in cobblemon.
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:seeds</summary>
|
||||
|
||||
- #cobblemon:cobblemon_seeds
|
||||
- minecraft:beetroot_seeds
|
||||
- minecraft:melon_seeds
|
||||
- minecraft:pumpkin_seeds
|
||||
- minecraft:torchflower_seeds
|
||||
- minecraft:wheat_seeds
|
||||
- #cobblemon:held/terrain_seeds
|
||||
- #cobblemon:mint_seeds
|
||||
- cobblemon:vivichoke_seeds
|
||||
|
||||
</details>
|
||||
|
||||
@@ -882,6 +885,7 @@ This file contains tags related to items in cobblemon.
|
||||
|
||||
- cobblemon:deepslate_sun_stone_ore
|
||||
- cobblemon:sun_stone_ore
|
||||
- cobblemon:terracotta_sun_stone_ore
|
||||
|
||||
</details>
|
||||
|
||||
@@ -949,7 +953,7 @@ This file contains tags related to items in cobblemon.
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:tier_1_poke_ball_materials</summary>
|
||||
|
||||
- minecraft:copper_ingot
|
||||
- #c:ingots/copper
|
||||
|
||||
</details>
|
||||
|
||||
@@ -977,7 +981,7 @@ This file contains tags related to items in cobblemon.
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:tier_2_poke_ball_materials</summary>
|
||||
|
||||
- minecraft:iron_ingot
|
||||
- #c:ingots/iron
|
||||
|
||||
</details>
|
||||
|
||||
@@ -1000,7 +1004,7 @@ This file contains tags related to items in cobblemon.
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:tier_3_poke_ball_materials</summary>
|
||||
|
||||
- minecraft:gold_ingot
|
||||
- #c:ingots/gold
|
||||
|
||||
</details>
|
||||
|
||||
@@ -1015,7 +1019,7 @@ This file contains tags related to items in cobblemon.
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:tier_4_poke_ball_materials</summary>
|
||||
|
||||
- minecraft:diamond
|
||||
- #c:gems/diamond
|
||||
|
||||
</details>
|
||||
|
||||
@@ -1345,6 +1349,13 @@ This file contains tags related to items in cobblemon.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:bookshelf_books</summary>
|
||||
|
||||
- #cobblemon:pokedex
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:chest_boats</summary>
|
||||
|
||||
@@ -1397,26 +1408,28 @@ This file contains tags related to items in cobblemon.
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:logs</summary>
|
||||
|
||||
- cobblemon:apricorn_log
|
||||
- cobblemon:apricorn_wood
|
||||
- cobblemon:stripped_apricorn_log
|
||||
- cobblemon:stripped_apricorn_wood
|
||||
- #cobblemon:apricorn_logs
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:logs_that_burn</summary>
|
||||
|
||||
- cobblemon:apricorn_log
|
||||
- cobblemon:apricorn_wood
|
||||
- cobblemon:stripped_apricorn_log
|
||||
- cobblemon:stripped_apricorn_wood
|
||||
- #cobblemon:apricorn_logs
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:parrot_food</summary>
|
||||
|
||||
- #cobblemon:seeds
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Tag:</b> #item:piglin_loved</summary>
|
||||
|
||||
- #cobblemon:gilded_chests
|
||||
- cobblemon:relic_coin
|
||||
- cobblemon:relic_coin_pouch
|
||||
- cobblemon:relic_coin_sack
|
||||
+29
-31
@@ -37,15 +37,15 @@ This file contains all current spawn presets of cobblemon.
|
||||
| **structures** | `minecraft:end_city` | |
|
||||
## foliage
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **neededNearbyBlocks** | `#minecraft:leaves`; `#c:leaves` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|------------------------|----------------------------------|----------------|
|
||||
| **neededNearbyBlocks** | `#minecraft:leaves`; `#c:leaves` | |
|
||||
## illager_structures
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **minY** | `62` | |
|
||||
| **structures** | `minecraft:pillager_outpost`; `minecraft:swamp_hut`; `minecraft:mansion` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|----------------|--------------------------------------------------------------------------|----------------|
|
||||
| **minY** | `62` | |
|
||||
| **structures** | `minecraft:pillager_outpost`; `minecraft:swamp_hut`; `minecraft:mansion` | |
|
||||
## jungle_pyramid
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
@@ -54,12 +54,11 @@ This file contains all current spawn presets of cobblemon.
|
||||
| **neededBaseBlocks** | `minecraft:cobblestone`; `#minecraft:mossy_cobblestone` | |
|
||||
| **neededNearbyBlocks** | `#cobblemon:jungle_pyramid_blocks` | |
|
||||
| **structures** | `minecraft:jungle_pyramid` | |
|
||||
|
||||
## lava
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **fluid** | `#minecraft:lava` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|-----------|-------------------|----------------|
|
||||
| **fluid** | `#minecraft:lava` | |
|
||||
## mansion
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
@@ -75,10 +74,10 @@ This file contains all current spawn presets of cobblemon.
|
||||
| **neededBaseBlocks** | `#cobblemon:natural` | `minecraft:farmland` |
|
||||
## nether_fossil
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **neededNearbyBlocks** | `minecraft:bone_block` | |
|
||||
| **structures** | `minecraft:nether_fossil` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|------------------------|---------------------------|----------------|
|
||||
| **neededNearbyBlocks** | `minecraft:bone_block` | |
|
||||
| **structures** | `minecraft:nether_fossil` | |
|
||||
## nether_structures
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
@@ -120,17 +119,17 @@ This file contains all current spawn presets of cobblemon.
|
||||
| **structures** | `#minecraft:ruined_portal` | |
|
||||
## salt
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **biomes** | `biomesoplenty:hot_springs`; `biomesoplenty:wasteland`; `biomesoplenty:wasteland_steppe`; `terralith:amethyst_canyon`; `terralith:amethyst_rainforest`; `terralith:skylands_winter`; `terralith:yellowstone`; `wythers:calcite_caverns`; `wythers:calcite_coast`; `wythers:mediterranean_island_thermal_spring`; `wythers:salt_lakes_pink`; `wythers:salt_lakes_turquoise`; `wythers:salt_lakes_white`; `wythers:thermal_taiga` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|
|
||||
| **biomes** | `biomesoplenty:hot_springs`; `biomesoplenty:wasteland`; `biomesoplenty:wasteland_steppe`; `terralith:amethyst_canyon`; `terralith:amethyst_rainforest`; `terralith:skylands_winter`; `terralith:yellowstone`; `wythers:calcite_caverns`; `wythers:calcite_coast`; `wythers:mediterranean_island_thermal_spring`; `wythers:salt_lakes_pink`; `wythers:salt_lakes_turquoise`; `wythers:salt_lakes_white`; `wythers:thermal_taiga` | |
|
||||
## stronghold
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **maxY** | `62` | |
|
||||
| **neededBaseBlocks** | `#minecraft:stone_bricks` | |
|
||||
| **neededNearbyBlocks** | `minecraft:cracked_stone_bricks`; `minecraft:mossy_stone_bricks` | |
|
||||
| **structures** | `minecraft:stronghold` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|------------------------|------------------------------------------------------------------|----------------|
|
||||
| **maxY** | `62` | |
|
||||
| **neededBaseBlocks** | `#minecraft:stone_bricks` | |
|
||||
| **neededNearbyBlocks** | `minecraft:cracked_stone_bricks`; `minecraft:mossy_stone_bricks` | |
|
||||
| **structures** | `minecraft:stronghold` | |
|
||||
## trail_ruins
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
@@ -150,17 +149,16 @@ This file contains all current spawn presets of cobblemon.
|
||||
|------------------------|------------------------------|-----------------------------------------------|
|
||||
| **neededNearbyBlocks** | `#cobblemon:concrete_blocks` | |
|
||||
| **structures** | | `#minecraft:village`; `minecraft:trail_ruins` |
|
||||
|
||||
## water
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **fluid** | `#minecraft:water` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|-----------|--------------------|----------------|
|
||||
| **fluid** | `#minecraft:water` | |
|
||||
## webs
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
| --- | ---------- | -------------- |
|
||||
| **biomes** | `biomesoplenty:spider_nest`; `terralith:cave/infested_caves`; `wythers:forbidden_forest`; `wythers:phantasmal_forest`; `wythers:phantasmal_swamp` | |
|
||||
| Key | Conditions | Anticonditions |
|
||||
|------------|---------------------------------------------------------------------------------------------------------------------------------------------------|----------------|
|
||||
| **biomes** | `biomesoplenty:spider_nest`; `terralith:cave/infested_caves`; `wythers:forbidden_forest`; `wythers:phantasmal_forest`; `wythers:phantasmal_swamp` | |
|
||||
## wild
|
||||
|
||||
| Key | Conditions | Anticonditions |
|
||||
@@ -39,6 +39,7 @@ repositories {
|
||||
mavenLocal()
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
maven(url = "https://api.modrinth.com/maven")
|
||||
maven(url = "https://maven.terraformersmc.com/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -56,10 +57,13 @@ dependencies {
|
||||
modApi(libs.fabric.api)
|
||||
modApi(libs.bundles.fabric)
|
||||
|
||||
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
modCompileOnly(libs.bundles.common.integrations.compileOnly) {
|
||||
isTransitive = false
|
||||
}
|
||||
|
||||
modImplementation(libs.bundles.fabric.integrations.implementation)
|
||||
modRuntimeOnly(libs.bundles.fabric.integrations.runtimeOnly)
|
||||
|
||||
// modImplementation(libs.flywheelFabric)
|
||||
// include(libs.flywheelFabric)
|
||||
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.fabric.client.integration.modmenu
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen
|
||||
import com.terraformersmc.modmenu.api.ConfigScreenFactory
|
||||
import com.terraformersmc.modmenu.api.ModMenuApi
|
||||
|
||||
class CobblemonModMenu : ModMenuApi {
|
||||
override fun getModConfigScreenFactory(): ConfigScreenFactory<*> {
|
||||
return ConfigScreenFactory { parent ->
|
||||
CobblemonConfigScreen(parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,9 @@
|
||||
],
|
||||
"dynamiclights": [
|
||||
"com.cobblemon.mod.fabric.compat.lambdynamiclights.LambDynamicLightsCompatEntrypoint"
|
||||
],
|
||||
"modmenu": [
|
||||
"com.cobblemon.mod.fabric.client.integration.modmenu.CobblemonModMenu"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ mc_version = 1.21.1
|
||||
parchment_version = 2024.07.28@zip
|
||||
|
||||
mod_id=cobblemon
|
||||
mod_version=1.6.1
|
||||
snapshot=false
|
||||
mod_version=1.7.0
|
||||
snapshot=true
|
||||
|
||||
fabric.loom.multiProjectOptimisation=false
|
||||
@@ -7,6 +7,7 @@ repositories {
|
||||
maven("https://maven.architectury.dev/")
|
||||
maven("https://maven.fabricmc.net/")
|
||||
maven("https://maven.minecraftforge.net/")
|
||||
maven("https://maven.terraformersmc.com/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -25,6 +25,7 @@ fabric-kotlin = "1.11.0+kotlin.2.0.0"
|
||||
fabric-permissions-api = "0.2-SNAPSHOT"
|
||||
lambDynamicLights = "3.0.1+1.21.1"
|
||||
debugutils-fabric = "1.21-1.0.6-fabric"
|
||||
mod-menu = "11.0.3"
|
||||
|
||||
# NeoForge
|
||||
neoforge = "21.1.66"
|
||||
@@ -70,6 +71,7 @@ lambDynamicLights = { group = "maven.modrinth", name = "lambdynamiclights", vers
|
||||
jei-api-fabric = { group = "mezz.jei", name = "jei-1.21-fabric-api", version.ref = "jei-api" }
|
||||
jei-fabric = { group = "mezz.jei", name = "jei-1.21-fabric", version.ref = "jei-api"}
|
||||
fabric-debugutils = { group = "maven.modrinth", name = "debugutils", version.ref = "debugutils-fabric"}
|
||||
mod-menu = { group = "com.terraformersmc", name = "modmenu", version.ref = "mod-menu" }
|
||||
|
||||
# NeoForge
|
||||
neoforge = { group = "net.neoforged", name = "neoforge", version.ref = "neoforge" }
|
||||
@@ -90,7 +92,8 @@ classgraph = { group = "io.github.classgraph", name = "classgraph", version.ref
|
||||
[bundles]
|
||||
kotlin = [ "kotlin-stdlib", "kotlin-reflect" ]
|
||||
fabric = [ "fabric-kotlin", "fabric-permissions" ]
|
||||
fabric-integrations-compileOnly = [ "adorn-fabric", "lambDynamicLights", "jei-api-fabric" ]
|
||||
common-integrations-compileOnly = [ "adorn-fabric", "lambDynamicLights", "jei-api-fabric" ]
|
||||
fabric-integrations-implementation = [ "mod-menu" ]
|
||||
fabric-integrations-runtimeOnly = [ "jei-fabric" ]
|
||||
mongo = [ "mongo-driver-core", "mongo-driver-sync" ]
|
||||
unitTesting = [ "junit-fabric", "junit-params", "mockito-core", "mock-kotlin", "classgraph" ]
|
||||
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonClient.pokedexUsageContext
|
||||
import com.cobblemon.mod.common.client.CobblemonClient.reloadCodedAssets
|
||||
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen
|
||||
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinds
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.client.render.atlas.CobblemonAtlases
|
||||
@@ -31,6 +32,7 @@ import java.util.function.Supplier
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.color.block.BlockColor
|
||||
import net.minecraft.client.color.item.ItemColor
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.model.geom.ModelLayerLocation
|
||||
import net.minecraft.client.model.geom.builders.LayerDefinition
|
||||
import net.minecraft.client.particle.ParticleProvider
|
||||
@@ -54,6 +56,8 @@ import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.neoforged.fml.ModContainer
|
||||
import net.neoforged.fml.ModList
|
||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent
|
||||
import net.neoforged.neoforge.client.ClientHooks
|
||||
import net.neoforged.neoforge.client.event.ClientTickEvent
|
||||
@@ -64,6 +68,7 @@ import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent
|
||||
import net.neoforged.neoforge.client.event.RegisterShadersEvent
|
||||
import net.neoforged.neoforge.client.event.RenderGuiEvent
|
||||
import net.neoforged.neoforge.client.event.RenderGuiLayerEvent
|
||||
import net.neoforged.neoforge.client.gui.IConfigScreenFactory
|
||||
import net.neoforged.neoforge.client.gui.VanillaGuiLayers
|
||||
import net.neoforged.neoforge.common.NeoForge
|
||||
import thedarkcolour.kotlinforforge.neoforge.forge.MOD_BUS
|
||||
@@ -93,6 +98,11 @@ object CobblemonNeoForgeClient : CobblemonClientImplementation {
|
||||
CobblemonModelPredicateRegistry.registerPredicates()
|
||||
}
|
||||
NeoForgeClientPlatformEventHandler.register()
|
||||
|
||||
val modContainer = ModList.get().getModContainerById(Cobblemon.MODID).get()
|
||||
modContainer.registerExtensionPoint(IConfigScreenFactory::class.java, object : IConfigScreenFactory {
|
||||
override fun createScreen(modContainer: ModContainer, arg: Screen): Screen = CobblemonConfigScreen(arg)
|
||||
})
|
||||
}
|
||||
|
||||
private fun onRegisterReloadListener(event: RegisterClientReloadListenersEvent) {
|
||||
|
||||
Reference in New Issue
Block a user